activemerchant 1.56.0 → 1.66.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +331 -0
- data/README.md +9 -9
- data/lib/active_merchant/billing/check.rb +3 -0
- data/lib/active_merchant/billing/credit_card.rb +8 -3
- data/lib/active_merchant/billing/credit_card_methods.rb +41 -1
- data/lib/active_merchant/billing/gateway.rb +14 -6
- data/lib/active_merchant/billing/gateways/adyen.rb +228 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +157 -44
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +7 -4
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +283 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +68 -2
- data/lib/active_merchant/billing/gateways/blue_pay.rb +2 -2
- data/lib/active_merchant/billing/gateways/blue_snap.rb +348 -0
- data/lib/active_merchant/billing/gateways/bpoint.rb +1 -1
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +58 -20
- data/lib/active_merchant/billing/gateways/bridge_pay.rb +37 -8
- data/lib/active_merchant/billing/gateways/card_stream.rb +161 -40
- data/lib/active_merchant/billing/gateways/cashnet.rb +1 -0
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +5 -2
- data/lib/active_merchant/billing/gateways/citrus_pay.rb +24 -0
- data/lib/active_merchant/billing/gateways/clearhaus.rb +24 -40
- data/lib/active_merchant/billing/gateways/conekta.rb +6 -1
- data/lib/active_merchant/billing/gateways/creditcall.rb +1 -1
- data/lib/active_merchant/billing/gateways/credorax.rb +310 -0
- data/lib/active_merchant/billing/gateways/culqi.rb +279 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +80 -64
- data/lib/active_merchant/billing/gateways/data_cash.rb +10 -304
- data/lib/active_merchant/billing/gateways/digitzs.rb +292 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +40 -26
- data/lib/active_merchant/billing/gateways/element.rb +356 -0
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +16 -2
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -1
- data/lib/active_merchant/billing/gateways/forte.rb +10 -2
- data/lib/active_merchant/billing/gateways/global_collect.rb +311 -0
- data/lib/active_merchant/billing/gateways/global_transport.rb +1 -0
- data/lib/active_merchant/billing/gateways/iats_payments.rb +13 -0
- data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +15 -0
- data/lib/active_merchant/billing/gateways/iveri.rb +251 -0
- data/lib/active_merchant/billing/gateways/jetpay.rb +33 -19
- data/lib/active_merchant/billing/gateways/kushki.rb +217 -0
- data/lib/active_merchant/billing/gateways/latitude19.rb +416 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +2 -0
- data/lib/active_merchant/billing/gateways/litle.rb +29 -13
- data/lib/active_merchant/billing/gateways/mastercard.rb +268 -0
- data/lib/active_merchant/billing/gateways/maxipago.rb +145 -122
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +15 -1
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +10 -7
- data/lib/active_merchant/billing/gateways/mercury.rb +13 -5
- data/lib/active_merchant/billing/gateways/metrics_global.rb +1 -1
- data/lib/active_merchant/billing/gateways/migs.rb +23 -1
- data/lib/active_merchant/billing/gateways/monei.rb +1 -1
- data/lib/active_merchant/billing/gateways/moneris.rb +21 -1
- data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -0
- data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +165 -0
- data/lib/active_merchant/billing/gateways/netbanx.rb +245 -0
- data/lib/active_merchant/billing/gateways/nmi.rb +30 -9
- data/lib/active_merchant/billing/gateways/omise.rb +9 -5
- data/lib/active_merchant/billing/gateways/openpay.rb +10 -1
- data/lib/active_merchant/billing/gateways/opp.rb +362 -0
- data/lib/active_merchant/billing/gateways/orbital.rb +28 -7
- data/lib/active_merchant/billing/gateways/pagarme.rb +248 -0
- data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +190 -0
- data/lib/active_merchant/billing/gateways/payeezy.rb +61 -12
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
- data/lib/active_merchant/billing/gateways/payflow.rb +6 -0
- data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
- data/lib/active_merchant/billing/gateways/paymill.rb +29 -11
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
- data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -6
- data/lib/active_merchant/billing/gateways/payu_in.rb +3 -2
- data/lib/active_merchant/billing/gateways/payu_latam.rb +402 -0
- data/lib/active_merchant/billing/gateways/pin.rb +6 -3
- data/lib/active_merchant/billing/gateways/pro_pay.rb +326 -0
- data/lib/active_merchant/billing/gateways/psl_card.rb +3 -3
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +1 -1
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +0 -2
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +1 -1
- data/lib/active_merchant/billing/gateways/quickpay.rb +3 -3
- data/lib/active_merchant/billing/gateways/qvalent.rb +44 -1
- data/lib/active_merchant/billing/gateways/redsys.rb +3 -0
- data/lib/active_merchant/billing/gateways/s5.rb +8 -5
- data/lib/active_merchant/billing/gateways/safe_charge.rb +220 -0
- data/lib/active_merchant/billing/gateways/sage.rb +397 -128
- data/lib/active_merchant/billing/gateways/sage_pay.rb +45 -20
- data/lib/active_merchant/billing/gateways/secure_net.rb +0 -5
- data/lib/active_merchant/billing/gateways/secure_pay.rb +1 -1
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -0
- data/lib/active_merchant/billing/gateways/securion_pay.rb +46 -17
- data/lib/active_merchant/billing/gateways/stripe.rb +125 -29
- data/lib/active_merchant/billing/gateways/telr.rb +275 -0
- data/lib/active_merchant/billing/gateways/tns.rb +13 -222
- data/lib/active_merchant/billing/gateways/trans_first.rb +40 -16
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +606 -0
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +114 -9
- data/lib/active_merchant/billing/gateways/vanco.rb +14 -10
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +209 -0
- data/lib/active_merchant/billing/gateways/wepay.rb +73 -38
- data/lib/active_merchant/billing/gateways/wirecard.rb +1 -0
- data/lib/active_merchant/billing/gateways/world_net.rb +344 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +48 -16
- data/lib/active_merchant/billing/network_tokenization_credit_card.rb +15 -0
- data/lib/active_merchant/country.rb +6 -4
- data/lib/active_merchant/posts_data.rb +1 -1
- data/lib/active_merchant/version.rb +1 -1
- metadata +32 -13
- data/lib/active_merchant/billing/gateways/app55.rb +0 -176
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +0 -314
- data/lib/active_merchant/billing/gateways/certo_direct.rb +0 -278
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +0 -89
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +0 -115
- data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +0 -149
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +0 -97
@@ -20,7 +20,8 @@ module ActiveMerchant #:nodoc:
|
|
20
20
|
:void => 'VOID',
|
21
21
|
:abort => 'ABORT',
|
22
22
|
:store => 'TOKEN',
|
23
|
-
:unstore => 'REMOVETOKEN'
|
23
|
+
:unstore => 'REMOVETOKEN',
|
24
|
+
:repeat => 'REPEAT'
|
24
25
|
}
|
25
26
|
|
26
27
|
CREDIT_CARDS = {
|
@@ -36,8 +37,6 @@ module ActiveMerchant #:nodoc:
|
|
36
37
|
:jcb => "JCB"
|
37
38
|
}
|
38
39
|
|
39
|
-
ELECTRON = /^(424519|42496[23]|450875|48440[6-8]|4844[1-5][1-5]|4917[3-5][0-9]|491880)\d{10}(\d{3})?$/
|
40
|
-
|
41
40
|
AVS_CVV_CODE = {
|
42
41
|
"NOTPROVIDED" => nil,
|
43
42
|
"NOTCHECKED" => 'X',
|
@@ -45,6 +44,26 @@ module ActiveMerchant #:nodoc:
|
|
45
44
|
"NOTMATCHED" => 'N'
|
46
45
|
}
|
47
46
|
|
47
|
+
OPTIONAL_REQUEST_FIELDS = {
|
48
|
+
paypal_callback_url: :PayPalCallbackURL,
|
49
|
+
basket: :Basket,
|
50
|
+
gift_aid_payment: :GiftAidPayment ,
|
51
|
+
apply_avscv2: :ApplyAVSCV2 ,
|
52
|
+
apply_3d_secure: :Apply3DSecure,
|
53
|
+
account_type: :AccountType,
|
54
|
+
billing_agreement: :BillingAgreement,
|
55
|
+
basket_xml: :BasketXML,
|
56
|
+
customer_xml: :CustomerXML,
|
57
|
+
surcharge_xml: :SurchargeXML,
|
58
|
+
vendor_data: :VendorData,
|
59
|
+
language: :Language,
|
60
|
+
website: :Website,
|
61
|
+
recipient_account_number: :FIRecipientAcctNumber ,
|
62
|
+
recipient_surname: :FIRecipientSurname ,
|
63
|
+
recipient_postcode: :FIRecipientPostcode ,
|
64
|
+
recipient_dob: :FIRecipientDoB
|
65
|
+
}
|
66
|
+
|
48
67
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :switch, :solo, :maestro, :diners_club]
|
49
68
|
self.supported_countries = ['GB', 'IE']
|
50
69
|
self.default_currency = 'GBP'
|
@@ -69,7 +88,7 @@ module ActiveMerchant #:nodoc:
|
|
69
88
|
add_customer_data(post, options)
|
70
89
|
add_optional_data(post, options)
|
71
90
|
|
72
|
-
commit(:purchase, post)
|
91
|
+
commit((options[:repeat] ? :repeat : :purchase), post)
|
73
92
|
end
|
74
93
|
|
75
94
|
def authorize(money, payment_method, options = {})
|
@@ -112,7 +131,7 @@ module ActiveMerchant #:nodoc:
|
|
112
131
|
|
113
132
|
post = {}
|
114
133
|
|
115
|
-
|
134
|
+
add_related_reference(post, identification)
|
116
135
|
add_amount(post, money, options)
|
117
136
|
add_invoice(post, options)
|
118
137
|
|
@@ -157,6 +176,17 @@ module ActiveMerchant #:nodoc:
|
|
157
176
|
end
|
158
177
|
|
159
178
|
private
|
179
|
+
def truncate(value, max_size)
|
180
|
+
return nil unless value
|
181
|
+
return value.to_s if CGI.escape(value.to_s).length <= max_size
|
182
|
+
|
183
|
+
if value.size > max_size
|
184
|
+
truncate(super(value, max_size), max_size)
|
185
|
+
else
|
186
|
+
truncate(value.to_s.chop, max_size)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
160
190
|
def add_reference(post, identification)
|
161
191
|
order_id, transaction_id, authorization, security_key = identification.split(';')
|
162
192
|
|
@@ -166,7 +196,7 @@ module ActiveMerchant #:nodoc:
|
|
166
196
|
add_pair(post, :SecurityKey, security_key)
|
167
197
|
end
|
168
198
|
|
169
|
-
def
|
199
|
+
def add_related_reference(post, identification)
|
170
200
|
order_id, transaction_id, authorization, security_key = identification.split(';')
|
171
201
|
|
172
202
|
add_pair(post, :RelatedVendorTxCode, order_id)
|
@@ -197,14 +227,11 @@ module ActiveMerchant #:nodoc:
|
|
197
227
|
end
|
198
228
|
|
199
229
|
def add_optional_data(post, options)
|
200
|
-
add_pair(post, :GiftAidPayment, options[:gift_aid_payment]) unless options[:gift_aid_payment].blank?
|
201
|
-
add_pair(post, :ApplyAVSCV2, options[:apply_avscv2]) unless options[:apply_avscv2].blank?
|
202
|
-
add_pair(post, :Apply3DSecure, options[:apply_3d_secure]) unless options[:apply_3d_secure].blank?
|
203
230
|
add_pair(post, :CreateToken, 1) unless options[:store].blank?
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
231
|
+
|
232
|
+
OPTIONAL_REQUEST_FIELDS.each do |gateway_option, sagepay_field|
|
233
|
+
add_pair(post, sagepay_field, options[gateway_option])
|
234
|
+
end
|
208
235
|
end
|
209
236
|
|
210
237
|
def add_address(post, options)
|
@@ -241,7 +268,9 @@ module ActiveMerchant #:nodoc:
|
|
241
268
|
end
|
242
269
|
|
243
270
|
def add_payment_method(post, payment_method, options)
|
244
|
-
if
|
271
|
+
if options[:repeat]
|
272
|
+
add_related_reference(post, payment_method)
|
273
|
+
elsif payment_method.respond_to?(:number)
|
245
274
|
add_credit_card(post, payment_method)
|
246
275
|
else
|
247
276
|
add_token_details(post, payment_method, options)
|
@@ -266,6 +295,7 @@ module ActiveMerchant #:nodoc:
|
|
266
295
|
def add_token_details(post, token, options)
|
267
296
|
add_token(post, token)
|
268
297
|
add_pair(post, :StoreToken, options[:customer])
|
298
|
+
add_pair(post, :CV2, options[:verification_value])
|
269
299
|
end
|
270
300
|
|
271
301
|
def add_token(post, token)
|
@@ -292,8 +322,7 @@ module ActiveMerchant #:nodoc:
|
|
292
322
|
|
293
323
|
card_type = card_brand(credit_card).to_sym
|
294
324
|
|
295
|
-
|
296
|
-
if card_type == :visa && credit_card.number =~ ELECTRON
|
325
|
+
if card_type == :visa && credit_card.electron?
|
297
326
|
CREDIT_CARDS[:electron]
|
298
327
|
else
|
299
328
|
CREDIT_CARDS[card_type]
|
@@ -393,10 +422,6 @@ module ActiveMerchant #:nodoc:
|
|
393
422
|
post[key] = value if !value.blank? || options[:required]
|
394
423
|
end
|
395
424
|
|
396
|
-
def localized_amount(money, currency)
|
397
|
-
amount = amount(money)
|
398
|
-
CURRENCIES_WITHOUT_FRACTIONS.include?(currency.to_s) ? amount.split('.').first : amount
|
399
|
-
end
|
400
425
|
end
|
401
426
|
|
402
427
|
end
|
@@ -219,11 +219,6 @@ module ActiveMerchant #:nodoc:
|
|
219
219
|
end
|
220
220
|
|
221
221
|
def message_from(response)
|
222
|
-
if response[:response_code].to_i == DECLINED
|
223
|
-
return CVVResult.messages[ response[:card_code_response_code] ] if CARD_CODE_ERRORS.include?(response[:card_code_response_code])
|
224
|
-
return AVSResult.messages[ response[:avs_result_code] ] if AVS_ERRORS.include?(response[:avs_result_code])
|
225
|
-
end
|
226
|
-
|
227
222
|
return response[:response_reason_text].nil? ? '' : response[:response_reason_text][0..-1]
|
228
223
|
end
|
229
224
|
|
@@ -100,7 +100,7 @@ module ActiveMerchant #:nodoc:
|
|
100
100
|
post[:delim_data] = "TRUE"
|
101
101
|
post[:delim_char] = ","
|
102
102
|
post[:encap_char] = "$"
|
103
|
-
post[:solution_ID] = application_id if application_id
|
103
|
+
post[:solution_ID] = application_id if application_id
|
104
104
|
|
105
105
|
request = post.merge(parameters).collect { |key, value| "x_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
106
106
|
request
|
@@ -103,6 +103,18 @@ module ActiveMerchant #:nodoc:
|
|
103
103
|
commit_periodic(build_periodic_item(:remove_triggered, options[:amount], nil, options))
|
104
104
|
end
|
105
105
|
|
106
|
+
def supports_scrubbing?
|
107
|
+
true
|
108
|
+
end
|
109
|
+
|
110
|
+
def scrub(transcript)
|
111
|
+
transcript.
|
112
|
+
gsub(%r((<merchantID>).+(</merchantID>)), '\1[FILTERED]\2').
|
113
|
+
gsub(%r((<password>).+(</password>)), '\1[FILTERED]\2').
|
114
|
+
gsub(%r((<cardNumber>).+(</cardNumber>)), '\1[FILTERED]\2').
|
115
|
+
gsub(%r((<cvv>).+(</cvv>)), '\1[FILTERED]\2')
|
116
|
+
end
|
117
|
+
|
106
118
|
private
|
107
119
|
|
108
120
|
def build_purchase_request(money, credit_card, options)
|
@@ -4,18 +4,10 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
self.test_url = 'https://api.securionpay.com/'
|
5
5
|
self.live_url = 'https://api.securionpay.com/'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
"GH", "GI", "GR", "GL", "GD", "GP", "GU", "GT", "GG", "GN", "GW", "GY", "HT", "HM", "VA", "HN", "HK", "HU", "IS", "IN", "ID",
|
12
|
-
"IR", "IQ", "IE", "IM", "IL", "IT", "JM", "JP", "JE", "JO", "KZ", "KE", "KI", "KP", "KR", "KV", "KW", "KG", "LA", "LV", "LB",
|
13
|
-
"LS", "LR", "LY", "LI", "LT", "LU", "MO", "MK", "MG", "MW", "MY", "MV", "ML", "MT", "MH", "MQ", "MR", "MU", "YT", "MX", "FM",
|
14
|
-
"MD", "MC", "MN", "ME", "MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "AN", "NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MP",
|
15
|
-
"NO", "OM", "PK", "PW", "PS", "PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA", "RE", "RO", "RU", "RW", "BL", "SH",
|
16
|
-
"KN", "LC", "MF", "PM", "VC", "WS", "SM", "ST", "SA", "SN", "RS", "SC", "SL", "SG", "SK", "SI", "SB", "SO", "ZA", "GS", "ES",
|
17
|
-
"LK", "SD", "SR", "SJ", "SZ", "SE", "CH", "SY", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM", "TC",
|
18
|
-
"TV", "UG", "UA", "AE", "GB", "US", "UM", "UY", "UZ", "VU", "VE", "VN", "VG", "VI", "WF", "EH", "YE", "ZM", "ZW", "AX"]
|
7
|
+
|
8
|
+
self.supported_countries = %w(AL AD AT BY BE BG HR CY CZ RE DK EE IS FI FR DE GI GR HU IS IE IT IL LV LI LT LU
|
9
|
+
MK MT MD MC NL NO PL PT RO RU MA RS SK SI ES SE CH UA GB KI CI ME)
|
10
|
+
|
19
11
|
self.default_currency = 'USD'
|
20
12
|
self.money_format = :cents
|
21
13
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
|
@@ -79,6 +71,29 @@ module ActiveMerchant #:nodoc:
|
|
79
71
|
end
|
80
72
|
end
|
81
73
|
|
74
|
+
def store(credit_card, options = {})
|
75
|
+
if options[:customer_id].blank?
|
76
|
+
MultiResponse.run() do |r|
|
77
|
+
#create charge object
|
78
|
+
r.process { authorize(100, credit_card, options) }
|
79
|
+
#create customer and save card
|
80
|
+
r.process { create_customer_add_card(r.authorization, options) }
|
81
|
+
#void the charge
|
82
|
+
r.process(:ignore_result) { void(r.params["metadata"]["chargeId"], options) }
|
83
|
+
end
|
84
|
+
else
|
85
|
+
verify(credit_card, options)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def customer(options = {})
|
90
|
+
if options[:customer_id].blank?
|
91
|
+
return nil
|
92
|
+
else
|
93
|
+
commit("customers/#{CGI.escape(options[:customer_id])}", nil, options, :get)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
82
97
|
def supports_scrubbing?
|
83
98
|
true
|
84
99
|
end
|
@@ -92,8 +107,18 @@ module ActiveMerchant #:nodoc:
|
|
92
107
|
|
93
108
|
private
|
94
109
|
|
110
|
+
def create_customer_add_card(authorization, options)
|
111
|
+
post = {}
|
112
|
+
post[:email] = options[:email]
|
113
|
+
post[:description] = options[:description]
|
114
|
+
post[:card] = authorization
|
115
|
+
post[:metadata] = {}
|
116
|
+
post[:metadata][:chargeId] = authorization
|
117
|
+
commit('customers', post, options)
|
118
|
+
end
|
119
|
+
|
95
120
|
def add_customer(post, payment, options)
|
96
|
-
post[:
|
121
|
+
post[:customerId] = options[:customer_id] if options[:customer_id]
|
97
122
|
end
|
98
123
|
|
99
124
|
def add_customer_data(post, options)
|
@@ -156,8 +181,8 @@ module ActiveMerchant #:nodoc:
|
|
156
181
|
JSON.parse(body)
|
157
182
|
end
|
158
183
|
|
159
|
-
def commit(url, parameters = nil, options = {})
|
160
|
-
response = api_request(url, parameters, options)
|
184
|
+
def commit(url, parameters = nil, options = {}, method = nil)
|
185
|
+
response = api_request(url, parameters, options, method)
|
161
186
|
success = !response.key?("error")
|
162
187
|
|
163
188
|
Response.new(success,
|
@@ -206,10 +231,14 @@ module ActiveMerchant #:nodoc:
|
|
206
231
|
end.compact.join("&")
|
207
232
|
end
|
208
233
|
|
209
|
-
def api_request(endpoint, parameters = nil, options = {})
|
234
|
+
def api_request(endpoint, parameters = nil, options = {}, method = nil)
|
210
235
|
raw_response = response = nil
|
211
236
|
begin
|
212
|
-
|
237
|
+
if method.blank?
|
238
|
+
raw_response = ssl_post(self.live_url + endpoint, post_data(parameters), headers(options))
|
239
|
+
else
|
240
|
+
raw_response = ssl_request(method, self.live_url + endpoint, post_data(parameters), headers(options))
|
241
|
+
end
|
213
242
|
response = parse(raw_response)
|
214
243
|
rescue ResponseError => e
|
215
244
|
raw_response = e.response.body
|
@@ -21,12 +21,11 @@ module ActiveMerchant #:nodoc:
|
|
21
21
|
'unchecked' => 'P'
|
22
22
|
}
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
self.supported_countries = %w(AT AU BE CA CH DE DK ES FI FR GB IE IT LU NL NO SE US)
|
24
|
+
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)
|
27
25
|
self.default_currency = 'USD'
|
28
26
|
self.money_format = :cents
|
29
27
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
|
28
|
+
self.currencies_without_fractions = %w(BIF CLP DJF GNF JPY KMF KRW MGA PYG RWF VND VUV XAF XOF XPF)
|
30
29
|
|
31
30
|
self.homepage_url = 'https://stripe.com/'
|
32
31
|
self.display_name = 'Stripe'
|
@@ -43,14 +42,35 @@ module ActiveMerchant #:nodoc:
|
|
43
42
|
'card_declined' => STANDARD_ERROR_CODE[:card_declined],
|
44
43
|
'call_issuer' => STANDARD_ERROR_CODE[:call_issuer],
|
45
44
|
'processing_error' => STANDARD_ERROR_CODE[:processing_error],
|
46
|
-
'incorrect_pin' => STANDARD_ERROR_CODE[:incorrect_pin]
|
45
|
+
'incorrect_pin' => STANDARD_ERROR_CODE[:incorrect_pin],
|
46
|
+
'test_mode_live_card' => STANDARD_ERROR_CODE[:test_mode_live_card]
|
47
|
+
}
|
48
|
+
|
49
|
+
BANK_ACCOUNT_HOLDER_TYPE_MAPPING = {
|
50
|
+
"personal" => "individual",
|
51
|
+
"business" => "company",
|
52
|
+
}
|
53
|
+
|
54
|
+
MINIMUM_AUTHORIZE_AMOUNTS = {
|
55
|
+
"USD" => 100,
|
56
|
+
"CAD" => 100,
|
57
|
+
"GBP" => 60,
|
58
|
+
"EUR" => 100,
|
59
|
+
"DKK" => 500,
|
60
|
+
"NOK" => 600,
|
61
|
+
"SEK" => 600,
|
62
|
+
"CHF" => 100,
|
63
|
+
"AUD" => 100,
|
64
|
+
"JPY" => 100,
|
65
|
+
"MXN" => 2000,
|
66
|
+
"SGD" => 100,
|
67
|
+
"HKD" => 800
|
47
68
|
}
|
48
69
|
|
49
70
|
def initialize(options = {})
|
50
71
|
requires!(options, :login)
|
51
72
|
@api_key = options[:login]
|
52
73
|
@fee_refund_api_key = options[:fee_refund_login]
|
53
|
-
|
54
74
|
super
|
55
75
|
end
|
56
76
|
|
@@ -80,6 +100,11 @@ module ActiveMerchant #:nodoc:
|
|
80
100
|
#
|
81
101
|
# purchase(money, nil, { :customer => id, ... })
|
82
102
|
def purchase(money, payment, options = {})
|
103
|
+
if ach?(payment)
|
104
|
+
direct_bank_error = "Direct bank account transactions are not supported. Bank accounts must be stored and verified before use."
|
105
|
+
return Response.new(false, direct_bank_error)
|
106
|
+
end
|
107
|
+
|
83
108
|
MultiResponse.run do |r|
|
84
109
|
if payment.is_a?(ApplePayPaymentToken)
|
85
110
|
r.process { tokenize_apple_pay_token(payment) }
|
@@ -107,6 +132,7 @@ module ActiveMerchant #:nodoc:
|
|
107
132
|
|
108
133
|
def void(identification, options = {})
|
109
134
|
post = {}
|
135
|
+
post[:metadata] = options[:metadata] if options[:metadata]
|
110
136
|
post[:expand] = [:charge]
|
111
137
|
commit(:post, "charges/#{CGI.escape(identification)}/refunds", post, options)
|
112
138
|
end
|
@@ -131,7 +157,8 @@ module ActiveMerchant #:nodoc:
|
|
131
157
|
|
132
158
|
def verify(payment, options = {})
|
133
159
|
MultiResponse.run(:use_first_response) do |r|
|
134
|
-
r.process { authorize(
|
160
|
+
r.process { authorize(auth_minimum_amount(options), payment, options) }
|
161
|
+
options[:idempotency_key] = nil
|
135
162
|
r.process(:ignore_result) { void(r.authorization, options) }
|
136
163
|
end
|
137
164
|
end
|
@@ -155,24 +182,33 @@ module ActiveMerchant #:nodoc:
|
|
155
182
|
|
156
183
|
# Note: creating a new credit card will not change the customer's existing default credit card (use :set_default => true)
|
157
184
|
def store(payment, options = {})
|
158
|
-
|
185
|
+
params = {}
|
159
186
|
post = {}
|
160
187
|
|
161
188
|
if payment.is_a?(ApplePayPaymentToken)
|
162
189
|
token_exchange_response = tokenize_apple_pay_token(payment)
|
163
|
-
|
190
|
+
params = { card: token_exchange_response.params["token"]["id"] } if token_exchange_response.success?
|
191
|
+
elsif payment.is_a?(StripePaymentToken)
|
192
|
+
add_payment_token(params, payment, options)
|
193
|
+
elsif payment.is_a?(Check)
|
194
|
+
bank_token_response = tokenize_bank_account(payment)
|
195
|
+
return bank_token_response unless bank_token_response.success?
|
196
|
+
params = { source: bank_token_response.params["token"]["id"] }
|
164
197
|
else
|
165
|
-
add_creditcard(
|
198
|
+
add_creditcard(params, payment, options)
|
166
199
|
end
|
167
200
|
|
168
201
|
post[:validate] = options[:validate] unless options[:validate].nil?
|
169
202
|
post[:description] = options[:description] if options[:description]
|
170
203
|
post[:email] = options[:email] if options[:email]
|
171
204
|
|
172
|
-
if options[:
|
205
|
+
if options[:account]
|
206
|
+
add_external_account(post, params, payment)
|
207
|
+
commit(:post, "accounts/#{CGI.escape(options[:account])}/external_accounts", post, options)
|
208
|
+
elsif options[:customer]
|
173
209
|
MultiResponse.run(:first) do |r|
|
174
210
|
# The /cards endpoint does not update other customer parameters.
|
175
|
-
r.process { commit(:post, "customers/#{CGI.escape(options[:customer])}/cards",
|
211
|
+
r.process { commit(:post, "customers/#{CGI.escape(options[:customer])}/cards", params, options) }
|
176
212
|
|
177
213
|
if options[:set_default] and r.success? and !r.params['id'].blank?
|
178
214
|
post[:default_card] = r.params['id']
|
@@ -183,7 +219,7 @@ module ActiveMerchant #:nodoc:
|
|
183
219
|
end
|
184
220
|
end
|
185
221
|
else
|
186
|
-
commit(:post, 'customers', post.merge(
|
222
|
+
commit(:post, 'customers', post.merge(params), options)
|
187
223
|
end
|
188
224
|
end
|
189
225
|
|
@@ -218,6 +254,16 @@ module ActiveMerchant #:nodoc:
|
|
218
254
|
end
|
219
255
|
end
|
220
256
|
|
257
|
+
def verify_credentials
|
258
|
+
begin
|
259
|
+
ssl_get(live_url + "charges/nonexistent", headers)
|
260
|
+
rescue ResponseError => e
|
261
|
+
return false if e.response.code.to_i == 401
|
262
|
+
end
|
263
|
+
|
264
|
+
true
|
265
|
+
end
|
266
|
+
|
221
267
|
def supports_scrubbing?
|
222
268
|
true
|
223
269
|
end
|
@@ -225,13 +271,15 @@ module ActiveMerchant #:nodoc:
|
|
225
271
|
def scrub(transcript)
|
226
272
|
transcript.
|
227
273
|
gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
|
228
|
-
gsub(%r((card\[number\]=)\d+), '\1[FILTERED]').
|
229
|
-
gsub(%r((card\[cvc\]=)\d+), '\1[FILTERED]').
|
230
274
|
gsub(%r((&?three_d_secure\[cryptogram\]=)[\w=]*(&?)), '\1[FILTERED]\2').
|
231
|
-
gsub(%r((card\[
|
275
|
+
gsub(%r((card\[cryptogram\]=)[^&]+(&?)), '\1[FILTERED]\2').
|
276
|
+
gsub(%r((card\[cvc\]=)\d+), '\1[FILTERED]').
|
277
|
+
gsub(%r((card\[emv_approval_data\]=)[^&]+(&?)), '\1[FILTERED]\2').
|
278
|
+
gsub(%r((card\[emv_auth_data\]=)[^&]+(&?)), '\1[FILTERED]\2').
|
232
279
|
gsub(%r((card\[encrypted_pin\]=)[^&]+(&?)), '\1[FILTERED]\2').
|
233
280
|
gsub(%r((card\[encrypted_pin_key_id\]=)[\w=]+(&?)), '\1[FILTERED]\2').
|
234
|
-
gsub(%r((card\[
|
281
|
+
gsub(%r((card\[number\]=)\d+), '\1[FILTERED]').
|
282
|
+
gsub(%r((card\[swipe_data\]=)[^&]+(&?)), '\1[FILTERED]\2')
|
235
283
|
end
|
236
284
|
|
237
285
|
def supports_network_tokenization?
|
@@ -258,7 +306,6 @@ module ActiveMerchant #:nodoc:
|
|
258
306
|
unless emv_payment?(payment)
|
259
307
|
add_amount(post, money, options, true)
|
260
308
|
add_customer_data(post, options)
|
261
|
-
add_metadata(post, options)
|
262
309
|
post[:description] = options[:description]
|
263
310
|
post[:statement_descriptor] = options[:statement_description]
|
264
311
|
post[:receipt_email] = options[:receipt_email] if options[:receipt_email]
|
@@ -266,6 +313,7 @@ module ActiveMerchant #:nodoc:
|
|
266
313
|
add_flags(post, options)
|
267
314
|
end
|
268
315
|
|
316
|
+
add_metadata(post, options)
|
269
317
|
add_application_fee(post, options)
|
270
318
|
add_destination(post, options)
|
271
319
|
post
|
@@ -290,6 +338,13 @@ module ActiveMerchant #:nodoc:
|
|
290
338
|
post[:expand].concat(Array.wrap(options[:expand]).map(&:to_sym)).uniq!
|
291
339
|
end
|
292
340
|
|
341
|
+
def add_external_account(post, card_params, payment)
|
342
|
+
external_account = {}
|
343
|
+
external_account[:object] ="card"
|
344
|
+
external_account[:currency] = (options[:currency] || currency(payment)).downcase
|
345
|
+
post[:external_account] = external_account.merge(card_params[:card])
|
346
|
+
end
|
347
|
+
|
293
348
|
def add_customer_data(post, options)
|
294
349
|
metadata_options = [:description, :ip, :user_agent, :referrer]
|
295
350
|
post.update(options.slice(*metadata_options))
|
@@ -314,7 +369,8 @@ module ActiveMerchant #:nodoc:
|
|
314
369
|
card = {}
|
315
370
|
if emv_payment?(creditcard)
|
316
371
|
add_emv_creditcard(post, creditcard.icc_data)
|
317
|
-
post[:card][:read_method] = "contactless" if creditcard.
|
372
|
+
post[:card][:read_method] = "contactless" if creditcard.contactless_emv
|
373
|
+
post[:card][:read_method] = "contactless_magstripe_mode" if creditcard.contactless_magstripe
|
318
374
|
if creditcard.encrypted_pin_cryptogram.present? && creditcard.encrypted_pin_ksn.present?
|
319
375
|
post[:card][:encrypted_pin] = creditcard.encrypted_pin_cryptogram
|
320
376
|
post[:card][:encrypted_pin_key_id] = creditcard.encrypted_pin_ksn
|
@@ -323,7 +379,8 @@ module ActiveMerchant #:nodoc:
|
|
323
379
|
if creditcard.respond_to?(:track_data) && creditcard.track_data.present?
|
324
380
|
card[:swipe_data] = creditcard.track_data
|
325
381
|
card[:fallback_reason] = creditcard.fallback_reason if creditcard.fallback_reason
|
326
|
-
card[:read_method] = "contactless" if creditcard.
|
382
|
+
card[:read_method] = "contactless" if creditcard.contactless_emv
|
383
|
+
card[:read_method] = "contactless_magstripe_mode" if creditcard.contactless_magstripe
|
327
384
|
else
|
328
385
|
card[:number] = creditcard.number
|
329
386
|
card[:exp_month] = creditcard.month
|
@@ -331,14 +388,13 @@ module ActiveMerchant #:nodoc:
|
|
331
388
|
card[:cvc] = creditcard.verification_value if creditcard.verification_value?
|
332
389
|
card[:name] = creditcard.name if creditcard.name
|
333
390
|
end
|
334
|
-
post[:card] = card
|
335
391
|
|
336
392
|
if creditcard.is_a?(NetworkTokenizationCreditCard)
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
}
|
393
|
+
card[:cryptogram] = creditcard.payment_cryptogram
|
394
|
+
card[:eci] = creditcard.eci.rjust(2, '0') if creditcard.eci =~ /^[0-9]+$/
|
395
|
+
card[:tokenization_method] = creditcard.source.to_s
|
341
396
|
end
|
397
|
+
post[:card] = card
|
342
398
|
|
343
399
|
add_address(post, options)
|
344
400
|
elsif creditcard.kind_of?(String)
|
@@ -419,13 +475,19 @@ module ActiveMerchant #:nodoc:
|
|
419
475
|
"Authorization" => "Basic " + Base64.encode64(key.to_s + ":").strip,
|
420
476
|
"User-Agent" => "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
|
421
477
|
"Stripe-Version" => api_version(options),
|
422
|
-
"X-Stripe-Client-User-Agent" =>
|
478
|
+
"X-Stripe-Client-User-Agent" => stripe_client_user_agent(options),
|
423
479
|
"X-Stripe-Client-User-Metadata" => {:ip => options[:ip]}.to_json
|
424
480
|
}
|
425
481
|
headers.merge!("Idempotency-Key" => idempotency_key) if idempotency_key
|
482
|
+
headers.merge!("Stripe-Account" => options[:stripe_account]) if options[:stripe_account]
|
426
483
|
headers
|
427
484
|
end
|
428
485
|
|
486
|
+
def stripe_client_user_agent(options)
|
487
|
+
return user_agent unless options[:application]
|
488
|
+
JSON.dump(JSON.parse(user_agent).merge!({application: options[:application]}))
|
489
|
+
end
|
490
|
+
|
429
491
|
def api_version(options)
|
430
492
|
options[:version] || @options[:version] || "2015-04-07"
|
431
493
|
end
|
@@ -506,10 +568,6 @@ module ActiveMerchant #:nodoc:
|
|
506
568
|
end
|
507
569
|
end
|
508
570
|
|
509
|
-
def non_fractional_currency?(currency)
|
510
|
-
CURRENCIES_WITHOUT_FRACTIONS.include?(currency.to_s)
|
511
|
-
end
|
512
|
-
|
513
571
|
def emv_payment?(payment)
|
514
572
|
payment.respond_to?(:emv?) && payment.emv?
|
515
573
|
end
|
@@ -532,6 +590,44 @@ module ActiveMerchant #:nodoc:
|
|
532
590
|
error_code ||= STANDARD_ERROR_CODE_MAPPING[code]
|
533
591
|
error_code
|
534
592
|
end
|
593
|
+
|
594
|
+
def tokenize_bank_account(bank_account, options = {})
|
595
|
+
account_holder_type = BANK_ACCOUNT_HOLDER_TYPE_MAPPING[bank_account.account_holder_type]
|
596
|
+
|
597
|
+
post = {
|
598
|
+
bank_account: {
|
599
|
+
account_number: bank_account.account_number,
|
600
|
+
country: 'US',
|
601
|
+
currency: 'usd',
|
602
|
+
routing_number: bank_account.routing_number,
|
603
|
+
name: bank_account.name,
|
604
|
+
account_holder_type: account_holder_type,
|
605
|
+
}
|
606
|
+
}
|
607
|
+
|
608
|
+
token_response = api_request(:post, "tokens?#{post_data(post)}")
|
609
|
+
success = token_response["error"].nil?
|
610
|
+
|
611
|
+
if success && token_response["id"]
|
612
|
+
Response.new(success, nil, token: token_response)
|
613
|
+
else
|
614
|
+
Response.new(success, token_response["error"]["message"])
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
def ach?(payment_method)
|
619
|
+
case payment_method
|
620
|
+
when String, nil
|
621
|
+
false
|
622
|
+
else
|
623
|
+
card_brand(payment_method) == "check"
|
624
|
+
end
|
625
|
+
end
|
626
|
+
|
627
|
+
def auth_minimum_amount(options)
|
628
|
+
return 100 unless options[:currency]
|
629
|
+
return MINIMUM_AUTHORIZE_AMOUNTS[options[:currency].upcase] || 100
|
630
|
+
end
|
535
631
|
end
|
536
632
|
end
|
537
633
|
end
|