solidus_paypal_commerce_platform 0.3.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +25 -2
  3. data/.rubocop.yml +6 -5
  4. data/CHANGELOG.md +180 -122
  5. data/Gemfile +16 -3
  6. data/README.md +27 -2
  7. data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/button_actions.js +3 -1
  8. data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/buttons.js +14 -0
  9. data/app/controllers/solidus_paypal_commerce_platform/orders_controller.rb +1 -1
  10. data/app/controllers/solidus_paypal_commerce_platform/payments_controller.rb +4 -2
  11. data/app/helpers/solidus_paypal_commerce_platform/button_options_helper.rb +4 -0
  12. data/app/models/solidus_paypal_commerce_platform/gateway.rb +20 -3
  13. data/app/models/solidus_paypal_commerce_platform/payment_method.rb +21 -1
  14. data/app/models/solidus_paypal_commerce_platform/payment_source.rb +12 -1
  15. data/app/models/solidus_paypal_commerce_platform/paypal_order.rb +6 -21
  16. data/app/models/solidus_paypal_commerce_platform/wizard.rb +1 -1
  17. data/bin/rails-engine +1 -1
  18. data/config/locales/en.yml +34 -1
  19. data/db/migrate/20211220133406_add_paypal_funding_source_to_paypal_commerce_platform_sources.rb +5 -0
  20. data/lib/paypal/access_token.rb +22 -0
  21. data/lib/paypal/lib.rb +19 -0
  22. data/lib/paypal/paypal_checkout_sdk/orders/orders_authorize_request.rb +44 -0
  23. data/lib/paypal/paypal_checkout_sdk/orders/orders_capture_request.rb +42 -0
  24. data/lib/paypal/paypal_checkout_sdk/orders/orders_create_request.rb +36 -0
  25. data/lib/paypal/paypal_checkout_sdk/orders/orders_get_request.rb +26 -0
  26. data/lib/paypal/paypal_checkout_sdk/orders/orders_patch_request.rb +77 -0
  27. data/lib/paypal/paypal_checkout_sdk/orders/orders_validate_request.rb +34 -0
  28. data/lib/paypal/paypal_checkout_sdk/payments/authorizations_capture_request.rb +38 -0
  29. data/lib/paypal/paypal_checkout_sdk/payments/authorizations_get_request.rb +26 -0
  30. data/lib/paypal/paypal_checkout_sdk/payments/authorizations_reauthorize_request.rb +45 -0
  31. data/lib/paypal/paypal_checkout_sdk/payments/authorizations_void_request.rb +27 -0
  32. data/lib/paypal/paypal_checkout_sdk/payments/captures_get_request.rb +26 -0
  33. data/lib/paypal/paypal_checkout_sdk/payments/captures_refund_request.rb +40 -0
  34. data/lib/paypal/paypal_checkout_sdk/payments/refunds_get_request.rb +26 -0
  35. data/lib/paypal/paypal_environment.rb +39 -0
  36. data/lib/paypal/paypal_http_client.rb +56 -0
  37. data/lib/paypal/token_requests.rb +42 -0
  38. data/lib/solidus_paypal_commerce_platform/access_token_authorization_request.rb +1 -1
  39. data/lib/solidus_paypal_commerce_platform/client.rb +4 -4
  40. data/lib/solidus_paypal_commerce_platform/configuration.rb +4 -4
  41. data/lib/solidus_paypal_commerce_platform/engine.rb +11 -3
  42. data/lib/solidus_paypal_commerce_platform/paypal_checkout_sdk/orders/orders_authorize_request.rb +48 -0
  43. data/lib/solidus_paypal_commerce_platform/paypal_checkout_sdk/orders/orders_capture_request.rb +46 -0
  44. data/lib/solidus_paypal_commerce_platform/paypal_checkout_sdk/orders/orders_patch_request.rb +80 -0
  45. data/lib/solidus_paypal_commerce_platform/paypal_checkout_sdk/orders/orders_validate_request.rb +36 -0
  46. data/lib/solidus_paypal_commerce_platform/paypal_checkout_sdk/payments/authorizations_reauthorize_request.rb +50 -0
  47. data/lib/solidus_paypal_commerce_platform/paypal_checkout_sdk/payments/captures_refund_request.rb +43 -0
  48. data/lib/solidus_paypal_commerce_platform/testing_support/factories.rb +2 -1
  49. data/lib/solidus_paypal_commerce_platform/version.rb +1 -1
  50. data/lib/solidus_paypal_commerce_platform.rb +1 -0
  51. data/lib/views/backend/spree/admin/payments/source_views/_paypal_commerce_platform.html.erb +3 -0
  52. data/lib/views/frontend/solidus_paypal_commerce_platform/payments/_payment.html.erb +4 -0
  53. data/lib/views/frontend/spree/checkout/payment/_paypal_commerce_platform.html.erb +17 -3
  54. data/solidus_paypal_commerce_platform.gemspec +9 -8
  55. metadata +52 -78
  56. data/spec/features/backend/new_payment_method_spec.rb +0 -40
  57. data/spec/features/frontend/cart_spec.rb +0 -46
  58. data/spec/features/frontend/checkout_spec.rb +0 -89
  59. data/spec/features/frontend/product_spec.rb +0 -91
  60. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/CHECKOUT.ORDER.COMPLETED.v2.json +0 -121
  61. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/CHECKOUT.ORDER.PROCESSED.v2.json +0 -121
  62. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.COMPLETED.v1.json +0 -50
  63. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.COMPLETED.v2.json +0 -72
  64. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.DENIED.v1.json +0 -50
  65. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.DENIED.v2.json +0 -68
  66. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.REFUNDED.v1.json +0 -51
  67. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.REFUNDED.v2.json +0 -63
  68. data/spec/jobs/solidus_paypal_commerce_platform/webhook_job_spec.rb +0 -44
  69. data/spec/lib/solidus_paypal_commerce_platform/client_spec.rb +0 -21
  70. data/spec/lib/solidus_paypal_commerce_platform/configuration_spec.rb +0 -91
  71. data/spec/models/solidus_paypal_commerce_platform/payment_method_spec.rb +0 -129
  72. data/spec/models/solidus_paypal_commerce_platform/payment_source_spec.rb +0 -62
  73. data/spec/models/solidus_paypal_commerce_platform/paypal_address_spec.rb +0 -67
  74. data/spec/models/solidus_paypal_commerce_platform/paypal_order_spec.rb +0 -33
  75. data/spec/models/solidus_paypal_commerce_platform/state_guesser_spec.rb +0 -38
  76. data/spec/models/solidus_paypal_commerce_platform/wizard_spec.rb +0 -9
  77. data/spec/requests/solidus_paypal_commerce_platform/orders_controller_spec.rb +0 -36
  78. data/spec/requests/solidus_paypal_commerce_platform/shipping_rates_controller_spec.rb +0 -44
  79. data/spec/requests/solidus_paypal_commerce_platform/wizard_controller_spec.rb +0 -44
  80. data/spec/spec_helper.rb +0 -32
  81. data/spec/support/capybara.rb +0 -11
  82. data/spec/support/paypal_sdk_script_tag_helper.rb +0 -13
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Solidus Paypal Commerce Platform
2
2
 
3
- [![CircleCI](https://circleci.com/gh/solidusio-contrib/solidus_paypal_commerce_platform.svg?style=shield)](https://circleci.com/gh/solidusio-contrib/solidus_paypal_commerce_platform)
4
- [![codecov](https://codecov.io/gh/solidusio-contrib/solidus_paypal_commerce_platform/branch/master/graph/badge.svg)](https://codecov.io/gh/solidusio-contrib/solidus_paypal_commerce_platform)
3
+ [![CircleCI](https://circleci.com/gh/solidusio/solidus_paypal_commerce_platform.svg?style=shield)](https://circleci.com/gh/solidusio/solidus_paypal_commerce_platform)
4
+ [![codecov](https://codecov.io/gh/solidusio/solidus_paypal_commerce_platform/branch/master/graph/badge.svg)](https://codecov.io/gh/solidusio/solidus_paypal_commerce_platform)
5
5
 
6
6
  The official PayPal integration of Solidus.
7
7
 
@@ -120,6 +120,25 @@ With product and cart page checkout, the user is directed to the checkout confir
120
120
 
121
121
  PayPals API does not allow for admin-side payments. Instead, backend users taking payments for customers will need to use the PayPal Virtual Terminal to take payments. [More info is available on the PayPal website.](https://www.paypal.com/merchantapps/appcenter/acceptpayments/virtualterminal?locale.x=en_US)
122
122
 
123
+ ## Venmo
124
+ Venmo is currently available to US merchants and buyers. There are also other [prequisites](https://developer.paypal.com/docs/business/checkout/pay-with-venmo/#eligibility).
125
+
126
+ If the transaction supports Venmo and it is enabled by the following, then a button should appear for it on checkout payment page. Note, Venmo cannot currently be rendered on the product or cart pages.
127
+
128
+ Set the PaypalCommercePlatform `PaymentMethod` `venmo_standalone` preference to:
129
+ - `render only standalone`, show Venmo on the payment page and do not show the other funding sources (i.e. PayPal, Credit); or
130
+ - `enabled`, show Venmo on the payment page; or
131
+ - `disabled` (default), do not show the Venmo button.
132
+
133
+ See more about preferences([Configuration](#configuration)) below.
134
+
135
+ [_As Venmo is only available in the US, you may want to mock your location for testing_](#mocking-your-buyer-country)
136
+
137
+ ## Configuration
138
+ The easiest way to change the `Payment Method`'s preferences is through admin: `Settings > Payments > "PayPal Commerce Platform" > Edit`.
139
+
140
+ See more about preferences [here](https://guides.solidus.io/developers/preferences/add-model-preferences.html#access-your-preferences)/
141
+
123
142
  ## Development
124
143
 
125
144
  ### Testing the extension
@@ -162,6 +181,12 @@ $ bin/rails server
162
181
  Use Ctrl-C to stop
163
182
  ```
164
183
 
184
+ ### Mocking your buyer country
185
+ PayPal normally looks at your IP geolocation to see where you are located to determine what funding sources are available to you. For example, Venmo is currently only available to US buyers.
186
+ Because of this, you may want to pretend you are from US check that that Venmo is correctly integrated for these customers. To do this, set the payment method's preference of `force_buyer_country` to "US". See more information about preferences above.
187
+
188
+ This preference has no effect on production.
189
+
165
190
  ### Updating the changelog
166
191
 
167
192
  Before and after releases the changelog should be updated to reflect the up-to-date status of
@@ -84,6 +84,7 @@ SolidusPaypalCommercePlatform.approveOrder = function(data, actions) {
84
84
  SolidusPaypalCommercePlatform.verifyTotal(response.purchase_units[0].amount.value).then(function(){
85
85
  $("#payments_source_paypal_order_id").val(data.orderID)
86
86
  $("#payments_source_paypal_email").val(response.payer.email_address)
87
+ $("#payments_source_paypal_funding_source").val(SolidusPaypalCommercePlatform.fundingSource)
87
88
  $("#checkout_form_payment").submit()
88
89
  })
89
90
  })
@@ -168,7 +169,8 @@ SolidusPaypalCommercePlatform.addPayment = function(paypal_amount, payment_metho
168
169
  payment_method_id: payment_method_id,
169
170
  source_attributes: {
170
171
  paypal_order_id: data.orderID,
171
- paypal_email: email
172
+ paypal_email: email,
173
+ paypal_funding_source: SolidusPaypalCommercePlatform.fundingSource
172
174
  }
173
175
  }
174
176
  },
@@ -2,6 +2,7 @@ SolidusPaypalCommercePlatform.renderButton = function(payment_method_id, style)
2
2
  paypal.Buttons({
3
3
  style: style,
4
4
  createOrder: SolidusPaypalCommercePlatform.sendOrder.bind(null, payment_method_id),
5
+ onClick: (data) => { SolidusPaypalCommercePlatform.fundingSource = data.fundingSource },
5
6
  onApprove: SolidusPaypalCommercePlatform.approveOrder,
6
7
  onShippingChange: SolidusPaypalCommercePlatform.shippingChange,
7
8
  onError: SolidusPaypalCommercePlatform.handleError
@@ -12,6 +13,7 @@ SolidusPaypalCommercePlatform.renderCartButton = function(payment_method_id, sty
12
13
  paypal.Buttons({
13
14
  style: style,
14
15
  createOrder: SolidusPaypalCommercePlatform.sendOrder.bind(null, payment_method_id),
16
+ onClick: (data) => { SolidusPaypalCommercePlatform.fundingSource = data.fundingSource },
15
17
  onApprove: SolidusPaypalCommercePlatform.finalizeOrder.bind(null, payment_method_id),
16
18
  onShippingChange: SolidusPaypalCommercePlatform.shippingChange,
17
19
  onError: SolidusPaypalCommercePlatform.handleError
@@ -22,8 +24,20 @@ SolidusPaypalCommercePlatform.renderProductButton = function(payment_method_id,
22
24
  paypal.Buttons({
23
25
  style: style,
24
26
  createOrder: SolidusPaypalCommercePlatform.createAndSendOrder.bind(null, payment_method_id),
27
+ onClick: (data) => { SolidusPaypalCommercePlatform.fundingSource = data.fundingSource },
25
28
  onApprove: SolidusPaypalCommercePlatform.finalizeOrder.bind(null, payment_method_id),
26
29
  onShippingChange: SolidusPaypalCommercePlatform.shippingChange,
27
30
  onError: SolidusPaypalCommercePlatform.handleError
28
31
  }).render('#paypal-button-container')
29
32
  }
33
+
34
+ SolidusPaypalCommercePlatform.renderVenmoStandalone = function(payment_method_id, style) {
35
+ paypal.Buttons({
36
+ style: style,
37
+ fundingSource: paypal.FUNDING.VENMO,
38
+ createOrder: SolidusPaypalCommercePlatform.sendOrder.bind(null, payment_method_id),
39
+ onClick: () => { SolidusPaypalCommercePlatform.fundingSource = paypal.FUNDING.VENMO },
40
+ onApprove: SolidusPaypalCommercePlatform.approveOrder,
41
+ onError: SolidusPaypalCommercePlatform.handleError
42
+ }).render('#paypal-button-container')
43
+ }
@@ -10,7 +10,7 @@ module SolidusPaypalCommercePlatform
10
10
  authorize! :create, ::Spree::Order
11
11
 
12
12
  @order = ::Spree::Order.create!(
13
- user: try_spree_current_user,
13
+ user: current_api_user,
14
14
  store: current_store,
15
15
  currency: current_pricing_options.currency
16
16
  )
@@ -10,11 +10,13 @@ module SolidusPaypalCommercePlatform
10
10
  paypal_order_id = paypal_params[:paypal_order_id]
11
11
 
12
12
  if !paypal_order_id
13
- return redirect_to checkout_state_path(@order.state), notice: "Invalid order confirmation data passed in"
13
+ return redirect_to checkout_state_path(@order.state),
14
+ notice: I18n.t("solidus_paypal_commerce_platform.controllers.payments_controller.invalid_paypal_order_id")
14
15
  end
15
16
 
16
17
  if @order.complete?
17
- return redirect_to spree.order_path(@order), notice: "Order is already in complete state"
18
+ return redirect_to spree.order_path(@order),
19
+ notice: I18n.t("solidus_paypal_commerce_platform.controllers.payments_controller.order_complete")
18
20
  end
19
21
 
20
22
  source = SolidusPaypalCommercePlatform::PaymentSource.new(paypal_order_id: paypal_order_id)
@@ -17,5 +17,9 @@ module SolidusPaypalCommercePlatform
17
17
  def preferred_paypal_button_layout_options
18
18
  [["Vertical", "vertical"], ["Horizontal", "horizontal"]]
19
19
  end
20
+
21
+ def preferred_venmo_standalone_options
22
+ [['Render only standalone', 'render only standalone'], ['Enabled', 'Enabled'], ['Disabled', 'disabled']]
23
+ end
20
24
  end
21
25
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'paypal-checkout-sdk'
4
-
5
3
  module SolidusPaypalCommercePlatform
6
4
  class Gateway
7
5
  include PayPalCheckoutSdk::Orders
@@ -45,7 +43,7 @@ module SolidusPaypalCommercePlatform
45
43
  request = AuthorizationsCaptureRequest.new(source.authorization_id)
46
44
  request.request_body(amount: { currency_code: options[:currency], value: Money.new(money).dollars })
47
45
 
48
- response = @client.execute_with_response(request)
46
+ response = capture_with_response(request)
49
47
  if response.success?
50
48
  source.update(capture_id: response.params["result"].id)
51
49
  end
@@ -83,5 +81,24 @@ module SolidusPaypalCommercePlatform
83
81
  def get_order(order_id)
84
82
  @client.execute(OrdersGetRequest.new(order_id)).result
85
83
  end
84
+
85
+ private
86
+
87
+ def capture_with_response(request, success_message: nil, failure_message: nil)
88
+ response = @client.execute(request)
89
+ if response.result&.status == "PENDING"
90
+ ActiveMerchant::Billing::Response.new(
91
+ false,
92
+ "Payment is awaiting processing on PayPal's side"
93
+ )
94
+ else
95
+ i18n_scope = @client.i18n_scope_for(request)
96
+ @client.wrap_response(
97
+ response,
98
+ success_message: success_message || I18n.t("#{i18n_scope}.success", default: nil),
99
+ failure_message: failure_message || I18n.t("#{i18n_scope}.failure", default: nil)
100
+ )
101
+ end
102
+ end
86
103
  end
87
104
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusPaypalCommercePlatform
4
- class PaymentMethod < SolidusSupport.payment_method_parent_class
4
+ class PaymentMethod < ::Spree::PaymentMethod
5
5
  include SolidusPaypalCommercePlatform::ButtonOptionsHelper
6
6
  preference :client_id, :string
7
7
  preference :client_secret, :string
@@ -12,6 +12,21 @@ module SolidusPaypalCommercePlatform
12
12
  preference :display_on_cart, :boolean, default: true
13
13
  preference :display_on_product_page, :boolean, default: true
14
14
  preference :display_credit_messaging, :boolean, default: true
15
+ preference :venmo_standalone, :paypal_select, default: 'disabled'
16
+ preference :force_buyer_country, :string
17
+
18
+ validates :preferred_paypal_button_color, exclusion: {
19
+ in: %w[gold],
20
+ message: I18n.t("solidus_paypal_commerce_platform.payment_method.gold_button_message")
21
+ }, if: :venmo_standalone_enabled?
22
+
23
+ def venmo_standalone_enabled?
24
+ options[:venmo_standalone] != 'disabled'
25
+ end
26
+
27
+ def render_only_venmo_standalone?
28
+ options[:venmo_standalone] == 'render only standalone'
29
+ end
15
30
 
16
31
  def partial_name
17
32
  "paypal_commerce_platform"
@@ -73,6 +88,11 @@ module SolidusPaypalCommercePlatform
73
88
  }
74
89
 
75
90
  parameters[:shipping_preference] = 'NO_SHIPPING' if step_names.exclude? 'delivery'
91
+ parameters['enable-funding'] = 'venmo' if venmo_standalone_enabled?
92
+
93
+ if !Rails.env.production? && options[:force_buyer_country].present?
94
+ parameters['buyer-country'] = options[:force_buyer_country]
95
+ end
76
96
 
77
97
  "https://www.paypal.com/sdk/js?#{parameters.to_query}"
78
98
  end
@@ -1,10 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusPaypalCommercePlatform
4
- class PaymentSource < SolidusSupport.payment_source_parent_class
4
+ class PaymentSource < ::Spree::PaymentSource
5
5
  self.table_name = "paypal_commerce_platform_sources"
6
+ enum paypal_funding_source: {
7
+ applepay: 0, bancontact: 1, blik: 2, boleto: 3, card: 4, credit: 5, eps: 6, giropay: 7, ideal: 8,
8
+ itau: 9, maxima: 10, mercadopago: 11, mybank: 12, oxxo: 13, p24: 14, paylater: 15, paypal: 16, payu: 17,
9
+ sepa: 18, sofort: 19, trustly: 20, venmo: 21, verkkopankki: 22, wechatpay: 23, zimpler: 24
10
+ }, _suffix: :funding
6
11
  validates :paypal_order_id, :payment_method_id, presence: true
7
12
 
13
+ def display_paypal_funding_source
14
+ I18n.t(paypal_funding_source,
15
+ scope: 'solidus_paypal_commerce_platform.paypal_funding_sources',
16
+ default: paypal_funding_source)
17
+ end
18
+
8
19
  def actions
9
20
  %w(capture void credit)
10
21
  end
@@ -44,19 +44,12 @@ module SolidusPaypalCommercePlatform
44
44
  end
45
45
 
46
46
  def name(address)
47
- if greater_than_2_10?
48
- name = ::Spree::Address::Name.new @order.ship_address.name
47
+ name = ::Spree::Address::Name.new address.name
49
48
 
50
- {
51
- given_name: name.first_name,
52
- surname: name.last_name
53
- }
54
- else
55
- {
56
- given_name: address.firstname,
57
- surname: address.lastname
58
- }
59
- end
49
+ {
50
+ given_name: name.first_name,
51
+ surname: name.last_name
52
+ }
60
53
  end
61
54
 
62
55
  def purchase_units(include_shipping_address: true)
@@ -80,11 +73,7 @@ module SolidusPaypalCommercePlatform
80
73
  end
81
74
 
82
75
  def full_name
83
- if greater_than_2_10?
84
- @order.ship_address.name
85
- else
86
- @order.ship_address.full_name
87
- end
76
+ @order.ship_address.name
88
77
  end
89
78
 
90
79
  def line_items
@@ -120,9 +109,5 @@ module SolidusPaypalCommercePlatform
120
109
  value: amount
121
110
  }
122
111
  end
123
-
124
- def greater_than_2_10?
125
- ::Spree.solidus_gem_version >= Gem::Version.new('2.11')
126
- end
127
112
  end
128
113
  end
@@ -34,7 +34,7 @@ module SolidusPaypalCommercePlatform
34
34
  private
35
35
 
36
36
  def logo
37
- ActionController::Base.helpers.image_url(::Spree::Config[:admin_interface_logo])
37
+ ActionController::Base.helpers.image_path(::Spree::Config[:admin_interface_logo])
38
38
  end
39
39
  end
40
40
  end
data/bin/rails-engine CHANGED
@@ -7,7 +7,7 @@ ENGINE_PATH = File.expand_path('../lib/solidus_paypal_commerce_platform/engine',
7
7
 
8
8
  # Set up gems listed in the Gemfile.
9
9
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
10
- require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
10
+ require 'bundler/setup' if File.exist?(ENV.fetch('BUNDLE_GEMFILE', nil))
11
11
 
12
12
  require 'rails/all'
13
13
  require 'rails/engine/commands'
@@ -18,9 +18,15 @@ en:
18
18
  paypal_capture_id: PayPal Capture ID
19
19
  paypal_debug_id: PayPal Debug ID
20
20
  paypal_email: PayPal Email
21
+ paypal_funding: 'PayPal Funding: %{funding}'
22
+ paypal_funding_source: 'PayPal Funding Source'
21
23
  payment_email: "Payment Email: %{email}"
22
24
  virtual_terminal_notice_html: Backend Credit Card payments can only be accepted through PayPal via the <a href="https://www.paypal.com/merchantapps/appcenter/acceptpayments/virtualterminal">PayPal Virtual Terminal</a>.
23
25
  solidus_paypal_commerce_platform:
26
+ controllers:
27
+ payments_controller:
28
+ invalid_paypal_order_id: "Invalid order confirmation data passed in"
29
+ order_complete: "Order is already in complete state"
24
30
  responses:
25
31
  pay_pal_checkout_sdk/orders/orders_capture_request:
26
32
  success: "Payment captured"
@@ -34,4 +40,31 @@ en:
34
40
  success: "Payment refunded for %{amount}"
35
41
  pay_pal_checkout_sdk/payments/authorizations_void_request:
36
42
  success: "Payment voided"
37
-
43
+ payment_method:
44
+ gold_button_message: "cannot be 'gold' when Venmo standalone is enabled."
45
+ paypal_funding_sources:
46
+ applepay: 'Apple Pay'
47
+ bancontact: 'Bancontact'
48
+ blik: 'BLIK'
49
+ boleto: 'Boleto'
50
+ card: 'Credit or debit card'
51
+ credit: 'PayPal Credit'
52
+ eps: 'eps'
53
+ giropay: 'giropay'
54
+ ideal: 'iDEAL'
55
+ itau: 'Itau'
56
+ maxima: 'Maxima'
57
+ mercadopago: 'Mercado Pago'
58
+ mybank: 'MyBank'
59
+ oxxo: 'Oxxo'
60
+ p24: 'Przelewy24'
61
+ paylater: 'Pay Later'
62
+ paypal: 'PayPal'
63
+ payu: 'PayU'
64
+ sepa: 'SEPA-Lastschrift'
65
+ sofort: 'Sofort'
66
+ trustly: 'Trustly'
67
+ venmo: 'Venmo'
68
+ verkkopankki: 'Verkkopankki'
69
+ wechatpay: 'WeChat Pay'
70
+ zimpler: 'Zimpler'
@@ -0,0 +1,5 @@
1
+ class AddPaypalFundingSourceToPaypalCommercePlatformSources < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :paypal_commerce_platform_sources, :paypal_funding_source, :integer
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: false
2
+
3
+ module PayPal
4
+ class AccessToken
5
+ attr_accessor :access_token, :token_type, :expires_in, :date_created
6
+
7
+ def initialize(options)
8
+ @access_token = options.access_token
9
+ @token_type = options.token_type
10
+ @expires_in = options.expires_in
11
+ @date_created = Time.zone.now
12
+ end
13
+
14
+ def expired?
15
+ Time.zone.now > @date_created + @expires_in
16
+ end
17
+
18
+ def authorization_string
19
+ "#{@token_type} #{@access_token}"
20
+ end
21
+ end
22
+ end
data/lib/paypal/lib.rb ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'paypal/paypal_environment'
4
+ require 'paypal/paypal_http_client'
5
+ require 'paypal/token_requests'
6
+ require 'paypal/access_token'
7
+ require 'paypal/paypal_checkout_sdk/orders/orders_authorize_request'
8
+ require 'paypal/paypal_checkout_sdk/orders/orders_capture_request'
9
+ require 'paypal/paypal_checkout_sdk/orders/orders_create_request'
10
+ require 'paypal/paypal_checkout_sdk/orders/orders_get_request'
11
+ require 'paypal/paypal_checkout_sdk/orders/orders_patch_request'
12
+ require 'paypal/paypal_checkout_sdk/orders/orders_validate_request'
13
+ require 'paypal/paypal_checkout_sdk/payments/authorizations_capture_request'
14
+ require 'paypal/paypal_checkout_sdk/payments/authorizations_get_request'
15
+ require 'paypal/paypal_checkout_sdk/payments/authorizations_reauthorize_request'
16
+ require 'paypal/paypal_checkout_sdk/payments/authorizations_void_request'
17
+ require 'paypal/paypal_checkout_sdk/payments/captures_get_request'
18
+ require 'paypal/paypal_checkout_sdk/payments/refunds_get_request'
19
+ require 'paypal/paypal_checkout_sdk/payments/captures_refund_request'
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: false
2
+
3
+ # This class was generated on Mon, 27 Aug 2018 13:51:59 PDT by version 0.1.0-dev+904328-dirty of Braintree SDK Generator
4
+
5
+ require 'cgi'
6
+
7
+ module PayPalCheckoutSdk
8
+ module Orders
9
+ #
10
+ # Authorizes payment for an order. The response shows details
11
+ # of authorizations. You can make this call only if you specified
12
+ # `intent=AUTHORIZE` in the create order call.
13
+ #
14
+ class OrdersAuthorizeRequest
15
+ attr_accessor :path, :body, :headers, :verb
16
+
17
+ def initialize(order_id)
18
+ @headers = {}
19
+ @body = nil
20
+ @verb = "POST"
21
+ @path = "/v2/checkout/orders/{order_id}/authorize?"
22
+
23
+ @path = @path.gsub("{order_id}", CGI.escape(order_id.to_s))
24
+ @headers["Content-Type"] = "application/json"
25
+ end
26
+
27
+ def pay_pal_client_metadata_id(pay_pal_client_metadata_id)
28
+ @headers["PayPal-Client-Metadata-Id"] = pay_pal_client_metadata_id
29
+ end
30
+
31
+ def pay_pal_request_id(pay_pal_request_id)
32
+ @headers["PayPal-Request-Id"] = pay_pal_request_id
33
+ end
34
+
35
+ def prefer(prefer)
36
+ @headers["Prefer"] = prefer
37
+ end
38
+
39
+ def request_body(order_action_request)
40
+ @body = order_action_request
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: false
2
+
3
+ # This class was generated on Mon, 27 Aug 2018 13:51:59 PDT by version 0.1.0-dev+904328-dirty of Braintree SDK Generator
4
+
5
+ require 'cgi'
6
+
7
+ module PayPalCheckoutSdk
8
+ module Orders
9
+ #
10
+ # Captures a payment for an order.
11
+ #
12
+ class OrdersCaptureRequest
13
+ attr_accessor :path, :body, :headers, :verb
14
+
15
+ def initialize(order_id)
16
+ @headers = {}
17
+ @body = nil
18
+ @verb = "POST"
19
+ @path = "/v2/checkout/orders/{order_id}/capture?"
20
+
21
+ @path = @path.gsub("{order_id}", CGI.escape(order_id.to_s))
22
+ @headers["Content-Type"] = "application/json"
23
+ end
24
+
25
+ def pay_pal_client_metadata_id(pay_pal_client_metadata_id)
26
+ @headers["PayPal-Client-Metadata-Id"] = pay_pal_client_metadata_id
27
+ end
28
+
29
+ def pay_pal_request_id(pay_pal_request_id)
30
+ @headers["PayPal-Request-Id"] = pay_pal_request_id
31
+ end
32
+
33
+ def prefer(prefer)
34
+ @headers["Prefer"] = prefer
35
+ end
36
+
37
+ def request_body(order_action_request)
38
+ @body = order_action_request
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: false
2
+
3
+ # This class was generated on Mon, 27 Aug 2018 13:51:59 PDT by version 0.1.0-dev+904328-dirty of Braintree SDK Generator
4
+
5
+ require 'cgi'
6
+
7
+ module PayPalCheckoutSdk
8
+ module Orders
9
+ #
10
+ # Creates an order. Supports only orders with one purchase unit.
11
+ #
12
+ class OrdersCreateRequest
13
+ attr_accessor :path, :body, :headers, :verb
14
+
15
+ def initialize
16
+ @headers = {}
17
+ @body = nil
18
+ @verb = "POST"
19
+ @path = "/v2/checkout/orders?"
20
+ @headers["Content-Type"] = "application/json"
21
+ end
22
+
23
+ def pay_pal_partner_attribution_id(pay_pal_partner_attribution_id)
24
+ @headers["PayPal-Partner-Attribution-Id"] = pay_pal_partner_attribution_id
25
+ end
26
+
27
+ def prefer(prefer)
28
+ @headers["Prefer"] = prefer
29
+ end
30
+
31
+ def request_body(order)
32
+ @body = order
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: false
2
+
3
+ # This class was generated on Mon, 27 Aug 2018 13:51:59 PDT by version 0.1.0-dev+904328-dirty of Braintree SDK Generator
4
+
5
+ require 'cgi'
6
+
7
+ module PayPalCheckoutSdk
8
+ module Orders
9
+ #
10
+ # Shows details for an order, by ID.
11
+ #
12
+ class OrdersGetRequest
13
+ attr_accessor :path, :body, :headers, :verb
14
+
15
+ def initialize(order_id)
16
+ @headers = {}
17
+ @body = nil
18
+ @verb = "GET"
19
+ @path = "/v2/checkout/orders/{order_id}?"
20
+
21
+ @path = @path.gsub("{order_id}", CGI.escape(order_id.to_s))
22
+ @headers["Content-Type"] = "application/json"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: false
2
+
3
+ # This class was generated on Mon, 27 Aug 2018 13:51:59 PDT by version 0.1.0-dev+904328-dirty of Braintree SDK Generator
4
+
5
+ require 'cgi'
6
+
7
+ module PayPalCheckoutSdk
8
+ module Orders
9
+ #
10
+ # Updates an order that has the `CREATED` or `APPROVED` status. You cannot update an order with `COMPLETED` status.
11
+ # You can patch these attributes and objects:
12
+ # <table>
13
+ # <thead>
14
+ # <tr>
15
+ # <th align="left">Attribute or object</th>
16
+ # <th align="left">Operations</th>
17
+ # </tr>
18
+ # </thead>
19
+ # <tbody>
20
+ # <tr>
21
+ # <td><code>intent</code></td>
22
+ # <td align="left">Replace</td>
23
+ # </tr>
24
+ # <tr>
25
+ # <td><code>purchase_units</code></td>
26
+ # <td align="left">Replace, add</td>
27
+ # </tr>
28
+ # <tr>
29
+ # <td><code>purchase_units[].custom_id</code></td>
30
+ # <td align="left">Replace, add, remove</td>
31
+ # </tr>
32
+ # <tr>
33
+ # <td><code>purchase_units[].description</code></td>
34
+ # <td align="left">Replace, add, remove</td>
35
+ # </tr>
36
+ # <tr>
37
+ # <td><code>purchase_units[].payee.email</code></td>
38
+ # <td align="left">Replace, add</td>
39
+ # </tr>
40
+ # <tr>
41
+ # <td><code>purchase_units[].shipping</code></td>
42
+ # <td align="left">Replace, add, remove</td>
43
+ # </tr>
44
+ # <tr>
45
+ # <td><code>purchase_units[].soft_descriptor</code></td>
46
+ # <td align="left">Replace, add, remove</td>
47
+ # </tr>
48
+ # <tr>
49
+ # <td><code>purchase_units[].amount</code></td>
50
+ # <td align="left">Replace</td>
51
+ # </tr>
52
+ # <tr>
53
+ # <td><code>purchase_units[].invoice_id</code></td>
54
+ # <td align="left">Replace, add, remove</td>
55
+ # </tr>
56
+ # </tbody>
57
+ # </table>
58
+ #
59
+ class OrdersPatchRequest
60
+ attr_accessor :path, :body, :headers, :verb
61
+
62
+ def initialize(order_id)
63
+ @headers = {}
64
+ @body = nil
65
+ @verb = "PATCH"
66
+ @path = "/v2/checkout/orders/{order_id}?"
67
+
68
+ @path = @path.gsub("{order_id}", CGI.escape(order_id.to_s))
69
+ @headers["Content-Type"] = "application/json"
70
+ end
71
+
72
+ def request_body(patch_request)
73
+ @body = patch_request
74
+ end
75
+ end
76
+ end
77
+ end