activemerchant 1.94.0 → 1.99.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.
- checksums.yaml +4 -4
- data/CHANGELOG +120 -1
- data/README.md +3 -0
- data/lib/active_merchant/billing/avs_result.rb +4 -5
- data/lib/active_merchant/billing/credit_card.rb +6 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +65 -2
- data/lib/active_merchant/billing/gateway.rb +10 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +119 -34
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +43 -10
- data/lib/active_merchant/billing/gateways/beanstream.rb +11 -6
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +3 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +22 -2
- data/lib/active_merchant/billing/gateways/bpoint.rb +4 -4
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +56 -9
- data/lib/active_merchant/billing/gateways/card_connect.rb +2 -1
- data/lib/active_merchant/billing/gateways/cecabank.rb +7 -7
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +37 -27
- data/lib/active_merchant/billing/gateways/credorax.rb +69 -4
- data/lib/active_merchant/billing/gateways/cyber_source.rb +51 -11
- data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
- data/lib/active_merchant/billing/gateways/decidir.rb +245 -0
- data/lib/active_merchant/billing/gateways/epay.rb +13 -2
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +42 -12
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +6 -0
- data/lib/active_merchant/billing/gateways/global_collect.rb +3 -7
- data/lib/active_merchant/billing/gateways/hps.rb +46 -1
- data/lib/active_merchant/billing/gateways/kushki.rb +1 -1
- data/lib/active_merchant/billing/gateways/mastercard.rb +30 -5
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +1 -1
- data/lib/active_merchant/billing/gateways/migs.rb +8 -0
- data/lib/active_merchant/billing/gateways/monei.rb +31 -0
- data/lib/active_merchant/billing/gateways/mundipagg.rb +33 -6
- data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
- data/lib/active_merchant/billing/gateways/nmi.rb +39 -1
- data/lib/active_merchant/billing/gateways/opp.rb +20 -1
- data/lib/active_merchant/billing/gateways/orbital.rb +60 -10
- data/lib/active_merchant/billing/gateways/payflow.rb +64 -14
- data/lib/active_merchant/billing/gateways/paymill.rb +5 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +14 -1
- data/lib/active_merchant/billing/gateways/payu_latam.rb +6 -2
- data/lib/active_merchant/billing/gateways/qvalent.rb +43 -1
- data/lib/active_merchant/billing/gateways/realex.rb +32 -9
- data/lib/active_merchant/billing/gateways/redsys.rb +113 -30
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +43 -29
- data/lib/active_merchant/billing/gateways/stripe.rb +38 -9
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +271 -0
- data/lib/active_merchant/billing/gateways/tns.rb +10 -5
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -2
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +45 -6
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +8 -5
- data/lib/active_merchant/billing/gateways/worldpay.rb +177 -39
- data/lib/active_merchant/country.rb +1 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +19 -4
@@ -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,7 +23,9 @@ module ActiveMerchant #:nodoc:
|
|
21
23
|
'unchecked' => 'P'
|
22
24
|
}
|
23
25
|
|
24
|
-
|
26
|
+
DEFAULT_API_VERSION = '2015-04-07'
|
27
|
+
|
28
|
+
self.supported_countries = %w(AT AU BE BR CA CH DE DK EE ES FI FR GB GR HK IE IT JP LT LU LV MX NL NO NZ PL PT SE SG SI SK US)
|
25
29
|
self.default_currency = 'USD'
|
26
30
|
self.money_format = :cents
|
27
31
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
|
@@ -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
|
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]}
|
@@ -347,6 +351,12 @@ module ActiveMerchant #:nodoc:
|
|
347
351
|
add_creditcard(post, payment, options)
|
348
352
|
end
|
349
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)
|
350
360
|
if emv_payment?(payment)
|
351
361
|
add_statement_address(post, options)
|
352
362
|
add_emv_metadata(post, payment)
|
@@ -449,7 +459,7 @@ module ActiveMerchant #:nodoc:
|
|
449
459
|
post[:statement_address][:state] = statement_address[:state]
|
450
460
|
end
|
451
461
|
|
452
|
-
def add_creditcard(post, creditcard, options)
|
462
|
+
def add_creditcard(post, creditcard, options, use_sources = false)
|
453
463
|
card = {}
|
454
464
|
if emv_payment?(creditcard)
|
455
465
|
add_emv_creditcard(post, creditcard.icc_data)
|
@@ -472,7 +482,7 @@ module ActiveMerchant #:nodoc:
|
|
472
482
|
card[:exp_month] = creditcard.month
|
473
483
|
card[:exp_year] = creditcard.year
|
474
484
|
card[:cvc] = creditcard.verification_value if creditcard.verification_value?
|
475
|
-
card[:name] = creditcard.name if creditcard.name
|
485
|
+
card[:name] = creditcard.name if creditcard.name && !use_sources
|
476
486
|
end
|
477
487
|
|
478
488
|
if creditcard.is_a?(NetworkTokenizationCreditCard)
|
@@ -482,7 +492,7 @@ module ActiveMerchant #:nodoc:
|
|
482
492
|
end
|
483
493
|
post[:card] = card
|
484
494
|
|
485
|
-
add_address(post, options)
|
495
|
+
add_address(post, options) unless use_sources
|
486
496
|
elsif creditcard.kind_of?(String)
|
487
497
|
if options[:track_data]
|
488
498
|
card[:swipe_data] = options[:track_data]
|
@@ -530,6 +540,25 @@ module ActiveMerchant #:nodoc:
|
|
530
540
|
post[:metadata][:card_read_method] = creditcard.read_method if creditcard.respond_to?(:read_method)
|
531
541
|
end
|
532
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
|
+
|
533
562
|
def parse(body)
|
534
563
|
JSON.parse(body)
|
535
564
|
end
|
@@ -589,7 +618,7 @@ module ActiveMerchant #:nodoc:
|
|
589
618
|
end
|
590
619
|
|
591
620
|
def api_version(options)
|
592
|
-
options[:version] || @options[:version] ||
|
621
|
+
options[:version] || @options[:version] || self.class::DEFAULT_API_VERSION
|
593
622
|
end
|
594
623
|
|
595
624
|
def api_request(method, endpoint, parameters = nil, options = {})
|
@@ -632,8 +661,8 @@ module ActiveMerchant #:nodoc:
|
|
632
661
|
return response.fetch('error', {})['charge'] unless success
|
633
662
|
|
634
663
|
if url == 'customers'
|
635
|
-
[response['id'], response
|
636
|
-
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/))
|
637
666
|
[response['customer'], response['id']].join('|')
|
638
667
|
else
|
639
668
|
response['id']
|
@@ -0,0 +1,271 @@
|
|
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 EE ES FI FR GB GR HK IE IT JP LT LU LV MX NL NO NZ PL PT SE SG SI SK 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
|
+
if options[:transfer_amount]
|
96
|
+
post[:transfer_data] = {}
|
97
|
+
post[:transfer_data][:amount] = options[:transfer_amount]
|
98
|
+
end
|
99
|
+
post[:application_fee_amount] = options[:application_fee] if options[:application_fee]
|
100
|
+
commit(:post, "payment_intents/#{intent_id}/capture", post, options)
|
101
|
+
end
|
102
|
+
|
103
|
+
def void(intent_id, options = {})
|
104
|
+
post = {}
|
105
|
+
post[:cancellation_reason] = options[:cancellation_reason] if ALLOWED_CANCELLATION_REASONS.include?(options[:cancellation_reason])
|
106
|
+
commit(:post, "payment_intents/#{intent_id}/cancel", post, options)
|
107
|
+
end
|
108
|
+
|
109
|
+
def refund(money, intent_id, options = {})
|
110
|
+
intent = commit(:get, "payment_intents/#{intent_id}", nil, options)
|
111
|
+
charge_id = intent.params.dig('charges', 'data')[0].dig('id')
|
112
|
+
super(money, charge_id, options)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Note: Not all payment methods are currently supported by the {Payment Methods API}[https://stripe.com/docs/payments/payment-methods]
|
116
|
+
# Current implementation will create a PaymentMethod object if the method is a token or credit card
|
117
|
+
# All other types will default to legacy Stripe store
|
118
|
+
def store(payment_method, options = {})
|
119
|
+
params = {}
|
120
|
+
post = {}
|
121
|
+
|
122
|
+
# If customer option is provided, create a payment method and attach to customer id
|
123
|
+
# Otherwise, create a customer, then attach
|
124
|
+
if payment_method.is_a?(StripePaymentToken) || payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
|
125
|
+
add_payment_method_token(params, payment_method, options)
|
126
|
+
if options[:customer]
|
127
|
+
customer_id = options[:customer]
|
128
|
+
else
|
129
|
+
post[:validate] = options[:validate] unless options[:validate].nil?
|
130
|
+
post[:description] = options[:description] if options[:description]
|
131
|
+
post[:email] = options[:email] if options[:email]
|
132
|
+
customer = commit(:post, 'customers', post, options)
|
133
|
+
customer_id = customer.params['id']
|
134
|
+
end
|
135
|
+
commit(:post, "payment_methods/#{params[:payment_method]}/attach", { customer: customer_id }, options)
|
136
|
+
else
|
137
|
+
super(payment, options)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def unstore(identification, options = {}, deprecated_options = {})
|
142
|
+
if identification.include?('pm_')
|
143
|
+
_, payment_method = identification.split('|')
|
144
|
+
commit(:post, "payment_methods/#{payment_method}/detach", nil, options)
|
145
|
+
else
|
146
|
+
super(identification, options, deprecated_options)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
def add_whitelisted_attribute(post, options, attribute)
|
153
|
+
post[attribute] = options[attribute] if options[attribute]
|
154
|
+
post
|
155
|
+
end
|
156
|
+
|
157
|
+
def add_capture_method(post, options)
|
158
|
+
capture_method = options[:capture_method].to_s
|
159
|
+
post[:capture_method] = capture_method if ALLOWED_METHOD_STATES.include?(capture_method)
|
160
|
+
post
|
161
|
+
end
|
162
|
+
|
163
|
+
def add_confirmation_method(post, options)
|
164
|
+
confirmation_method = options[:confirmation_method].to_s
|
165
|
+
post[:confirmation_method] = confirmation_method if ALLOWED_METHOD_STATES.include?(confirmation_method)
|
166
|
+
post
|
167
|
+
end
|
168
|
+
|
169
|
+
def add_customer(post, options)
|
170
|
+
customer = options[:customer].to_s
|
171
|
+
post[:customer] = customer if customer.start_with?('cus_')
|
172
|
+
post
|
173
|
+
end
|
174
|
+
|
175
|
+
def add_return_url(post, options)
|
176
|
+
return unless options[:confirm]
|
177
|
+
post[:confirm] = options[:confirm]
|
178
|
+
post[:return_url] = options[:return_url] if options[:return_url]
|
179
|
+
post
|
180
|
+
end
|
181
|
+
|
182
|
+
def add_payment_method_token(post, payment_method, options)
|
183
|
+
return if payment_method.nil?
|
184
|
+
|
185
|
+
if payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
|
186
|
+
p = create_payment_method(payment_method, options)
|
187
|
+
payment_method = p.params['id']
|
188
|
+
end
|
189
|
+
|
190
|
+
if payment_method.is_a?(StripePaymentToken)
|
191
|
+
post[:payment_method] = payment_method.payment_data['id']
|
192
|
+
elsif payment_method.is_a?(String)
|
193
|
+
if payment_method.include?('|')
|
194
|
+
customer_id, payment_method_id = payment_method.split('|')
|
195
|
+
token = payment_method_id
|
196
|
+
post[:customer] = customer_id
|
197
|
+
else
|
198
|
+
token = payment_method
|
199
|
+
end
|
200
|
+
post[:payment_method] = token
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def add_payment_method_types(post, options)
|
205
|
+
payment_method_types = options[:payment_method_types] if options[:payment_method_types]
|
206
|
+
return if payment_method_types.nil?
|
207
|
+
|
208
|
+
post[:payment_method_types] = Array(payment_method_types)
|
209
|
+
post
|
210
|
+
end
|
211
|
+
|
212
|
+
def add_exemption(post, options = {})
|
213
|
+
return unless options[:confirm]
|
214
|
+
post[:payment_method_options] ||= {}
|
215
|
+
post[:payment_method_options][:card] ||= {}
|
216
|
+
post[:payment_method_options][:card][:moto] = true if options[:moto]
|
217
|
+
end
|
218
|
+
|
219
|
+
def setup_future_usage(post, options = {})
|
220
|
+
post[:setup_future_usage] = options[:setup_future_usage] if %w( on_session off_session ).include?(options[:setup_future_usage])
|
221
|
+
post[:off_session] = options[:off_session] if options[:off_session] && options[:confirm] == true
|
222
|
+
post
|
223
|
+
end
|
224
|
+
|
225
|
+
def add_connected_account(post, options = {})
|
226
|
+
return unless options[:transfer_destination]
|
227
|
+
post[:transfer_data] = {}
|
228
|
+
post[:transfer_data][:destination] = options[:transfer_destination]
|
229
|
+
post[:transfer_data][:amount] = options[:transfer_amount] if options[:transfer_amount]
|
230
|
+
post[:on_behalf_of] = options[:on_behalf_of] if options[:on_behalf_of]
|
231
|
+
post[:transfer_group] = options[:transfer_group] if options[:transfer_group]
|
232
|
+
post[:application_fee_amount] = options[:application_fee] if options[:application_fee]
|
233
|
+
post
|
234
|
+
end
|
235
|
+
|
236
|
+
def add_billing_address(post, options = {})
|
237
|
+
return unless billing = options[:billing_address] || options[:address]
|
238
|
+
post[:billing_details] = {}
|
239
|
+
post[:billing_details][:address] = {}
|
240
|
+
post[:billing_details][:address][:city] = billing[:city] if billing[:city]
|
241
|
+
post[:billing_details][:address][:country] = billing[:country] if billing[:country]
|
242
|
+
post[:billing_details][:address][:line1] = billing[:address1] if billing[:address1]
|
243
|
+
post[:billing_details][:address][:line2] = billing[:address2] if billing[:address2]
|
244
|
+
post[:billing_details][:address][:postal_code] = billing[:zip] if billing[:zip]
|
245
|
+
post[:billing_details][:address][:state] = billing[:state] if billing[:state]
|
246
|
+
post[:billing_details][:email] = billing[:email] if billing[:email]
|
247
|
+
post[:billing_details][:name] = billing[:name] if billing[:name]
|
248
|
+
post[:billing_details][:phone] = billing[:phone] if billing[:phone]
|
249
|
+
post
|
250
|
+
end
|
251
|
+
|
252
|
+
def add_shipping_address(post, options = {})
|
253
|
+
return unless shipping = options[:shipping]
|
254
|
+
post[:shipping] = {}
|
255
|
+
post[:shipping][:address] = {}
|
256
|
+
post[:shipping][:address][:line1] = shipping[:address][:line1]
|
257
|
+
post[:shipping][:address][:city] = shipping[:address][:city] if shipping[:address][:city]
|
258
|
+
post[:shipping][:address][:country] = shipping[:address][:country] if shipping[:address][:country]
|
259
|
+
post[:shipping][:address][:line2] = shipping[:address][:line2] if shipping[:address][:line2]
|
260
|
+
post[:shipping][:address][:postal_code] = shipping[:address][:postal_code] if shipping[:address][:postal_code]
|
261
|
+
post[:shipping][:address][:state] = shipping[:address][:state] if shipping[:address][:state]
|
262
|
+
|
263
|
+
post[:shipping][:name] = shipping[:name]
|
264
|
+
post[:shipping][:carrier] = shipping[:carrier] if shipping[:carrier]
|
265
|
+
post[:shipping][:phone] = shipping[:phone] if shipping[:phone]
|
266
|
+
post[:shipping][:tracking_number] = shipping[:tracking_number] if shipping[:tracking_number]
|
267
|
+
post
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
@@ -3,13 +3,18 @@ module ActiveMerchant
|
|
3
3
|
class TnsGateway < Gateway
|
4
4
|
include MastercardGateway
|
5
5
|
|
6
|
-
class_attribute :live_na_url, :live_ap_url, :test_na_url, :test_ap_url
|
6
|
+
class_attribute :live_na_url, :live_ap_url, :live_eu_url, :test_na_url, :test_ap_url, :test_eu_url
|
7
7
|
|
8
|
-
|
9
|
-
self.test_na_url = 'https://secure.na.tnspayments.com/api/rest/version/36/'
|
8
|
+
VERSION = '52'
|
10
9
|
|
11
|
-
self.
|
12
|
-
self.
|
10
|
+
self.live_na_url = "https://secure.na.tnspayments.com/api/rest/version/#{VERSION}/"
|
11
|
+
self.test_na_url = "https://secure.na.tnspayments.com/api/rest/version/#{VERSION}/"
|
12
|
+
|
13
|
+
self.live_ap_url = "https://secure.ap.tnspayments.com/api/rest/version/#{VERSION}/"
|
14
|
+
self.test_ap_url = "https://secure.ap.tnspayments.com/api/rest/version/#{VERSION}/"
|
15
|
+
|
16
|
+
self.live_eu_url = "https://secure.eu.tnspayments.com/api/rest/version/#{VERSION}/"
|
17
|
+
self.test_eu_url = "https://secure.eu.tnspayments.com/api/rest/version/#{VERSION}/"
|
13
18
|
|
14
19
|
self.display_name = 'TNS'
|
15
20
|
self.homepage_url = 'http://www.tnsi.com/'
|
@@ -544,7 +544,7 @@ module ActiveMerchant #:nodoc:
|
|
544
544
|
end
|
545
545
|
end
|
546
546
|
doc['v1'].addrLn1 billing_address[:address1] if billing_address[:address1]
|
547
|
-
doc['v1'].addrLn2 billing_address[:address2]
|
547
|
+
doc['v1'].addrLn2 billing_address[:address2] unless billing_address[:address2].blank?
|
548
548
|
doc['v1'].city billing_address[:city] if billing_address[:city]
|
549
549
|
doc['v1'].state billing_address[:state] if billing_address[:state]
|
550
550
|
doc['v1'].zipCode billing_address[:zip] if billing_address[:zip]
|
@@ -559,7 +559,7 @@ module ActiveMerchant #:nodoc:
|
|
559
559
|
doc['v1'].ship do
|
560
560
|
doc['v1'].fullName fullname unless fullname.blank?
|
561
561
|
doc['v1'].addrLn1 shipping_address[:address1] if shipping_address[:address1]
|
562
|
-
doc['v1'].addrLn2 shipping_address[:address2]
|
562
|
+
doc['v1'].addrLn2 shipping_address[:address2] unless shipping_address[:address2].blank?
|
563
563
|
doc['v1'].city shipping_address[:city] if shipping_address[:city]
|
564
564
|
doc['v1'].state shipping_address[:state] if shipping_address[:state]
|
565
565
|
doc['v1'].zipCode shipping_address[:zip] if shipping_address[:zip]
|
@@ -104,6 +104,8 @@ module ActiveMerchant #:nodoc:
|
|
104
104
|
TEST_LOGIN = 'TestMerchant'
|
105
105
|
TEST_PASSWORD = 'password'
|
106
106
|
|
107
|
+
VOIDABLE_ACTIONS = %w(preauth sale postauth credit)
|
108
|
+
|
107
109
|
self.money_format = :cents
|
108
110
|
self.supported_cardtypes = [:visa, :master, :discover, :american_express, :diners_club, :jcb]
|
109
111
|
self.supported_countries = ['US']
|
@@ -157,6 +159,8 @@ module ActiveMerchant #:nodoc:
|
|
157
159
|
add_customer_data(parameters, options)
|
158
160
|
add_payment_source(parameters, creditcard_or_billing_id)
|
159
161
|
add_addresses(parameters, options)
|
162
|
+
add_custom_fields(parameters, options)
|
163
|
+
|
160
164
|
commit('preauth', parameters)
|
161
165
|
end
|
162
166
|
|
@@ -172,6 +176,8 @@ module ActiveMerchant #:nodoc:
|
|
172
176
|
add_customer_data(parameters, options)
|
173
177
|
add_payment_source(parameters, creditcard_or_billing_id)
|
174
178
|
add_addresses(parameters, options)
|
179
|
+
add_custom_fields(parameters, options)
|
180
|
+
|
175
181
|
commit('sale', parameters)
|
176
182
|
end
|
177
183
|
|
@@ -179,11 +185,13 @@ module ActiveMerchant #:nodoc:
|
|
179
185
|
# postauth, we preserve active_merchant's nomenclature of capture() for consistency with the rest of the library. To process
|
180
186
|
# a postauthorization with TC, you need an amount in cents or a money object, and a TC transid.
|
181
187
|
def capture(money, authorization, options = {})
|
188
|
+
transaction_id, _ = split_authorization(authorization)
|
182
189
|
parameters = {
|
183
190
|
:amount => amount(money),
|
184
|
-
:transid =>
|
191
|
+
:transid => transaction_id,
|
185
192
|
}
|
186
193
|
add_aggregator(parameters, options)
|
194
|
+
add_custom_fields(parameters, options)
|
187
195
|
|
188
196
|
commit('postauth', parameters)
|
189
197
|
end
|
@@ -191,11 +199,15 @@ module ActiveMerchant #:nodoc:
|
|
191
199
|
# refund() allows you to return money to a card that was previously billed. You need to supply the amount, in cents or a money object,
|
192
200
|
# that you want to refund, and a TC transid for the transaction that you are refunding.
|
193
201
|
def refund(money, identification, options = {})
|
202
|
+
transaction_id, _ = split_authorization(identification)
|
203
|
+
|
194
204
|
parameters = {
|
195
205
|
:amount => amount(money),
|
196
|
-
:transid =>
|
206
|
+
:transid => transaction_id
|
197
207
|
}
|
208
|
+
|
198
209
|
add_aggregator(parameters, options)
|
210
|
+
add_custom_fields(parameters, options)
|
199
211
|
|
200
212
|
commit('credit', parameters)
|
201
213
|
end
|
@@ -214,18 +226,26 @@ module ActiveMerchant #:nodoc:
|
|
214
226
|
# TrustCommerce to allow for reversal transactions before you can use this
|
215
227
|
# method.
|
216
228
|
#
|
229
|
+
# void() is also used to to cancel a capture (postauth), purchase (sale),
|
230
|
+
# or refund (credit) or a before it is sent for settlement.
|
231
|
+
#
|
217
232
|
# NOTE: AMEX preauth's cannot be reversed. If you want to clear it more
|
218
233
|
# quickly than the automatic expiration (7-10 days), you will have to
|
219
234
|
# capture it and then immediately issue a credit for the same amount
|
220
235
|
# which should clear the customers credit card with 48 hours according to
|
221
236
|
# TC.
|
222
237
|
def void(authorization, options = {})
|
238
|
+
transaction_id, original_action = split_authorization(authorization)
|
239
|
+
action = (VOIDABLE_ACTIONS - ['preauth']).include?(original_action) ? 'void' : 'reversal'
|
240
|
+
|
223
241
|
parameters = {
|
224
|
-
:transid =>
|
242
|
+
:transid => transaction_id,
|
225
243
|
}
|
244
|
+
|
226
245
|
add_aggregator(parameters, options)
|
246
|
+
add_custom_fields(parameters, options)
|
227
247
|
|
228
|
-
commit(
|
248
|
+
commit(action, parameters)
|
229
249
|
end
|
230
250
|
|
231
251
|
# recurring() a TrustCommerce account that is activated for Citadel, TrustCommerce's
|
@@ -284,6 +304,8 @@ module ActiveMerchant #:nodoc:
|
|
284
304
|
|
285
305
|
add_creditcard(parameters, creditcard)
|
286
306
|
add_addresses(parameters, options)
|
307
|
+
add_custom_fields(parameters, options)
|
308
|
+
|
287
309
|
commit('store', parameters)
|
288
310
|
end
|
289
311
|
|
@@ -294,6 +316,8 @@ module ActiveMerchant #:nodoc:
|
|
294
316
|
:billingid => identification,
|
295
317
|
}
|
296
318
|
|
319
|
+
add_custom_fields(parameters, options)
|
320
|
+
|
297
321
|
commit('unstore', parameters)
|
298
322
|
end
|
299
323
|
|
@@ -311,6 +335,12 @@ module ActiveMerchant #:nodoc:
|
|
311
335
|
|
312
336
|
private
|
313
337
|
|
338
|
+
def add_custom_fields(params, options)
|
339
|
+
options[:custom_fields]&.each do |key, value|
|
340
|
+
params[key.to_sym] = value
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
314
344
|
def add_aggregator(params, options)
|
315
345
|
if @options[:aggregator_id] || application_id != Gateway.application_id
|
316
346
|
params[:aggregators] = 1
|
@@ -409,14 +439,14 @@ module ActiveMerchant #:nodoc:
|
|
409
439
|
TCLink.send(parameters)
|
410
440
|
else
|
411
441
|
parse(ssl_post(self.live_url, post_data(parameters)))
|
412
|
-
|
442
|
+
end
|
413
443
|
|
414
444
|
# to be considered successful, transaction status must be either "approved" or "accepted"
|
415
445
|
success = SUCCESS_TYPES.include?(data['status'])
|
416
446
|
message = message_from(data)
|
417
447
|
Response.new(success, message, data,
|
418
448
|
:test => test?,
|
419
|
-
:authorization => data
|
449
|
+
:authorization => authorization_from(action, data),
|
420
450
|
:cvv_result => data['cvv'],
|
421
451
|
:avs_result => { :code => data['avs'] }
|
422
452
|
)
|
@@ -446,6 +476,15 @@ module ActiveMerchant #:nodoc:
|
|
446
476
|
end
|
447
477
|
end
|
448
478
|
|
479
|
+
def authorization_from(action, data)
|
480
|
+
authorization = data['transid']
|
481
|
+
authorization = "#{authorization}|#{action}" if authorization && VOIDABLE_ACTIONS.include?(action)
|
482
|
+
authorization
|
483
|
+
end
|
484
|
+
|
485
|
+
def split_authorization(authorization)
|
486
|
+
authorization&.split('|')
|
487
|
+
end
|
449
488
|
end
|
450
489
|
end
|
451
490
|
end
|