activemerchant 1.63.0 → 1.64.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 +26 -0
- data/README.md +1 -1
- data/lib/active_merchant/billing/gateway.rb +5 -1
- data/lib/active_merchant/billing/gateways/authorize_net.rb +13 -12
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +6 -3
- data/lib/active_merchant/billing/gateways/card_stream.rb +72 -1
- data/lib/active_merchant/billing/gateways/credorax.rb +78 -1
- data/lib/active_merchant/billing/gateways/digitzs.rb +292 -0
- data/lib/active_merchant/billing/gateways/global_collect.rb +2 -2
- data/lib/active_merchant/billing/gateways/kushki.rb +217 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +2 -2
- data/lib/active_merchant/billing/gateways/omise.rb +9 -5
- data/lib/active_merchant/billing/gateways/paymill.rb +18 -10
- data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -1
- data/lib/active_merchant/billing/gateways/sage.rb +5 -3
- data/lib/active_merchant/billing/gateways/stripe.rb +1 -1
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -3
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +114 -9
- data/lib/active_merchant/billing/gateways/wepay.rb +1 -1
- data/lib/active_merchant/version.rb +1 -1
- metadata +5 -3
@@ -46,7 +46,7 @@ module ActiveMerchant #:nodoc:
|
|
46
46
|
|
47
47
|
def refund(money, authorization, options={})
|
48
48
|
post = nestable_hash
|
49
|
-
add_amount(post, money, options
|
49
|
+
add_amount(post, money, options)
|
50
50
|
add_refund_customer_data(post, options)
|
51
51
|
commit(:refund, post, authorization)
|
52
52
|
end
|
@@ -99,7 +99,7 @@ module ActiveMerchant #:nodoc:
|
|
99
99
|
}
|
100
100
|
end
|
101
101
|
|
102
|
-
def add_amount(post, money, options)
|
102
|
+
def add_amount(post, money, options={})
|
103
103
|
post["amountOfMoney"] = {
|
104
104
|
"amount" => amount(money),
|
105
105
|
"currencyCode" => options[:currency] || currency(money)
|
@@ -0,0 +1,217 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class KushkiGateway < Gateway
|
4
|
+
self.display_name = "Kushki"
|
5
|
+
self.homepage_url = "https://www.kushkipagos.com"
|
6
|
+
|
7
|
+
self.test_url = "https://api-uat.kushkipagos.com/v1/"
|
8
|
+
self.live_url = "https://api.kushkipagos.com/v1/"
|
9
|
+
|
10
|
+
self.supported_countries = ["CO", "EC"]
|
11
|
+
self.default_currency = "USD"
|
12
|
+
self.money_format = :dollars
|
13
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club]
|
14
|
+
|
15
|
+
def initialize(options={})
|
16
|
+
requires!(options, :public_merchant_id, :private_merchant_id)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def purchase(amount, payment_method, options={})
|
21
|
+
MultiResponse.run() do |r|
|
22
|
+
r.process { tokenize(amount, payment_method, options) }
|
23
|
+
r.process { charge(amount, r.authorization, options) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def void(authorization, options={})
|
28
|
+
action = "void"
|
29
|
+
|
30
|
+
post = {}
|
31
|
+
post[:ticketNumber] = authorization
|
32
|
+
|
33
|
+
commit(action, post)
|
34
|
+
end
|
35
|
+
|
36
|
+
def supports_scrubbing?
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def scrub(transcript)
|
41
|
+
transcript.
|
42
|
+
gsub(%r((Private-Merchant-Id: )\d+), '\1[FILTERED]').
|
43
|
+
gsub(%r((\"card\\\":{\\\"number\\\":\\\")\d+), '\1[FILTERED]').
|
44
|
+
gsub(%r((\"cvv\\\":\\\")\d+), '\1[FILTERED]')
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def tokenize(amount, payment_method, options)
|
50
|
+
action = "tokenize"
|
51
|
+
|
52
|
+
post = {}
|
53
|
+
add_invoice(action, post, amount, options)
|
54
|
+
add_payment_method(post, payment_method, options)
|
55
|
+
|
56
|
+
commit(action, post)
|
57
|
+
end
|
58
|
+
|
59
|
+
def charge(amount, authorization, options)
|
60
|
+
action = "charge"
|
61
|
+
|
62
|
+
post = {}
|
63
|
+
add_reference(post, authorization, options)
|
64
|
+
add_invoice(action, post, amount, options)
|
65
|
+
|
66
|
+
commit(action, post)
|
67
|
+
end
|
68
|
+
|
69
|
+
def add_invoice(action, post, money, options)
|
70
|
+
if action == "tokenize"
|
71
|
+
post[:totalAmount] = amount(money).to_f
|
72
|
+
post[:currency] = options[:currency] || currency(money)
|
73
|
+
post[:isDeferred] = false
|
74
|
+
else
|
75
|
+
sum = {}
|
76
|
+
sum[:currency] = options[:currency] || currency(money)
|
77
|
+
add_amount_defaults(sum, money, options)
|
78
|
+
add_amount_by_country(sum, options)
|
79
|
+
post[:amount] = sum
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_amount_defaults(sum, money, options)
|
84
|
+
sum[:subtotalIva] = amount(money).to_f
|
85
|
+
sum[:iva] = 0
|
86
|
+
sum[:subtotalIva0] = 0
|
87
|
+
|
88
|
+
if sum[:currency] == "COP"
|
89
|
+
extra_taxes = {}
|
90
|
+
extra_taxes[:propina] = 0
|
91
|
+
extra_taxes[:tasaAeroportuaria] = 0
|
92
|
+
extra_taxes[:agenciaDeViaje] = 0
|
93
|
+
extra_taxes[:iac] = 0
|
94
|
+
sum[:extraTaxes] = extra_taxes
|
95
|
+
else
|
96
|
+
sum[:ice] = 0
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def add_amount_by_country(sum, options)
|
101
|
+
if amount = options[:amount]
|
102
|
+
sum[:subtotalIva] = amount[:subtotal_iva].to_f if amount[:subtotal_iva]
|
103
|
+
sum[:iva] = amount[:iva].to_f if amount[:iva]
|
104
|
+
sum[:subtotalIva0] = amount[:subtotal_iva_0].to_f if amount[:subtotal_iva_0]
|
105
|
+
sum[:ice] = amount[:ice].to_f if amount[:ice]
|
106
|
+
if extra_taxes = amount[:extra_taxes] && sum[:currency] == "COP"
|
107
|
+
sum[:extraTaxes][:propina] = extra_taxes[:propina].to_f if extra_taxes[:propina]
|
108
|
+
sum[:extraTaxes][:tasaAeroportuaria] = extra_taxes[:tasa_aeroportuaria].to_f if extra_taxes[:tasa_aeroportuaria]
|
109
|
+
sum[:extraTaxes][:agenciaDeViaje] = extra_taxes[:agencia_de_viaje].to_f if extra_taxes[:agencia_de_viaje]
|
110
|
+
sum[:extraTaxes][:iac] = extra_taxes[:iac].to_f if extra_taxes[:iac]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_payment_method(post, payment_method, options)
|
116
|
+
card = {}
|
117
|
+
card[:number] = payment_method.number
|
118
|
+
card[:cvv] = payment_method.verification_value
|
119
|
+
card[:expiryMonth] = format(payment_method.month, :two_digits)
|
120
|
+
card[:expiryYear] = format(payment_method.year, :two_digits)
|
121
|
+
card[:name] = payment_method.name
|
122
|
+
post[:card] = card
|
123
|
+
end
|
124
|
+
|
125
|
+
def add_reference(post, authorization, options)
|
126
|
+
post[:token] = authorization
|
127
|
+
end
|
128
|
+
|
129
|
+
ENDPOINT = {
|
130
|
+
"tokenize" => "tokens",
|
131
|
+
"charge" => "charges",
|
132
|
+
"void" => "charges"
|
133
|
+
}
|
134
|
+
|
135
|
+
def commit(action, params)
|
136
|
+
response = begin
|
137
|
+
parse(ssl_invoke(action, params))
|
138
|
+
rescue ResponseError => e
|
139
|
+
parse(e.response.body)
|
140
|
+
end
|
141
|
+
|
142
|
+
success = success_from(response)
|
143
|
+
|
144
|
+
Response.new(
|
145
|
+
success,
|
146
|
+
message_from(success, response),
|
147
|
+
response,
|
148
|
+
authorization: success ? authorization_from(response) : nil,
|
149
|
+
error_code: success ? nil : error_from(response),
|
150
|
+
test: test?
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
def ssl_invoke(action, params)
|
155
|
+
if action == "void"
|
156
|
+
ssl_request(:delete, url(action, params), nil, headers(action))
|
157
|
+
else
|
158
|
+
ssl_post(url(action, params), post_data(params), headers(action))
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def headers(action)
|
163
|
+
hfields = {}
|
164
|
+
hfields["Public-Merchant-Id"] = @options[:public_merchant_id] if action == "tokenize"
|
165
|
+
hfields["Private-Merchant-Id"] = @options[:private_merchant_id] unless action == "tokenize"
|
166
|
+
hfields["Content-Type"] = "application/json"
|
167
|
+
hfields
|
168
|
+
end
|
169
|
+
|
170
|
+
def post_data(params)
|
171
|
+
params.to_json
|
172
|
+
end
|
173
|
+
|
174
|
+
def url(action, params)
|
175
|
+
base_url = test? ? test_url : live_url
|
176
|
+
|
177
|
+
if action == "void"
|
178
|
+
base_url + ENDPOINT[action] + "/" + params[:ticketNumber]
|
179
|
+
else
|
180
|
+
base_url + ENDPOINT[action]
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def parse(body)
|
185
|
+
begin
|
186
|
+
JSON.parse(body)
|
187
|
+
rescue JSON::ParserError
|
188
|
+
message = "Invalid JSON response received from KushkiGateway. Please contact KushkiGateway if you continue to receive this message."
|
189
|
+
message += " (The raw response returned by the API was #{body.inspect})"
|
190
|
+
{
|
191
|
+
"message" => message
|
192
|
+
}
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def success_from(response)
|
197
|
+
return true if response["token"] || response["ticketNumber"]
|
198
|
+
end
|
199
|
+
|
200
|
+
def message_from(succeeded, response)
|
201
|
+
if succeeded
|
202
|
+
"Succeeded"
|
203
|
+
else
|
204
|
+
response["message"]
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def authorization_from(response)
|
209
|
+
response["token"] || response["ticketNumber"]
|
210
|
+
end
|
211
|
+
|
212
|
+
def error_from(response)
|
213
|
+
response["code"]
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -143,9 +143,9 @@ module ActiveMerchant #:nodoc:
|
|
143
143
|
:pem => LinkpointGateway.pem_file
|
144
144
|
}.update(options)
|
145
145
|
|
146
|
-
@options[:pem].strip!
|
147
|
-
|
148
146
|
raise ArgumentError, "You need to pass in your pem file using the :pem parameter or set it globally using ActiveMerchant::Billing::LinkpointGateway.pem_file = File.read( File.dirname(__FILE__) + '/../mycert.pem' ) or similar" if @options[:pem].blank?
|
147
|
+
|
148
|
+
@options[:pem].strip!
|
149
149
|
end
|
150
150
|
|
151
151
|
# Send a purchase request with periodic options
|
@@ -14,18 +14,20 @@ module ActiveMerchant #:nodoc:
|
|
14
14
|
self.live_url = self.test_url = API_URL
|
15
15
|
|
16
16
|
# Currency supported by Omise
|
17
|
-
# * Thai Baht with Satang,
|
17
|
+
# * Thai Baht with Satang, 50000 (THB500.00)
|
18
|
+
# * Japanese Yen, 500 (JPY500)
|
18
19
|
self.default_currency = 'THB'
|
19
20
|
self.money_format = :cents
|
20
21
|
|
21
22
|
#Country supported by Omise
|
22
23
|
# * Thailand
|
23
|
-
self.supported_countries = %w( TH )
|
24
|
+
self.supported_countries = %w( TH JP )
|
24
25
|
|
25
26
|
# Credit cards supported by Omise
|
26
27
|
# * VISA
|
27
28
|
# * MasterCard
|
28
|
-
|
29
|
+
# * JCB
|
30
|
+
self.supported_cardtypes = [:visa, :master, :jcb]
|
29
31
|
|
30
32
|
# Omise main page
|
31
33
|
self.homepage_url = 'https://www.omise.co/'
|
@@ -39,8 +41,10 @@ module ActiveMerchant #:nodoc:
|
|
39
41
|
#
|
40
42
|
# ==== Options
|
41
43
|
#
|
42
|
-
# * <tt>:public_key</tt>
|
43
|
-
# * <tt>:secret_key</tt>
|
44
|
+
# * <tt>:public_key</tt> -- Omise's public key (REQUIRED).
|
45
|
+
# * <tt>:secret_key</tt> -- Omise's secret key (REQUIRED).
|
46
|
+
# * <tt>:api_version</tt> -- Omise's API Version (OPTIONAL), default version is '2014-07-27'
|
47
|
+
# See version at page https://dashboard.omise.co/api-version/edit
|
44
48
|
|
45
49
|
def initialize(options={})
|
46
50
|
requires!(options, :public_key, :secret_key)
|
@@ -17,7 +17,7 @@ module ActiveMerchant #:nodoc:
|
|
17
17
|
super
|
18
18
|
end
|
19
19
|
|
20
|
-
def purchase(money, payment_method, options
|
20
|
+
def purchase(money, payment_method, options={})
|
21
21
|
action_with_token(:purchase, money, payment_method, options)
|
22
22
|
end
|
23
23
|
|
@@ -48,7 +48,7 @@ module ActiveMerchant #:nodoc:
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def store(credit_card, options={})
|
51
|
-
save_card(credit_card)
|
51
|
+
save_card(credit_card, options)
|
52
52
|
end
|
53
53
|
|
54
54
|
def supports_scrubbing
|
@@ -74,11 +74,15 @@ module ActiveMerchant #:nodoc:
|
|
74
74
|
|
75
75
|
private
|
76
76
|
|
77
|
-
def add_credit_card(post, credit_card)
|
77
|
+
def add_credit_card(post, credit_card, options)
|
78
|
+
post['account.holder'] = (credit_card.try(:name) || "")
|
78
79
|
post['account.number'] = credit_card.number
|
79
80
|
post['account.expiry.month'] = sprintf("%.2i", credit_card.month)
|
80
81
|
post['account.expiry.year'] = sprintf("%.4i", credit_card.year)
|
81
82
|
post['account.verification'] = credit_card.verification_value
|
83
|
+
post['account.email'] = (options[:email] || nil)
|
84
|
+
post['presentation.amount3D'] = (options[:money] || nil)
|
85
|
+
post['presentation.currency3D'] = (options[:currency] || currency( options[:money]))
|
82
86
|
end
|
83
87
|
|
84
88
|
def headers
|
@@ -122,12 +126,13 @@ module ActiveMerchant #:nodoc:
|
|
122
126
|
end
|
123
127
|
|
124
128
|
def action_with_token(action, money, payment_method, options)
|
129
|
+
options[:money] = money
|
125
130
|
case payment_method
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
r.process { save_card(payment_method) }
|
131
|
+
when String
|
132
|
+
self.send("#{action}_with_token", money, payment_method, options)
|
133
|
+
else
|
134
|
+
MultiResponse.run do |r|
|
135
|
+
r.process { save_card(payment_method, options) }
|
131
136
|
r.process { self.send("#{action}_with_token", money, r.authorization, options) }
|
132
137
|
end
|
133
138
|
end
|
@@ -153,10 +158,10 @@ module ActiveMerchant #:nodoc:
|
|
153
158
|
commit(:post, 'preauthorizations', post)
|
154
159
|
end
|
155
160
|
|
156
|
-
def save_card(credit_card)
|
161
|
+
def save_card(credit_card, options)
|
157
162
|
post = {}
|
158
163
|
|
159
|
-
add_credit_card(post, credit_card)
|
164
|
+
add_credit_card(post, credit_card, options)
|
160
165
|
post['channel.id'] = @options[:public_key]
|
161
166
|
post['jsonPFunction'] = 'jsonPFunction'
|
162
167
|
post['transaction.mode'] = (test? ? 'CONNECTOR_TEST' : 'LIVE')
|
@@ -219,6 +224,7 @@ module ActiveMerchant #:nodoc:
|
|
219
224
|
20203 => "Reversed due to complaint by buyer",
|
220
225
|
20204 => "Payment has been refunded",
|
221
226
|
20300 => "Reversal has been canceled",
|
227
|
+
22000 => "Initiation of transaction successful",
|
222
228
|
|
223
229
|
30000 => "Transaction still in progress",
|
224
230
|
30100 => "Transaction has been accepted",
|
@@ -258,6 +264,8 @@ module ActiveMerchant #:nodoc:
|
|
258
264
|
40420 => "Problem with address data",
|
259
265
|
40500 => "Permission error with acquirer API",
|
260
266
|
40510 => "Rate limit reached for acquirer API",
|
267
|
+
42000 => "Initiation of transaction failed",
|
268
|
+
42410 => "Initiation of transaction expired",
|
261
269
|
|
262
270
|
50000 => "Problem with back end",
|
263
271
|
50001 => "Country blacklisted",
|
@@ -65,7 +65,7 @@ module ActiveMerchant #:nodoc:
|
|
65
65
|
commit('void', post)
|
66
66
|
end
|
67
67
|
|
68
|
-
def refund(authorization, options={})
|
68
|
+
def refund(amount, authorization, options={})
|
69
69
|
post = {}
|
70
70
|
|
71
71
|
add_credentials(post, 'SUBMIT_TRANSACTION')
|
@@ -321,6 +321,8 @@ module ActiveMerchant #:nodoc:
|
|
321
321
|
response["code"] == "SUCCESS" && response["creditCardToken"] && response["creditCardToken"]["creditCardTokenId"].present?
|
322
322
|
when 'verify_credentials'
|
323
323
|
response["code"] == "SUCCESS"
|
324
|
+
when 'refund'
|
325
|
+
response["code"] == "SUCCESS" && response["transactionResponse"] && (response["transactionResponse"]["state"] == "PENDING" || response["transactionResponse"]["state"] == "APPROVED")
|
324
326
|
else
|
325
327
|
response["code"] == "SUCCESS" && response["transactionResponse"] && (response["transactionResponse"]["state"] == "APPROVED")
|
326
328
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Billing #:nodoc:
|
3
3
|
class SageGateway < Gateway
|
4
|
+
include Empty
|
5
|
+
|
4
6
|
self.display_name = 'http://www.sagepayments.com'
|
5
7
|
self.homepage_url = 'Sage Payment Solutions'
|
6
8
|
self.live_url = 'https://www.sagepayments.net/cgi-bin'
|
@@ -204,8 +206,8 @@ module ActiveMerchant #:nodoc:
|
|
204
206
|
|
205
207
|
def add_invoice(post, options)
|
206
208
|
post[:T_ordernum] = (options[:order_id] || generate_unique_id).slice(0, 20)
|
207
|
-
post[:T_tax] = amount(options[:tax]) unless options[:tax]
|
208
|
-
post[:T_shipping] = amount(options[:shipping]) unless options[:shipping]
|
209
|
+
post[:T_tax] = amount(options[:tax]) unless empty?(options[:tax])
|
210
|
+
post[:T_shipping] = amount(options[:shipping]) unless empty?(options[:shipping])
|
209
211
|
end
|
210
212
|
|
211
213
|
def add_reference(post, reference)
|
@@ -226,7 +228,7 @@ module ActiveMerchant #:nodoc:
|
|
226
228
|
|
227
229
|
post[:C_address] = billing_address[:address1]
|
228
230
|
post[:C_city] = billing_address[:city]
|
229
|
-
post[:C_state] = billing_address[:state]
|
231
|
+
post[:C_state] = empty?(billing_address[:state]) ? "Outside of US" : billing_address[:state]
|
230
232
|
post[:C_zip] = billing_address[:zip]
|
231
233
|
post[:C_country] = billing_address[:country]
|
232
234
|
post[:C_telephone] = billing_address[:phone]
|
@@ -71,7 +71,6 @@ module ActiveMerchant #:nodoc:
|
|
71
71
|
requires!(options, :login)
|
72
72
|
@api_key = options[:login]
|
73
73
|
@fee_refund_api_key = options[:fee_refund_login]
|
74
|
-
|
75
74
|
super
|
76
75
|
end
|
77
76
|
|
@@ -159,6 +158,7 @@ module ActiveMerchant #:nodoc:
|
|
159
158
|
def verify(payment, options = {})
|
160
159
|
MultiResponse.run(:use_first_response) do |r|
|
161
160
|
r.process { authorize(auth_minimum_amount(options), payment, options) }
|
161
|
+
options[:idempotency_key] = nil
|
162
162
|
r.process(:ignore_result) { void(r.authorization, options) }
|
163
163
|
end
|
164
164
|
end
|
@@ -248,7 +248,6 @@ module ActiveMerchant #:nodoc:
|
|
248
248
|
request = build_xml_transaction_request do |doc|
|
249
249
|
add_amount(doc, amount)
|
250
250
|
add_original_transaction_data(doc, transaction_id)
|
251
|
-
add_order_number(doc, options)
|
252
251
|
end
|
253
252
|
|
254
253
|
commit(:refund, request)
|
@@ -338,8 +337,8 @@ module ActiveMerchant #:nodoc:
|
|
338
337
|
response,
|
339
338
|
error_code: error_code_from(succeeded, response),
|
340
339
|
authorization: authorization_from(action, response),
|
341
|
-
avs_result: AVSResult.new(code: response["
|
342
|
-
cvv_result: CVVResult.new(response["
|
340
|
+
avs_result: AVSResult.new(code: response["avsRslt"]),
|
341
|
+
cvv_result: CVVResult.new(response["secRslt"]),
|
343
342
|
test: test?
|
344
343
|
)
|
345
344
|
end
|