activemerchant 1.93.0 → 1.98.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +111 -0
- 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 +67 -4
- data/lib/active_merchant/billing/gateway.rb +10 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +106 -22
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +43 -10
- data/lib/active_merchant/billing/gateways/beanstream.rb +2 -0
- 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 +3 -1
- data/lib/active_merchant/billing/gateways/cecabank.rb +7 -7
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +98 -61
- data/lib/active_merchant/billing/gateways/credorax.rb +29 -3
- data/lib/active_merchant/billing/gateways/cyber_source.rb +30 -13
- data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
- data/lib/active_merchant/billing/gateways/decidir.rb +233 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +9 -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/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 +3 -2
- 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 +40 -2
- 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/spreedly_core.rb +43 -29
- data/lib/active_merchant/billing/gateways/stripe.rb +54 -9
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +267 -0
- 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 +171 -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: acfbb780d39dd416b823a9abef4cdcf4de902ec75210ed78e6771314d00b069b
|
4
|
+
data.tar.gz: 95e9bf94b3610b33d843fd82af8e4f204380e7c53557d24141b654c553160d9f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6222cdad43482972e2a799981936dc1d8114ccbede88604880d350650f7b81422b6551a07375dd1a7e06ef562d4f128c332dabc2fc16ebb7b635f774de18a54e
|
7
|
+
data.tar.gz: 2f9fe3fe9dfe17fc045f0a3e97940ae4b38a461c48f0416a26ed4b5a4e2bb549464911fbe7527392c8dfbcbbee16bfa82266e3ad644060199ee9552b5b82659b
|
data/CHANGELOG
CHANGED
@@ -1,6 +1,117 @@
|
|
1
1
|
= ActiveMerchant CHANGELOG
|
2
2
|
|
3
3
|
== HEAD
|
4
|
+
== Version 1.98.0 (Sep 9, 2019)
|
5
|
+
* Stripe Payment Intents: Add new gateway [britth] #3290
|
6
|
+
* Stripe: Send cardholder name and address when creating sources for 3DS 1.0 [jknipp] #3300
|
7
|
+
* Checkout_v2: Support for native 3DS2.0 [nfarve] #3303
|
8
|
+
* Adds new Maestro BINs [tanyajajodia] #3305
|
9
|
+
* eWAY Rapid: If no address is available, default to the name associated with the payment method when setting the Customer fields [jasonxp] #3306
|
10
|
+
* eWAY Rapid: Fix a bug in which the email was not set in Customer fields if no address was provided [jasonxp] #3306
|
11
|
+
* eWAY Rapid: Support both `phone` and `phone_number` fields under the `shipping_address` option [jasonxp] #3306
|
12
|
+
* PayU Latam: Add support for the `merchant_buyer_id` field in the `options` and `buyer` hashes [jasonxp] #3308
|
13
|
+
* Update Braintree Gem [curiousepic] #3311
|
14
|
+
* Fat Zebra: Send metadata for purchase and authorize [montdidier] #3101
|
15
|
+
* TrustCommerce: Add support for custom fields [jasonxp] #3313
|
16
|
+
* Stripe Payment Intents: Support option fields `transfer_destination` and `transfer_amount` and remove `transfer_data` hash [britth] #3317
|
17
|
+
* Barclaycard Smartpay: Add support for `shopperStatement` gateway-specific field [jasonxp] #3319
|
18
|
+
* Stripe Payment Intents: Add support for billing_details on payment methods [britth] #3320
|
19
|
+
* BlueSnap: add standardized 3DS 2 auth fields [bayprogrammer] #3318
|
20
|
+
* Barclaycard Smartpay: Add app based 3DS requests for auth and purchase [britth] #3327
|
21
|
+
* Stripe Payment Intents, Checkout V2: Add support for `MOTO` flagging [britth] #3323
|
22
|
+
* Braintree Blue: Adding 3DS2 passthru support [molbrown] #3328
|
23
|
+
* Global Collect: Add Cabal card [leila-alderman] #3310
|
24
|
+
* WorldPay: Add Cabal card [leila-alderman] #3316
|
25
|
+
* Decidir: Add Cabal card [leila-alderman] #3322
|
26
|
+
* PayU Latam: Add Cabal card [leila-alderman] #3324
|
27
|
+
* dLocal: Add Cabal card [leila-alderman] #3325
|
28
|
+
* BlueSnap: Add Cabal card [leila-alderman] #3326
|
29
|
+
* Adyen: added 3DS support through external [rikterbeek] #3294
|
30
|
+
* Worldpay: Add support for MOTO flagging [britth] #3329
|
31
|
+
* ePay: 3DS support [AllaWLie] #3321
|
32
|
+
* Checkout.com: added options[:metadata][:manual_entry] support for MOTO transactions [filipebarcos] #3330
|
33
|
+
|
34
|
+
== Version 1.97.0 (Aug 15, 2019)
|
35
|
+
* CyberSource: Add issuer `additionalData` gateway-specific field [jasonxp] #3296
|
36
|
+
* PayU Latam: Add Naranja card type [hdeters] #3299
|
37
|
+
* Adyen: Add app based 3DS requests for auth and purchase [jeremywrowe] #3298
|
38
|
+
* MercadoPago: Add Cabal card type [leila-alderman] #3295
|
39
|
+
* MONEI: Add external MPI 3DS 1 support [jimmyn] #3292
|
40
|
+
* Bambora formerly Beanstream: Pass card owner when storing tokenized cards [alexdunae] #3006
|
41
|
+
* Realex: Prevent error calculating `refund_hash` or `credit_hash` when the secret is nil [jasonxp] #3291
|
42
|
+
* Orbital: Add external MPI support for 3DS1 [pi3r] #3261
|
43
|
+
* Paymill: Add currency and amount to store requests [jasonxp] #3289
|
44
|
+
* Realex: Re-implement credit as general credit [leila-alderman] #3280
|
45
|
+
* Braintree Blue: Support for stored credentials [hdeters] #3286
|
46
|
+
* CardConnect: Move domain from gateway specific to gateway field [hdeters] #3283
|
47
|
+
|
48
|
+
== Version 1.96.0 (Jul 26, 2019)
|
49
|
+
* Bluesnap: Omit state codes for unsupported countries [therufs] #3229
|
50
|
+
* Adyen: Pass updateShopperStatement, industryUsage [curiousepic] #3233
|
51
|
+
* TransFirst Transaction Express: Fix blank address2 values [britth] #3231
|
52
|
+
* WorldPay: Add support for store method [bayprogrammer] #3232
|
53
|
+
* Adyen: Support for additional AVS code mapping [jknipp] #3236
|
54
|
+
* Adyen: Update message for AVS result code 'A' to generically cover postal code mismatches [jknipp] #3237
|
55
|
+
* CyberSource: Update CyberSource SOAP documentation link [vince-smith] #3204
|
56
|
+
* USAePay: Handle additional error codes and add default error code [estelendur] #3167
|
57
|
+
* Braintree: Add `skip_avs` and `skip_cvv` gateway specific fields [leila-alderman] #3241
|
58
|
+
* NAB Transact: Update periodic test url [mengqing] #3177
|
59
|
+
* NMI: Add level 3 gateway-specific fields tax, shipping, and ponumber [jasonxp] #3239
|
60
|
+
* Checkout V2: Update stored card flag [curiousepic] #3247
|
61
|
+
* NMI: Add support for stored credentials [bayprogrammer] #3243
|
62
|
+
* Spreedly: Consolidate API requests and support bank accounts [lancecarlson] #3105
|
63
|
+
* BPoint: Hook up merchant_reference and CRN fields [curiousepic] #3249
|
64
|
+
* Checkout V2: Stop sending phone number to Checkout V2 integration [filipebarcos] #3248
|
65
|
+
* Barclaycard Smartpay: Add support for 3DS2 [britth] #3251
|
66
|
+
* Adyen: Add support for non-fractional currencies [molbrown] #3257
|
67
|
+
* Decidir: Add new gateway [jknipp] #3254
|
68
|
+
* Checkout V2: Reapply Update stored card flag [curiousepic]
|
69
|
+
* CyberSource: Update supported countries [molbrown] #3260
|
70
|
+
* Credorax: Update supported countries [molbrown] #3260
|
71
|
+
* Kushki: Update supported countries [molbrown] #3260
|
72
|
+
* Paypal: Update supported countries [molbrown] #3260
|
73
|
+
* BlueSnap: Send amount in capture requests [jknipp] #3262
|
74
|
+
* Mundipagg: Add Alelo card support [jasonxp] #3255
|
75
|
+
* Adyen: Remove temporary amount modification for non-fractional currencies [molbrown] #3263
|
76
|
+
* Adyen: Set blank state to N/A [therufs] #3252
|
77
|
+
* MiGS: Add tx_source gateway specific field [leila-alderman] #3264
|
78
|
+
* NMI: Correct password scrubber to scrub symbols [hdeters] #3267
|
79
|
+
* Global Collect: Only add name if present [curiousepic] #3268
|
80
|
+
* HPS: Add Apple Pay raw cryptogram support [slogsdon] #3209
|
81
|
+
* CardConnect: Fix parsing of level 3 fields [hdeters] #3273
|
82
|
+
* TrustCommerce: Support void after purchase [jknipp] #3265
|
83
|
+
* Payflow: Support arbitrary level 2 + level 3 fields [therufs] #3272
|
84
|
+
* BlueSnap: Default to not send amount on capture [molbrown] #3270
|
85
|
+
* Spreedly: extra fields, remove extraneous check [montdidier] #3102 #3281
|
86
|
+
* Cecabank: Update encryption to SHA2 [leila-alderman] #3278
|
87
|
+
* Checkout V2: Fix 3DS 1&2 integration [nicolas-maalouf-cko] #3240
|
88
|
+
* Credorax: add 3DS2 MPI auth data support [bayprogrammer] #3274
|
89
|
+
* Add Kosovo to the list of countries [AnotherJoSmith] #3226
|
90
|
+
* Realex: Adds 3DS 1&2 support through external MPI [filipebarcos] #3284
|
91
|
+
* PayPal: Adds 3DS 1 support through external MPI [nebdil] #3279
|
92
|
+
|
93
|
+
== Version 1.95.0 (May 23, 2019)
|
94
|
+
* Adyen: Constantize version to fix subdomains [curiousepic] #3228
|
95
|
+
* Qvalent: Adds support for standard stored credential framework [molbrown] #3227
|
96
|
+
* Cybersource: Send tokenization data when card is :master [pi3r] #3230
|
97
|
+
|
98
|
+
== Version 1.94.0 (May 21, 2019)
|
99
|
+
* Mundipagg: Fix number lengths for both VR and Sodexo [dtykocki] #3195
|
100
|
+
* Stripe: Support show and list webhook endpoints [jknipp] #3196
|
101
|
+
* CardConnect: Add frontendid parameter to requests [gcatlin] #3198
|
102
|
+
* Adyen: Correct formatting of Billing Address [nfarve] #3200
|
103
|
+
* Stripe: Stripe: Show payment source [jknipp] #3202
|
104
|
+
* Checkout V2: Checkout V2: Correct success criteria [curiousepic] #3205
|
105
|
+
* Adyen: Add normalized hash of 3DS 2.0 data fields from web browsers [davidsantoso] #3207
|
106
|
+
* Stripe: Do not attempt application fee refund if refund was not successful [jasonwebster] #3206
|
107
|
+
* Elavon: Send transaction_currency if currency is provided [gcatlin] #3201
|
108
|
+
* Elavon: Multi-currency support [jknipp] #3210
|
109
|
+
* Adyen: Support preAuths and Synchronous Adjusts [curiousepic] #3212
|
110
|
+
* WorldPay: Support Unknown Card Type [tanyajajodia] #3213
|
111
|
+
* Mundipagg: Make gateway_affiliation_id an option [curiousepic] #3219
|
112
|
+
* CyberSource: Adds Elo Card Type [tanyajajodia] #3220
|
113
|
+
* CyberSource: Support standalone credit for cards [curiousepic] #3225
|
114
|
+
|
4
115
|
== Version 1.93.0 (April 18, 2019)
|
5
116
|
* Stripe: Do not consider a refund unsuccessful if only refunding the fee failed [jasonwebster] #3188
|
6
117
|
* Stripe: Fix webhook creation for connected account [jknipp] #3193
|
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,15 +6,18 @@ 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}$/ },
|
14
16
|
'maestro' => ->(num) { (12..19).cover?(num&.size) && in_bin_range?(num.slice(0, 6), MAESTRO_RANGES) },
|
15
17
|
'forbrugsforeningen' => ->(num) { num =~ /^600722\d{10}$/ },
|
16
|
-
'sodexo' => ->(num) { num =~ /^(606071|603389|606070|606069|606068|600818)\d{
|
17
|
-
'vr' => ->(num) { num =~ /^(627416|637036)\d{
|
18
|
+
'sodexo' => ->(num) { num =~ /^(606071|603389|606070|606069|606068|600818)\d{10}$/ },
|
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]
|
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
|
|
@@ -80,6 +84,7 @@ module ActiveMerchant #:nodoc:
|
|
80
84
|
post = init_post(options)
|
81
85
|
add_invoice_for_modification(post, money, options)
|
82
86
|
add_reference(post, authorization, options)
|
87
|
+
add_extra_data(post, nil, options)
|
83
88
|
commit('adjustAuthorisation', post, options)
|
84
89
|
end
|
85
90
|
|
@@ -137,10 +142,14 @@ module ActiveMerchant #:nodoc:
|
|
137
142
|
'16' => 'N', # Postal code doesn't match, address unknown
|
138
143
|
'17' => 'U', # Postal code doesn't match, address not checked
|
139
144
|
'18' => 'I', # Neither postal code nor address were checked
|
145
|
+
'19' => 'L', # Name and postal code matches.
|
140
146
|
'20' => 'V', # Name, address and postal code matches.
|
147
|
+
'21' => 'O', # Name and address matches.
|
148
|
+
'22' => 'K', # Name matches.
|
141
149
|
'23' => 'F', # Postal code matches, name doesn't match.
|
142
150
|
'24' => 'H', # Both postal code and address matches, name doesn't match.
|
143
|
-
'25' => 'T' # Address matches, name doesn't match.
|
151
|
+
'25' => 'T', # Address matches, name doesn't match.
|
152
|
+
'26' => 'N' # Neither postal code, address nor name matches.
|
144
153
|
}
|
145
154
|
|
146
155
|
CVC_MAPPING = {
|
@@ -174,6 +183,11 @@ module ActiveMerchant #:nodoc:
|
|
174
183
|
post[:additionalData][:overwriteBrand] = normalize(options[:overwrite_brand]) if options[:overwrite_brand]
|
175
184
|
post[:additionalData][:customRoutingFlag] = options[:custom_routing_flag] if options[:custom_routing_flag]
|
176
185
|
post[:additionalData]['paymentdatasource.type'] = NETWORK_TOKENIZATION_CARD_SOURCE[payment.source.to_s] if payment.is_a?(NetworkTokenizationCreditCard)
|
186
|
+
post[:additionalData][:authorisationType] = options[:authorisation_type] if options[:authorisation_type]
|
187
|
+
post[:additionalData][:adjustAuthorisationData] = options[:adjust_authorisation_data] if options[:adjust_authorisation_data]
|
188
|
+
post[:additionalData][:industryUsage] = options[:industry_usage] if options[:industry_usage]
|
189
|
+
post[:additionalData][:updateShopperStatement] = options[:update_shopper_statement] if options[:update_shopper_statement]
|
190
|
+
post[:additionalData][:RequestedTestAcquirerResponseCode] = options[:requested_test_acquirer_response_code] if options[:requested_test_acquirer_response_code] && test?
|
177
191
|
post[:deviceFingerprint] = options[:device_fingerprint] if options[:device_fingerprint]
|
178
192
|
add_risk_data(post, options)
|
179
193
|
end
|
@@ -214,28 +228,34 @@ module ActiveMerchant #:nodoc:
|
|
214
228
|
def add_address(post, options)
|
215
229
|
return unless post[:card]&.kind_of?(Hash)
|
216
230
|
if (address = options[:billing_address] || options[:address]) && address[:country]
|
217
|
-
post[:
|
218
|
-
post[:
|
219
|
-
post[:
|
220
|
-
post[:
|
221
|
-
post[:
|
222
|
-
post[:
|
223
|
-
post[:
|
231
|
+
post[:billingAddress] = {}
|
232
|
+
post[:billingAddress][:street] = address[:address1] || 'N/A'
|
233
|
+
post[:billingAddress][:houseNumberOrName] = address[:address2] || 'N/A'
|
234
|
+
post[:billingAddress][:postalCode] = address[:zip] if address[:zip]
|
235
|
+
post[:billingAddress][:city] = address[:city] || 'N/A'
|
236
|
+
post[:billingAddress][:stateOrProvince] = get_state(address)
|
237
|
+
post[:billingAddress][:country] = address[:country] if address[:country]
|
224
238
|
end
|
225
239
|
end
|
226
240
|
|
241
|
+
def get_state(address)
|
242
|
+
address[:state] && !address[:state].blank? ? address[:state] : 'N/A'
|
243
|
+
end
|
244
|
+
|
227
245
|
def add_invoice(post, money, options)
|
246
|
+
currency = options[:currency] || currency(money)
|
228
247
|
amount = {
|
229
|
-
value:
|
230
|
-
currency:
|
248
|
+
value: localized_amount(money, currency),
|
249
|
+
currency: currency
|
231
250
|
}
|
232
251
|
post[:amount] = amount
|
233
252
|
end
|
234
253
|
|
235
254
|
def add_invoice_for_modification(post, money, options)
|
255
|
+
currency = options[:currency] || currency(money)
|
236
256
|
amount = {
|
237
|
-
value:
|
238
|
-
currency:
|
257
|
+
value: localized_amount(money, currency),
|
258
|
+
currency: currency
|
239
259
|
}
|
240
260
|
post[:modificationAmount] = amount
|
241
261
|
end
|
@@ -308,9 +328,57 @@ module ActiveMerchant #:nodoc:
|
|
308
328
|
end
|
309
329
|
|
310
330
|
def add_3ds(post, options)
|
311
|
-
|
312
|
-
|
313
|
-
|
331
|
+
if three_ds_2_options = options[:three_ds_2]
|
332
|
+
device_channel = three_ds_2_options[:channel]
|
333
|
+
if device_channel == 'app'
|
334
|
+
post[:threeDS2RequestData] = { deviceChannel: device_channel }
|
335
|
+
else
|
336
|
+
add_browser_info(three_ds_2_options[:browser_info], post)
|
337
|
+
post[:threeDS2RequestData] = { deviceChannel: device_channel, notificationURL: three_ds_2_options[:notification_url] }
|
338
|
+
end
|
339
|
+
else
|
340
|
+
return unless options[:execute_threed] || options[:threed_dynamic]
|
341
|
+
post[:browserInfo] = { userAgent: options[:user_agent], acceptHeader: options[:accept_header] }
|
342
|
+
post[:additionalData] = { executeThreeD: 'true' } if options[:execute_threed]
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
def add_3ds_authenticated_data(post, options)
|
347
|
+
if options[:three_d_secure] && options[:three_d_secure][:eci] && options[:three_d_secure][:xid]
|
348
|
+
add_3ds1_authenticated_data(post, options)
|
349
|
+
elsif options[:three_d_secure]
|
350
|
+
add_3ds2_authenticated_data(post, options)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
def add_3ds1_authenticated_data(post, options)
|
355
|
+
three_d_secure_options = options[:three_d_secure]
|
356
|
+
post[:mpiData] = {
|
357
|
+
cavv: three_d_secure_options[:cavv],
|
358
|
+
cavvAlgorithm: three_d_secure_options[:cavv_algorithm],
|
359
|
+
eci: three_d_secure_options[:eci],
|
360
|
+
xid: three_d_secure_options[:xid],
|
361
|
+
directoryResponse: three_d_secure_options[:directory_response_status],
|
362
|
+
authenticationResponse: three_d_secure_options[:authentication_response_status]
|
363
|
+
}
|
364
|
+
end
|
365
|
+
|
366
|
+
def add_3ds2_authenticated_data(post, options)
|
367
|
+
three_d_secure_options = options[:three_d_secure]
|
368
|
+
# If the transaction was authenticated in a frictionless flow, send the transStatus from the ARes.
|
369
|
+
if(three_d_secure_options[:authentication_response_status].nil?)
|
370
|
+
authentication_response = three_d_secure_options[:directory_response_status]
|
371
|
+
else
|
372
|
+
authentication_response = three_d_secure_options[:authentication_response_status]
|
373
|
+
end
|
374
|
+
post[:mpiData] = {
|
375
|
+
threeDSVersion: three_d_secure_options[:version],
|
376
|
+
eci: three_d_secure_options[:eci],
|
377
|
+
cavv: three_d_secure_options[:cavv],
|
378
|
+
dsTransID: three_d_secure_options[:ds_transaction_id],
|
379
|
+
directoryResponse: three_d_secure_options[:directory_response_status],
|
380
|
+
authenticationResponse: authentication_response
|
381
|
+
}
|
314
382
|
end
|
315
383
|
|
316
384
|
def parse(body)
|
@@ -349,11 +417,11 @@ module ActiveMerchant #:nodoc:
|
|
349
417
|
|
350
418
|
def url
|
351
419
|
if test?
|
352
|
-
test_url
|
420
|
+
"#{test_url}#{API_VERSION}"
|
353
421
|
elsif @options[:subdomain]
|
354
|
-
"https://#{@options[:subdomain]}-pal-live.adyenpayments.com/pal/servlet/Payment
|
422
|
+
"https://#{@options[:subdomain]}-pal-live.adyenpayments.com/pal/servlet/Payment/#{API_VERSION}"
|
355
423
|
else
|
356
|
-
live_url
|
424
|
+
"#{live_url}#{API_VERSION}"
|
357
425
|
end
|
358
426
|
end
|
359
427
|
|
@@ -374,8 +442,10 @@ module ActiveMerchant #:nodoc:
|
|
374
442
|
case action.to_s
|
375
443
|
when 'authorise', 'authorise3d'
|
376
444
|
['Authorised', 'Received', 'RedirectShopper'].include?(response['resultCode'])
|
377
|
-
when 'capture', 'refund', 'cancel'
|
445
|
+
when 'capture', 'refund', 'cancel'
|
378
446
|
response['response'] == "[#{action}-received]"
|
447
|
+
when 'adjustAuthorisation'
|
448
|
+
response['response'] == 'Authorised' || response['response'] == '[adjustAuthorisation-received]'
|
379
449
|
else
|
380
450
|
false
|
381
451
|
end
|
@@ -414,6 +484,20 @@ module ActiveMerchant #:nodoc:
|
|
414
484
|
def error_code_from(response)
|
415
485
|
STANDARD_ERROR_CODE_MAPPING[response['errorCode']]
|
416
486
|
end
|
487
|
+
|
488
|
+
def add_browser_info(browser_info, post)
|
489
|
+
return unless browser_info
|
490
|
+
post[:browserInfo] = {
|
491
|
+
acceptHeader: browser_info[:accept_header],
|
492
|
+
colorDepth: browser_info[:depth],
|
493
|
+
javaEnabled: browser_info[:java],
|
494
|
+
language: browser_info[:language],
|
495
|
+
screenHeight: browser_info[:height],
|
496
|
+
screenWidth: browser_info[:width],
|
497
|
+
timeZoneOffset: browser_info[:timezone],
|
498
|
+
userAgent: browser_info[:user_agent]
|
499
|
+
}
|
500
|
+
end
|
417
501
|
end
|
418
502
|
end
|
419
503
|
end
|