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
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
|