spree_paypal_api_checkout 0.0.9 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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