activemerchant 1.90.0 → 1.91.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +38 -0
- data/README.md +3 -2
- data/lib/active_merchant/billing/credit_card_methods.rb +1 -1
- data/lib/active_merchant/billing/gateways/adyen.rb +26 -21
- data/lib/active_merchant/billing/gateways/bambora_apac.rb +186 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +189 -34
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +11 -9
- data/lib/active_merchant/billing/gateways/card_connect.rb +3 -0
- data/lib/active_merchant/billing/gateways/cecabank.rb +13 -2
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +20 -7
- data/lib/active_merchant/billing/gateways/ipp.rb +1 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +3 -4
- data/lib/active_merchant/billing/gateways/netbanx.rb +4 -0
- data/lib/active_merchant/billing/gateways/nmi.rb +6 -4
- data/lib/active_merchant/billing/gateways/openpay.rb +1 -1
- data/lib/active_merchant/billing/gateways/orbital.rb +8 -1
- data/lib/active_merchant/billing/gateways/payment_express.rb +4 -1
- data/lib/active_merchant/billing/gateways/paymentez.rb +4 -9
- data/lib/active_merchant/billing/gateways/pin.rb +19 -6
- data/lib/active_merchant/billing/gateways/pro_pay.rb +1 -1
- data/lib/active_merchant/billing/gateways/qvalent.rb +11 -0
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +3 -3
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +1 -0
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +11 -3
- data/lib/active_merchant/billing/gateways/worldpay.rb +51 -2
- data/lib/active_merchant/country.rb +1 -1
- data/lib/active_merchant/version.rb +1 -1
- metadata +3 -2
@@ -324,15 +324,15 @@ module ActiveMerchant #:nodoc:
|
|
324
324
|
:region => address[:state],
|
325
325
|
:postal_code => scrub_zip(address[:zip]),
|
326
326
|
}
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
mapped[:country_code_alpha3]
|
333
|
-
elsif address[:country_code_numeric]
|
334
|
-
mapped[:country_code_numeric] = address[:country_code_numeric]
|
327
|
+
|
328
|
+
mapped[:country_code_alpha2] = (address[:country] || address[:country_code_alpha2]) if address[:country] || address[:country_code_alpha2]
|
329
|
+
mapped[:country_name] = address[:country_name] if address[:country_name]
|
330
|
+
mapped[:country_code_alpha3] = address[:country_code_alpha3] if address[:country_code_alpha3]
|
331
|
+
unless address[:country].blank?
|
332
|
+
mapped[:country_code_alpha3] ||= Country.find(address[:country]).code(:alpha3).value
|
335
333
|
end
|
334
|
+
mapped[:country_code_numeric] = address[:country_code_numeric] if address[:country_code_numeric]
|
335
|
+
|
336
336
|
mapped
|
337
337
|
end
|
338
338
|
|
@@ -585,7 +585,9 @@ module ActiveMerchant #:nodoc:
|
|
585
585
|
parameters[:merchant_account_id] = merchant_account_id
|
586
586
|
end
|
587
587
|
|
588
|
-
if options[:
|
588
|
+
if options[:transaction_source]
|
589
|
+
parameters[:transaction_source] = options[:transaction_source]
|
590
|
+
elsif options[:recurring]
|
589
591
|
parameters[:recurring] = true
|
590
592
|
end
|
591
593
|
|
@@ -281,6 +281,9 @@ module ActiveMerchant #:nodoc:
|
|
281
281
|
test: test?,
|
282
282
|
error_code: error_code_from(response)
|
283
283
|
)
|
284
|
+
rescue ResponseError => e
|
285
|
+
return Response.new(false, 'Unable to authenticate. Please check your credentials.', {}, :test => test?) if e.response.code == '401'
|
286
|
+
raise
|
284
287
|
end
|
285
288
|
|
286
289
|
def success_from(response)
|
@@ -173,13 +173,24 @@ module ActiveMerchant #:nodoc:
|
|
173
173
|
response = parse(xml)
|
174
174
|
Response.new(
|
175
175
|
response[:success],
|
176
|
-
response
|
176
|
+
message_from(response),
|
177
177
|
response,
|
178
178
|
:test => test?,
|
179
|
-
:authorization => build_authorization(response)
|
179
|
+
:authorization => build_authorization(response),
|
180
|
+
:error_code => response[:error_code]
|
180
181
|
)
|
181
182
|
end
|
182
183
|
|
184
|
+
def message_from(response)
|
185
|
+
if response[:message] == 'ERROR' && response[:error_message]
|
186
|
+
response[:error_message]
|
187
|
+
elsif response[:error_message]
|
188
|
+
"#{response[:message]} #{response[:error_message]}"
|
189
|
+
else
|
190
|
+
response[:message]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
183
194
|
def post_data(params)
|
184
195
|
return nil unless params
|
185
196
|
|
@@ -46,14 +46,17 @@ module ActiveMerchant #:nodoc:
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def capture(money, authorization, options = {})
|
49
|
+
txn_id, _ = authorization.to_s.split('|')
|
49
50
|
post = {}
|
51
|
+
|
50
52
|
add_amount(post, money, options)
|
51
53
|
add_extra_options(post, options)
|
52
54
|
|
53
|
-
commit(:post, "purchases/#{CGI.escape(
|
55
|
+
commit(:post, "purchases/#{CGI.escape(txn_id)}/capture", post)
|
54
56
|
end
|
55
57
|
|
56
|
-
def refund(money,
|
58
|
+
def refund(money, authorization, options={})
|
59
|
+
txn_id, _ = authorization.to_s.split('|')
|
57
60
|
post = {}
|
58
61
|
|
59
62
|
add_extra_options(post, options)
|
@@ -64,8 +67,15 @@ module ActiveMerchant #:nodoc:
|
|
64
67
|
commit(:post, 'refunds', post)
|
65
68
|
end
|
66
69
|
|
70
|
+
def void(authorization, options={})
|
71
|
+
txn_id, endpoint = authorization.to_s.split('|')
|
72
|
+
|
73
|
+
commit(:post, "#{endpoint}/void?id=#{txn_id}", {})
|
74
|
+
end
|
75
|
+
|
67
76
|
def store(creditcard, options={})
|
68
77
|
post = {}
|
78
|
+
|
69
79
|
add_creditcard(post, creditcard)
|
70
80
|
|
71
81
|
commit(:post, 'credit_cards', post)
|
@@ -97,7 +107,8 @@ module ActiveMerchant #:nodoc:
|
|
97
107
|
post[:cvv] = creditcard.verification_value if creditcard.verification_value?
|
98
108
|
post[:card_holder] = creditcard.name if creditcard.name
|
99
109
|
elsif creditcard.is_a?(String)
|
100
|
-
|
110
|
+
id, _ = creditcard.to_s.split('|')
|
111
|
+
post[:card_token] = id
|
101
112
|
post[:cvv] = options[:cvv]
|
102
113
|
elsif creditcard.is_a?(Hash)
|
103
114
|
ActiveMerchant.deprecated 'Passing the credit card as a Hash is deprecated. Use a String and put the (optional) CVV in the options hash instead.'
|
@@ -141,7 +152,7 @@ module ActiveMerchant #:nodoc:
|
|
141
152
|
message_from(response),
|
142
153
|
response,
|
143
154
|
:test => response['test'],
|
144
|
-
:authorization => authorization_from(response, success)
|
155
|
+
:authorization => authorization_from(response, success, uri)
|
145
156
|
)
|
146
157
|
end
|
147
158
|
|
@@ -149,13 +160,15 @@ module ActiveMerchant #:nodoc:
|
|
149
160
|
(
|
150
161
|
response['successful'] &&
|
151
162
|
response['response'] &&
|
152
|
-
(response['response']['successful'] || response['response']['token'])
|
163
|
+
(response['response']['successful'] || response['response']['token'] || response['response']['response_code'] == '00')
|
153
164
|
)
|
154
165
|
end
|
155
166
|
|
156
|
-
def authorization_from(response, success)
|
167
|
+
def authorization_from(response, success, uri)
|
168
|
+
endpoint = uri.split('/')[0]
|
157
169
|
if success
|
158
|
-
|
170
|
+
id = response['response']['id'] || response['response']['token']
|
171
|
+
"#{id}|#{endpoint}"
|
159
172
|
else
|
160
173
|
nil
|
161
174
|
end
|
@@ -33,7 +33,6 @@ module ActiveMerchant #:nodoc:
|
|
33
33
|
requires!(options, :login, :password)
|
34
34
|
@cvv_enabled = options[:cvv_enabled]
|
35
35
|
@avs_enabled = options[:avs_enabled]
|
36
|
-
@cof_enabled = options[:cof_enabled]
|
37
36
|
options[:crypt_type] = 7 unless options.has_key?(:crypt_type)
|
38
37
|
super
|
39
38
|
end
|
@@ -51,7 +50,7 @@ module ActiveMerchant #:nodoc:
|
|
51
50
|
post[:order_id] = options[:order_id]
|
52
51
|
post[:address] = options[:billing_address] || options[:address]
|
53
52
|
post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
|
54
|
-
add_cof(post, options)
|
53
|
+
add_cof(post, options)
|
55
54
|
action = if post[:cavv]
|
56
55
|
'cavv_preauth'
|
57
56
|
elsif post[:data_key].blank?
|
@@ -74,7 +73,7 @@ module ActiveMerchant #:nodoc:
|
|
74
73
|
post[:order_id] = options[:order_id]
|
75
74
|
post[:address] = options[:billing_address] || options[:address]
|
76
75
|
post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
|
77
|
-
add_cof(post, options)
|
76
|
+
add_cof(post, options)
|
78
77
|
action = if post[:cavv]
|
79
78
|
'cavv_purchase'
|
80
79
|
elsif post[:data_key].blank?
|
@@ -293,7 +292,7 @@ module ActiveMerchant #:nodoc:
|
|
293
292
|
when :cvd_info
|
294
293
|
transaction.add_element(cvd_element(parameters[:cvd_value])) if @cvv_enabled
|
295
294
|
when :cof_info
|
296
|
-
transaction.add_element(credential_on_file(parameters)) if
|
295
|
+
transaction.add_element(credential_on_file(parameters)) if cof_details_present?(parameters)
|
297
296
|
else
|
298
297
|
transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
|
299
298
|
end
|
@@ -55,6 +55,10 @@ module ActiveMerchant #:nodoc:
|
|
55
55
|
post = {}
|
56
56
|
add_invoice(post, money, options)
|
57
57
|
|
58
|
+
# Setting merchantRefNumber to a unique id for each refund
|
59
|
+
# This is to support multiple partial refunds for the same order
|
60
|
+
post[:merchantRefNum] = SecureRandom.uuid
|
61
|
+
|
58
62
|
commit(:post, "settlements/#{authorization}/refunds", post)
|
59
63
|
end
|
60
64
|
|
@@ -144,7 +144,8 @@ module ActiveMerchant #:nodoc:
|
|
144
144
|
|
145
145
|
def add_payment_method(post, payment_method, options)
|
146
146
|
if(payment_method.is_a?(String))
|
147
|
-
|
147
|
+
customer_vault_id, _ = split_authorization(payment_method)
|
148
|
+
post[:customer_vault_id] = customer_vault_id
|
148
149
|
elsif payment_method.is_a?(NetworkTokenizationCreditCard)
|
149
150
|
post[:ccnumber] = payment_method.number
|
150
151
|
post[:ccexp] = exp_date(payment_method)
|
@@ -236,15 +237,16 @@ module ActiveMerchant #:nodoc:
|
|
236
237
|
succeeded,
|
237
238
|
message_from(succeeded, response),
|
238
239
|
response,
|
239
|
-
authorization: authorization_from(response, params[:payment]),
|
240
|
+
authorization: authorization_from(response, params[:payment], action),
|
240
241
|
avs_result: AVSResult.new(code: response[:avsresponse]),
|
241
242
|
cvv_result: CVVResult.new(response[:cvvresponse]),
|
242
243
|
test: test?
|
243
244
|
)
|
244
245
|
end
|
245
246
|
|
246
|
-
def authorization_from(response, payment_type)
|
247
|
-
|
247
|
+
def authorization_from(response, payment_type, action)
|
248
|
+
authorization = (action == 'add_customer' ? response[:customer_vault_id] : response[:transactionid])
|
249
|
+
[ authorization, payment_type ].join('#')
|
248
250
|
end
|
249
251
|
|
250
252
|
def split_authorization(authorization)
|
@@ -30,7 +30,7 @@ module ActiveMerchant #:nodoc:
|
|
30
30
|
class OrbitalGateway < Gateway
|
31
31
|
include Empty
|
32
32
|
|
33
|
-
API_VERSION = '7.
|
33
|
+
API_VERSION = '7.7'
|
34
34
|
|
35
35
|
POST_HEADERS = {
|
36
36
|
'MIME-Version' => '1.1',
|
@@ -506,6 +506,12 @@ module ActiveMerchant #:nodoc:
|
|
506
506
|
end
|
507
507
|
end
|
508
508
|
|
509
|
+
def add_stored_credentials(xml, parameters)
|
510
|
+
xml.tag! :MITMsgType, parameters[:mit_msg_type] if parameters[:mit_msg_type]
|
511
|
+
xml.tag! :MITStoredCredentialInd, parameters[:mit_stored_credential_ind] if parameters[:mit_stored_credential_ind]
|
512
|
+
xml.tag! :MITSubmittedTransactionID, parameters[:mit_submitted_transaction_id] if parameters[:mit_submitted_transaction_id]
|
513
|
+
end
|
514
|
+
|
509
515
|
def parse(body)
|
510
516
|
response = {}
|
511
517
|
xml = REXML::Document.new(body)
|
@@ -635,6 +641,7 @@ module ActiveMerchant #:nodoc:
|
|
635
641
|
end
|
636
642
|
|
637
643
|
add_level_2_purchase(xml, parameters)
|
644
|
+
add_stored_credentials(xml, parameters)
|
638
645
|
end
|
639
646
|
end
|
640
647
|
xml.target!
|
@@ -241,7 +241,8 @@ module ActiveMerchant #:nodoc:
|
|
241
241
|
# :client_type => :web, # Possible values are: :web, :ivr, :moto, :unattended, :internet, or :recurring
|
242
242
|
# :txn_data1 => "String up to 255 characters",
|
243
243
|
# :txn_data2 => "String up to 255 characters",
|
244
|
-
# :txn_data3 => "String up to 255 characters"
|
244
|
+
# :txn_data3 => "String up to 255 characters",
|
245
|
+
# :client_info => "String up to 15 characters. The IP address of the user who processed the transaction."
|
245
246
|
# }
|
246
247
|
#
|
247
248
|
# +:client_type+, while not documented for PxPost, will be sent as
|
@@ -277,6 +278,8 @@ module ActiveMerchant #:nodoc:
|
|
277
278
|
xml.add_element('TxnData1').text = options[:txn_data1].to_s.slice(0, 255) unless options[:txn_data1].blank?
|
278
279
|
xml.add_element('TxnData2').text = options[:txn_data2].to_s.slice(0, 255) unless options[:txn_data2].blank?
|
279
280
|
xml.add_element('TxnData3').text = options[:txn_data3].to_s.slice(0, 255) unless options[:txn_data3].blank?
|
281
|
+
|
282
|
+
xml.add_element('ClientInfo').text = options[:client_info] if options[:client_info]
|
280
283
|
end
|
281
284
|
|
282
285
|
def new_transaction
|
@@ -171,15 +171,10 @@ module ActiveMerchant #:nodoc:
|
|
171
171
|
end
|
172
172
|
|
173
173
|
def add_extra_params(post, options)
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
items[key.to_sym] = value
|
179
|
-
end
|
180
|
-
end
|
181
|
-
post[:extra_params] = items
|
182
|
-
end
|
174
|
+
extra_params = {}
|
175
|
+
extra_params.merge!(options[:extra_params]) if options[:extra_params]
|
176
|
+
|
177
|
+
post['extra_params'] = extra_params unless extra_params.empty?
|
183
178
|
end
|
184
179
|
|
185
180
|
def parse(body)
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Billing #:nodoc:
|
3
3
|
class PinGateway < Gateway
|
4
|
-
self.test_url = 'https://test-api.
|
5
|
-
self.live_url = 'https://api.
|
4
|
+
self.test_url = 'https://test-api.pinpayments.com/1'
|
5
|
+
self.live_url = 'https://api.pinpayments.com/1'
|
6
6
|
|
7
7
|
self.default_currency = 'AUD'
|
8
8
|
self.money_format = :cents
|
9
9
|
self.supported_countries = ['AU']
|
10
10
|
self.supported_cardtypes = [:visa, :master, :american_express]
|
11
|
-
self.homepage_url = 'http://www.
|
11
|
+
self.homepage_url = 'http://www.pinpayments.com/'
|
12
12
|
self.display_name = 'Pin Payments'
|
13
13
|
|
14
14
|
def initialize(options = {})
|
@@ -67,6 +67,7 @@ module ActiveMerchant #:nodoc:
|
|
67
67
|
# Updates the credit card for the customer.
|
68
68
|
def update(token, creditcard, options = {})
|
69
69
|
post = {}
|
70
|
+
token = get_customer_token(token)
|
70
71
|
|
71
72
|
add_creditcard(post, creditcard)
|
72
73
|
add_customer_data(post, options)
|
@@ -137,13 +138,21 @@ module ActiveMerchant #:nodoc:
|
|
137
138
|
)
|
138
139
|
elsif creditcard.kind_of?(String)
|
139
140
|
if creditcard =~ /^card_/
|
140
|
-
post[:card_token] = creditcard
|
141
|
+
post[:card_token] = get_card_token(creditcard)
|
141
142
|
else
|
142
143
|
post[:customer_token] = creditcard
|
143
144
|
end
|
144
145
|
end
|
145
146
|
end
|
146
147
|
|
148
|
+
def get_customer_token(token)
|
149
|
+
token.split(/;(?=cus)/).last
|
150
|
+
end
|
151
|
+
|
152
|
+
def get_card_token(token)
|
153
|
+
token.split(/;(?=cus)/).first
|
154
|
+
end
|
155
|
+
|
147
156
|
def add_metadata(post, options)
|
148
157
|
post[:metadata] = options[:metadata] if options[:metadata]
|
149
158
|
end
|
@@ -200,13 +209,17 @@ module ActiveMerchant #:nodoc:
|
|
200
209
|
end
|
201
210
|
|
202
211
|
def unparsable_response(raw_response)
|
203
|
-
message = 'Invalid JSON response received from Pin Payments. Please contact support@
|
212
|
+
message = 'Invalid JSON response received from Pin Payments. Please contact support@pinpayments.com if you continue to receive this message.'
|
204
213
|
message += " (The raw response returned by the API was #{raw_response.inspect})"
|
205
214
|
return Response.new(false, message)
|
206
215
|
end
|
207
216
|
|
208
217
|
def token(response)
|
209
|
-
response['token']
|
218
|
+
if response['token'].start_with?('cus')
|
219
|
+
"#{response.dig('card', 'token')};#{response['token']}"
|
220
|
+
else
|
221
|
+
response['token']
|
222
|
+
end
|
210
223
|
end
|
211
224
|
|
212
225
|
def parse(body)
|
@@ -12,6 +12,10 @@ module ActiveMerchant #:nodoc:
|
|
12
12
|
self.money_format = :cents
|
13
13
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners]
|
14
14
|
|
15
|
+
CVV_CODE_MAPPING = {
|
16
|
+
'S' => 'D'
|
17
|
+
}
|
18
|
+
|
15
19
|
def initialize(options={})
|
16
20
|
requires!(options, :username, :password, :merchant, :pem, :pem_password)
|
17
21
|
super
|
@@ -168,11 +172,18 @@ module ActiveMerchant #:nodoc:
|
|
168
172
|
message_from(succeeded, raw),
|
169
173
|
raw,
|
170
174
|
authorization: raw['response.orderNumber'] || raw['response.customerReferenceNumber'],
|
175
|
+
cvv_result: cvv_result(succeeded, raw),
|
171
176
|
error_code: error_code_from(succeeded, raw),
|
172
177
|
test: test?
|
173
178
|
)
|
174
179
|
end
|
175
180
|
|
181
|
+
def cvv_result(succeeded, raw)
|
182
|
+
return unless succeeded
|
183
|
+
code = CVV_CODE_MAPPING[raw['response.cvnResponse']] || raw['response.cvnResponse']
|
184
|
+
CVVResult.new(code)
|
185
|
+
end
|
186
|
+
|
176
187
|
def headers
|
177
188
|
{
|
178
189
|
'Content-Type' => 'application/x-www-form-urlencoded'
|
@@ -532,7 +532,7 @@ module ActiveMerchant #:nodoc:
|
|
532
532
|
|
533
533
|
def add_contact(doc, fullname, options)
|
534
534
|
doc['v1'].contact do
|
535
|
-
doc['v1'].fullName fullname
|
535
|
+
doc['v1'].fullName fullname unless fullname.blank?
|
536
536
|
doc['v1'].coName options[:company_name] if options[:company_name]
|
537
537
|
doc['v1'].title options[:title] if options[:title]
|
538
538
|
|
@@ -557,7 +557,7 @@ module ActiveMerchant #:nodoc:
|
|
557
557
|
|
558
558
|
if (shipping_address = options[:shipping_address])
|
559
559
|
doc['v1'].ship do
|
560
|
-
doc['v1'].fullName fullname
|
560
|
+
doc['v1'].fullName fullname unless fullname.blank?
|
561
561
|
doc['v1'].addrLn1 shipping_address[:address1] if shipping_address[:address1]
|
562
562
|
doc['v1'].addrLn2 shipping_address[:address2] if shipping_address[:address2]
|
563
563
|
doc['v1'].city shipping_address[:city] if shipping_address[:city]
|
@@ -572,7 +572,7 @@ module ActiveMerchant #:nodoc:
|
|
572
572
|
|
573
573
|
def add_name(doc, payment_method)
|
574
574
|
doc['v1'].contact do
|
575
|
-
doc['v1'].fullName payment_method.name
|
575
|
+
doc['v1'].fullName payment_method.name unless payment_method.name.blank?
|
576
576
|
end
|
577
577
|
end
|
578
578
|
|
@@ -333,6 +333,7 @@ module ActiveMerchant #:nodoc:
|
|
333
333
|
params[:routing] = check.routing_number
|
334
334
|
params[:account] = check.account_number
|
335
335
|
params[:savings] = 'y' if check.account_type == 'savings'
|
336
|
+
params[:name] = check.name
|
336
337
|
end
|
337
338
|
|
338
339
|
def add_creditcard(params, creditcard)
|