spree_paypal_checkout 0.7.0 → 0.7.1
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 +4 -4
- data/app/models/spree/payment_setup_sessions/paypal_checkout.rb +22 -0
- data/app/models/spree_paypal_checkout/gateway/payment_setup_sessions.rb +116 -0
- data/app/presenters/spree_paypal_checkout/setup_token_presenter.rb +37 -0
- data/app/views/spree/admin/payment_methods/configuration_guides/_spree_paypal_checkout.html.erb +2 -1
- data/lib/spree_paypal_checkout/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bfb11878efce5e64446b6e83c9f16a69b64203ff47ce9ca601f1404b6f0ed017
|
|
4
|
+
data.tar.gz: 86705e3ed5b1c0314c2518c793edc022d5149e64a32d710919455b0e3ef4fe42
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fb11160ee57ed3ab5275c2e32c8d13463b74149002ed2297cd95045f53dc3101c8a1f97fff3b8424c4d0ae6e5ba5003c623ad2d12d4226183dbb30aa8c5a4c95
|
|
7
|
+
data.tar.gz: 74a7e4a0cdd3f55e976bb948ee8bc8a9799b55ec076319c353720342ffb0b80e087f0229e1046e0fc6f4b74dae88ff019ad1231f6a8f127ddbdfff1cc73dba23
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
class PaymentSetupSessions::PaypalCheckout < PaymentSetupSession
|
|
3
|
+
# PayPal's Vault API uses setup tokens (temporary) that get exchanged for
|
|
4
|
+
# permanent payment tokens once the buyer approves on PayPal.
|
|
5
|
+
def paypal_setup_token_id
|
|
6
|
+
external_id
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def paypal_payment_token_id
|
|
10
|
+
external_data&.dig('payment_token', 'id')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# The approve link the storefront redirects the buyer to.
|
|
14
|
+
def approve_link
|
|
15
|
+
Array(external_data&.dig('links')).find { |l| l['rel'] == 'approve' }&.dig('href')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def successful?
|
|
19
|
+
status == 'completed'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
module SpreePaypalCheckout
|
|
2
|
+
class Gateway < ::Spree::Gateway
|
|
3
|
+
module PaymentSetupSessions
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
def setup_session_supported?
|
|
7
|
+
true
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def payment_setup_session_class
|
|
11
|
+
Spree::PaymentSetupSessions::PaypalCheckout
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Creates a PayPal Vault setup token (temporary, awaiting buyer approval)
|
|
15
|
+
# and persists a Spree::PaymentSetupSessions::PaypalCheckout record.
|
|
16
|
+
#
|
|
17
|
+
# @param customer [Spree::User] the customer to vault the PayPal account for
|
|
18
|
+
# @param external_data [Hash] optional :return_url and :cancel_url for the
|
|
19
|
+
# PayPal redirect flow
|
|
20
|
+
# @return [Spree::PaymentSetupSessions::PaypalCheckout]
|
|
21
|
+
def create_payment_setup_session(customer:, external_data: {})
|
|
22
|
+
return_url = external_data[:return_url] || external_data['return_url'] || default_setup_return_url
|
|
23
|
+
cancel_url = external_data[:cancel_url] || external_data['cancel_url'] || default_setup_cancel_url
|
|
24
|
+
|
|
25
|
+
protect_from_error do
|
|
26
|
+
response = client.vault.create_setup_token(
|
|
27
|
+
SpreePaypalCheckout::SetupTokenPresenter.new(
|
|
28
|
+
customer: customer,
|
|
29
|
+
return_url: return_url,
|
|
30
|
+
cancel_url: cancel_url
|
|
31
|
+
).to_h
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
payment_setup_session_class.create!(
|
|
35
|
+
customer: customer,
|
|
36
|
+
payment_method: self,
|
|
37
|
+
status: 'pending',
|
|
38
|
+
external_id: response.data.id,
|
|
39
|
+
external_data: response.data.as_json.merge(
|
|
40
|
+
'return_url' => return_url,
|
|
41
|
+
'cancel_url' => cancel_url
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Completes a setup session by exchanging the approved setup token for a
|
|
48
|
+
# permanent payment token, creates a Spree::PaymentSource representing the
|
|
49
|
+
# vaulted PayPal account, and transitions the session.
|
|
50
|
+
#
|
|
51
|
+
# @param setup_session [Spree::PaymentSetupSessions::PaypalCheckout]
|
|
52
|
+
# @param params [Hash] unused — PayPal needs no params beyond the setup_session
|
|
53
|
+
def complete_payment_setup_session(setup_session:, params: {})
|
|
54
|
+
protect_from_error do
|
|
55
|
+
response = client.vault.create_payment_token(
|
|
56
|
+
'body' => {
|
|
57
|
+
'payment_source' => {
|
|
58
|
+
'token' => {
|
|
59
|
+
'id' => setup_session.external_id,
|
|
60
|
+
'type' => 'SETUP_TOKEN'
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
payment_token = response.data
|
|
67
|
+
|
|
68
|
+
setup_session.payment_source = build_payment_source_from_token(setup_session, payment_token)
|
|
69
|
+
setup_session.update!(
|
|
70
|
+
external_data: setup_session.external_data.to_h.merge('payment_token' => payment_token.as_json)
|
|
71
|
+
)
|
|
72
|
+
setup_session.complete if setup_session.can_complete?
|
|
73
|
+
rescue PaypalServerSdk::APIException => e
|
|
74
|
+
setup_session.fail if setup_session.can_fail?
|
|
75
|
+
raise Spree::Core::GatewayError, "PayPal Vault error: #{e.message}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
setup_session
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def build_payment_source_from_token(setup_session, payment_token)
|
|
84
|
+
paypal = payment_token.as_json.dig('payment_source', 'paypal') || {}
|
|
85
|
+
account_id = paypal['email_address'] || payment_token.id
|
|
86
|
+
|
|
87
|
+
source = SpreePaypalCheckout::PaymentSources::Paypal.find_or_initialize_by(
|
|
88
|
+
payment_method: self,
|
|
89
|
+
gateway_payment_profile_id: payment_token.id
|
|
90
|
+
)
|
|
91
|
+
source.update!(
|
|
92
|
+
user: setup_session.customer,
|
|
93
|
+
email: paypal['email_address'],
|
|
94
|
+
name: [paypal.dig('name', 'given_name'), paypal.dig('name', 'surname')].compact.join(' ').strip.presence,
|
|
95
|
+
account_id: account_id,
|
|
96
|
+
account_status: paypal['account_status']
|
|
97
|
+
)
|
|
98
|
+
source
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def default_setup_return_url
|
|
102
|
+
store = stores.first
|
|
103
|
+
return nil unless store
|
|
104
|
+
|
|
105
|
+
"#{store.storefront_url}/paypal/payment_setup_sessions/return"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def default_setup_cancel_url
|
|
109
|
+
store = stores.first
|
|
110
|
+
return nil unless store
|
|
111
|
+
|
|
112
|
+
"#{store.storefront_url}/paypal/payment_setup_sessions/cancel"
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module SpreePaypalCheckout
|
|
2
|
+
# Builds the body of a PayPal Vault /v3/vault/setup-tokens request for tokenizing
|
|
3
|
+
# a buyer's PayPal account without an immediate purchase.
|
|
4
|
+
class SetupTokenPresenter
|
|
5
|
+
def initialize(customer:, return_url:, cancel_url:)
|
|
6
|
+
@customer = customer
|
|
7
|
+
@return_url = return_url
|
|
8
|
+
@cancel_url = cancel_url
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_h
|
|
12
|
+
{
|
|
13
|
+
'body' => {
|
|
14
|
+
'payment_source' => {
|
|
15
|
+
'paypal' => {
|
|
16
|
+
'usage_type' => 'MERCHANT',
|
|
17
|
+
'experience_context' => {
|
|
18
|
+
'return_url' => return_url,
|
|
19
|
+
'cancel_url' => cancel_url
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}.merge(customer_payload)
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
attr_reader :customer, :return_url, :cancel_url
|
|
30
|
+
|
|
31
|
+
def customer_payload
|
|
32
|
+
return {} unless customer&.id
|
|
33
|
+
|
|
34
|
+
{ 'customer' => { 'id' => "customer_#{customer.id}" } }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/app/views/spree/admin/payment_methods/configuration_guides/_spree_paypal_checkout.html.erb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<div class="alert alert-info">
|
|
2
2
|
<p class="mb-0">
|
|
3
3
|
To find your <strong>Client ID</strong> and <strong>Client Secret</strong>, go to the
|
|
4
|
-
<%= external_link_to 'PayPal
|
|
4
|
+
<%= external_link_to 'PayPal Developer Dashboard', 'https://developer.paypal.com/dashboard/', class: 'alert-link' %>.
|
|
5
|
+
For more information, see the <%= external_link_to 'PayPal REST API documentation', 'https://developer.paypal.com/api/rest/', class: 'alert-link' %>.
|
|
5
6
|
</p>
|
|
6
7
|
</div>
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_paypal_checkout
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vendo Connect Inc.
|
|
@@ -121,15 +121,18 @@ files:
|
|
|
121
121
|
- app/javascript/spree_paypal_checkout/application.js
|
|
122
122
|
- app/javascript/spree_paypal_checkout/controllers/checkout_paypal_controller.js
|
|
123
123
|
- app/models/spree/payment_sessions/paypal_checkout.rb
|
|
124
|
+
- app/models/spree/payment_setup_sessions/paypal_checkout.rb
|
|
124
125
|
- app/models/spree_paypal_checkout/base.rb
|
|
125
126
|
- app/models/spree_paypal_checkout/gateway.rb
|
|
126
127
|
- app/models/spree_paypal_checkout/gateway/payment_sessions.rb
|
|
128
|
+
- app/models/spree_paypal_checkout/gateway/payment_setup_sessions.rb
|
|
127
129
|
- app/models/spree_paypal_checkout/order.rb
|
|
128
130
|
- app/models/spree_paypal_checkout/order_decorator.rb
|
|
129
131
|
- app/models/spree_paypal_checkout/payment_method_decorator.rb
|
|
130
132
|
- app/models/spree_paypal_checkout/payment_sources/paypal.rb
|
|
131
133
|
- app/models/spree_paypal_checkout/store_decorator.rb
|
|
132
134
|
- app/presenters/spree_paypal_checkout/order_presenter.rb
|
|
135
|
+
- app/presenters/spree_paypal_checkout/setup_token_presenter.rb
|
|
133
136
|
- app/services/spree_paypal_checkout/capture_order.rb
|
|
134
137
|
- app/services/spree_paypal_checkout/create_payment.rb
|
|
135
138
|
- app/services/spree_paypal_checkout/create_source.rb
|
|
@@ -157,9 +160,9 @@ licenses:
|
|
|
157
160
|
- MIT
|
|
158
161
|
metadata:
|
|
159
162
|
bug_tracker_uri: https://github.com/spree/spree_paypal_checkout/issues
|
|
160
|
-
changelog_uri: https://github.com/spree/spree_paypal_checkout/releases/tag/v0.7.
|
|
163
|
+
changelog_uri: https://github.com/spree/spree_paypal_checkout/releases/tag/v0.7.1
|
|
161
164
|
documentation_uri: https://docs.spreecommerce.org/
|
|
162
|
-
source_code_uri: https://github.com/spree/spree_paypal_checkout/tree/v0.7.
|
|
165
|
+
source_code_uri: https://github.com/spree/spree_paypal_checkout/tree/v0.7.1
|
|
163
166
|
rdoc_options: []
|
|
164
167
|
require_paths:
|
|
165
168
|
- lib
|