activemerchant 1.94.0 → 1.99.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbb76da56e87639a3f9129d70297b78a0edabe9faf2300e682e06e872e019419
|
4
|
+
data.tar.gz: 94cb0693e867b03071fe55a7e71b3cfbaf53a7c340d480f24108948822e9e1e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa96ed1337c57fa00d0405ff07a70b9423bac6a26ec69fde450d73bc9cabfc0ae27b75a46faddcdf3e79f2198db8214e8e6c5926468f0acb999bef43fc220a73
|
7
|
+
data.tar.gz: f672640992309d545629a41e4f89d505732d0bb88559648a96935ef01293bcff737de41c8a7b8992993dafdfdb71d29bcbf8b85133c3d9ae5311f7b720b7c9c7
|
data/CHANGELOG
CHANGED
@@ -1,6 +1,125 @@
|
|
1
1
|
= ActiveMerchant CHANGELOG
|
2
2
|
|
3
3
|
== HEAD
|
4
|
+
== Version 1.99.0 (Sep 26, 2019)
|
5
|
+
* Adyen: Add functionality to set 3DS exemptions via API [britth] #3331
|
6
|
+
* Adyen: Send "NA" instead of "N/A" [leila-alderman] #3339
|
7
|
+
* Stripe Payment Intents: Set application fee or transfer amount on capture [britth] #3340
|
8
|
+
* TNS: Support Europe endpoint [curiousepic] #3346
|
9
|
+
* Redsys: Add 3DS support to gateway [britth] #3336
|
10
|
+
* Worldpay: Allow multiple refunds per authorization [jknipp] #3349
|
11
|
+
* MercadoPago: Add remote and unit tests for Naranja card [hdeters] #3345
|
12
|
+
* CyberSource: Pass commerce indicator if present [curiousepic] #3350
|
13
|
+
* Worldpay: Add 3DS2 Support [nfarve] #3344
|
14
|
+
* Credorax: Add 3DS 2.0 [nfarve] #3342
|
15
|
+
* TNS: Update verison and support pay mode [curiousepic] #3355
|
16
|
+
* Stripe: Add supported countries [therufs] #3358
|
17
|
+
* Stripe Payment Intents: Add supported countries [therufs] #3359
|
18
|
+
* Mundipagg: Append error messages to the message response field [jasonxp] #3353
|
19
|
+
* Redsys: Add ability to pass sca_exemption and moto fields to request exemptions [britth] #3354
|
20
|
+
* Credorax: Add A Mandatory 3DS field [nfarve] #3360
|
21
|
+
* CyberSource: Support 3DS2 pass-through fields [curiousepic] #3363
|
22
|
+
* Credorax: Add support for MOTO flagging [britth] #3366
|
23
|
+
* Credorax: Enable selecting a processor [leila-alderman] #3302
|
24
|
+
* Adyen: Add Cabal card [leila-alderman] #3361
|
25
|
+
* Decidir: Add remote tests for Cabal and Naranja [leila-alderman] #3337
|
26
|
+
* Payflow: Pass correct field in Status for 3DS in Payflow [nebdil] #3362
|
27
|
+
* CyberSource: Use 3DS hash for enrolled field [curiousepic] #3371
|
28
|
+
|
29
|
+
== Version 1.98.0 (Sep 9, 2019)
|
30
|
+
* Stripe Payment Intents: Add new gateway [britth] #3290
|
31
|
+
* Stripe: Send cardholder name and address when creating sources for 3DS 1.0 [jknipp] #3300
|
32
|
+
* Checkout_v2: Support for native 3DS2.0 [nfarve] #3303
|
33
|
+
* Adds new Maestro BINs [tanyajajodia] #3305
|
34
|
+
* eWAY Rapid: If no address is available, default to the name associated with the payment method when setting the Customer fields [jasonxp] #3306
|
35
|
+
* eWAY Rapid: Fix a bug in which the email was not set in Customer fields if no address was provided [jasonxp] #3306
|
36
|
+
* eWAY Rapid: Support both `phone` and `phone_number` fields under the `shipping_address` option [jasonxp] #3306
|
37
|
+
* PayU Latam: Add support for the `merchant_buyer_id` field in the `options` and `buyer` hashes [jasonxp] #3308
|
38
|
+
* Update Braintree Gem [curiousepic] #3311
|
39
|
+
* Fat Zebra: Send metadata for purchase and authorize [montdidier] #3101
|
40
|
+
* TrustCommerce: Add support for custom fields [jasonxp] #3313
|
41
|
+
* Stripe Payment Intents: Support option fields `transfer_destination` and `transfer_amount` and remove `transfer_data` hash [britth] #3317
|
42
|
+
* Barclaycard Smartpay: Add support for `shopperStatement` gateway-specific field [jasonxp] #3319
|
43
|
+
* Stripe Payment Intents: Add support for billing_details on payment methods [britth] #3320
|
44
|
+
* BlueSnap: add standardized 3DS 2 auth fields [bayprogrammer] #3318
|
45
|
+
* Barclaycard Smartpay: Add app based 3DS requests for auth and purchase [britth] #3327
|
46
|
+
* Stripe Payment Intents, Checkout V2: Add support for `MOTO` flagging [britth] #3323
|
47
|
+
* Braintree Blue: Adding 3DS2 passthru support [molbrown] #3328
|
48
|
+
* Global Collect: Add Cabal card [leila-alderman] #3310
|
49
|
+
* WorldPay: Add Cabal card [leila-alderman] #3316
|
50
|
+
* Decidir: Add Cabal card [leila-alderman] #3322
|
51
|
+
* PayU Latam: Add Cabal card [leila-alderman] #3324
|
52
|
+
* dLocal: Add Cabal card [leila-alderman] #3325
|
53
|
+
* BlueSnap: Add Cabal card [leila-alderman] #3326
|
54
|
+
* Adyen: added 3DS support through external [rikterbeek] #3294
|
55
|
+
* Worldpay: Add support for MOTO flagging [britth] #3329
|
56
|
+
* ePay: 3DS support [AllaWLie] #3321
|
57
|
+
* Checkout.com: added options[:metadata][:manual_entry] support for MOTO transactions [filipebarcos] #3330
|
58
|
+
|
59
|
+
== Version 1.97.0 (Aug 15, 2019)
|
60
|
+
* CyberSource: Add issuer `additionalData` gateway-specific field [jasonxp] #3296
|
61
|
+
* PayU Latam: Add Naranja card type [hdeters] #3299
|
62
|
+
* Adyen: Add app based 3DS requests for auth and purchase [jeremywrowe] #3298
|
63
|
+
* MercadoPago: Add Cabal card type [leila-alderman] #3295
|
64
|
+
* MONEI: Add external MPI 3DS 1 support [jimmyn] #3292
|
65
|
+
* Bambora formerly Beanstream: Pass card owner when storing tokenized cards [alexdunae] #3006
|
66
|
+
* Realex: Prevent error calculating `refund_hash` or `credit_hash` when the secret is nil [jasonxp] #3291
|
67
|
+
* Orbital: Add external MPI support for 3DS1 [pi3r] #3261
|
68
|
+
* Paymill: Add currency and amount to store requests [jasonxp] #3289
|
69
|
+
* Realex: Re-implement credit as general credit [leila-alderman] #3280
|
70
|
+
* Braintree Blue: Support for stored credentials [hdeters] #3286
|
71
|
+
* CardConnect: Move domain from gateway specific to gateway field [hdeters] #3283
|
72
|
+
|
73
|
+
== Version 1.96.0 (Jul 26, 2019)
|
74
|
+
* Bluesnap: Omit state codes for unsupported countries [therufs] #3229
|
75
|
+
* Adyen: Pass updateShopperStatement, industryUsage [curiousepic] #3233
|
76
|
+
* TransFirst Transaction Express: Fix blank address2 values [britth] #3231
|
77
|
+
* WorldPay: Add support for store method [bayprogrammer] #3232
|
78
|
+
* Adyen: Support for additional AVS code mapping [jknipp] #3236
|
79
|
+
* Adyen: Update message for AVS result code 'A' to generically cover postal code mismatches [jknipp] #3237
|
80
|
+
* CyberSource: Update CyberSource SOAP documentation link [vince-smith] #3204
|
81
|
+
* USAePay: Handle additional error codes and add default error code [estelendur] #3167
|
82
|
+
* Braintree: Add `skip_avs` and `skip_cvv` gateway specific fields [leila-alderman] #3241
|
83
|
+
* NAB Transact: Update periodic test url [mengqing] #3177
|
84
|
+
* NMI: Add level 3 gateway-specific fields tax, shipping, and ponumber [jasonxp] #3239
|
85
|
+
* Checkout V2: Update stored card flag [curiousepic] #3247
|
86
|
+
* NMI: Add support for stored credentials [bayprogrammer] #3243
|
87
|
+
* Spreedly: Consolidate API requests and support bank accounts [lancecarlson] #3105
|
88
|
+
* BPoint: Hook up merchant_reference and CRN fields [curiousepic] #3249
|
89
|
+
* Checkout V2: Stop sending phone number to Checkout V2 integration [filipebarcos] #3248
|
90
|
+
* Barclaycard Smartpay: Add support for 3DS2 [britth] #3251
|
91
|
+
* Adyen: Add support for non-fractional currencies [molbrown] #3257
|
92
|
+
* Decidir: Add new gateway [jknipp] #3254
|
93
|
+
* Checkout V2: Reapply Update stored card flag [curiousepic]
|
94
|
+
* CyberSource: Update supported countries [molbrown] #3260
|
95
|
+
* Credorax: Update supported countries [molbrown] #3260
|
96
|
+
* Kushki: Update supported countries [molbrown] #3260
|
97
|
+
* Paypal: Update supported countries [molbrown] #3260
|
98
|
+
* BlueSnap: Send amount in capture requests [jknipp] #3262
|
99
|
+
* Mundipagg: Add Alelo card support [jasonxp] #3255
|
100
|
+
* Adyen: Remove temporary amount modification for non-fractional currencies [molbrown] #3263
|
101
|
+
* Adyen: Set blank state to N/A [therufs] #3252
|
102
|
+
* MiGS: Add tx_source gateway specific field [leila-alderman] #3264
|
103
|
+
* NMI: Correct password scrubber to scrub symbols [hdeters] #3267
|
104
|
+
* Global Collect: Only add name if present [curiousepic] #3268
|
105
|
+
* HPS: Add Apple Pay raw cryptogram support [slogsdon] #3209
|
106
|
+
* CardConnect: Fix parsing of level 3 fields [hdeters] #3273
|
107
|
+
* TrustCommerce: Support void after purchase [jknipp] #3265
|
108
|
+
* Payflow: Support arbitrary level 2 + level 3 fields [therufs] #3272
|
109
|
+
* BlueSnap: Default to not send amount on capture [molbrown] #3270
|
110
|
+
* Spreedly: extra fields, remove extraneous check [montdidier] #3102 #3281
|
111
|
+
* Cecabank: Update encryption to SHA2 [leila-alderman] #3278
|
112
|
+
* Checkout V2: Fix 3DS 1&2 integration [nicolas-maalouf-cko] #3240
|
113
|
+
* Credorax: add 3DS2 MPI auth data support [bayprogrammer] #3274
|
114
|
+
* Add Kosovo to the list of countries [AnotherJoSmith] #3226
|
115
|
+
* Realex: Adds 3DS 1&2 support through external MPI [filipebarcos] #3284
|
116
|
+
* PayPal: Adds 3DS 1 support through external MPI [nebdil] #3279
|
117
|
+
|
118
|
+
== Version 1.95.0 (May 23, 2019)
|
119
|
+
* Adyen: Constantize version to fix subdomains [curiousepic] #3228
|
120
|
+
* Qvalent: Adds support for standard stored credential framework [molbrown] #3227
|
121
|
+
* Cybersource: Send tokenization data when card is :master [pi3r] #3230
|
122
|
+
|
4
123
|
== Version 1.94.0 (May 21, 2019)
|
5
124
|
* Mundipagg: Fix number lengths for both VR and Sodexo [dtykocki] #3195
|
6
125
|
* Stripe: Support show and list webhook endpoints [jknipp] #3196
|
@@ -16,7 +135,7 @@
|
|
16
135
|
* WorldPay: Support Unknown Card Type [tanyajajodia] #3213
|
17
136
|
* Mundipagg: Make gateway_affiliation_id an option [curiousepic] #3219
|
18
137
|
* CyberSource: Adds Elo Card Type [tanyajajodia] #3220
|
19
|
-
* CyberSource: Support standalone credit for cards [curiousepic] 3225
|
138
|
+
* CyberSource: Support standalone credit for cards [curiousepic] #3225
|
20
139
|
|
21
140
|
== Version 1.93.0 (April 18, 2019)
|
22
141
|
* Stripe: Do not consider a refund unsuccessful if only refunding the fee failed [jasonwebster] #3188
|
data/README.md
CHANGED
@@ -84,6 +84,9 @@ end
|
|
84
84
|
For more in-depth documentation and tutorials, see [GettingStarted.md](GettingStarted.md) and the
|
85
85
|
[API documentation](http://www.rubydoc.info/github/activemerchant/active_merchant/).
|
86
86
|
|
87
|
+
Emerging ActiveMerchant 3DS conventions are documented in the [Contributing](https://github.com/activemerchant/active_merchant/wiki/Contributing#3ds-options)
|
88
|
+
guide and [Standardized 3DS Fields](https://github.com/activemerchant/active_merchant/wiki/Standardized-3DS-Fields) guide of the wiki.
|
89
|
+
|
87
90
|
## Supported Payment Gateways
|
88
91
|
|
89
92
|
The [ActiveMerchant Wiki](https://github.com/activemerchant/active_merchant/wikis) contains a [table of features supported by each gateway](https://github.com/activemerchant/active_merchant/wiki/Gateway-Feature-Matrix).
|
@@ -3,14 +3,13 @@
|
|
3
3
|
module ActiveMerchant
|
4
4
|
module Billing
|
5
5
|
# Implements the Address Verification System
|
6
|
-
# https://www.
|
6
|
+
# https://www.cybersource.com/developers/other_resources/quick_references/avs_results/.
|
7
7
|
# http://en.wikipedia.org/wiki/Address_Verification_System
|
8
|
-
# http://apps.cybersource.com/library/documentation/dev_guides/CC_Svcs_IG/html/app_avs_cvn_codes.htm#app_AVS_CVN_codes_7891_48375
|
9
|
-
# http://imgserver.skipjack.com/imgServer/5293710/AVS%20and%20CVV2.pdf
|
10
8
|
# http://www.emsecommerce.net/avs_cvv2_response_codes.htm
|
9
|
+
# https://www.cardfellow.com/blog/address-verification-service-avs/
|
11
10
|
class AVSResult
|
12
11
|
MESSAGES = {
|
13
|
-
'A' => 'Street address matches, but
|
12
|
+
'A' => 'Street address matches, but postal code does not match.',
|
14
13
|
'B' => 'Street address matches, but postal code not verified.',
|
15
14
|
'C' => 'Street address and postal code do not match.',
|
16
15
|
'D' => 'Street address and postal code match.',
|
@@ -23,7 +22,7 @@ module ActiveMerchant
|
|
23
22
|
'K' => 'Card member\'s name matches but billing address and billing postal code do not match.',
|
24
23
|
'L' => 'Card member\'s name and billing postal code match, but billing address does not match.',
|
25
24
|
'M' => 'Street address and postal code match.',
|
26
|
-
'N' => 'Street address and postal code do not match.',
|
25
|
+
'N' => 'Street address and postal code do not match. For American Express: Card member\'s name, street address and postal code do not match.',
|
27
26
|
'O' => 'Card member\'s name and billing address match, but billing postal code does not match.',
|
28
27
|
'P' => 'Postal code matches, but street address not verified.',
|
29
28
|
'Q' => 'Card member\'s name, billing address, and postal code match. Shipping information verified but chargeback protection not guaranteed.',
|
@@ -19,6 +19,9 @@ module ActiveMerchant #:nodoc:
|
|
19
19
|
# * Maestro
|
20
20
|
# * Forbrugsforeningen
|
21
21
|
# * Elo
|
22
|
+
# * Alelo
|
23
|
+
# * Cabal
|
24
|
+
# * Naranja
|
22
25
|
#
|
23
26
|
# For testing purposes, use the 'bogus' credit card brand. This skips the vast majority of
|
24
27
|
# validations, allowing you to focus on your core concerns until you're ready to be more concerned
|
@@ -90,6 +93,9 @@ module ActiveMerchant #:nodoc:
|
|
90
93
|
# * +'maestro'+
|
91
94
|
# * +'forbrugsforeningen'+
|
92
95
|
# * +'elo'+
|
96
|
+
# * +'alelo'+
|
97
|
+
# * +'cabal'+
|
98
|
+
# * +'naranja'+
|
93
99
|
#
|
94
100
|
# Or, if you wish to test your implementation, +'bogus'+.
|
95
101
|
#
|
@@ -6,8 +6,10 @@ module ActiveMerchant #:nodoc:
|
|
6
6
|
'visa' => ->(num) { num =~ /^4\d{12}(\d{3})?(\d{3})?$/ },
|
7
7
|
'master' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 6), MASTERCARD_RANGES) },
|
8
8
|
'elo' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 6), ELO_RANGES) },
|
9
|
+
'alelo' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 6), ALELO_RANGES) },
|
9
10
|
'discover' => ->(num) { num =~ /^(6011|65\d{2}|64[4-9]\d)\d{12,15}|(62\d{14,17})$/ },
|
10
11
|
'american_express' => ->(num) { num =~ /^3[47]\d{13}$/ },
|
12
|
+
'naranja' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 6), NARANJA_RANGES) },
|
11
13
|
'diners_club' => ->(num) { num =~ /^3(0[0-5]|[68]\d)\d{11}$/ },
|
12
14
|
'jcb' => ->(num) { num =~ /^35(28|29|[3-8]\d)\d{12}$/ },
|
13
15
|
'dankort' => ->(num) { num =~ /^5019\d{12}$/ },
|
@@ -15,6 +17,7 @@ module ActiveMerchant #:nodoc:
|
|
15
17
|
'forbrugsforeningen' => ->(num) { num =~ /^600722\d{10}$/ },
|
16
18
|
'sodexo' => ->(num) { num =~ /^(606071|603389|606070|606069|606068|600818)\d{10}$/ },
|
17
19
|
'vr' => ->(num) { num =~ /^(627416|637036)\d{10}$/ },
|
20
|
+
'cabal' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 8), CABAL_RANGES) },
|
18
21
|
'carnet' => lambda { |num|
|
19
22
|
num&.size == 16 && (
|
20
23
|
in_bin_range?(num.slice(0, 6), CARNET_RANGES) ||
|
@@ -63,6 +66,24 @@ module ActiveMerchant #:nodoc:
|
|
63
66
|
|
64
67
|
# https://www.mastercard.us/content/dam/mccom/global/documents/mastercard-rules.pdf, page 73
|
65
68
|
MAESTRO_RANGES = [
|
69
|
+
(561200..561269),
|
70
|
+
(561271..561299),
|
71
|
+
(561320..561356),
|
72
|
+
(581700..581751),
|
73
|
+
(581753..581800),
|
74
|
+
(589998..591259),
|
75
|
+
(591261..596770),
|
76
|
+
(596772..598744),
|
77
|
+
(598746..599999),
|
78
|
+
(600297..600314),
|
79
|
+
(600316..600335),
|
80
|
+
(600337..600362),
|
81
|
+
(600364..600382),
|
82
|
+
(601232..601254),
|
83
|
+
(601256..601276),
|
84
|
+
(601640..601652),
|
85
|
+
(601689..601700),
|
86
|
+
(602011..602050),
|
66
87
|
(639000..639099),
|
67
88
|
(670000..679999),
|
68
89
|
]
|
@@ -79,6 +100,29 @@ module ActiveMerchant #:nodoc:
|
|
79
100
|
651652..651667, 651675..651678, 655000..655010, 655012..655015, 655051..655052, 655056..655057
|
80
101
|
]
|
81
102
|
|
103
|
+
# Alelo provides BIN ranges by e-mailing them out periodically.
|
104
|
+
# The BINs beginning with the digit 4 overlap with Visa's range of valid card numbers.
|
105
|
+
# By placing the 'alelo' entry in CARD_COMPANY_DETECTORS below the 'visa' entry, we
|
106
|
+
# identify these cards as Visa. This works because transactions with such cards will
|
107
|
+
# run on Visa rails.
|
108
|
+
ALELO_RANGES = [
|
109
|
+
402588..402588, 404347..404347, 405876..405876, 405882..405882, 405884..405884,
|
110
|
+
405886..405886, 430471..430471, 438061..438061, 438064..438064, 470063..470066,
|
111
|
+
496067..496067, 506699..506704, 506706..506706, 506713..506714, 506716..506716,
|
112
|
+
506749..506750, 506752..506752, 506754..506756, 506758..506762, 506764..506767,
|
113
|
+
506770..506771, 509015..509019, 509880..509882, 509884..509885, 509987..509988
|
114
|
+
]
|
115
|
+
|
116
|
+
CABAL_RANGES = [
|
117
|
+
60420100..60440099,
|
118
|
+
58965700..58965799,
|
119
|
+
60352200..60352299
|
120
|
+
]
|
121
|
+
|
122
|
+
NARANJA_RANGES = [
|
123
|
+
589562..589562
|
124
|
+
]
|
125
|
+
|
82
126
|
def self.included(base)
|
83
127
|
base.extend(ClassMethods)
|
84
128
|
end
|
@@ -154,7 +198,7 @@ module ActiveMerchant #:nodoc:
|
|
154
198
|
valid_test_mode_card_number?(number) ||
|
155
199
|
valid_card_number_length?(number) &&
|
156
200
|
valid_card_number_characters?(number) &&
|
157
|
-
|
201
|
+
valid_by_algorithm?(brand?(number), number)
|
158
202
|
end
|
159
203
|
|
160
204
|
def card_companies
|
@@ -228,6 +272,15 @@ module ActiveMerchant #:nodoc:
|
|
228
272
|
%w[1 2 3 success failure error].include?(number)
|
229
273
|
end
|
230
274
|
|
275
|
+
def valid_by_algorithm?(brand, numbers) #:nodoc:
|
276
|
+
case brand
|
277
|
+
when 'naranja'
|
278
|
+
valid_naranja_algo?(numbers)
|
279
|
+
else
|
280
|
+
valid_luhn?(numbers)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
231
284
|
ODD_LUHN_VALUE = {
|
232
285
|
48 => 0,
|
233
286
|
49 => 1,
|
@@ -258,7 +311,7 @@ module ActiveMerchant #:nodoc:
|
|
258
311
|
# Checks the validity of a card number by use of the Luhn Algorithm.
|
259
312
|
# Please see http://en.wikipedia.org/wiki/Luhn_algorithm for details.
|
260
313
|
# This implementation is from the luhn_checksum gem, https://github.com/zendesk/luhn_checksum.
|
261
|
-
def
|
314
|
+
def valid_luhn?(numbers) #:nodoc:
|
262
315
|
sum = 0
|
263
316
|
|
264
317
|
odd = true
|
@@ -274,6 +327,16 @@ module ActiveMerchant #:nodoc:
|
|
274
327
|
|
275
328
|
sum % 10 == 0
|
276
329
|
end
|
330
|
+
|
331
|
+
# Checks the validity of a card number by use of Naranja's specific algorithm.
|
332
|
+
def valid_naranja_algo?(numbers) #:nodoc:
|
333
|
+
num_array = numbers.to_s.chars.map(&:to_i)
|
334
|
+
multipliers = [4, 3, 2, 7, 6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2]
|
335
|
+
num_sum = num_array[0..14].zip(multipliers).map { |a, b| a*b }.reduce(:+)
|
336
|
+
intermediate = 11 - (num_sum % 11)
|
337
|
+
final_num = intermediate > 9 ? 0 : intermediate
|
338
|
+
final_num == num_array[15]
|
339
|
+
end
|
277
340
|
end
|
278
341
|
end
|
279
342
|
end
|
@@ -200,6 +200,16 @@ module ActiveMerchant #:nodoc:
|
|
200
200
|
false
|
201
201
|
end
|
202
202
|
|
203
|
+
def add_fields_to_post_if_present(post, options, fields)
|
204
|
+
fields.each do |field|
|
205
|
+
add_field_to_post_if_present(post, options, field)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def add_field_to_post_if_present(post, options, field)
|
210
|
+
post[field] = options[field] if options[field]
|
211
|
+
end
|
212
|
+
|
203
213
|
protected # :nodoc: all
|
204
214
|
|
205
215
|
def normalize(field)
|
@@ -4,18 +4,21 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
|
5
5
|
# we recommend setting up merchant-specific endpoints.
|
6
6
|
# https://docs.adyen.com/developers/api-manual#apiendpoints
|
7
|
-
self.test_url = 'https://pal-test.adyen.com/pal/servlet/Payment/
|
8
|
-
self.live_url = 'https://pal-live.adyen.com/pal/servlet/Payment/
|
7
|
+
self.test_url = 'https://pal-test.adyen.com/pal/servlet/Payment/'
|
8
|
+
self.live_url = 'https://pal-live.adyen.com/pal/servlet/Payment/'
|
9
9
|
|
10
10
|
self.supported_countries = ['AT', 'AU', 'BE', 'BG', 'BR', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GI', 'GR', 'HK', 'HU', 'IE', 'IS', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'MX', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SG', 'SK', 'SI', 'US']
|
11
11
|
self.default_currency = 'USD'
|
12
|
-
self.
|
12
|
+
self.currencies_without_fractions = %w(CVE DJF GNF IDR JPY KMF KRW PYG RWF UGX VND VUV XAF XOF XPF)
|
13
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb, :dankort, :maestro, :discover, :elo, :naranja, :cabal]
|
13
14
|
|
14
15
|
self.money_format = :cents
|
15
16
|
|
16
17
|
self.homepage_url = 'https://www.adyen.com/'
|
17
18
|
self.display_name = 'Adyen'
|
18
19
|
|
20
|
+
API_VERSION = 'v40'
|
21
|
+
|
19
22
|
STANDARD_ERROR_CODE_MAPPING = {
|
20
23
|
'101' => STANDARD_ERROR_CODE[:incorrect_number],
|
21
24
|
'103' => STANDARD_ERROR_CODE[:invalid_cvc],
|
@@ -53,6 +56,7 @@ module ActiveMerchant #:nodoc:
|
|
53
56
|
add_address(post, options)
|
54
57
|
add_installments(post, options) if options[:installments]
|
55
58
|
add_3ds(post, options)
|
59
|
+
add_3ds_authenticated_data(post, options)
|
56
60
|
commit('authorise', post, options)
|
57
61
|
end
|
58
62
|
|
@@ -93,7 +97,14 @@ module ActiveMerchant #:nodoc:
|
|
93
97
|
add_stored_credentials(post, credit_card, options)
|
94
98
|
add_recurring_contract(post, options)
|
95
99
|
add_address(post, options)
|
96
|
-
|
100
|
+
|
101
|
+
initial_response = commit('authorise', post, options)
|
102
|
+
|
103
|
+
if initial_response.success? && card_not_stored?(initial_response)
|
104
|
+
unsupported_failure_response(initial_response)
|
105
|
+
else
|
106
|
+
initial_response
|
107
|
+
end
|
97
108
|
end
|
98
109
|
|
99
110
|
def verify(credit_card, options={})
|
@@ -138,10 +149,14 @@ module ActiveMerchant #:nodoc:
|
|
138
149
|
'16' => 'N', # Postal code doesn't match, address unknown
|
139
150
|
'17' => 'U', # Postal code doesn't match, address not checked
|
140
151
|
'18' => 'I', # Neither postal code nor address were checked
|
152
|
+
'19' => 'L', # Name and postal code matches.
|
141
153
|
'20' => 'V', # Name, address and postal code matches.
|
154
|
+
'21' => 'O', # Name and address matches.
|
155
|
+
'22' => 'K', # Name matches.
|
142
156
|
'23' => 'F', # Postal code matches, name doesn't match.
|
143
157
|
'24' => 'H', # Both postal code and address matches, name doesn't match.
|
144
|
-
'25' => 'T' # Address matches, name doesn't match.
|
158
|
+
'25' => 'T', # Address matches, name doesn't match.
|
159
|
+
'26' => 'N' # Neither postal code, address nor name matches.
|
145
160
|
}
|
146
161
|
|
147
162
|
CVC_MAPPING = {
|
@@ -177,6 +192,8 @@ module ActiveMerchant #:nodoc:
|
|
177
192
|
post[:additionalData]['paymentdatasource.type'] = NETWORK_TOKENIZATION_CARD_SOURCE[payment.source.to_s] if payment.is_a?(NetworkTokenizationCreditCard)
|
178
193
|
post[:additionalData][:authorisationType] = options[:authorisation_type] if options[:authorisation_type]
|
179
194
|
post[:additionalData][:adjustAuthorisationData] = options[:adjust_authorisation_data] if options[:adjust_authorisation_data]
|
195
|
+
post[:additionalData][:industryUsage] = options[:industry_usage] if options[:industry_usage]
|
196
|
+
post[:additionalData][:updateShopperStatement] = options[:update_shopper_statement] if options[:update_shopper_statement]
|
180
197
|
post[:additionalData][:RequestedTestAcquirerResponseCode] = options[:requested_test_acquirer_response_code] if options[:requested_test_acquirer_response_code] && test?
|
181
198
|
post[:deviceFingerprint] = options[:device_fingerprint] if options[:device_fingerprint]
|
182
199
|
add_risk_data(post, options)
|
@@ -219,27 +236,33 @@ module ActiveMerchant #:nodoc:
|
|
219
236
|
return unless post[:card]&.kind_of?(Hash)
|
220
237
|
if (address = options[:billing_address] || options[:address]) && address[:country]
|
221
238
|
post[:billingAddress] = {}
|
222
|
-
post[:billingAddress][:street] = address[:address1] || '
|
223
|
-
post[:billingAddress][:houseNumberOrName] = address[:address2] || '
|
239
|
+
post[:billingAddress][:street] = address[:address1] || 'NA'
|
240
|
+
post[:billingAddress][:houseNumberOrName] = address[:address2] || 'NA'
|
224
241
|
post[:billingAddress][:postalCode] = address[:zip] if address[:zip]
|
225
|
-
post[:billingAddress][:city] = address[:city] || '
|
226
|
-
post[:billingAddress][:stateOrProvince] = address
|
242
|
+
post[:billingAddress][:city] = address[:city] || 'NA'
|
243
|
+
post[:billingAddress][:stateOrProvince] = get_state(address)
|
227
244
|
post[:billingAddress][:country] = address[:country] if address[:country]
|
228
245
|
end
|
229
246
|
end
|
230
247
|
|
248
|
+
def get_state(address)
|
249
|
+
address[:state] && !address[:state].blank? ? address[:state] : 'NA'
|
250
|
+
end
|
251
|
+
|
231
252
|
def add_invoice(post, money, options)
|
253
|
+
currency = options[:currency] || currency(money)
|
232
254
|
amount = {
|
233
|
-
value:
|
234
|
-
currency:
|
255
|
+
value: localized_amount(money, currency),
|
256
|
+
currency: currency
|
235
257
|
}
|
236
258
|
post[:amount] = amount
|
237
259
|
end
|
238
260
|
|
239
261
|
def add_invoice_for_modification(post, money, options)
|
262
|
+
currency = options[:currency] || currency(money)
|
240
263
|
amount = {
|
241
|
-
value:
|
242
|
-
currency:
|
264
|
+
value: localized_amount(money, currency),
|
265
|
+
currency: currency
|
243
266
|
}
|
244
267
|
post[:modificationAmount] = amount
|
245
268
|
end
|
@@ -313,24 +336,17 @@ module ActiveMerchant #:nodoc:
|
|
313
336
|
|
314
337
|
def add_3ds(post, options)
|
315
338
|
if three_ds_2_options = options[:three_ds_2]
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
if device_channel = three_ds_2_options[:channel]
|
329
|
-
post[:threeDS2RequestData] = {
|
330
|
-
deviceChannel: device_channel,
|
331
|
-
notificationURL: three_ds_2_options[:notification_url] || 'https://example.com/notification'
|
332
|
-
}
|
333
|
-
end
|
339
|
+
device_channel = three_ds_2_options[:channel]
|
340
|
+
if device_channel == 'app'
|
341
|
+
post[:threeDS2RequestData] = { deviceChannel: device_channel }
|
342
|
+
else
|
343
|
+
add_browser_info(three_ds_2_options[:browser_info], post)
|
344
|
+
post[:threeDS2RequestData] = { deviceChannel: device_channel, notificationURL: three_ds_2_options[:notification_url] }
|
345
|
+
end
|
346
|
+
|
347
|
+
if options.has_key?(:execute_threed)
|
348
|
+
post[:additionalData][:executeThreeD] = options[:execute_threed]
|
349
|
+
post[:additionalData][:scaExemption] = options[:sca_exemption] if options[:sca_exemption]
|
334
350
|
end
|
335
351
|
else
|
336
352
|
return unless options[:execute_threed] || options[:threed_dynamic]
|
@@ -339,6 +355,44 @@ module ActiveMerchant #:nodoc:
|
|
339
355
|
end
|
340
356
|
end
|
341
357
|
|
358
|
+
def add_3ds_authenticated_data(post, options)
|
359
|
+
if options[:three_d_secure] && options[:three_d_secure][:eci] && options[:three_d_secure][:xid]
|
360
|
+
add_3ds1_authenticated_data(post, options)
|
361
|
+
elsif options[:three_d_secure]
|
362
|
+
add_3ds2_authenticated_data(post, options)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
def add_3ds1_authenticated_data(post, options)
|
367
|
+
three_d_secure_options = options[:three_d_secure]
|
368
|
+
post[:mpiData] = {
|
369
|
+
cavv: three_d_secure_options[:cavv],
|
370
|
+
cavvAlgorithm: three_d_secure_options[:cavv_algorithm],
|
371
|
+
eci: three_d_secure_options[:eci],
|
372
|
+
xid: three_d_secure_options[:xid],
|
373
|
+
directoryResponse: three_d_secure_options[:directory_response_status],
|
374
|
+
authenticationResponse: three_d_secure_options[:authentication_response_status]
|
375
|
+
}
|
376
|
+
end
|
377
|
+
|
378
|
+
def add_3ds2_authenticated_data(post, options)
|
379
|
+
three_d_secure_options = options[:three_d_secure]
|
380
|
+
# If the transaction was authenticated in a frictionless flow, send the transStatus from the ARes.
|
381
|
+
if(three_d_secure_options[:authentication_response_status].nil?)
|
382
|
+
authentication_response = three_d_secure_options[:directory_response_status]
|
383
|
+
else
|
384
|
+
authentication_response = three_d_secure_options[:authentication_response_status]
|
385
|
+
end
|
386
|
+
post[:mpiData] = {
|
387
|
+
threeDSVersion: three_d_secure_options[:version],
|
388
|
+
eci: three_d_secure_options[:eci],
|
389
|
+
cavv: three_d_secure_options[:cavv],
|
390
|
+
dsTransID: three_d_secure_options[:ds_transaction_id],
|
391
|
+
directoryResponse: three_d_secure_options[:directory_response_status],
|
392
|
+
authenticationResponse: authentication_response
|
393
|
+
}
|
394
|
+
end
|
395
|
+
|
342
396
|
def parse(body)
|
343
397
|
return {} if body.blank?
|
344
398
|
JSON.parse(body)
|
@@ -375,11 +429,11 @@ module ActiveMerchant #:nodoc:
|
|
375
429
|
|
376
430
|
def url
|
377
431
|
if test?
|
378
|
-
test_url
|
432
|
+
"#{test_url}#{API_VERSION}"
|
379
433
|
elsif @options[:subdomain]
|
380
|
-
"https://#{@options[:subdomain]}-pal-live.adyenpayments.com/pal/servlet/Payment
|
434
|
+
"https://#{@options[:subdomain]}-pal-live.adyenpayments.com/pal/servlet/Payment/#{API_VERSION}"
|
381
435
|
else
|
382
|
-
live_url
|
436
|
+
"#{live_url}#{API_VERSION}"
|
383
437
|
end
|
384
438
|
end
|
385
439
|
|
@@ -442,6 +496,37 @@ module ActiveMerchant #:nodoc:
|
|
442
496
|
def error_code_from(response)
|
443
497
|
STANDARD_ERROR_CODE_MAPPING[response['errorCode']]
|
444
498
|
end
|
499
|
+
|
500
|
+
def add_browser_info(browser_info, post)
|
501
|
+
return unless browser_info
|
502
|
+
post[:browserInfo] = {
|
503
|
+
acceptHeader: browser_info[:accept_header],
|
504
|
+
colorDepth: browser_info[:depth],
|
505
|
+
javaEnabled: browser_info[:java],
|
506
|
+
language: browser_info[:language],
|
507
|
+
screenHeight: browser_info[:height],
|
508
|
+
screenWidth: browser_info[:width],
|
509
|
+
timeZoneOffset: browser_info[:timezone],
|
510
|
+
userAgent: browser_info[:user_agent]
|
511
|
+
}
|
512
|
+
end
|
513
|
+
|
514
|
+
def unsupported_failure_response(initial_response)
|
515
|
+
Response.new(
|
516
|
+
false,
|
517
|
+
'Recurring transactions are not supported for this card type.',
|
518
|
+
initial_response.params,
|
519
|
+
authorization: initial_response.authorization,
|
520
|
+
test: initial_response.test,
|
521
|
+
error_code: initial_response.error_code,
|
522
|
+
avs_result: initial_response.avs_result,
|
523
|
+
cvv_result: initial_response.cvv_result[:code]
|
524
|
+
)
|
525
|
+
end
|
526
|
+
|
527
|
+
def card_not_stored?(response)
|
528
|
+
response.authorization ? response.authorization.split('#')[2].nil? : true
|
529
|
+
end
|
445
530
|
end
|
446
531
|
end
|
447
532
|
end
|