solidus_paypal_commerce_platform 0.0.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 +7 -0
- data/.circleci/config.yml +41 -0
- data/.gem_release.yml +5 -0
- data/.github/stale.yml +17 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.rubocop.yml +56 -0
- data/Gemfile +33 -0
- data/LICENSE +26 -0
- data/README.md +173 -0
- data/Rakefile +6 -0
- data/app/assets/javascripts/spree/backend/solidus_paypal_commerce_platform.js +2 -0
- data/app/assets/javascripts/spree/backend/solidus_paypal_commerce_platform/namespace.js +1 -0
- data/app/assets/javascripts/spree/backend/solidus_paypal_commerce_platform/wizard.js +28 -0
- data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform.js +3 -0
- data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/button_actions.js +191 -0
- data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/buttons.js +26 -0
- data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/namespace.js +1 -0
- data/app/assets/stylesheets/spree/backend/solidus_paypal_commerce_platform.css +4 -0
- data/app/assets/stylesheets/spree/frontend/solidus_paypal_commerce_platform.css +17 -0
- data/app/controllers/solidus_paypal_commerce_platform/orders_controller.rb +83 -0
- data/app/controllers/solidus_paypal_commerce_platform/payments_controller.rb +44 -0
- data/app/controllers/solidus_paypal_commerce_platform/paypal_orders_controller.rb +19 -0
- data/app/controllers/solidus_paypal_commerce_platform/shipping_rates_controller.rb +31 -0
- data/app/controllers/solidus_paypal_commerce_platform/wizard_controller.rb +47 -0
- data/app/decorators/solidus_paypal_commerce_platform/remove_required_phone_from_address.rb +13 -0
- data/app/helpers/solidus_paypal_commerce_platform/button_options_helper.rb +21 -0
- data/app/jobs/solidus_paypal_commerce_platform/application_job.rb +6 -0
- data/app/jobs/solidus_paypal_commerce_platform/webhook_job.rb +22 -0
- data/app/models/solidus_paypal_commerce_platform/gateway.rb +88 -0
- data/app/models/solidus_paypal_commerce_platform/payment_method.rb +75 -0
- data/app/models/solidus_paypal_commerce_platform/payment_source.rb +27 -0
- data/app/models/solidus_paypal_commerce_platform/paypal_address.rb +81 -0
- data/app/models/solidus_paypal_commerce_platform/paypal_order.rb +107 -0
- data/app/models/solidus_paypal_commerce_platform/pricing_options.rb +9 -0
- data/app/models/solidus_paypal_commerce_platform/wizard.rb +40 -0
- data/app/overrides/spree/admin/payment_methods/form/insert_email_verification_notification.rb +9 -0
- data/app/overrides/spree/admin/payment_methods/index/insert_setup_wizards.rb +17 -0
- data/app/overrides/spree/admin/payments/log_entries/add_paypal_debug_id.rb +9 -0
- data/app/overrides/spree/orders/edit/insert_cart_buttons.rb +9 -0
- data/app/overrides/spree/payments/payment/add_paypal_email_to_payment.rb +9 -0
- data/app/overrides/spree/products/cart_form/insert_product_buttons.rb +10 -0
- data/app/views/solidus_paypal_commerce_platform/admin/payment_methods/_available_to_users.html.erb +6 -0
- data/app/views/solidus_paypal_commerce_platform/admin/payment_methods/_paypal_wizard.html.erb +16 -0
- data/app/views/solidus_paypal_commerce_platform/admin/payment_methods/_setup_wizards.html.erb +16 -0
- data/app/views/solidus_paypal_commerce_platform/admin/payments/_log_entries.html.erb +32 -0
- data/bin/console +17 -0
- data/bin/rails +7 -0
- data/bin/rails-engine +13 -0
- data/bin/rails-sandbox +18 -0
- data/bin/rake +7 -0
- data/bin/sandbox +86 -0
- data/bin/setup +8 -0
- data/codecov.yml +14 -0
- data/config/locales/en.yml +37 -0
- data/config/routes.rb +12 -0
- data/db/migrate/20200521190038_add_paypal_commerce_platform_sources.rb +13 -0
- data/lib/generators/solidus_paypal_commerce_platform/install/install_generator.rb +38 -0
- data/lib/solidus_paypal_commerce_platform.rb +21 -0
- data/lib/solidus_paypal_commerce_platform/access_token_authorization_request.rb +21 -0
- data/lib/solidus_paypal_commerce_platform/client.rb +84 -0
- data/lib/solidus_paypal_commerce_platform/configuration.rb +64 -0
- data/lib/solidus_paypal_commerce_platform/engine.rb +45 -0
- data/lib/solidus_paypal_commerce_platform/factories.rb +14 -0
- data/lib/solidus_paypal_commerce_platform/fetch_merchant_credentials_request.rb +17 -0
- data/lib/solidus_paypal_commerce_platform/version.rb +5 -0
- data/lib/views/api/spree/api/payments/source_views/_paypal_commerce_platform.json.jbuilder +3 -0
- data/lib/views/backend/spree/admin/payments/source_forms/_paypal_commerce_platform.html.erb +1 -0
- data/lib/views/backend/spree/admin/payments/source_views/_paypal_commerce_platform.html.erb +18 -0
- data/lib/views/backend/spree/admin/shared/preference_fields/_paypal_select.html.erb +13 -0
- data/lib/views/frontend/solidus_paypal_commerce_platform/cart/_cart_buttons.html.erb +3 -0
- data/lib/views/frontend/solidus_paypal_commerce_platform/payments/_payment.html.erb +4 -0
- data/lib/views/frontend/solidus_paypal_commerce_platform/product/_product_buttons.html.erb +3 -0
- data/lib/views/frontend/spree/checkout/payment/_paypal_commerce_platform.html.erb +13 -0
- data/lib/views/frontend/spree/orders/payment/_paypal_commerce_platform.html.erb +17 -0
- data/lib/views/frontend/spree/products/payment/_paypal_commerce_platform.html.erb +15 -0
- data/solidus_paypal_commerce_platform.gemspec +39 -0
- data/spec/features/backend/new_payment_method_spec.rb +40 -0
- data/spec/features/frontend/cart_spec.rb +38 -0
- data/spec/features/frontend/checkout_spec.rb +81 -0
- data/spec/features/frontend/product_spec.rb +79 -0
- data/spec/jobs/solidus_paypal_commerce_platform/fixtures/CHECKOUT.ORDER.COMPLETED.v2.json +121 -0
- data/spec/jobs/solidus_paypal_commerce_platform/fixtures/CHECKOUT.ORDER.PROCESSED.v2.json +121 -0
- data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.COMPLETED.v1.json +50 -0
- data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.COMPLETED.v2.json +72 -0
- data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.DENIED.v1.json +50 -0
- data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.DENIED.v2.json +68 -0
- data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.REFUNDED.v1.json +51 -0
- data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.REFUNDED.v2.json +63 -0
- data/spec/jobs/solidus_paypal_commerce_platform/webhook_job_spec.rb +44 -0
- data/spec/lib/solidus_paypal_commerce_platform/client_spec.rb +21 -0
- data/spec/lib/solidus_paypal_commerce_platform/configuration_spec.rb +67 -0
- data/spec/models/solidus_paypal_commerce_platform/payment_method_spec.rb +102 -0
- data/spec/models/solidus_paypal_commerce_platform/payment_source_spec.rb +62 -0
- data/spec/models/solidus_paypal_commerce_platform/paypal_address_spec.rb +55 -0
- data/spec/models/solidus_paypal_commerce_platform/wizard_spec.rb +9 -0
- data/spec/requests/solidus_paypal_commerce_platform/orders_controller_spec.rb +36 -0
- data/spec/requests/solidus_paypal_commerce_platform/shipping_rates_controller_spec.rb +44 -0
- data/spec/requests/solidus_paypal_commerce_platform/wizard_controller_spec.rb +44 -0
- data/spec/spec_helper.rb +30 -0
- metadata +258 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
SolidusPaypalCommercePlatform.renderButton = function(payment_method_id, style) {
|
|
2
|
+
paypal.Buttons({
|
|
3
|
+
style: style,
|
|
4
|
+
createOrder: SolidusPaypalCommercePlatform.sendOrder.bind(null, payment_method_id),
|
|
5
|
+
onApprove: SolidusPaypalCommercePlatform.approveOrder,
|
|
6
|
+
onShippingChange: SolidusPaypalCommercePlatform.shippingChange
|
|
7
|
+
}).render('#paypal-button-container')
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
SolidusPaypalCommercePlatform.renderCartButton = function(payment_method_id, style) {
|
|
11
|
+
paypal.Buttons({
|
|
12
|
+
style: style,
|
|
13
|
+
createOrder: SolidusPaypalCommercePlatform.sendOrder.bind(null, payment_method_id),
|
|
14
|
+
onApprove: SolidusPaypalCommercePlatform.finalizeOrder.bind(null, payment_method_id),
|
|
15
|
+
onShippingChange: SolidusPaypalCommercePlatform.shippingChange
|
|
16
|
+
}).render('#paypal-button-container')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
SolidusPaypalCommercePlatform.renderProductButton = function(payment_method_id, style) {
|
|
20
|
+
paypal.Buttons({
|
|
21
|
+
style: style,
|
|
22
|
+
createOrder: SolidusPaypalCommercePlatform.createAndSendOrder.bind(null, payment_method_id),
|
|
23
|
+
onApprove: SolidusPaypalCommercePlatform.finalizeOrder.bind(null, payment_method_id),
|
|
24
|
+
onShippingChange: SolidusPaypalCommercePlatform.shippingChange
|
|
25
|
+
}).render('#paypal-button-container')
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
window.SolidusPaypalCommercePlatform = {}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Placeholder manifest file.
|
|
3
|
+
the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/frontend/all.css'
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#paypal_commerce_platform_overlay{
|
|
7
|
+
position: fixed;
|
|
8
|
+
display: none;
|
|
9
|
+
width: 100%;
|
|
10
|
+
height: 100%;
|
|
11
|
+
top: 0;
|
|
12
|
+
left: 0;
|
|
13
|
+
right: 0;
|
|
14
|
+
bottom: 0;
|
|
15
|
+
background-color: rgba(0, 0, 0, 0.8);
|
|
16
|
+
z-index: 100;
|
|
17
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidusPaypalCommercePlatform
|
|
4
|
+
class OrdersController < ::Spree::Api::BaseController
|
|
5
|
+
before_action :load_order, except: :create
|
|
6
|
+
skip_before_action :authenticate_user
|
|
7
|
+
include ::Spree::Core::ControllerHelpers::Auth
|
|
8
|
+
|
|
9
|
+
def create
|
|
10
|
+
authorize! :create, ::Spree::Order
|
|
11
|
+
|
|
12
|
+
@order = ::Spree::Order.create!(
|
|
13
|
+
user: try_spree_current_user,
|
|
14
|
+
store: current_store
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
if @order.contents.update_cart order_params
|
|
18
|
+
# Overriding any existing orders
|
|
19
|
+
cookies.signed[:guest_token] = @order.guest_token
|
|
20
|
+
render json: @order, status: :ok
|
|
21
|
+
else
|
|
22
|
+
render json: @order.errors.full_messages, status: :unprocessable_entity
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def update_address
|
|
27
|
+
authorize! :update, @order, order_token
|
|
28
|
+
paypal_address = SolidusPaypalCommercePlatform::PaypalAddress.new(@order)
|
|
29
|
+
|
|
30
|
+
if paypal_address.update(paypal_address_params).valid?
|
|
31
|
+
@order.ensure_updated_shipments
|
|
32
|
+
@order.contents.advance
|
|
33
|
+
render json: {}, status: :ok
|
|
34
|
+
else
|
|
35
|
+
render json: paypal_address.errors.full_messages, status: :unprocessable_entity
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def verify_total
|
|
40
|
+
authorize! :show, @order, order_token
|
|
41
|
+
|
|
42
|
+
if total_is_correct?(params[:paypal_total])
|
|
43
|
+
render json: {}, status: :ok
|
|
44
|
+
else
|
|
45
|
+
respond_with(@order, default_template: 'spree/api/orders/expected_total_mismatch', status: 400)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def total_is_correct?(paypal_total)
|
|
52
|
+
@order.total == BigDecimal(paypal_total)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def paypal_address_params
|
|
56
|
+
params.require(:address).permit(
|
|
57
|
+
updated_address: [
|
|
58
|
+
:address_line_1,
|
|
59
|
+
:address_line_2,
|
|
60
|
+
:admin_area_1,
|
|
61
|
+
:admin_area_2,
|
|
62
|
+
:postal_code,
|
|
63
|
+
:country_code,
|
|
64
|
+
],
|
|
65
|
+
recipient: [
|
|
66
|
+
:email_address,
|
|
67
|
+
name: [
|
|
68
|
+
:given_name,
|
|
69
|
+
:surname,
|
|
70
|
+
]
|
|
71
|
+
]
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def order_params
|
|
76
|
+
params.require(:order).permit(permitted_order_attributes)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def load_order
|
|
80
|
+
@order = ::Spree::Order.find_by!(number: params[:order_id])
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidusPaypalCommercePlatform
|
|
4
|
+
class PaymentsController < ::Spree::Api::BaseController
|
|
5
|
+
before_action :load_order
|
|
6
|
+
skip_before_action :authenticate_user
|
|
7
|
+
|
|
8
|
+
def create
|
|
9
|
+
authorize! :update, @order, order_token
|
|
10
|
+
paypal_order_id = paypal_params[:paypal_order_id]
|
|
11
|
+
|
|
12
|
+
if !paypal_order_id
|
|
13
|
+
return redirect_to checkout_state_path(@order.state), notice: "Invalid order confirmation data passed in"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if @order.complete?
|
|
17
|
+
return redirect_to spree.order_path(@order), notice: "Order is already in complete state"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
source = SolidusPaypalCommercePlatform::PaymentSource.new(paypal_order_id: paypal_order_id)
|
|
21
|
+
|
|
22
|
+
source.transaction do
|
|
23
|
+
if source.save!
|
|
24
|
+
@order.payments.create!(
|
|
25
|
+
payment_method_id: paypal_params[:payment_method_id],
|
|
26
|
+
source: source
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
render json: {}, status: :ok
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def paypal_params
|
|
37
|
+
params.permit(:paypal_order_id, :order_id, :order_token, :payment_method_id)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def load_order
|
|
41
|
+
@order = ::Spree::Order.find_by!(number: params[:order_id])
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidusPaypalCommercePlatform
|
|
4
|
+
class PaypalOrdersController < ::Spree::Api::BaseController
|
|
5
|
+
before_action :load_payment_method
|
|
6
|
+
skip_before_action :authenticate_user
|
|
7
|
+
|
|
8
|
+
def show
|
|
9
|
+
authorize! :show, @order, order_token
|
|
10
|
+
render json: @payment_method.gateway.create_order(@order, @payment_method.auto_capture), status: :ok
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def load_payment_method
|
|
16
|
+
@payment_method = ::Spree::PaymentMethod.find(params[:payment_method_id])
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidusPaypalCommercePlatform
|
|
4
|
+
class ShippingRatesController < ::Spree::Api::BaseController
|
|
5
|
+
before_action :load_order
|
|
6
|
+
skip_before_action :authenticate_user
|
|
7
|
+
|
|
8
|
+
def simulate_shipping_rates
|
|
9
|
+
authorize! :show, @order, order_token
|
|
10
|
+
|
|
11
|
+
@order.transaction do
|
|
12
|
+
SolidusPaypalCommercePlatform::PaypalAddress.new(@order).simulate_update(params[:address])
|
|
13
|
+
@errors = @order.ship_address.errors.dup
|
|
14
|
+
@paypal_order = SolidusPaypalCommercePlatform::PaypalOrder.new(@order).to_replace_json
|
|
15
|
+
raise ActiveRecord::Rollback
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
if @errors.none?
|
|
19
|
+
render json: @paypal_order, status: :ok
|
|
20
|
+
else
|
|
21
|
+
render json: @errors.full_messages, status: :unprocessable_entity
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def load_order
|
|
28
|
+
@order = ::Spree::Order.find_by(number: params[:order_id])
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidusPaypalCommercePlatform
|
|
4
|
+
class WizardController < ::Spree::Api::BaseController
|
|
5
|
+
helper ::Spree::Core::Engine.routes.url_helpers
|
|
6
|
+
|
|
7
|
+
def create
|
|
8
|
+
authorize! :create, ::Spree::PaymentMethod
|
|
9
|
+
|
|
10
|
+
@payment_method = ::Spree::PaymentMethod.new(payment_method_params)
|
|
11
|
+
|
|
12
|
+
if @payment_method.save
|
|
13
|
+
edit_url = spree.edit_admin_payment_method_url(@payment_method)
|
|
14
|
+
|
|
15
|
+
render(
|
|
16
|
+
json: { redirectUrl: edit_url },
|
|
17
|
+
status: :created,
|
|
18
|
+
location: edit_url,
|
|
19
|
+
notice: "The PayPal Commerce Platform payment method has been successfully created"
|
|
20
|
+
)
|
|
21
|
+
else
|
|
22
|
+
render json: @payment_method.errors, status: :unprocessable_entity
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def payment_method_params
|
|
29
|
+
{
|
|
30
|
+
name: "PayPal Commerce Platform",
|
|
31
|
+
type: SolidusPaypalCommercePlatform::PaymentMethod,
|
|
32
|
+
preferred_client_id: api_credentials.client_id,
|
|
33
|
+
preferred_client_secret: api_credentials.client_secret,
|
|
34
|
+
preferred_test_mode: SolidusPaypalCommercePlatform.config.env.sandbox?,
|
|
35
|
+
available_to_admin: false,
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def api_credentials
|
|
40
|
+
@api_credentials ||= SolidusPaypalCommercePlatform::Client.fetch_api_credentials(
|
|
41
|
+
auth_code: params.fetch(:authCode),
|
|
42
|
+
client_id: params.fetch(:sharedId),
|
|
43
|
+
nonce: params.fetch(:nonce),
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RemoveRequiredPhoneFromAddress
|
|
4
|
+
# PayPal doesn't use the phone number, so in cases where the user checks out via
|
|
5
|
+
# PayPal, this field will be unpopulated. If you want to require phone numbers,
|
|
6
|
+
# you'll need to turn off cart & product page displays on the payment method edit
|
|
7
|
+
# page.
|
|
8
|
+
def require_phone?
|
|
9
|
+
super && false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
::Spree::Address.prepend self
|
|
13
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidusPaypalCommercePlatform
|
|
4
|
+
module ButtonOptionsHelper
|
|
5
|
+
def preferred_paypal_button_color_options
|
|
6
|
+
[["Gold", "gold"], ["Blue", "blue"], ["Silver", "silver"], ["White", "white"], ["Black", "black"]]
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def preferred_paypal_button_size_options
|
|
10
|
+
[["Small", "small"], ["Medium", "medium"], ["Large", "large"], ["Responsive", "responsive"]]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def preferred_paypal_button_shape_options
|
|
14
|
+
[["Pill", "pill"], ["Rectangular", "rect"]]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def preferred_paypal_button_layout_options
|
|
18
|
+
[["Vertical", "vertical"], ["Horizontal", "horizontal"]]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidusPaypalCommercePlatform
|
|
4
|
+
class WebhookJob < SolidusPaypalCommercePlatform::ApplicationJob
|
|
5
|
+
def perform(payload)
|
|
6
|
+
case payload["resource_type"]
|
|
7
|
+
when "checkout-order"
|
|
8
|
+
payment_source = PaymentSource.find_by!(paypal_order_id: payload.dig("resource", "id"))
|
|
9
|
+
payment = Spree::Payment.where(source: payment_source).last!
|
|
10
|
+
payment.log_entries.create!(details: payload.to_yaml)
|
|
11
|
+
when "capture"
|
|
12
|
+
payment_source = PaymentSource.find_by!(capture_id: payload.dig("resource", "id"))
|
|
13
|
+
payment = Spree::Payment.where(source: payment_source).last!
|
|
14
|
+
payment.log_entries.create!(details: payload.to_yaml)
|
|
15
|
+
when "refund"
|
|
16
|
+
payment_source = PaymentSource.find_by!(refund_id: payload.dig("resource", "id"))
|
|
17
|
+
payment = Spree::Payment.where(source: payment_source).last!
|
|
18
|
+
payment.log_entries.create!(details: payload.to_yaml)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'paypal-checkout-sdk'
|
|
4
|
+
|
|
5
|
+
module SolidusPaypalCommercePlatform
|
|
6
|
+
class Gateway
|
|
7
|
+
include PayPalCheckoutSdk::Orders
|
|
8
|
+
include PayPalCheckoutSdk::Payments
|
|
9
|
+
|
|
10
|
+
def initialize(options)
|
|
11
|
+
# Cannot use kwargs because of how the Gateway is initialize by Solidus.
|
|
12
|
+
@client = Client.new(
|
|
13
|
+
test_mode: options.fetch(:test_mode, nil),
|
|
14
|
+
client_id: options.fetch(:client_id),
|
|
15
|
+
client_secret: options.fetch(:client_secret),
|
|
16
|
+
)
|
|
17
|
+
@options = options
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def purchase(money, source, options)
|
|
21
|
+
request = OrdersCaptureRequest.new(source.paypal_order_id)
|
|
22
|
+
request.request_body(amount: { currency_code: options[:currency], value: Money.new(money).dollars })
|
|
23
|
+
|
|
24
|
+
response = @client.execute_with_response(request)
|
|
25
|
+
if response.success?
|
|
26
|
+
capture_id = response.params["result"].purchase_units[0].payments.captures[0].id
|
|
27
|
+
source.update(capture_id: capture_id)
|
|
28
|
+
end
|
|
29
|
+
response
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def authorize(_money, source, _options)
|
|
33
|
+
request = OrdersAuthorizeRequest.new(source.paypal_order_id)
|
|
34
|
+
|
|
35
|
+
response = @client.execute_with_response(request)
|
|
36
|
+
if response.success?
|
|
37
|
+
authorization_id = response.params["result"].purchase_units[0].payments.authorizations[0].id
|
|
38
|
+
source.update(authorization_id: authorization_id)
|
|
39
|
+
end
|
|
40
|
+
response
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def capture(money, _response_code, options)
|
|
44
|
+
source = options[:originator].source
|
|
45
|
+
request = AuthorizationsCaptureRequest.new(source.authorization_id)
|
|
46
|
+
request.request_body(amount: { currency_code: options[:currency], value: Money.new(money).dollars })
|
|
47
|
+
|
|
48
|
+
response = @client.execute_with_response(request)
|
|
49
|
+
if response.success?
|
|
50
|
+
source.update(capture_id: response.params["result"].id)
|
|
51
|
+
end
|
|
52
|
+
response
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def credit(_money_cents, _transaction_id, options)
|
|
56
|
+
refund = options[:originator]
|
|
57
|
+
source = refund.payment.source
|
|
58
|
+
capture_id = source.capture_id
|
|
59
|
+
request = CapturesRefundRequest.new(capture_id)
|
|
60
|
+
request.request_body(amount: { currency_code: refund.currency, value: refund.amount })
|
|
61
|
+
message = I18n.t('success', scope: @client.i18n_scope_for(request), amount: refund.amount)
|
|
62
|
+
|
|
63
|
+
response = @client.execute_with_response(request, success_message: message)
|
|
64
|
+
source.update(refund_id: response.params["result"].id) if response.success?
|
|
65
|
+
response
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def void(_response_code, options)
|
|
69
|
+
authorization_id = options[:originator].source.authorization_id
|
|
70
|
+
request = AuthorizationsVoidRequest.new(authorization_id)
|
|
71
|
+
|
|
72
|
+
@client.execute_with_response(request)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def create_order(order, auto_capture)
|
|
76
|
+
intent = auto_capture ? "CAPTURE" : "AUTHORIZE"
|
|
77
|
+
request = OrdersCreateRequest.new
|
|
78
|
+
paypal_order = SolidusPaypalCommercePlatform::PaypalOrder.new(order)
|
|
79
|
+
request.request_body paypal_order.to_json(intent)
|
|
80
|
+
|
|
81
|
+
@client.execute(request).result
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def get_order(order_id)
|
|
85
|
+
@client.execute(OrdersGetRequest.new(order_id)).result
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidusPaypalCommercePlatform
|
|
4
|
+
class PaymentMethod < SolidusSupport.payment_method_parent_class
|
|
5
|
+
include SolidusPaypalCommercePlatform::ButtonOptionsHelper
|
|
6
|
+
preference :client_id, :string
|
|
7
|
+
preference :client_secret, :string
|
|
8
|
+
preference :paypal_button_color, :paypal_select, default: "gold"
|
|
9
|
+
preference :paypal_button_size, :paypal_select, default: "responsive"
|
|
10
|
+
preference :paypal_button_shape, :paypal_select, default: "rect"
|
|
11
|
+
preference :paypal_button_layout, :paypal_select, default: "vertical"
|
|
12
|
+
preference :display_on_cart, :boolean, default: true
|
|
13
|
+
preference :display_on_product_page, :boolean, default: true
|
|
14
|
+
|
|
15
|
+
def partial_name
|
|
16
|
+
"paypal_commerce_platform"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def display_on_cart
|
|
20
|
+
options[:display_on_cart] || false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def cart_partial_name
|
|
24
|
+
"paypal_commerce_platform"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def display_on_product_page
|
|
28
|
+
options[:display_on_product_page] || false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def product_page_partial_name
|
|
32
|
+
"paypal_commerce_platform"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def client_id
|
|
36
|
+
options[:client_id]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def client_secret
|
|
40
|
+
options[:client_secret]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def payment_source_class
|
|
44
|
+
PaymentSource
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def gateway_class
|
|
48
|
+
Gateway
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def button_style
|
|
52
|
+
{
|
|
53
|
+
color: options[:paypal_button_color] || "gold",
|
|
54
|
+
size: options[:paypal_button_size] || "responsive",
|
|
55
|
+
shape: options[:paypal_button_shape] || "rect",
|
|
56
|
+
layout: options[:paypal_button_layout] || "vertical"
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def javascript_sdk_url(order: nil)
|
|
61
|
+
# Both instance and class respond to checkout_steps.
|
|
62
|
+
step_names = order ? order.checkout_steps : ::Spree::Order.checkout_steps.keys
|
|
63
|
+
|
|
64
|
+
commit_immediately = step_names.include? "confirm"
|
|
65
|
+
|
|
66
|
+
parameters = {
|
|
67
|
+
'client-id': client_id,
|
|
68
|
+
intent: auto_capture ? "capture" : "authorize",
|
|
69
|
+
commit: commit_immediately ? "false" : "true",
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
"https://www.paypal.com/sdk/js?#{parameters.to_query}"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|