spree_paypal_api_checkout 0.0.9 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07c55f4fc562fc1c5cafec50afb576a3498ff4569cc6d390c1f02fc174efa002
4
- data.tar.gz: 7ad4654823019c8eb7b7ee1b14132ce1974240ae373c42fafba6ef0d22d8656a
3
+ metadata.gz: ac381ac7aa6843029df5f451f7d1808a637e0b830157b66459d946cb79788d15
4
+ data.tar.gz: dacb44b1f3407eec37c1b181361c946511811c423a0e0f01ce90c70e9f88f8f2
5
5
  SHA512:
6
- metadata.gz: 168e3b4bf6eb7f34e7f0838853a2bdbfdc4b14bb19520cf7ec737a1e9124b8f6c972786022dccaf8353ac9fb8ffdd5f323f1d7011d096411b93f5c4dae93aaa4
7
- data.tar.gz: 36ca56115090032c1487903d9f7b8bde7a7612a37d061fbd37ebe8fd7e02a81e5f4ba2e9b70d30b76b63e1538a068d5a5592db9b7eb0176f40b2df7dc8285a89
6
+ metadata.gz: 833dac68e15e27afc15f50babc6c334020db77d5c76e72efb4663d36b1b814ba785b070e342a1a573a4c8197fbab9e67b7dd366881f1dc833676e0c94fecd438
7
+ data.tar.gz: '0678f4ca959ade6bf86e26f3540ab73ada30bb5e3b87bd855b9cb6582712a955938dab9b66f4cabbf0f8d8ed96115aa659a51e5816e886a183451c733bed6122'
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  1. Add this extension to your Gemfile with this line:
6
6
 
7
- gem 'spree_paypal_api_checkout', '~> 0.0.9'
7
+ gem 'spree_paypal_api_checkout', '~> 0.1.2'
8
8
 
9
9
  2. Install the gem using Bundler:
10
10
 
@@ -1,6 +1,7 @@
1
1
  module Spree
2
2
  class PaypalCheckoutController < StoreController
3
3
  skip_before_action :verify_authenticity_token
4
+
4
5
  def express
5
6
  order = current_order || raise(ActiveRecord::RecordNotFound)
6
7
  items = order.line_items.map(&method(:line_item))
@@ -8,13 +9,14 @@ module Spree
8
9
  additional_adjustments = order.all_adjustments.additional
9
10
  tax_adjustments = additional_adjustments.tax
10
11
  shipping_adjustments = additional_adjustments.shipping
12
+ promotion_adjustments = additional_adjustments.promotion
11
13
 
12
14
  additional_adjustments.eligible.each do |adjustment|
13
15
  # Because PayPal doesn't accept $0 items at all. See #10
14
16
  # https://cms.paypal.com/uk/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ECCustomizing
15
17
  # "It can be a positive or negative value but not zero."
16
18
  next if adjustment.amount.zero?
17
- next if tax_adjustments.include?(adjustment) || shipping_adjustments.include?(adjustment)
19
+ next if tax_adjustments.include?(adjustment) || shipping_adjustments.include?(adjustment) || promotion_adjustments.include?(adjustment)
18
20
 
19
21
  items << {
20
22
  name: adjustment.label,
@@ -26,28 +28,24 @@ module Spree
26
28
  }
27
29
  end
28
30
 
29
- pp_response = provider.create_order(order, express_checkout_request_details(order, items))
31
+ details = express_checkout_request_details(order: order, items: items, tax_adjustments: tax_adjustments, promotion_adjustments: promotion_adjustments)
32
+ pp_response = provider.parse_response(provider.create_order(order, details))
30
33
 
31
34
  render json: pp_response
32
35
  end
33
36
 
34
37
  def confirm
35
38
  order = current_order || raise(ActiveRecord::RecordNotFound)
36
- response = provider.capture_payment(params[:number])
37
- order.payments.create!({
38
- source: Spree::PaypalApiCheckout.create({
39
- token: response['id'],
40
- payer_id: response['payer']['payer_id']
41
- }),
42
- amount: order.total,
43
- payment_method: payment_method
44
- })
39
+
40
+ response = provider.set_payment_records(order, params[:number], payment_method)
41
+
45
42
  render json: response
46
43
  end
47
44
 
48
45
  def proceed
49
46
  order = current_order || raise(ActiveRecord::RecordNotFound)
50
47
  order.payments.last.source.update(transaction_id: params[:transaction_id])
48
+ order.payments.last.update(response_code: params[:transaction_id])
51
49
  order.next
52
50
  path = checkout_state_path(order.state)
53
51
  if order.complete?
@@ -81,7 +79,7 @@ module Spree
81
79
  }
82
80
  end
83
81
 
84
- def express_checkout_request_details order, items
82
+ def express_checkout_request_details order:, items:, tax_adjustments:, promotion_adjustments:
85
83
  {
86
84
  intent: 'CAPTURE',
87
85
  purchase_units: [
@@ -93,6 +91,18 @@ module Spree
93
91
  item_total: {
94
92
  currency_code: current_order.currency,
95
93
  value: items.sum{|r| (r[:unit_amount][:value] * r[:quantity]) }
94
+ },
95
+ shipping: {
96
+ currency_code: current_order.currency,
97
+ value: current_order.shipments.sum(:cost)
98
+ },
99
+ tax_total: {
100
+ currency_code: current_order.currency,
101
+ value: tax_adjustments.sum(:amount)
102
+ },
103
+ discount: {
104
+ currency_code: current_order.currency,
105
+ value: promotion_adjustments.sum(:amount).abs
96
106
  }
97
107
  }
98
108
  },
@@ -20,75 +20,25 @@ module Spree
20
20
  'paypal_checkout'
21
21
  end
22
22
 
23
- def generate_client_token
24
- uri = URI.parse("https://#{preferred_server}/v1/identity/generate-token")
25
- request = Net::HTTP::Post.new(uri)
26
- request['Authorization'] = "Bearer #{generate_access_token}"
27
- request.content_type = "application/json"
28
-
29
- req_options = { use_ssl: uri.scheme == "https" }
30
-
31
- response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
32
- response = http.request(request)
33
- end
34
- return response
35
- end
36
-
37
23
  def generate_access_token
38
- uri = URI.parse("https://#{preferred_server}/v1/oauth2/token")
39
- request = Net::HTTP::Post.new(uri)
40
- request.basic_auth("#{preferred_api_key}", "#{preferred_secret_key}")
41
- request.content_type = "application/json"
42
- request.body = "grant_type=client_credentials"
43
-
44
- req_options = { use_ssl: uri.scheme == "https" }
24
+ response = post_response_without_token(api_url('v1/oauth2/token'))
25
+ return response['access_token']
26
+ end
45
27
 
46
- response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
47
- response = http.request(request)
48
- end
49
- return JSON.parse(response.read_body)['access_token']
28
+ def generate_client_token
29
+ post_response(api_url('v1/identity/generate-token'))
50
30
  end
51
31
 
52
32
  def create_order order, body
53
- uri = URI.parse("https://#{preferred_server}/v2/checkout/orders")
54
- request = Net::HTTP::Post.new(uri)
55
- request['Authorization'] = "Bearer #{generate_access_token}"
56
- request.content_type = "application/json"
57
-
58
- request.body = body.to_json
59
- req_options = { use_ssl: uri.scheme == "https" }
60
-
61
- response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
62
- response = http.request(request)
63
- end
64
- return JSON.parse(response.read_body)
33
+ post_response(api_url('v2/checkout/orders'), body)
65
34
  end
66
35
 
67
36
  def capture_payment order_id
68
- uri = URI.parse("https://#{preferred_server}/v2/checkout/orders/#{order_id}/capture")
69
- request = Net::HTTP::Post.new(uri)
70
- request['Authorization'] = "Bearer #{generate_access_token}"
71
- request.content_type = "application/json"
72
- req_options = { use_ssl: uri.scheme == "https" }
73
-
74
- response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
75
- response = http.request(request)
76
- end
77
- return JSON.parse(response.read_body)
37
+ post_response(api_url("v2/checkout/orders/#{order_id}/capture"))
78
38
  end
79
39
 
80
40
  def refund_payment id, body
81
- uri = URI.parse("https://#{preferred_server}/v2/payments/captures/#{id}/refund")
82
- request = Net::HTTP::Post.new(uri)
83
- request['Authorization'] = "Bearer #{generate_access_token}"
84
- request.body = body.to_json
85
- request.content_type = "application/json"
86
- req_options = { use_ssl: uri.scheme == "https" }
87
-
88
- response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
89
- response = http.request(request)
90
- end
91
- return JSON.parse(response.read_body)
41
+ post_response(api_url("v2/payments/captures/#{id}/refund"), body)
92
42
  end
93
43
 
94
44
  def purchase(amount, express_checkout, gateway_options={})
@@ -114,8 +64,10 @@ module Spree
114
64
  refund_type: refund_type,
115
65
  refund_source: 'any'
116
66
  }
117
- refund_transaction_response = refund_payment(payment.source.transaction_id, refund_transaction)
118
- if refund_transaction_response['status']=='COMPLETED'
67
+ refund_entry = refund_payment(payment.source.transaction_id, refund_transaction)
68
+ refund_transaction_response = parse_response(refund_entry)
69
+
70
+ if success_response?(refund_transaction_response)
119
71
  payment.source.update({
120
72
  :refunded_at => Time.now,
121
73
  :refund_transaction_id => refund_transaction_response['id'],
@@ -123,7 +75,7 @@ module Spree
123
75
  :refund_type => refund_type
124
76
  })
125
77
 
126
- payment.class.create!(
78
+ refund_payment = payment.class.create!(
127
79
  :order => payment.order,
128
80
  :source => payment,
129
81
  :payment_method => payment.payment_method,
@@ -131,9 +83,93 @@ module Spree
131
83
  :response_code => refund_transaction_response['id'],
132
84
  :state => 'completed'
133
85
  )
86
+ refund_payment.log_entries.create!(details: refund_entry.to_yaml)
134
87
  end
135
88
  refund_transaction_response
136
89
  end
90
+
91
+ def post_response uri, body={}
92
+ request = Net::HTTP::Post.new(uri)
93
+ request['Authorization'] = "Bearer #{generate_access_token}"
94
+ request.body = body.to_json if body.present?
95
+
96
+ return hit_api(request: request, body: body, uri: uri)
97
+ end
98
+
99
+ def post_response_without_token uri, body={}
100
+ request = Net::HTTP::Post.new(uri)
101
+ request.basic_auth("#{preferred_api_key}", "#{preferred_secret_key}")
102
+ request.body = 'grant_type=client_credentials'
103
+
104
+ return parse_response(hit_api(request: request, body: body, uri: uri))
105
+ end
106
+
107
+ def hit_api request:, body:, uri:
108
+ request.content_type = 'application/json'
109
+ req_options = { use_ssl: uri.scheme == 'https' }
110
+
111
+ response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
112
+ response = http.request(request)
113
+ end
114
+ response
115
+ end
116
+
117
+ def parse_response response
118
+ JSON.parse(response.read_body) rescue response
119
+ end
120
+
121
+ def api_url url
122
+ URI.parse("https://#{preferred_server}/#{url}")
123
+ end
124
+
125
+ def set_payment_records order, number, payment_method
126
+ raw_response = response = nil
127
+ success = false
128
+ begin
129
+ payment_entry = capture_payment(number)
130
+ response = parse_response(payment_entry)
131
+ success = success_response?(response)
132
+
133
+ payment = order.payments.create!({
134
+ source: Spree::PaypalApiCheckout.create({
135
+ token: response['id'],
136
+ payer_id: response['payer']['payer_id']
137
+ }),
138
+ amount: order.total,
139
+ payment_method: payment_method
140
+ })
141
+ rescue Exception => e
142
+ raw_response = e.response.body
143
+ response = response_error(raw_response)
144
+ rescue JSON::ParserError
145
+ response = json_error(raw_response)
146
+ end
147
+
148
+ payment.log_entries.create!(details: payment_entry.to_yaml)
149
+ response
150
+ end
151
+
152
+ def response_error(raw_response)
153
+ begin
154
+ parse(raw_response)
155
+ rescue JSON::ParserError
156
+ json_error(raw_response)
157
+ end
158
+ end
159
+
160
+ def json_error(raw_response)
161
+ msg = 'Invalid response. Please contact team if you continue to receive this message.'
162
+ msg += " (The raw response returned by the API was #{raw_response.inspect})"
163
+ {
164
+ "error" => {
165
+ "message" => msg
166
+ }
167
+ }
168
+ end
169
+
170
+ def success_response? response
171
+ response.key?('status') && response.key?('id') && (response['status'] == 'COMPLETED')
172
+ end
137
173
  end
138
174
  end
139
175
 
@@ -1,5 +1,5 @@
1
1
  <div id="paypal-button-container" class="paypal-button-container"></div>
2
- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
2
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
3
3
  <script type="text/javascript" src="https://www.paypal.com/sdk/js?client-id=<%= payment_method.preferred_api_key %>&currency=<%= @order.currency %>"></script>
4
4
 
5
5
  <script type="text/javascript">
@@ -15,6 +15,7 @@ de:
15
15
  refund_unsuccessful: "PayPal Erstattung nicht erfolgreich"
16
16
  actions:
17
17
  refund: "Erstatten"
18
+ status: 'Toestand'
18
19
  flash:
19
20
  cancel: "Sie wollen PayPal doch nicht benutzen? Kein Problem."
20
21
  connection_failed: "Verbindung zu Paypal nicht erfolgreich."
@@ -15,6 +15,7 @@ en:
15
15
  refund_unsuccessful: "PayPal refund unsuccessful"
16
16
  actions:
17
17
  refund: "Refund"
18
+ status: Status
18
19
  flash:
19
20
  cancel: "Don't want to use PayPal? No problems."
20
21
  connection_failed: "Could not connect to PayPal."
@@ -15,6 +15,7 @@ es:
15
15
  refund_unsuccessful: "No se pudo rembolsar el pago de PayPal"
16
16
  actions:
17
17
  refund: "Reembolso"
18
+ status: Estado
18
19
  flash:
19
20
  cancel: "No quieres usar PayPal? No hay problema."
20
21
  connection_failed: "No se pudo conectar con PayPal."
@@ -15,6 +15,7 @@ it:
15
15
  refund_unsuccessful: "Rimborso PayPal non completato"
16
16
  actions:
17
17
  refund: "Rimborso"
18
+ status: Stato
18
19
  flash:
19
20
  cancel: "Non vuoi usare PayPal? Nessun problema."
20
21
  connection_failed: "Impossibile connettersi a PayPal."
@@ -15,6 +15,7 @@ pl:
15
15
  refund_unsuccessful: "Błąd podczas wykonywania zwrotu PayPal"
16
16
  actions:
17
17
  refund: "Zwróć Płatność"
18
+ status: Status
18
19
  flash:
19
20
  cancel: "Nie chcesz użyć PayPal? Nie ma problemu."
20
21
  connection_failed: "Nie można było połączyć się z usługą PayPal."
@@ -15,6 +15,7 @@ pt:
15
15
  refund_unsuccessful: "Não foi possível reembolsar o pagamento de PayPal"
16
16
  actions:
17
17
  refund: "Reembolso"
18
+ status: Status
18
19
  flash:
19
20
  cancel: "Não pretende usar PayPal? Não há problema."
20
21
  connection_failed: "Não foi possível estabelecer ligação com o PayPal."
@@ -1,3 +1,3 @@
1
1
  module SpreePaypalApiCheckout
2
- VERSION = '0.0.9'
2
+ VERSION = '0.1.2'
3
3
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "spree_paypal_api_checkout".freeze
3
- s.version = "0.0.9"
3
+ s.version = "0.1.2"
4
4
 
5
5
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
6
6
  s.require_paths = ["lib".freeze]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_paypal_api_checkout
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Spree Commerce