activemerchant 1.57.0 → 1.58.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 +21 -0
- data/README.md +2 -1
- data/lib/active_merchant/billing/credit_card_methods.rb +36 -0
- data/lib/active_merchant/billing/gateways/card_stream.rb +17 -15
- data/lib/active_merchant/billing/gateways/clearhaus.rb +6 -1
- data/lib/active_merchant/billing/gateways/mercury.rb +12 -4
- data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +1 -1
- data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -1
- data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -4
- data/lib/active_merchant/billing/gateways/stripe.rb +58 -7
- data/lib/active_merchant/billing/gateways/trans_first.rb +15 -10
- data/lib/active_merchant/version.rb +1 -1
- metadata +2 -3
- data/lib/active_merchant/billing/gateways/app55.rb +0 -176
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da3af9432d84476a6bb80c8c2ce551def7cb9aad
|
4
|
+
data.tar.gz: f0fca6c6c9aea70ec6fe8ba476aee0e0087bab14
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2d71c5586712ab174a2aea4da55ce52e10e4df6d11207ee46d85e3ea337feb698137e5b9c80b9f764f33e7d157bd31f15e3f097e5aaa866c60df2c48960525e
|
7
|
+
data.tar.gz: 831bc61882f81730b31b6f46d29e45a4d41e239c15209ff40a20abca24fe89bee9a1b04e31df0a900ccab1edd0a12ad501b46c7ae818c19dadcde21930c00da9
|
data/CHANGELOG
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
= ActiveMerchant CHANGELOG
|
2
2
|
|
3
|
+
== Version 1.58.0 (March 1, 2016)
|
4
|
+
* Move Electron check out of CreditCard into CreditCardMethods [ThereExistsX]
|
5
|
+
* CardStream: Add AED and NZD currencies [sdball]
|
6
|
+
* App55: Remove Gateway [ThereExistsX]
|
7
|
+
* Mercury: Stripping the start and end sentinels on card-present track data for max-length track1 requests [ryanbalsdon]
|
8
|
+
* SagePay: Update VISA Electron ranges [sdball]
|
9
|
+
* Clearhaus: Make request signing more transparent & robust [sdball]
|
10
|
+
* NCRSecurePay: Fix production URL [rwdaigle]
|
11
|
+
* Add ACH support to Stripe [sdball]
|
12
|
+
* PayPal Express: Fixing list of currencies without fractions [Krystosterone]
|
13
|
+
* Cashnet: Default custcode option and proper redirect handling [rwdaigle]
|
14
|
+
* TransFirst: Fix missing address and remove CC only fields for ACH [davidsantoso]
|
15
|
+
* More prominent links to contribution docs [rwdaigle]
|
16
|
+
|
17
|
+
|
3
18
|
== Version 1.57.0 (February 1, 2016)
|
4
19
|
* AuthorizeNetCim: Add unmaskExpirationDate option [RamilGilmanov]
|
5
20
|
* Element: Add gateway support [davidsantoso]
|
@@ -37,6 +52,12 @@
|
|
37
52
|
* Stripe: Add `stripe_account` header option [anellis]
|
38
53
|
* Cardstream: Add AVS code and message [anellis]
|
39
54
|
* Barclaycard Smartpay: New gateway support [curiousepic]
|
55
|
+
* Transfirst: Fix missing address and remove CC only fields for ACH [davidsantoso]
|
56
|
+
* Stripe: Support ACH payments [sdball]
|
57
|
+
* NCRSecurePay: Fix production URL [rwdaigle]
|
58
|
+
* Clearhaus: Make request signing more transparent & robust [sdball]
|
59
|
+
* SagePay: Properly detect Electron brand [sdball]
|
60
|
+
* Mercury: Fix for max-length track 1 [ryanbalsdon]
|
40
61
|
|
41
62
|
|
42
63
|
== Version 1.56.0 (December 1, 2015)
|
data/README.md
CHANGED
@@ -17,6 +17,8 @@ from an ever-growing set of contributors.
|
|
17
17
|
See [GettingStarted.md](GettingStarted.md) if you want to learn more about using Active Merchant in your
|
18
18
|
applications.
|
19
19
|
|
20
|
+
If you'd like to contribute to Active Merchant, please start with our [contribution guide](CONTRIBUTING.md).
|
21
|
+
|
20
22
|
## Installation
|
21
23
|
|
22
24
|
### From Git
|
@@ -82,7 +84,6 @@ For more in-depth documentation and tutorials, see [GettingStarted.md](GettingSt
|
|
82
84
|
|
83
85
|
The [ActiveMerchant Wiki](http://github.com/activemerchant/active_merchant/wikis) contains a [table of features supported by each gateway](http://github.com/activemerchant/active_merchant/wikis/gatewayfeaturematrix).
|
84
86
|
|
85
|
-
* [App55](https://www.app55.com/) - AU, BR, CA, CH, CL, CN, CO, CZ, DK, EU, GB, HK, HU, ID, IS, JP, KE, KR, MX, MY, NO, NZ, PH, PL, TH, TW, US, VN, ZA
|
86
87
|
* [Authorize.Net CIM](http://www.authorize.net/) - US
|
87
88
|
* [Authorize.Net](http://www.authorize.net/) - AD, AT, AU, BE, BG, CA, CH, CY, CZ, DE, DK, ES, FI, FR, GB, GB, GI, GR, HU, IE, IT, LI, LU, MC, MT, NL, NO, PL, PT, RO, SE, SI, SK, SM, TR, US, VA
|
88
89
|
* [Axcess MS](http://www.axcessms.com/) - AD, AT, BE, BG, BR, CA, CH, CY, CZ, DE, DK, EE, ES, FI, FO, FR, GB, GI, GR, HR, HU, IE, IL, IM, IS, IT, LI, LT, LU, LV, MC, MT, MX, NL, NO, PL, PT, RO, RU, SE, SI, SK, TR, US, VA
|
@@ -17,6 +17,26 @@ module ActiveMerchant #:nodoc:
|
|
17
17
|
'laser' => /^(6304|6706|6709|6771(?!89))\d{8}(\d{4}|\d{6,7})?$/
|
18
18
|
}
|
19
19
|
|
20
|
+
# http://www.barclaycard.co.uk/business/files/bin_rules.pdf
|
21
|
+
ELECTRON_RANGES = [
|
22
|
+
[400115],
|
23
|
+
(400837..400839),
|
24
|
+
(412921..412923),
|
25
|
+
[417935],
|
26
|
+
(419740..419741),
|
27
|
+
(419773..419775),
|
28
|
+
[424519],
|
29
|
+
(424962..424963),
|
30
|
+
[437860],
|
31
|
+
[444000],
|
32
|
+
[459472],
|
33
|
+
(484406..484411),
|
34
|
+
(484413..484414),
|
35
|
+
(484418..484418),
|
36
|
+
(484428..484455),
|
37
|
+
(491730..491759),
|
38
|
+
]
|
39
|
+
|
20
40
|
def self.included(base)
|
21
41
|
base.extend(ClassMethods)
|
22
42
|
end
|
@@ -58,6 +78,11 @@ module ActiveMerchant #:nodoc:
|
|
58
78
|
(number.to_s =~ /^\d{1,2}$/)
|
59
79
|
end
|
60
80
|
|
81
|
+
# Returns if the card matches known Electron BINs
|
82
|
+
def electron?
|
83
|
+
self.class.electron?(number)
|
84
|
+
end
|
85
|
+
|
61
86
|
module ClassMethods
|
62
87
|
# Returns true if it validates. Optionally, you can pass a card brand as an argument and
|
63
88
|
# make sure it is of the correct brand.
|
@@ -106,6 +131,17 @@ module ActiveMerchant #:nodoc:
|
|
106
131
|
return nil
|
107
132
|
end
|
108
133
|
|
134
|
+
def electron?(number)
|
135
|
+
return false unless [16, 19].include?(number.length)
|
136
|
+
|
137
|
+
# don't recalculate for each range
|
138
|
+
bank_identification_number = first_digits(number).to_i
|
139
|
+
|
140
|
+
ELECTRON_RANGES.any? do |range|
|
141
|
+
range.include?(bank_identification_number)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
109
145
|
def type?(number)
|
110
146
|
ActiveMerchant.deprecated "CreditCard#type? is deprecated and will be removed from a future release of ActiveMerchant. Please use CreditCard#brand? instead."
|
111
147
|
brand?(number)
|
@@ -13,21 +13,23 @@ module ActiveMerchant #:nodoc:
|
|
13
13
|
self.display_name = 'CardStream'
|
14
14
|
|
15
15
|
CURRENCY_CODES = {
|
16
|
-
"
|
17
|
-
"
|
18
|
-
"
|
19
|
-
"
|
20
|
-
"
|
21
|
-
"
|
22
|
-
"
|
23
|
-
"
|
24
|
-
"
|
25
|
-
"
|
26
|
-
"
|
27
|
-
"
|
28
|
-
"
|
29
|
-
"
|
30
|
-
"
|
16
|
+
"AED" => "784",
|
17
|
+
"AUD" => "036",
|
18
|
+
"BRL" => "986",
|
19
|
+
"CAD" => "124",
|
20
|
+
"CHF" => "756",
|
21
|
+
"CZK" => "203",
|
22
|
+
"DKK" => "208",
|
23
|
+
"EUR" => "978",
|
24
|
+
"GBP" => "826",
|
25
|
+
"HKD" => "344",
|
26
|
+
"ICK" => "352",
|
27
|
+
"JPY" => "392",
|
28
|
+
"NOK" => "578",
|
29
|
+
"NZD" => "554",
|
30
|
+
"SEK" => "752",
|
31
|
+
"SGD" => "702",
|
32
|
+
"USD" => "840",
|
31
33
|
}
|
32
34
|
|
33
35
|
CVV_CODE = {
|
@@ -44,6 +44,7 @@ module ActiveMerchant #:nodoc:
|
|
44
44
|
# :signing_key - merchant's private key for optionally signing request
|
45
45
|
def initialize(options={})
|
46
46
|
requires!(options, :api_key)
|
47
|
+
options[:signing_key].strip! if options[:signing_key]
|
47
48
|
super
|
48
49
|
end
|
49
50
|
|
@@ -183,7 +184,11 @@ module ActiveMerchant #:nodoc:
|
|
183
184
|
body = parameters.to_query
|
184
185
|
|
185
186
|
if signing_key = @options[:signing_key]
|
186
|
-
|
187
|
+
begin
|
188
|
+
headers["Signature"] = generate_signature(@options[:api_key], signing_key, body)
|
189
|
+
rescue OpenSSL::PKey::RSAError => e
|
190
|
+
return Response.new(false, e.message)
|
191
|
+
end
|
187
192
|
end
|
188
193
|
|
189
194
|
response = begin
|
@@ -197,12 +197,20 @@ module ActiveMerchant #:nodoc:
|
|
197
197
|
if credit_card.track_data.present?
|
198
198
|
# Track 1 has a start sentinel (STX) of '%' and track 2 is ';'
|
199
199
|
# Track 1 and 2 have identical end sentinels (ETX) of '?'
|
200
|
+
# Tracks may or may not have checksum (LRC) after the ETX
|
200
201
|
# If the track has no STX or is corrupt, we send it as track 1, to let Mercury
|
201
202
|
#handle with the validation error as it sees fit.
|
202
|
-
# Track 2 requires having the
|
203
|
-
|
204
|
-
|
205
|
-
|
203
|
+
# Track 2 requires having the STX and ETX stripped. Track 1 does not.
|
204
|
+
# Max-length track 1s require having the STX and ETX stripped. Max is 79 bytes including LRC.
|
205
|
+
is_track_2 = credit_card.track_data[0] == ';'
|
206
|
+
etx_index = credit_card.track_data.rindex('?') || credit_card.track_data.length
|
207
|
+
is_max_track1 = etx_index >= 77
|
208
|
+
|
209
|
+
if is_track_2
|
210
|
+
xml.tag! 'Track2', credit_card.track_data[1...etx_index]
|
211
|
+
elsif is_max_track1
|
212
|
+
xml.tag! 'Track1', credit_card.track_data[1...etx_index]
|
213
|
+
else
|
206
214
|
xml.tag! 'Track1', credit_card.track_data
|
207
215
|
end
|
208
216
|
else
|
@@ -4,7 +4,7 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
module Billing #:nodoc:
|
5
5
|
class NcrSecurePayGateway < Gateway
|
6
6
|
self.test_url = 'https://testbox.monetra.com:8665/'
|
7
|
-
self.live_url = 'https://
|
7
|
+
self.live_url = 'https://portal.ncrsecurepay.com:8444/'
|
8
8
|
|
9
9
|
self.supported_countries = ['US']
|
10
10
|
self.default_currency = 'USD'
|
@@ -26,7 +26,7 @@ module ActiveMerchant #:nodoc:
|
|
26
26
|
'TW' => 'zh_TW'
|
27
27
|
}
|
28
28
|
|
29
|
-
CURRENCIES_WITHOUT_FRACTIONS = %w(
|
29
|
+
CURRENCIES_WITHOUT_FRACTIONS = %w(HUF JPY TWD)
|
30
30
|
|
31
31
|
self.test_redirect_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'
|
32
32
|
self.supported_countries = ['US']
|
@@ -36,8 +36,6 @@ module ActiveMerchant #:nodoc:
|
|
36
36
|
:jcb => "JCB"
|
37
37
|
}
|
38
38
|
|
39
|
-
ELECTRON = /^(424519|42496[23]|450875|48440[6-8]|4844[1-5][1-5]|4917[3-5][0-9]|491880)\d{10}(\d{3})?$/
|
40
|
-
|
41
39
|
AVS_CVV_CODE = {
|
42
40
|
"NOTPROVIDED" => nil,
|
43
41
|
"NOTCHECKED" => 'X',
|
@@ -292,8 +290,7 @@ module ActiveMerchant #:nodoc:
|
|
292
290
|
|
293
291
|
card_type = card_brand(credit_card).to_sym
|
294
292
|
|
295
|
-
|
296
|
-
if card_type == :visa && credit_card.number =~ ELECTRON
|
293
|
+
if card_type == :visa && credit_card.electron?
|
297
294
|
CREDIT_CARDS[:electron]
|
298
295
|
else
|
299
296
|
CREDIT_CARDS[card_type]
|
@@ -46,6 +46,11 @@ module ActiveMerchant #:nodoc:
|
|
46
46
|
'incorrect_pin' => STANDARD_ERROR_CODE[:incorrect_pin]
|
47
47
|
}
|
48
48
|
|
49
|
+
BANK_ACCOUNT_HOLDER_TYPE_MAPPING = {
|
50
|
+
"personal" => "individual",
|
51
|
+
"business" => "company",
|
52
|
+
}
|
53
|
+
|
49
54
|
def initialize(options = {})
|
50
55
|
requires!(options, :login)
|
51
56
|
@api_key = options[:login]
|
@@ -80,6 +85,11 @@ module ActiveMerchant #:nodoc:
|
|
80
85
|
#
|
81
86
|
# purchase(money, nil, { :customer => id, ... })
|
82
87
|
def purchase(money, payment, options = {})
|
88
|
+
if ach?(payment)
|
89
|
+
direct_bank_error = "Direct bank account transactions are not supported. Bank accounts must be stored and verified before use."
|
90
|
+
return Response.new(false, direct_bank_error)
|
91
|
+
end
|
92
|
+
|
83
93
|
MultiResponse.run do |r|
|
84
94
|
if payment.is_a?(ApplePayPaymentToken)
|
85
95
|
r.process { tokenize_apple_pay_token(payment) }
|
@@ -155,26 +165,34 @@ module ActiveMerchant #:nodoc:
|
|
155
165
|
|
156
166
|
# Note: creating a new credit card will not change the customer's existing default credit card (use :set_default => true)
|
157
167
|
def store(payment, options = {})
|
158
|
-
|
168
|
+
params = {}
|
159
169
|
post = {}
|
160
170
|
|
161
|
-
if payment
|
171
|
+
if card_brand(payment) == "check"
|
172
|
+
bank_token_response = tokenize_bank_account(payment)
|
173
|
+
if bank_token_response.success?
|
174
|
+
params = { source: bank_token_response.params["token"]["id"] }
|
175
|
+
else
|
176
|
+
return bank_token_response
|
177
|
+
end
|
178
|
+
elsif payment.is_a?(ApplePayPaymentToken)
|
162
179
|
token_exchange_response = tokenize_apple_pay_token(payment)
|
163
|
-
|
180
|
+
params = { card: token_exchange_response.params["token"]["id"] } if token_exchange_response.success?
|
164
181
|
else
|
165
|
-
add_creditcard(
|
182
|
+
add_creditcard(params, payment, options)
|
166
183
|
end
|
167
184
|
|
168
185
|
post[:validate] = options[:validate] unless options[:validate].nil?
|
169
186
|
post[:description] = options[:description] if options[:description]
|
170
187
|
post[:email] = options[:email] if options[:email]
|
188
|
+
|
171
189
|
if options[:account]
|
172
|
-
add_external_account(post,
|
190
|
+
add_external_account(post, params, payment)
|
173
191
|
commit(:post, "accounts/#{CGI.escape(options[:account])}/external_accounts", post, options)
|
174
192
|
elsif options[:customer]
|
175
193
|
MultiResponse.run(:first) do |r|
|
176
194
|
# The /cards endpoint does not update other customer parameters.
|
177
|
-
r.process { commit(:post, "customers/#{CGI.escape(options[:customer])}/cards",
|
195
|
+
r.process { commit(:post, "customers/#{CGI.escape(options[:customer])}/cards", params, options) }
|
178
196
|
|
179
197
|
if options[:set_default] and r.success? and !r.params['id'].blank?
|
180
198
|
post[:default_card] = r.params['id']
|
@@ -185,7 +203,7 @@ module ActiveMerchant #:nodoc:
|
|
185
203
|
end
|
186
204
|
end
|
187
205
|
else
|
188
|
-
commit(:post, 'customers', post.merge(
|
206
|
+
commit(:post, 'customers', post.merge(params), options)
|
189
207
|
end
|
190
208
|
end
|
191
209
|
|
@@ -542,6 +560,39 @@ module ActiveMerchant #:nodoc:
|
|
542
560
|
error_code ||= STANDARD_ERROR_CODE_MAPPING[code]
|
543
561
|
error_code
|
544
562
|
end
|
563
|
+
|
564
|
+
def tokenize_bank_account(bank_account, options = {})
|
565
|
+
account_holder_type = BANK_ACCOUNT_HOLDER_TYPE_MAPPING[bank_account.account_holder_type]
|
566
|
+
|
567
|
+
post = {
|
568
|
+
bank_account: {
|
569
|
+
account_number: bank_account.account_number,
|
570
|
+
country: 'US',
|
571
|
+
currency: 'usd',
|
572
|
+
routing_number: bank_account.routing_number,
|
573
|
+
name: bank_account.name,
|
574
|
+
account_holder_type: account_holder_type,
|
575
|
+
}
|
576
|
+
}
|
577
|
+
|
578
|
+
token_response = api_request(:post, "tokens?#{post_data(post)}")
|
579
|
+
success = token_response["error"].nil?
|
580
|
+
|
581
|
+
if success && token_response["id"]
|
582
|
+
Response.new(success, nil, token: token_response)
|
583
|
+
else
|
584
|
+
Response.new(success, token_response["error"]["message"])
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
588
|
+
def ach?(payment_method)
|
589
|
+
case payment_method
|
590
|
+
when String, nil
|
591
|
+
false
|
592
|
+
else
|
593
|
+
card_brand(payment_method) == "check"
|
594
|
+
end
|
595
|
+
end
|
545
596
|
end
|
546
597
|
end
|
547
598
|
end
|
@@ -38,24 +38,27 @@ module ActiveMerchant #:nodoc:
|
|
38
38
|
post = {}
|
39
39
|
|
40
40
|
add_amount(post, money)
|
41
|
-
add_invoice(post, options)
|
42
41
|
add_payment(post, payment)
|
43
42
|
add_address(post, options)
|
43
|
+
add_invoice(post, options) if payment.is_a?(CreditCard)
|
44
|
+
add_pair(post, :RefID, options[:order_id], required: true)
|
44
45
|
|
45
46
|
commit((payment.is_a?(Check) ? :purchase_echeck : :purchase), post)
|
46
47
|
end
|
47
48
|
|
48
49
|
def refund(money, authorization, options={})
|
49
50
|
post = {}
|
51
|
+
|
50
52
|
transaction_id, payment_type = split_authorization(authorization)
|
51
53
|
add_amount(post, money)
|
52
|
-
add_invoice(post, options)
|
53
54
|
add_pair(post, :TransID, transaction_id)
|
55
|
+
|
54
56
|
commit((payment_type == "check" ? :refund_echeck : :refund), post)
|
55
57
|
end
|
56
58
|
|
57
59
|
def void(authorization, options={})
|
58
60
|
post = {}
|
61
|
+
|
59
62
|
transaction_id, _ = split_authorization(authorization)
|
60
63
|
add_pair(post, :TransID, transaction_id)
|
61
64
|
|
@@ -85,13 +88,15 @@ module ActiveMerchant #:nodoc:
|
|
85
88
|
address = options[:billing_address] || options[:address]
|
86
89
|
|
87
90
|
if address
|
88
|
-
add_pair(post, :Address, address[:address1])
|
89
|
-
add_pair(post, :ZipCode, address[:zip])
|
91
|
+
add_pair(post, :Address, address[:address1], required: true)
|
92
|
+
add_pair(post, :ZipCode, address[:zip], required: true)
|
93
|
+
else
|
94
|
+
add_pair(post, :Address, "", required: true)
|
95
|
+
add_pair(post, :ZipCode, "", required: true)
|
90
96
|
end
|
91
97
|
end
|
92
98
|
|
93
99
|
def add_invoice(post, options)
|
94
|
-
add_pair(post, :RefID, options[:order_id], required: true)
|
95
100
|
add_pair(post, :SECCCode, options[:invoice], required: true)
|
96
101
|
add_pair(post, :PONumber, options[:invoice], required: true)
|
97
102
|
add_pair(post, :SaleTaxAmount, amount(options[:tax] || 0))
|
@@ -130,8 +135,8 @@ module ActiveMerchant #:nodoc:
|
|
130
135
|
return default_value
|
131
136
|
end
|
132
137
|
|
133
|
-
def add_unused_fields(post)
|
134
|
-
return
|
138
|
+
def add_unused_fields(action, post)
|
139
|
+
return unless action == :purchase
|
135
140
|
|
136
141
|
UNUSED_CREDIT_CARD_FIELDS.each do |f|
|
137
142
|
post[f] = ""
|
@@ -163,7 +168,7 @@ module ActiveMerchant #:nodoc:
|
|
163
168
|
end
|
164
169
|
|
165
170
|
def commit(action, params)
|
166
|
-
response = parse(ssl_post(url(action), post_data(params)))
|
171
|
+
response = parse(ssl_post(url(action), post_data(action, params)))
|
167
172
|
|
168
173
|
Response.new(
|
169
174
|
success_from(response),
|
@@ -208,8 +213,8 @@ module ActiveMerchant #:nodoc:
|
|
208
213
|
end
|
209
214
|
end
|
210
215
|
|
211
|
-
def post_data(params = {})
|
212
|
-
add_unused_fields(params)
|
216
|
+
def post_data(action, params = {})
|
217
|
+
add_unused_fields(action, params)
|
213
218
|
params[:MerchantID] = @options[:login]
|
214
219
|
params[:RegKey] = @options[:password]
|
215
220
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activemerchant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.58.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Luetke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -162,7 +162,6 @@ files:
|
|
162
162
|
- lib/active_merchant/billing/gateway.rb
|
163
163
|
- lib/active_merchant/billing/gateways.rb
|
164
164
|
- lib/active_merchant/billing/gateways/allied_wallet.rb
|
165
|
-
- lib/active_merchant/billing/gateways/app55.rb
|
166
165
|
- lib/active_merchant/billing/gateways/authorize_net.rb
|
167
166
|
- lib/active_merchant/billing/gateways/authorize_net_arb.rb
|
168
167
|
- lib/active_merchant/billing/gateways/authorize_net_cim.rb
|
@@ -1,176 +0,0 @@
|
|
1
|
-
module ActiveMerchant #:nodoc:
|
2
|
-
module Billing #:nodoc:
|
3
|
-
class App55Gateway < Gateway
|
4
|
-
self.test_url = 'https://sandbox.app55.com/v1/'
|
5
|
-
self.live_url = 'https://api.app55.com/v1/'
|
6
|
-
|
7
|
-
self.supported_countries = ['AU', 'BR', 'CA', 'CH', 'CL', 'CN', 'CO', 'CZ', 'DK', 'GB', 'HK', 'HU', 'ID', 'IS', 'JP', 'KE', 'KR', 'MX', 'MY', 'NO', 'NZ', 'PH', 'PL', 'TH', 'TW', 'US', 'VN', 'ZA']
|
8
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :maestro, :solo]
|
9
|
-
self.default_currency = 'UKP'
|
10
|
-
self.money_format = :dollars
|
11
|
-
self.homepage_url = 'https://www.app55.com/'
|
12
|
-
self.display_name = 'App55'
|
13
|
-
|
14
|
-
# Create gateway
|
15
|
-
#
|
16
|
-
# options:
|
17
|
-
# :api_key - merchants App55 API Key
|
18
|
-
# :api_secret - merchants App55 Secret Key
|
19
|
-
def initialize(options = {})
|
20
|
-
requires!(options, :api_key, :api_secret)
|
21
|
-
@api_key = options[:api_key]
|
22
|
-
@api_secret = options[:api_secret]
|
23
|
-
super
|
24
|
-
end
|
25
|
-
|
26
|
-
# Make a purchase (authorize and commit)
|
27
|
-
#
|
28
|
-
# money - The monetary amount of the transaction in cents.
|
29
|
-
# payment_method - The CreditCard or the App55 card token.
|
30
|
-
# options - A standard ActiveMerchant options hash
|
31
|
-
def purchase(money, payment_method, options = {})
|
32
|
-
authorize(money, payment_method, options.merge(commit: true))
|
33
|
-
end
|
34
|
-
|
35
|
-
# Authorize a transaction.
|
36
|
-
#
|
37
|
-
# money - The monetary amount of the transaction in cents.
|
38
|
-
# payment_method - The CreditCard or the App55 card token.
|
39
|
-
# options - A standard ActiveMerchant options hash
|
40
|
-
def authorize(money, payment_method, options = {})
|
41
|
-
post = {}
|
42
|
-
add_creditcard(post, payment_method, options)
|
43
|
-
add_transaction(post, money, options)
|
44
|
-
|
45
|
-
commit(:post, 'transaction', post)
|
46
|
-
end
|
47
|
-
|
48
|
-
# Commit a pre-authorized transaction.
|
49
|
-
#
|
50
|
-
# money - The monetary amount of the transaction in cents.
|
51
|
-
# authorization - The App55 transaction id string.
|
52
|
-
# options - A standard ActiveMerchant options hash
|
53
|
-
def capture(money, authorization, options = {})
|
54
|
-
commit(:post, "transaction/#{authorization}")
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def add_customer_data(post, options)
|
60
|
-
metadata_options = [:description, :browser_ip, :user_agent, :referrer]
|
61
|
-
post.update(options.slice(*metadata_options))
|
62
|
-
end
|
63
|
-
|
64
|
-
def add_creditcard(post, creditcard, options)
|
65
|
-
card = {}
|
66
|
-
card[:number] = creditcard.number
|
67
|
-
card[:expiry] = ("%02d". % creditcard.month) + '/' + creditcard.year.to_s
|
68
|
-
card[:security_code] = creditcard.verification_value if creditcard.verification_value?
|
69
|
-
card[:holder_name] = creditcard.name if creditcard.name
|
70
|
-
add_address(card, options)
|
71
|
-
post[:card] = card
|
72
|
-
end
|
73
|
-
|
74
|
-
def add_address(card, options)
|
75
|
-
return unless card && card.kind_of?(Hash)
|
76
|
-
address_hash = {}
|
77
|
-
if address = (options[:billing_address] || options[:address])
|
78
|
-
address_hash[:street] = address[:address1] if address[:address1]
|
79
|
-
address_hash[:street2] = address[:address2] if address[:address2]
|
80
|
-
address_hash[:country] = address[:country] if address[:country]
|
81
|
-
address_hash[:postal_code] = address[:zip] if address[:zip]
|
82
|
-
address_hash[:city] = address[:city] if address[:city]
|
83
|
-
card[:address] = address_hash
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def add_transaction(post, money, options)
|
88
|
-
transaction = {}
|
89
|
-
add_amount(transaction, money, options)
|
90
|
-
transaction[:description] = (options[:description] || options[:email])
|
91
|
-
transaction[:commit] = options[:commit]
|
92
|
-
post[:transaction] = transaction
|
93
|
-
end
|
94
|
-
|
95
|
-
def add_amount(obj, money, options)
|
96
|
-
obj[:amount] = amount(money)
|
97
|
-
obj[:currency] = (options[:currency] || currency(money))
|
98
|
-
end
|
99
|
-
|
100
|
-
def parse(body)
|
101
|
-
JSON.parse(body)
|
102
|
-
rescue JSON::ParserError
|
103
|
-
json_error(raw_response)
|
104
|
-
end
|
105
|
-
|
106
|
-
def commit(method, resource, parameters=nil, meta={})
|
107
|
-
success = false
|
108
|
-
begin
|
109
|
-
raw_response = ssl_request(
|
110
|
-
method,
|
111
|
-
url(resource),
|
112
|
-
post_data(parameters),
|
113
|
-
headers
|
114
|
-
)
|
115
|
-
response = parse(raw_response)
|
116
|
-
success = response.key?("sig")
|
117
|
-
rescue ResponseError => e
|
118
|
-
response = parse(e.response.body)
|
119
|
-
end
|
120
|
-
|
121
|
-
Response.new(
|
122
|
-
success,
|
123
|
-
(success ? "OK" : response["error"]["message"]),
|
124
|
-
response,
|
125
|
-
test: test?,
|
126
|
-
authorization: authorization_from(response)
|
127
|
-
)
|
128
|
-
end
|
129
|
-
|
130
|
-
def authorization_from(response)
|
131
|
-
if response.key?("transaction")
|
132
|
-
response["transaction"]["id"]
|
133
|
-
elsif response.key?("card")
|
134
|
-
response["card"]["token"]
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def json_error(raw_response)
|
139
|
-
msg = "Invalid response from app55 server: Received: #{raw_response.inspect})"
|
140
|
-
{
|
141
|
-
"error" => {
|
142
|
-
"message" => msg
|
143
|
-
}
|
144
|
-
}
|
145
|
-
end
|
146
|
-
|
147
|
-
def url(resource)
|
148
|
-
(test? ? self.test_url : self.live_url) + resource
|
149
|
-
end
|
150
|
-
|
151
|
-
def post_data(params)
|
152
|
-
return nil unless params
|
153
|
-
|
154
|
-
params.map do |key, value|
|
155
|
-
next if value.blank?
|
156
|
-
if value.is_a?(Hash)
|
157
|
-
h = {}
|
158
|
-
value.each do |k, v|
|
159
|
-
h["#{key}.#{k}"] = v unless v.blank?
|
160
|
-
end
|
161
|
-
post_data(h)
|
162
|
-
else
|
163
|
-
"#{key}=#{CGI.escape(value.to_s)}"
|
164
|
-
end
|
165
|
-
end.compact.join("&")
|
166
|
-
end
|
167
|
-
|
168
|
-
def headers
|
169
|
-
{
|
170
|
-
"Authorization" => "Basic " + Base64.strict_encode64(@options[:api_key].to_s + ":" + @options[:api_secret].to_s),
|
171
|
-
"User-Agent" => user_agent,
|
172
|
-
}
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|