activemerchant 1.93.0 → 1.98.0

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +111 -0
  3. data/README.md +3 -0
  4. data/lib/active_merchant/billing/avs_result.rb +4 -5
  5. data/lib/active_merchant/billing/credit_card.rb +6 -0
  6. data/lib/active_merchant/billing/credit_card_methods.rb +67 -4
  7. data/lib/active_merchant/billing/gateway.rb +10 -0
  8. data/lib/active_merchant/billing/gateways/adyen.rb +106 -22
  9. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +43 -10
  10. data/lib/active_merchant/billing/gateways/beanstream.rb +2 -0
  11. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +3 -0
  12. data/lib/active_merchant/billing/gateways/blue_snap.rb +22 -2
  13. data/lib/active_merchant/billing/gateways/bpoint.rb +4 -4
  14. data/lib/active_merchant/billing/gateways/braintree_blue.rb +56 -9
  15. data/lib/active_merchant/billing/gateways/card_connect.rb +3 -1
  16. data/lib/active_merchant/billing/gateways/cecabank.rb +7 -7
  17. data/lib/active_merchant/billing/gateways/checkout_v2.rb +98 -61
  18. data/lib/active_merchant/billing/gateways/credorax.rb +29 -3
  19. data/lib/active_merchant/billing/gateways/cyber_source.rb +30 -13
  20. data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
  21. data/lib/active_merchant/billing/gateways/decidir.rb +233 -0
  22. data/lib/active_merchant/billing/gateways/elavon.rb +9 -0
  23. data/lib/active_merchant/billing/gateways/epay.rb +13 -2
  24. data/lib/active_merchant/billing/gateways/eway_rapid.rb +42 -12
  25. data/lib/active_merchant/billing/gateways/fat_zebra.rb +6 -0
  26. data/lib/active_merchant/billing/gateways/global_collect.rb +3 -7
  27. data/lib/active_merchant/billing/gateways/hps.rb +46 -1
  28. data/lib/active_merchant/billing/gateways/kushki.rb +1 -1
  29. data/lib/active_merchant/billing/gateways/mercado_pago.rb +1 -1
  30. data/lib/active_merchant/billing/gateways/migs.rb +8 -0
  31. data/lib/active_merchant/billing/gateways/monei.rb +31 -0
  32. data/lib/active_merchant/billing/gateways/mundipagg.rb +3 -2
  33. data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
  34. data/lib/active_merchant/billing/gateways/nmi.rb +39 -1
  35. data/lib/active_merchant/billing/gateways/opp.rb +20 -1
  36. data/lib/active_merchant/billing/gateways/orbital.rb +60 -10
  37. data/lib/active_merchant/billing/gateways/payflow.rb +40 -2
  38. data/lib/active_merchant/billing/gateways/paymill.rb +5 -0
  39. data/lib/active_merchant/billing/gateways/paypal.rb +14 -1
  40. data/lib/active_merchant/billing/gateways/payu_latam.rb +6 -2
  41. data/lib/active_merchant/billing/gateways/qvalent.rb +43 -1
  42. data/lib/active_merchant/billing/gateways/realex.rb +32 -9
  43. data/lib/active_merchant/billing/gateways/spreedly_core.rb +43 -29
  44. data/lib/active_merchant/billing/gateways/stripe.rb +54 -9
  45. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +267 -0
  46. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -2
  47. data/lib/active_merchant/billing/gateways/trust_commerce.rb +45 -6
  48. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +8 -5
  49. data/lib/active_merchant/billing/gateways/worldpay.rb +171 -39
  50. data/lib/active_merchant/country.rb +1 -0
  51. data/lib/active_merchant/version.rb +1 -1
  52. metadata +19 -4
@@ -35,19 +35,13 @@ module ActiveMerchant #:nodoc:
35
35
  # Public: Run a purchase transaction.
36
36
  #
37
37
  # money - The monetary amount of the transaction in cents.
38
- # payment_method - The CreditCard or the Spreedly payment method token.
38
+ # payment_method - The CreditCard or Check or the Spreedly payment method token.
39
39
  # options - A hash of options:
40
40
  # :store - Retain the payment method if the purchase
41
41
  # succeeds. Defaults to false. (optional)
42
42
  def purchase(money, payment_method, options = {})
43
- if payment_method.is_a?(String)
44
- purchase_with_token(money, payment_method, options)
45
- else
46
- MultiResponse.run do |r|
47
- r.process { save_card(options[:store], payment_method, options) }
48
- r.process { purchase_with_token(money, r.authorization, options) }
49
- end
50
- end
43
+ request = build_transaction_request(money, payment_method, options)
44
+ commit("gateways/#{options[:gateway_token] || @options[:gateway_token]}/purchase.xml", request)
51
45
  end
52
46
 
53
47
  # Public: Run an authorize transaction.
@@ -58,14 +52,8 @@ module ActiveMerchant #:nodoc:
58
52
  # :store - Retain the payment method if the authorize
59
53
  # succeeds. Defaults to false. (optional)
60
54
  def authorize(money, payment_method, options = {})
61
- if payment_method.is_a?(String)
62
- authorize_with_token(money, payment_method, options)
63
- else
64
- MultiResponse.run do |r|
65
- r.process { save_card(options[:store], payment_method, options) }
66
- r.process { authorize_with_token(money, r.authorization, options) }
67
- end
68
- end
55
+ request = build_transaction_request(money, payment_method, options)
56
+ commit("gateways/#{@options[:gateway_token]}/authorize.xml", request)
69
57
  end
70
58
 
71
59
  def capture(money, authorization, options={})
@@ -79,6 +67,7 @@ module ActiveMerchant #:nodoc:
79
67
  def refund(money, authorization, options={})
80
68
  request = build_xml_request('transaction') do |doc|
81
69
  add_invoice(doc, money, options)
70
+ add_extra_options(:gateway_specific_fields, doc, options)
82
71
  end
83
72
 
84
73
  commit("transactions/#{authorization}/credit.xml", request)
@@ -155,32 +144,25 @@ module ActiveMerchant #:nodoc:
155
144
  end
156
145
 
157
146
  def purchase_with_token(money, payment_method_token, options)
158
- request = auth_purchase_request(money, payment_method_token, options)
147
+ request = build_transaction_request(money, payment_method_token, options)
159
148
  commit("gateways/#{options[:gateway_token] || @options[:gateway_token]}/purchase.xml", request)
160
149
  end
161
150
 
162
151
  def authorize_with_token(money, payment_method_token, options)
163
- request = auth_purchase_request(money, payment_method_token, options)
152
+ request = build_transaction_request(money, payment_method_token, options)
164
153
  commit("gateways/#{@options[:gateway_token]}/authorize.xml", request)
165
154
  end
166
155
 
167
156
  def verify_with_token(payment_method_token, options)
168
- request = build_xml_request('transaction') do |doc|
169
- add_invoice(doc, nil, options)
170
- doc.payment_method_token(payment_method_token)
171
- doc.retain_on_success(true) if options[:store]
172
- add_extra_options(:gateway_specific_fields, doc, options)
173
- end
174
-
157
+ request = build_transaction_request(nil, payment_method_token, options)
175
158
  commit("gateways/#{@options[:gateway_token]}/verify.xml", request)
176
159
  end
177
160
 
178
- def auth_purchase_request(money, payment_method_token, options)
161
+ def build_transaction_request(money, payment_method, options)
179
162
  build_xml_request('transaction') do |doc|
180
163
  add_invoice(doc, money, options)
164
+ add_payment_method(doc, payment_method, options)
181
165
  add_extra_options(:gateway_specific_fields, doc, options)
182
- doc.payment_method_token(payment_method_token)
183
- doc.retain_on_success(true) if options[:store]
184
166
  end
185
167
  end
186
168
 
@@ -190,6 +172,27 @@ module ActiveMerchant #:nodoc:
190
172
  doc.order_id(options[:order_id])
191
173
  doc.ip(options[:ip]) if options[:ip]
192
174
  doc.description(options[:description]) if options[:description]
175
+
176
+ if options[:merchant_name_descriptor]
177
+ doc.merchant_name_descriptor(options[:merchant_name_descriptor])
178
+ end
179
+ if options[:merchant_location_descriptor]
180
+ doc.merchant_location_descriptor(options[:merchant_location_descriptor])
181
+ end
182
+ end
183
+
184
+ def add_payment_method(doc, payment_method, options)
185
+ doc.retain_on_success(true) if options[:store]
186
+
187
+ if payment_method.is_a?(String)
188
+ doc.payment_method_token(payment_method)
189
+ elsif payment_method.is_a?(CreditCard)
190
+ add_credit_card(doc, payment_method, options)
191
+ elsif payment_method.is_a?(Check)
192
+ add_bank_account(doc, payment_method, options)
193
+ else
194
+ raise TypeError, 'Payment method not supported'
195
+ end
193
196
  end
194
197
 
195
198
  def add_credit_card(doc, credit_card, options)
@@ -210,6 +213,17 @@ module ActiveMerchant #:nodoc:
210
213
  end
211
214
  end
212
215
 
216
+ def add_bank_account(doc, bank_account, options)
217
+ doc.bank_account do
218
+ doc.first_name(bank_account.first_name)
219
+ doc.last_name(bank_account.last_name)
220
+ doc.bank_routing_number(bank_account.routing_number)
221
+ doc.bank_account_number(bank_account.account_number)
222
+ doc.bank_account_type(bank_account.account_type)
223
+ doc.bank_account_holder_type(bank_account.account_holder_type)
224
+ end
225
+ end
226
+
213
227
  def add_extra_options(type, doc, options)
214
228
  doc.send(type) do
215
229
  extra_options_to_doc(doc, options[type])
@@ -2,6 +2,8 @@ require 'active_support/core_ext/hash/slice'
2
2
 
3
3
  module ActiveMerchant #:nodoc:
4
4
  module Billing #:nodoc:
5
+ # This gateway uses an older version of the Stripe API.
6
+ # To utilize the updated {Payment Intents API}[https://stripe.com/docs/api/payment_intents], integrate with the StripePaymentIntents gateway
5
7
  class StripeGateway < Gateway
6
8
  self.live_url = 'https://api.stripe.com/v1/'
7
9
 
@@ -21,6 +23,8 @@ module ActiveMerchant #:nodoc:
21
23
  'unchecked' => 'P'
22
24
  }
23
25
 
26
+ DEFAULT_API_VERSION = '2015-04-07'
27
+
24
28
  self.supported_countries = %w(AT AU BE BR CA CH DE DK ES FI FR GB HK IE IT JP LU MX NL NO NZ PT SE SG US)
25
29
  self.default_currency = 'USD'
26
30
  self.money_format = :cents
@@ -152,7 +156,7 @@ module ActiveMerchant #:nodoc:
152
156
 
153
157
  response = commit(:post, "charges/#{CGI.escape(identification)}/refunds", post, options)
154
158
 
155
- if options[:refund_fee_amount] && options[:refund_fee_amount].to_s != '0'
159
+ if response.success? && options[:refund_fee_amount] && options[:refund_fee_amount].to_s != '0'
156
160
  charge = api_request(:get, "charges/#{CGI.escape(identification)}", nil, options)
157
161
 
158
162
  if application_fee = charge['application_fee']
@@ -300,8 +304,8 @@ module ActiveMerchant #:nodoc:
300
304
  add_amount(post, money, options, true)
301
305
  post[:type] = type
302
306
  if type == 'card'
303
- add_creditcard(post, payment, options)
304
- post[:card].delete(:name)
307
+ add_creditcard(post, payment, options, true)
308
+ add_source_owner(post, payment, options)
305
309
  elsif type == 'three_d_secure'
306
310
  post[:three_d_secure] = {card: payment}
307
311
  post[:redirect] = {return_url: options[:redirect_url]}
@@ -309,6 +313,10 @@ module ActiveMerchant #:nodoc:
309
313
  commit(:post, 'sources', post, options)
310
314
  end
311
315
 
316
+ def show_source(source_id, options)
317
+ commit(:get, "sources/#{source_id}", nil, options)
318
+ end
319
+
312
320
  def create_webhook_endpoint(options, events)
313
321
  post = {}
314
322
  post[:url] = options[:callback_url]
@@ -322,6 +330,18 @@ module ActiveMerchant #:nodoc:
322
330
  commit(:delete, "webhook_endpoints/#{options[:webhook_id]}", {}, options)
323
331
  end
324
332
 
333
+ def show_webhook_endpoint(options)
334
+ options.delete(:stripe_account)
335
+ commit(:get, "webhook_endpoints/#{options[:webhook_id]}", nil, options)
336
+ end
337
+
338
+ def list_webhook_endpoints(options)
339
+ params = {}
340
+ params[:limit] = options[:limit] if options[:limit]
341
+ options.delete(:stripe_account)
342
+ commit(:get, "webhook_endpoints?#{post_data(params)}", nil, options)
343
+ end
344
+
325
345
  def create_post_for_auth_or_purchase(money, payment, options)
326
346
  post = {}
327
347
 
@@ -331,6 +351,12 @@ module ActiveMerchant #:nodoc:
331
351
  add_creditcard(post, payment, options)
332
352
  end
333
353
 
354
+ add_charge_details(post, money, payment, options)
355
+ post
356
+ end
357
+
358
+ # Used internally by Spreedly to populate the charge object for 3DS 1.0 transactions
359
+ def add_charge_details(post, money, payment, options)
334
360
  if emv_payment?(payment)
335
361
  add_statement_address(post, options)
336
362
  add_emv_metadata(post, payment)
@@ -433,7 +459,7 @@ module ActiveMerchant #:nodoc:
433
459
  post[:statement_address][:state] = statement_address[:state]
434
460
  end
435
461
 
436
- def add_creditcard(post, creditcard, options)
462
+ def add_creditcard(post, creditcard, options, use_sources = false)
437
463
  card = {}
438
464
  if emv_payment?(creditcard)
439
465
  add_emv_creditcard(post, creditcard.icc_data)
@@ -456,7 +482,7 @@ module ActiveMerchant #:nodoc:
456
482
  card[:exp_month] = creditcard.month
457
483
  card[:exp_year] = creditcard.year
458
484
  card[:cvc] = creditcard.verification_value if creditcard.verification_value?
459
- card[:name] = creditcard.name if creditcard.name
485
+ card[:name] = creditcard.name if creditcard.name && !use_sources
460
486
  end
461
487
 
462
488
  if creditcard.is_a?(NetworkTokenizationCreditCard)
@@ -466,7 +492,7 @@ module ActiveMerchant #:nodoc:
466
492
  end
467
493
  post[:card] = card
468
494
 
469
- add_address(post, options)
495
+ add_address(post, options) unless use_sources
470
496
  elsif creditcard.kind_of?(String)
471
497
  if options[:track_data]
472
498
  card[:swipe_data] = options[:track_data]
@@ -514,6 +540,25 @@ module ActiveMerchant #:nodoc:
514
540
  post[:metadata][:card_read_method] = creditcard.read_method if creditcard.respond_to?(:read_method)
515
541
  end
516
542
 
543
+ def add_source_owner(post, creditcard, options)
544
+ post[:owner] = {}
545
+ post[:owner][:name] = creditcard.name if creditcard.name
546
+ post[:owner][:email] = options[:email] if options[:email]
547
+
548
+ if address = options[:billing_address] || options[:address]
549
+ owner_address = {}
550
+ owner_address[:line1] = address[:address1] if address[:address1]
551
+ owner_address[:line2] = address[:address2] if address[:address2]
552
+ owner_address[:country] = address[:country] if address[:country]
553
+ owner_address[:postal_code] = address[:zip] if address[:zip]
554
+ owner_address[:state] = address[:state] if address[:state]
555
+ owner_address[:city] = address[:city] if address[:city]
556
+
557
+ post[:owner][:phone] = address[:phone] if address[:phone]
558
+ post[:owner][:address] = owner_address
559
+ end
560
+ end
561
+
517
562
  def parse(body)
518
563
  JSON.parse(body)
519
564
  end
@@ -573,7 +618,7 @@ module ActiveMerchant #:nodoc:
573
618
  end
574
619
 
575
620
  def api_version(options)
576
- options[:version] || @options[:version] || '2015-04-07'
621
+ options[:version] || @options[:version] || self.class::DEFAULT_API_VERSION
577
622
  end
578
623
 
579
624
  def api_request(method, endpoint, parameters = nil, options = {})
@@ -616,8 +661,8 @@ module ActiveMerchant #:nodoc:
616
661
  return response.fetch('error', {})['charge'] unless success
617
662
 
618
663
  if url == 'customers'
619
- [response['id'], response['sources']['data'].first['id']].join('|')
620
- elsif method == :post && url.match(/customers\/.*\/cards/)
664
+ [response['id'], response.dig('sources', 'data').first&.dig('id')].join('|')
665
+ elsif method == :post && (url.match(/customers\/.*\/cards/) || url.match(/payment_methods\/.*\/attach/))
621
666
  [response['customer'], response['id']].join('|')
622
667
  else
623
668
  response['id']
@@ -0,0 +1,267 @@
1
+ require 'active_support/core_ext/hash/slice'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ # This gateway uses the current Stripe {Payment Intents API}[https://stripe.com/docs/api/payment_intents].
6
+ # For the legacy API, see the Stripe gateway
7
+ class StripePaymentIntentsGateway < StripeGateway
8
+
9
+ self.supported_countries = %w(AT AU BE BR CA CH DE DK ES FI FR GB HK IE IT JP LU MX NL NO NZ PT SE SG US)
10
+
11
+ ALLOWED_METHOD_STATES = %w[automatic manual].freeze
12
+ ALLOWED_CANCELLATION_REASONS = %w[duplicate fraudulent requested_by_customer abandoned].freeze
13
+ CREATE_INTENT_ATTRIBUTES = %i[description statement_descriptor receipt_email save_payment_method]
14
+ CONFIRM_INTENT_ATTRIBUTES = %i[receipt_email return_url save_payment_method setup_future_usage off_session]
15
+ UPDATE_INTENT_ATTRIBUTES = %i[description statement_descriptor receipt_email setup_future_usage]
16
+ DEFAULT_API_VERSION = '2019-05-16'
17
+
18
+ def create_intent(money, payment_method, options = {})
19
+ post = {}
20
+ add_amount(post, money, options, true)
21
+ add_capture_method(post, options)
22
+ add_confirmation_method(post, options)
23
+ add_customer(post, options)
24
+ add_payment_method_token(post, payment_method, options)
25
+ add_metadata(post, options)
26
+ add_return_url(post, options)
27
+ add_connected_account(post, options)
28
+ add_shipping_address(post, options)
29
+ setup_future_usage(post, options)
30
+ add_exemption(post, options)
31
+
32
+ CREATE_INTENT_ATTRIBUTES.each do |attribute|
33
+ add_whitelisted_attribute(post, options, attribute)
34
+ end
35
+
36
+ commit(:post, 'payment_intents', post, options)
37
+ end
38
+
39
+ def show_intent(intent_id, options)
40
+ commit(:get, "payment_intents/#{intent_id}", nil, options)
41
+ end
42
+
43
+ def confirm_intent(intent_id, payment_method, options = {})
44
+ post = {}
45
+ add_payment_method_token(post, payment_method, options)
46
+ CONFIRM_INTENT_ATTRIBUTES.each do |attribute|
47
+ add_whitelisted_attribute(post, options, attribute)
48
+ end
49
+
50
+ commit(:post, "payment_intents/#{intent_id}/confirm", post, options)
51
+ end
52
+
53
+ def create_payment_method(payment_method, options = {})
54
+ post = {}
55
+ post[:type] = 'card'
56
+ post[:card] = {}
57
+ post[:card][:number] = payment_method.number
58
+ post[:card][:exp_month] = payment_method.month
59
+ post[:card][:exp_year] = payment_method.year
60
+ post[:card][:cvc] = payment_method.verification_value if payment_method.verification_value
61
+ add_billing_address(post, options)
62
+
63
+ commit(:post, 'payment_methods', post, options)
64
+ end
65
+
66
+ def update_intent(money, intent_id, payment_method, options = {})
67
+ post = {}
68
+ post[:amount] = money if money
69
+
70
+ add_payment_method_token(post, payment_method, options)
71
+ add_payment_method_types(post, options)
72
+ add_customer(post, options)
73
+ add_metadata(post, options)
74
+ add_shipping_address(post, options)
75
+ add_connected_account(post, options)
76
+
77
+ UPDATE_INTENT_ATTRIBUTES.each do |attribute|
78
+ add_whitelisted_attribute(post, options, attribute)
79
+ end
80
+
81
+ commit(:post, "payment_intents/#{intent_id}", post, options)
82
+ end
83
+
84
+ def authorize(money, payment_method, options = {})
85
+ create_intent(money, payment_method, options.merge!(confirm: true, capture_method: 'manual'))
86
+ end
87
+
88
+ def purchase(money, payment_method, options = {})
89
+ create_intent(money, payment_method, options.merge!(confirm: true, capture_method: 'automatic'))
90
+ end
91
+
92
+ def capture(money, intent_id, options = {})
93
+ post = {}
94
+ post[:amount_to_capture] = money
95
+ add_connected_account(post, options)
96
+ commit(:post, "payment_intents/#{intent_id}/capture", post, options)
97
+ end
98
+
99
+ def void(intent_id, options = {})
100
+ post = {}
101
+ post[:cancellation_reason] = options[:cancellation_reason] if ALLOWED_CANCELLATION_REASONS.include?(options[:cancellation_reason])
102
+ commit(:post, "payment_intents/#{intent_id}/cancel", post, options)
103
+ end
104
+
105
+ def refund(money, intent_id, options = {})
106
+ intent = commit(:get, "payment_intents/#{intent_id}", nil, options)
107
+ charge_id = intent.params.dig('charges', 'data')[0].dig('id')
108
+ super(money, charge_id, options)
109
+ end
110
+
111
+ # Note: Not all payment methods are currently supported by the {Payment Methods API}[https://stripe.com/docs/payments/payment-methods]
112
+ # Current implementation will create a PaymentMethod object if the method is a token or credit card
113
+ # All other types will default to legacy Stripe store
114
+ def store(payment_method, options = {})
115
+ params = {}
116
+ post = {}
117
+
118
+ # If customer option is provided, create a payment method and attach to customer id
119
+ # Otherwise, create a customer, then attach
120
+ if payment_method.is_a?(StripePaymentToken) || payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
121
+ add_payment_method_token(params, payment_method, options)
122
+ if options[:customer]
123
+ customer_id = options[:customer]
124
+ else
125
+ post[:validate] = options[:validate] unless options[:validate].nil?
126
+ post[:description] = options[:description] if options[:description]
127
+ post[:email] = options[:email] if options[:email]
128
+ customer = commit(:post, 'customers', post, options)
129
+ customer_id = customer.params['id']
130
+ end
131
+ commit(:post, "payment_methods/#{params[:payment_method]}/attach", { customer: customer_id }, options)
132
+ else
133
+ super(payment, options)
134
+ end
135
+ end
136
+
137
+ def unstore(identification, options = {}, deprecated_options = {})
138
+ if identification.include?('pm_')
139
+ _, payment_method = identification.split('|')
140
+ commit(:post, "payment_methods/#{payment_method}/detach", nil, options)
141
+ else
142
+ super(identification, options, deprecated_options)
143
+ end
144
+ end
145
+
146
+ private
147
+
148
+ def add_whitelisted_attribute(post, options, attribute)
149
+ post[attribute] = options[attribute] if options[attribute]
150
+ post
151
+ end
152
+
153
+ def add_capture_method(post, options)
154
+ capture_method = options[:capture_method].to_s
155
+ post[:capture_method] = capture_method if ALLOWED_METHOD_STATES.include?(capture_method)
156
+ post
157
+ end
158
+
159
+ def add_confirmation_method(post, options)
160
+ confirmation_method = options[:confirmation_method].to_s
161
+ post[:confirmation_method] = confirmation_method if ALLOWED_METHOD_STATES.include?(confirmation_method)
162
+ post
163
+ end
164
+
165
+ def add_customer(post, options)
166
+ customer = options[:customer].to_s
167
+ post[:customer] = customer if customer.start_with?('cus_')
168
+ post
169
+ end
170
+
171
+ def add_return_url(post, options)
172
+ return unless options[:confirm]
173
+ post[:confirm] = options[:confirm]
174
+ post[:return_url] = options[:return_url] if options[:return_url]
175
+ post
176
+ end
177
+
178
+ def add_payment_method_token(post, payment_method, options)
179
+ return if payment_method.nil?
180
+
181
+ if payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
182
+ p = create_payment_method(payment_method, options)
183
+ payment_method = p.params['id']
184
+ end
185
+
186
+ if payment_method.is_a?(StripePaymentToken)
187
+ post[:payment_method] = payment_method.payment_data['id']
188
+ elsif payment_method.is_a?(String)
189
+ if payment_method.include?('|')
190
+ customer_id, payment_method_id = payment_method.split('|')
191
+ token = payment_method_id
192
+ post[:customer] = customer_id
193
+ else
194
+ token = payment_method
195
+ end
196
+ post[:payment_method] = token
197
+ end
198
+ end
199
+
200
+ def add_payment_method_types(post, options)
201
+ payment_method_types = options[:payment_method_types] if options[:payment_method_types]
202
+ return if payment_method_types.nil?
203
+
204
+ post[:payment_method_types] = Array(payment_method_types)
205
+ post
206
+ end
207
+
208
+ def add_exemption(post, options = {})
209
+ return unless options[:confirm]
210
+ post[:payment_method_options] ||= {}
211
+ post[:payment_method_options][:card] ||= {}
212
+ post[:payment_method_options][:card][:moto] = true if options[:moto]
213
+ end
214
+
215
+ def setup_future_usage(post, options = {})
216
+ post[:setup_future_usage] = options[:setup_future_usage] if %w( on_session off_session ).include?(options[:setup_future_usage])
217
+ post[:off_session] = options[:off_session] if options[:off_session] && options[:confirm] == true
218
+ post
219
+ end
220
+
221
+ def add_connected_account(post, options = {})
222
+ return unless options[:transfer_destination]
223
+ post[:transfer_data] = {}
224
+ post[:transfer_data][:destination] = options[:transfer_destination]
225
+ post[:transfer_data][:amount] = options[:transfer_amount] if options[:transfer_amount]
226
+ post[:on_behalf_of] = options[:on_behalf_of] if options[:on_behalf_of]
227
+ post[:transfer_group] = options[:transfer_group] if options[:transfer_group]
228
+ post[:application_fee_amount] = options[:application_fee] if options[:application_fee]
229
+ post
230
+ end
231
+
232
+ def add_billing_address(post, options = {})
233
+ return unless billing = options[:billing_address] || options[:address]
234
+ post[:billing_details] = {}
235
+ post[:billing_details][:address] = {}
236
+ post[:billing_details][:address][:city] = billing[:city] if billing[:city]
237
+ post[:billing_details][:address][:country] = billing[:country] if billing[:country]
238
+ post[:billing_details][:address][:line1] = billing[:address1] if billing[:address1]
239
+ post[:billing_details][:address][:line2] = billing[:address2] if billing[:address2]
240
+ post[:billing_details][:address][:postal_code] = billing[:zip] if billing[:zip]
241
+ post[:billing_details][:address][:state] = billing[:state] if billing[:state]
242
+ post[:billing_details][:email] = billing[:email] if billing[:email]
243
+ post[:billing_details][:name] = billing[:name] if billing[:name]
244
+ post[:billing_details][:phone] = billing[:phone] if billing[:phone]
245
+ post
246
+ end
247
+
248
+ def add_shipping_address(post, options = {})
249
+ return unless shipping = options[:shipping]
250
+ post[:shipping] = {}
251
+ post[:shipping][:address] = {}
252
+ post[:shipping][:address][:line1] = shipping[:address][:line1]
253
+ post[:shipping][:address][:city] = shipping[:address][:city] if shipping[:address][:city]
254
+ post[:shipping][:address][:country] = shipping[:address][:country] if shipping[:address][:country]
255
+ post[:shipping][:address][:line2] = shipping[:address][:line2] if shipping[:address][:line2]
256
+ post[:shipping][:address][:postal_code] = shipping[:address][:postal_code] if shipping[:address][:postal_code]
257
+ post[:shipping][:address][:state] = shipping[:address][:state] if shipping[:address][:state]
258
+
259
+ post[:shipping][:name] = shipping[:name]
260
+ post[:shipping][:carrier] = shipping[:carrier] if shipping[:carrier]
261
+ post[:shipping][:phone] = shipping[:phone] if shipping[:phone]
262
+ post[:shipping][:tracking_number] = shipping[:tracking_number] if shipping[:tracking_number]
263
+ post
264
+ end
265
+ end
266
+ end
267
+ end