activemerchant 1.93.0 → 1.98.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 +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
|