activemerchant 1.67.0 → 1.68.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 +29 -10
- data/lib/active_merchant/billing/gateway.rb +19 -7
- data/lib/active_merchant/billing/gateways/authorize_net.rb +7 -4
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +2 -1
- data/lib/active_merchant/billing/gateways/checkout.rb +1 -1
- data/lib/active_merchant/billing/gateways/credorax.rb +7 -2
- data/lib/active_merchant/billing/gateways/cyber_source.rb +7 -2
- data/lib/active_merchant/billing/gateways/first_pay.rb +2 -1
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +3 -6
- data/lib/active_merchant/billing/gateways/jetpay_v2.rb +57 -30
- data/lib/active_merchant/billing/gateways/moneris.rb +20 -12
- data/lib/active_merchant/billing/gateways/openpay.rb +12 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +7 -4
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +3 -4
- data/lib/active_merchant/billing/gateways/safe_charge.rb +25 -7
- data/lib/active_merchant/billing/gateways/trexle.rb +217 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ed51178560acbebf43bedcb1e5ce966b279c04a
|
4
|
+
data.tar.gz: fb02cd941337c8fb5a2e2ae2626a25d967e86750
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8fe0383adc62eb2a6af23bbe0ab0155d9121994fc7b9b0fe05f84ad7e521e3fe62db4814fb1efc02c8889e88fb561bba0807dc8133b3e39ad04d167d5b28c15
|
7
|
+
data.tar.gz: 2159f015c245a4ebd0dc2ba57808884f08b2923271c951c8ffd4d0b581139d1426c0cadaa6f66bb6a26de4d63a12c2dcc26cd0adafc6ac51229c04668a05b640
|
data/CHANGELOG
CHANGED
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
== HEAD
|
4
4
|
|
5
|
+
== Version 1.68.0 (June 27, 2017)
|
6
|
+
* Authorize.Net: Return failed response if forced refund settlement fails [bizla] #2476
|
7
|
+
* Authorize.net: Concatenate address1 and address2 [dtykocki] #2479
|
8
|
+
* Braintree Blue: Braintree Blue: Add ECI indicator to Android Pay transactions [davidsantoso] #2474
|
9
|
+
* Credorax: Support 0- and 3-exponent currencies [curiousepic]
|
10
|
+
* Cybersource: update supported card types [bdewater] #2477
|
11
|
+
* FirstData: Add a default network tokenization strategy for FirstData E4 [krystosterone] #2473
|
12
|
+
* FirstPay: FirstPay: Update hostname and force TLSv1 minimum [davidsantoso] #2478
|
13
|
+
* JetPay V2: Support store transactions and token based payments [shasum] #2475
|
14
|
+
* Moneris: Add 3DS fields for decrypted Apple and Android Pay data [davidsantoso] #2457
|
15
|
+
* Openpay: Send customer name and email in authorize and purchase [dtykocki] #2468
|
16
|
+
* Payflow: Moved to name value pair (NVP) with payflow [jusleg] #2462
|
17
|
+
* Payflow: Set PAYPAL_NVP header as optional [davidsantoso] #2480
|
18
|
+
* QuickPay V10: Return last response for purchase and authorize [curiousepic] #2461
|
19
|
+
* SafeCharge: Map billing address fields [davidsantoso] #2464
|
20
|
+
* SafeCharge: Track currency from original transaction [davidsantoso] #2470
|
21
|
+
* Support three-decimal currencies [curiousepic] #2466
|
22
|
+
* Trexle: Add gateway support [hossamhossny] #2351
|
23
|
+
|
5
24
|
== Version 1.67.0 (June 8, 2017)
|
6
25
|
* Acapture: Pass 3D Secure fields [davidsantoso] #2451
|
7
26
|
* Authorize.net: Pass Level 2 Data Fields [curiousepic] #2444
|
@@ -17,16 +36,6 @@
|
|
17
36
|
* Payeezy: Add client_email field for telecheck [davidsantoso] #2455
|
18
37
|
* Payeezy: Add customer_id_type and customer_id_number fields [davidsantoso] #2454
|
19
38
|
* Quickpay V10: Fix store and token use for recurring payments [wsmoak] #2180
|
20
|
-
|
21
|
-
== Version 1.66.0 (May 4, 2017)
|
22
|
-
* Support Rails 5.1 [jhawthorn] #2407
|
23
|
-
* ProPay: Add Canada as supported country [davidsantoso]
|
24
|
-
* ProPay: Add gateway support [davidsantoso] #2405
|
25
|
-
* SafeCharge: Support credit transactions [shasum] #2404
|
26
|
-
* WePay: Add scrub method [shasum] #2406
|
27
|
-
* iVeri: Add gateway support [curiousepic] #2400
|
28
|
-
* iVeri: Support 3DSecure data fields [davidsantoso] #2412
|
29
|
-
* Opp: Fix transaction success criteria and clean up options [shasum] #2414
|
30
39
|
* Elavon: Support custom fields [curiousepic] #2416
|
31
40
|
* WePay: Support risk headers [shasum] #2419
|
32
41
|
* WePay: Add Canada as supported country [shasum] #2419
|
@@ -39,6 +48,16 @@
|
|
39
48
|
* Payeezy: Default check number to 001 if not present [davidsantoso] #2439
|
40
49
|
* Opp: Fix incorrect customParameter key to disable 3DS [davidsantoso]
|
41
50
|
|
51
|
+
== Version 1.66.0 (May 4, 2017)
|
52
|
+
* Support Rails 5.1 [jhawthorn] #2407
|
53
|
+
* ProPay: Add Canada as supported country [davidsantoso]
|
54
|
+
* ProPay: Add gateway support [davidsantoso] #2405
|
55
|
+
* SafeCharge: Support credit transactions [shasum] #2404
|
56
|
+
* WePay: Add scrub method [shasum] #2406
|
57
|
+
* iVeri: Add gateway support [curiousepic] #2400
|
58
|
+
* iVeri: Support 3DSecure data fields [davidsantoso] #2412
|
59
|
+
* Opp: Fix transaction success criteria and clean up options [shasum] #2414
|
60
|
+
|
42
61
|
== Version 1.65.0 (April 26, 2017)
|
43
62
|
* Adyen: Add Adyen v18 gateway [adyenpayments] #2272
|
44
63
|
* Authorize.Net: Force refund of unsettled payments via void [bizla] #2399
|
@@ -125,8 +125,9 @@ module ActiveMerchant #:nodoc:
|
|
125
125
|
class_attribute :supported_cardtypes
|
126
126
|
self.supported_cardtypes = []
|
127
127
|
|
128
|
-
class_attribute :currencies_without_fractions
|
128
|
+
class_attribute :currencies_without_fractions, :currencies_with_three_decimal_places
|
129
129
|
self.currencies_without_fractions = %w(BIF BYR CLP CVE DJF GNF HUF ISK JPY KMF KRW PYG RWF UGX VND VUV XAF XOF XPF)
|
130
|
+
self.currencies_with_three_decimal_places = %w()
|
130
131
|
|
131
132
|
class_attribute :homepage_url
|
132
133
|
class_attribute :display_name
|
@@ -263,15 +264,26 @@ module ActiveMerchant #:nodoc:
|
|
263
264
|
self.currencies_without_fractions.include?(currency.to_s)
|
264
265
|
end
|
265
266
|
|
267
|
+
def three_decimal_currency?(currency)
|
268
|
+
self.currencies_with_three_decimal_places.include?(currency.to_s)
|
269
|
+
end
|
270
|
+
|
266
271
|
def localized_amount(money, currency)
|
267
272
|
amount = amount(money)
|
268
273
|
|
269
|
-
return amount unless non_fractional_currency?(currency)
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
274
|
+
return amount unless non_fractional_currency?(currency) || three_decimal_currency?(currency)
|
275
|
+
if non_fractional_currency?(currency)
|
276
|
+
if self.money_format == :cents
|
277
|
+
sprintf("%.0f", amount.to_f / 100)
|
278
|
+
else
|
279
|
+
amount.split('.').first
|
280
|
+
end
|
281
|
+
elsif three_decimal_currency?(currency)
|
282
|
+
if self.money_format == :cents
|
283
|
+
(amount.to_i * 10).to_s
|
284
|
+
else
|
285
|
+
sprintf("%.3f", amount.to_f)
|
286
|
+
end
|
275
287
|
end
|
276
288
|
end
|
277
289
|
|
@@ -143,6 +143,8 @@ module ActiveMerchant
|
|
143
143
|
|
144
144
|
if response.params["response_reason_code"] == INELIGIBLE_FOR_ISSUING_CREDIT_ERROR
|
145
145
|
void(authorization, options)
|
146
|
+
else
|
147
|
+
response
|
146
148
|
end
|
147
149
|
end
|
148
150
|
|
@@ -553,11 +555,12 @@ module ActiveMerchant
|
|
553
555
|
|
554
556
|
xml.billTo do
|
555
557
|
first_name, last_name = names_from(payment_source, address, options)
|
558
|
+
full_address = "#{address[:address1]} #{address[:address2]}".strip
|
559
|
+
|
556
560
|
xml.firstName(truncate(first_name, 50)) unless empty?(first_name)
|
557
561
|
xml.lastName(truncate(last_name, 50)) unless empty?(last_name)
|
558
|
-
|
559
562
|
xml.company(truncate(address[:company], 50)) unless empty?(address[:company])
|
560
|
-
xml.address(truncate(
|
563
|
+
xml.address(truncate(full_address, 60))
|
561
564
|
xml.city(truncate(address[:city], 40))
|
562
565
|
xml.state(empty?(address[:state]) ? 'n/a' : truncate(address[:state], 40))
|
563
566
|
xml.zip(truncate((address[:zip] || options[:zip]), 20))
|
@@ -577,12 +580,12 @@ module ActiveMerchant
|
|
577
580
|
else
|
578
581
|
[address[:first_name], address[:last_name]]
|
579
582
|
end
|
583
|
+
full_address = "#{address[:address1]} #{address[:address2]}".strip
|
580
584
|
|
581
585
|
xml.firstName(truncate(first_name, 50)) unless empty?(first_name)
|
582
586
|
xml.lastName(truncate(last_name, 50)) unless empty?(last_name)
|
583
|
-
|
584
587
|
xml.company(truncate(address[:company], 50)) unless empty?(address[:company])
|
585
|
-
xml.address(truncate(
|
588
|
+
xml.address(truncate(full_address, 60))
|
586
589
|
xml.city(truncate(address[:city], 40))
|
587
590
|
xml.state(truncate(address[:state], 40))
|
588
591
|
xml.zip(truncate(address[:zip], 20))
|
@@ -592,7 +592,8 @@ module ActiveMerchant #:nodoc:
|
|
592
592
|
:expiration_year => credit_card_or_vault_id.year.to_s,
|
593
593
|
:google_transaction_id => credit_card_or_vault_id.transaction_id,
|
594
594
|
:source_card_type => credit_card_or_vault_id.brand,
|
595
|
-
:source_card_last_four => credit_card_or_vault_id.last_digits
|
595
|
+
:source_card_last_four => credit_card_or_vault_id.last_digits,
|
596
|
+
:eci_indicator => credit_card_or_vault_id.eci
|
596
597
|
}
|
597
598
|
end
|
598
599
|
else
|
@@ -5,7 +5,7 @@ module ActiveMerchant #:nodoc:
|
|
5
5
|
module Billing #:nodoc:
|
6
6
|
class CheckoutGateway < Gateway
|
7
7
|
self.default_currency = 'USD'
|
8
|
-
self.money_format = :
|
8
|
+
self.money_format = :cents
|
9
9
|
|
10
10
|
self.supported_countries = ['AD', 'AT', 'BE', 'BG', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FO', 'FI', 'FR', 'GB', 'GI', 'GL', 'GR', 'HR', 'HU', 'IE', 'IS', 'IL', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SI', 'SM', 'SK', 'SJ', 'TR', 'VA']
|
11
11
|
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
|
@@ -17,6 +17,9 @@ module ActiveMerchant #:nodoc:
|
|
17
17
|
|
18
18
|
self.supported_countries = %w(DE GB FR IT ES PL NL BE GR CZ PT SE HU RS AT CH BG DK FI SK NO IE HR BA AL LT MK SI LV EE ME LU MT IS AD MC LI SM)
|
19
19
|
self.default_currency = "EUR"
|
20
|
+
self.currencies_without_fractions = %w(CLP JPY KRW PYG VND)
|
21
|
+
self.currencies_with_three_decimal_places = %w(BHD JOD KWD OMR RSD TND)
|
22
|
+
|
20
23
|
self.money_format = :cents
|
21
24
|
self.supported_cardtypes = [:visa, :master, :maestro]
|
22
25
|
|
@@ -187,9 +190,11 @@ module ActiveMerchant #:nodoc:
|
|
187
190
|
private
|
188
191
|
|
189
192
|
def add_invoice(post, money, options)
|
190
|
-
|
193
|
+
currency = options[:currency] || currency(money)
|
194
|
+
|
195
|
+
post[:a4] = localized_amount(money, currency)
|
191
196
|
post[:a1] = generate_unique_id
|
192
|
-
post[:a5] =
|
197
|
+
post[:a5] = currency
|
193
198
|
post[:h9] = options[:order_id]
|
194
199
|
end
|
195
200
|
|
@@ -26,7 +26,7 @@ module ActiveMerchant #:nodoc:
|
|
26
26
|
|
27
27
|
XSD_VERSION = "1.121"
|
28
28
|
|
29
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
29
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :switch, :dankort, :maestro]
|
30
30
|
self.supported_countries = %w(US BR CA CN DK FI FR DE JP MX NO SE GB SG LB)
|
31
31
|
|
32
32
|
self.default_currency = 'USD'
|
@@ -39,7 +39,12 @@ module ActiveMerchant #:nodoc:
|
|
39
39
|
:visa => '001',
|
40
40
|
:master => '002',
|
41
41
|
:american_express => '003',
|
42
|
-
:discover => '004'
|
42
|
+
:discover => '004',
|
43
|
+
:diners_club => '005',
|
44
|
+
:jcb => '007',
|
45
|
+
:switch => '024',
|
46
|
+
:dankort => '034',
|
47
|
+
:maestro => '042'
|
43
48
|
}
|
44
49
|
|
45
50
|
@@response_codes = {
|
@@ -3,7 +3,7 @@ require 'nokogiri'
|
|
3
3
|
module ActiveMerchant #:nodoc:
|
4
4
|
module Billing #:nodoc:
|
5
5
|
class FirstPayGateway < Gateway
|
6
|
-
self.live_url = 'https://secure.
|
6
|
+
self.live_url = 'https://secure.goemerchant.com/secure/gateway/xmlgateway.aspx'
|
7
7
|
|
8
8
|
self.supported_countries = ['US']
|
9
9
|
self.default_currency = 'USD'
|
@@ -12,6 +12,7 @@ module ActiveMerchant #:nodoc:
|
|
12
12
|
|
13
13
|
self.homepage_url = 'http://1stpaygateway.net/'
|
14
14
|
self.display_name = '1stPayGateway.Net'
|
15
|
+
self.ssl_version = :TLSv1
|
15
16
|
|
16
17
|
def initialize(options={})
|
17
18
|
requires!(options, :transaction_center_id, :gateway_id)
|
@@ -262,16 +262,13 @@ module ActiveMerchant #:nodoc:
|
|
262
262
|
|
263
263
|
def add_network_tokenization_credit_card(xml, credit_card)
|
264
264
|
case card_brand(credit_card).to_sym
|
265
|
-
when :visa
|
266
|
-
xml.tag!("XID", credit_card.transaction_id) if credit_card.transaction_id
|
267
|
-
xml.tag!("CAVV", credit_card.payment_cryptogram)
|
268
|
-
when :mastercard
|
269
|
-
xml.tag!("XID", credit_card.transaction_id) if credit_card.transaction_id
|
270
|
-
xml.tag!("CAVV", credit_card.payment_cryptogram)
|
271
265
|
when :american_express
|
272
266
|
cryptogram = Base64.decode64(credit_card.payment_cryptogram)
|
273
267
|
xml.tag!("XID", Base64.encode64(cryptogram[20...40]))
|
274
268
|
xml.tag!("CAVV", Base64.encode64(cryptogram[0...20]))
|
269
|
+
else
|
270
|
+
xml.tag!("XID", credit_card.transaction_id) if credit_card.transaction_id
|
271
|
+
xml.tag!("CAVV", credit_card.payment_cryptogram)
|
275
272
|
end
|
276
273
|
end
|
277
274
|
|
@@ -153,41 +153,41 @@ module ActiveMerchant #:nodoc:
|
|
153
153
|
super
|
154
154
|
end
|
155
155
|
|
156
|
-
def purchase(money,
|
157
|
-
commit(money, build_sale_request(money,
|
156
|
+
def purchase(money, payment, options = {})
|
157
|
+
commit(money, build_sale_request(money, payment, options))
|
158
158
|
end
|
159
159
|
|
160
|
-
def authorize(money,
|
161
|
-
commit(money, build_authonly_request(money,
|
160
|
+
def authorize(money, payment, options = {})
|
161
|
+
commit(money, build_authonly_request(money, payment, options))
|
162
162
|
end
|
163
163
|
|
164
164
|
def capture(money, reference, options = {})
|
165
|
-
|
166
|
-
transaction_id
|
167
|
-
token = split_authorization[3]
|
168
|
-
commit(money, build_capture_request(transaction_id, money, options), token)
|
165
|
+
transaction_id, _, _, token = reference.split(";")
|
166
|
+
commit(money, build_capture_request(money, transaction_id, options), token)
|
169
167
|
end
|
170
168
|
|
171
169
|
def void(reference, options = {})
|
172
|
-
transaction_id,
|
173
|
-
commit(amount.to_i, build_void_request(amount.to_i, transaction_id,
|
170
|
+
transaction_id, _, amount, token = reference.split(";")
|
171
|
+
commit(amount.to_i, build_void_request(amount.to_i, transaction_id, options), token)
|
174
172
|
end
|
175
173
|
|
176
|
-
def credit(money,
|
177
|
-
commit(money, build_credit_request(money, nil,
|
174
|
+
def credit(money, payment, options = {})
|
175
|
+
commit(money, build_credit_request(money, nil, payment, options))
|
178
176
|
end
|
179
177
|
|
180
178
|
def refund(money, reference, options = {})
|
181
|
-
|
182
|
-
transaction_id
|
183
|
-
token = split_authorization[3]
|
184
|
-
commit(money, build_credit_request(money, transaction_id, nil, token, options))
|
179
|
+
transaction_id, _, _, token = reference.split(";")
|
180
|
+
commit(money, build_credit_request(money, transaction_id, token, options), token)
|
185
181
|
end
|
186
182
|
|
187
|
-
def verify(credit_card, options={})
|
183
|
+
def verify(credit_card, options = {})
|
188
184
|
authorize(0, credit_card, options)
|
189
185
|
end
|
190
186
|
|
187
|
+
def store(credit_card, options = {})
|
188
|
+
commit(nil, build_store_request(credit_card, options))
|
189
|
+
end
|
190
|
+
|
191
191
|
def supports_scrubbing
|
192
192
|
true
|
193
193
|
end
|
@@ -224,9 +224,9 @@ module ActiveMerchant #:nodoc:
|
|
224
224
|
end
|
225
225
|
end
|
226
226
|
|
227
|
-
def build_sale_request(money,
|
227
|
+
def build_sale_request(money, payment, options)
|
228
228
|
build_xml_request('SALE', options) do |xml|
|
229
|
-
|
229
|
+
add_payment(xml, payment)
|
230
230
|
add_addresses(xml, options)
|
231
231
|
add_customer_data(xml, options)
|
232
232
|
add_invoice_data(xml, options)
|
@@ -237,9 +237,9 @@ module ActiveMerchant #:nodoc:
|
|
237
237
|
end
|
238
238
|
end
|
239
239
|
|
240
|
-
def build_authonly_request(money,
|
240
|
+
def build_authonly_request(money, payment, options)
|
241
241
|
build_xml_request('AUTHONLY', options) do |xml|
|
242
|
-
|
242
|
+
add_payment(xml, payment)
|
243
243
|
add_addresses(xml, options)
|
244
244
|
add_customer_data(xml, options)
|
245
245
|
add_invoice_data(xml, options)
|
@@ -250,9 +250,10 @@ module ActiveMerchant #:nodoc:
|
|
250
250
|
end
|
251
251
|
end
|
252
252
|
|
253
|
-
def build_capture_request(
|
253
|
+
def build_capture_request(money, transaction_id, options)
|
254
254
|
build_xml_request('CAPT', options, transaction_id) do |xml|
|
255
255
|
add_invoice_data(xml, options)
|
256
|
+
add_purchase_order(xml, options)
|
256
257
|
add_user_defined_fields(xml, options)
|
257
258
|
xml.tag! 'TotalAmount', amount(money)
|
258
259
|
|
@@ -260,25 +261,31 @@ module ActiveMerchant #:nodoc:
|
|
260
261
|
end
|
261
262
|
end
|
262
263
|
|
263
|
-
def build_void_request(money, transaction_id,
|
264
|
+
def build_void_request(money, transaction_id, options)
|
264
265
|
build_xml_request('VOID', options, transaction_id) do |xml|
|
265
|
-
xml.tag! 'Approval', approval
|
266
266
|
xml.tag! 'TotalAmount', amount(money)
|
267
|
-
xml.tag! 'Token', token if token
|
268
|
-
|
269
267
|
xml.target!
|
270
268
|
end
|
271
269
|
end
|
272
270
|
|
273
|
-
def build_credit_request(money, transaction_id,
|
271
|
+
def build_credit_request(money, transaction_id, payment, options)
|
274
272
|
build_xml_request('CREDIT', options, transaction_id) do |xml|
|
275
|
-
|
273
|
+
add_payment(xml, payment)
|
276
274
|
add_invoice_data(xml, options)
|
277
275
|
add_addresses(xml, options)
|
278
276
|
add_customer_data(xml, options)
|
279
277
|
add_user_defined_fields(xml, options)
|
280
278
|
xml.tag! 'TotalAmount', amount(money)
|
281
|
-
|
279
|
+
|
280
|
+
xml.target!
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def build_store_request(credit_card, options)
|
285
|
+
build_xml_request('TOKENIZE', options) do |xml|
|
286
|
+
add_payment(xml, credit_card)
|
287
|
+
add_addresses(xml, options)
|
288
|
+
add_customer_data(xml, options)
|
282
289
|
|
283
290
|
xml.target!
|
284
291
|
end
|
@@ -344,6 +351,18 @@ module ActiveMerchant #:nodoc:
|
|
344
351
|
response[:action_code]
|
345
352
|
end
|
346
353
|
|
354
|
+
def add_payment(xml, payment)
|
355
|
+
return unless payment
|
356
|
+
|
357
|
+
if payment.is_a? String
|
358
|
+
token = payment
|
359
|
+
_, _, _, token = payment.split(";") if payment.include? ";"
|
360
|
+
xml.tag! 'Token', token if token
|
361
|
+
else
|
362
|
+
add_credit_card(xml, payment)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
347
366
|
def add_credit_card(xml, credit_card)
|
348
367
|
xml.tag! 'CardNum', credit_card.number, "CardPresent" => false, "Tokenize" => true
|
349
368
|
xml.tag! 'CardExpMonth', format_exp(credit_card.month)
|
@@ -391,7 +410,15 @@ module ActiveMerchant #:nodoc:
|
|
391
410
|
def add_invoice_data(xml, options)
|
392
411
|
xml.tag! 'OrderNumber', options[:order_id] if options[:order_id]
|
393
412
|
if tax_amount = options[:tax_amount]
|
394
|
-
xml.tag! 'TaxAmount', tax_amount, {'ExemptInd' => options[:
|
413
|
+
xml.tag! 'TaxAmount', tax_amount, {'ExemptInd' => options[:tax_exempt] || "false"}
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
def add_purchase_order(xml, options)
|
418
|
+
if purchase_order = options[:purchase_order]
|
419
|
+
xml.tag! 'Billing' do
|
420
|
+
xml.tag! 'CustomerPO', purchase_order
|
421
|
+
end
|
395
422
|
end
|
396
423
|
end
|
397
424
|
|
@@ -181,21 +181,23 @@ module ActiveMerchant #:nodoc:
|
|
181
181
|
sprintf("%.4i", creditcard.year)[-2..-1] + sprintf("%.2i", creditcard.month)
|
182
182
|
end
|
183
183
|
|
184
|
-
def add_payment_source(post,
|
185
|
-
if
|
186
|
-
post[:data_key] =
|
184
|
+
def add_payment_source(post, payment_method, options)
|
185
|
+
if payment_method.is_a?(String)
|
186
|
+
post[:data_key] = payment_method
|
187
187
|
post[:cust_id] = options[:customer]
|
188
188
|
else
|
189
|
-
if
|
189
|
+
if payment_method.respond_to?(:track_data) && payment_method.track_data.present?
|
190
190
|
post[:pos_code] = '00'
|
191
|
-
post[:track2] =
|
191
|
+
post[:track2] = payment_method.track_data
|
192
192
|
else
|
193
|
-
post[:pan] =
|
194
|
-
post[:expdate] = expdate(
|
195
|
-
post[:cvd_value] =
|
196
|
-
post[:cavv] =
|
193
|
+
post[:pan] = payment_method.number
|
194
|
+
post[:expdate] = expdate(payment_method)
|
195
|
+
post[:cvd_value] = payment_method.verification_value if payment_method.verification_value?
|
196
|
+
post[:cavv] = payment_method.payment_cryptogram if payment_method.is_a?(NetworkTokenizationCreditCard)
|
197
|
+
post[:wallet_indicator] = wallet_indicator(payment_method.source.to_s) if payment_method.is_a?(NetworkTokenizationCreditCard)
|
198
|
+
post[:crypt_type] = (payment_method.eci || 7) if payment_method.is_a?(NetworkTokenizationCreditCard)
|
197
199
|
end
|
198
|
-
post[:cust_id] = options[:customer] ||
|
200
|
+
post[:cust_id] = options[:customer] || payment_method.name
|
199
201
|
end
|
200
202
|
end
|
201
203
|
|
@@ -310,6 +312,12 @@ module ActiveMerchant #:nodoc:
|
|
310
312
|
element
|
311
313
|
end
|
312
314
|
|
315
|
+
def wallet_indicator(token_source)
|
316
|
+
return 'APP' if token_source == 'apple_pay'
|
317
|
+
return 'ANP' if token_source == 'android_pay'
|
318
|
+
nil
|
319
|
+
end
|
320
|
+
|
313
321
|
def message_from(message)
|
314
322
|
return 'Unspecified error' if message.blank?
|
315
323
|
message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
|
@@ -324,8 +332,8 @@ module ActiveMerchant #:nodoc:
|
|
324
332
|
"indrefund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
|
325
333
|
"completion" => [:order_id, :comp_amount, :txn_number, :crypt_type],
|
326
334
|
"purchasecorrection" => [:order_id, :txn_number, :crypt_type],
|
327
|
-
"cavv_preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
|
328
|
-
"cavv_purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
|
335
|
+
"cavv_preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv, :crypt_type, :wallet_indicator],
|
336
|
+
"cavv_purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv, :crypt_type, :wallet_indicator],
|
329
337
|
"transact" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
|
330
338
|
"Batchcloseall" => [],
|
331
339
|
"opentotals" => [:ecr_number],
|
@@ -130,10 +130,22 @@ module ActiveMerchant #:nodoc:
|
|
130
130
|
holder_name: creditcard.name
|
131
131
|
}
|
132
132
|
add_address(card, options)
|
133
|
+
add_customer_data(post, creditcard, options)
|
133
134
|
post[:card] = card
|
134
135
|
end
|
135
136
|
end
|
136
137
|
|
138
|
+
def add_customer_data(post, creditcard, options)
|
139
|
+
if options[:email]
|
140
|
+
customer = {
|
141
|
+
name: creditcard.name || options[:name],
|
142
|
+
email: options[:email]
|
143
|
+
}
|
144
|
+
post[:customer] = customer
|
145
|
+
end
|
146
|
+
post
|
147
|
+
end
|
148
|
+
|
137
149
|
def add_address(card, options)
|
138
150
|
return unless card.kind_of?(Hash)
|
139
151
|
if address = (options[:billing_address] || options[:address])
|
@@ -180,8 +180,8 @@ module ActiveMerchant #:nodoc:
|
|
180
180
|
end
|
181
181
|
end
|
182
182
|
|
183
|
-
def build_headers(content_length)
|
184
|
-
{
|
183
|
+
def build_headers(content_length, options = {})
|
184
|
+
headers = {
|
185
185
|
"Content-Type" => "text/xml",
|
186
186
|
"Content-Length" => content_length.to_s,
|
187
187
|
"X-VPS-Client-Timeout" => timeout.to_s,
|
@@ -189,11 +189,14 @@ module ActiveMerchant #:nodoc:
|
|
189
189
|
"X-VPS-VIT-Runtime-Version" => RUBY_VERSION,
|
190
190
|
"X-VPS-Request-ID" => SecureRandom.hex(16)
|
191
191
|
}
|
192
|
+
|
193
|
+
headers.merge!("PAYPAL-NVP" => options[:paypal_nvp]) if options[:paypal_nvp]
|
194
|
+
headers
|
192
195
|
end
|
193
196
|
|
194
|
-
def commit(request_body, options
|
197
|
+
def commit(request_body, options = {})
|
195
198
|
request = build_request(request_body, options)
|
196
|
-
headers = build_headers(request.size)
|
199
|
+
headers = build_headers(request.size, options)
|
197
200
|
|
198
201
|
response = parse(ssl_post(test? ? self.test_url : self.live_url, request, headers))
|
199
202
|
|
@@ -15,7 +15,7 @@ module ActiveMerchant
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def purchase(money, credit_card_or_reference, options = {})
|
18
|
-
MultiResponse.run
|
18
|
+
MultiResponse.run do |r|
|
19
19
|
if credit_card_or_reference.is_a?(String)
|
20
20
|
r.process { create_token(credit_card_or_reference, options) }
|
21
21
|
credit_card_or_reference = r.authorization
|
@@ -34,7 +34,7 @@ module ActiveMerchant
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def authorize(money, credit_card_or_reference, options = {})
|
37
|
-
MultiResponse.run
|
37
|
+
MultiResponse.run do |r|
|
38
38
|
if credit_card_or_reference.is_a?(String)
|
39
39
|
r.process { create_token(credit_card_or_reference, options) }
|
40
40
|
credit_card_or_reference = r.authorization
|
@@ -132,7 +132,6 @@ module ActiveMerchant
|
|
132
132
|
|
133
133
|
def create_token(identification, options)
|
134
134
|
post = {}
|
135
|
-
# post[:id] = options[:id]
|
136
135
|
commit(synchronized_path("/cards/#{identification}/tokens"), post)
|
137
136
|
end
|
138
137
|
|
@@ -196,7 +195,7 @@ module ActiveMerchant
|
|
196
195
|
post[:shipping_address] = map_address(options[:shipping_address])
|
197
196
|
end
|
198
197
|
|
199
|
-
[:metadata, :
|
198
|
+
[:metadata, :branding_id, :variables].each do |field|
|
200
199
|
post[field] = options[field] if options[field]
|
201
200
|
end
|
202
201
|
end
|
@@ -24,6 +24,7 @@ module ActiveMerchant #:nodoc:
|
|
24
24
|
post = {}
|
25
25
|
add_transaction_data("Sale", post, money, options)
|
26
26
|
add_payment(post, payment)
|
27
|
+
add_customer_details(post, payment, options)
|
27
28
|
|
28
29
|
commit(post)
|
29
30
|
end
|
@@ -32,14 +33,15 @@ module ActiveMerchant #:nodoc:
|
|
32
33
|
post = {}
|
33
34
|
add_transaction_data("Auth", post, money, options)
|
34
35
|
add_payment(post, payment)
|
36
|
+
add_customer_details(post, payment, options)
|
35
37
|
|
36
38
|
commit(post)
|
37
39
|
end
|
38
40
|
|
39
41
|
def capture(money, authorization, options={})
|
40
42
|
post = {}
|
41
|
-
|
42
|
-
|
43
|
+
auth, transaction_id, token, exp_month, exp_year, _, original_currency = authorization.split("|")
|
44
|
+
add_transaction_data("Settle", post, money, (options.merge!({currency: original_currency})))
|
43
45
|
post[:sg_AuthCode] = auth
|
44
46
|
post[:sg_TransactionID] = transaction_id
|
45
47
|
post[:sg_CCToken] = token
|
@@ -51,8 +53,8 @@ module ActiveMerchant #:nodoc:
|
|
51
53
|
|
52
54
|
def refund(money, authorization, options={})
|
53
55
|
post = {}
|
54
|
-
|
55
|
-
|
56
|
+
auth, transaction_id, token, exp_month, exp_year, _, original_currency = authorization.split("|")
|
57
|
+
add_transaction_data("Credit", post, money, (options.merge!({currency: original_currency})))
|
56
58
|
post[:sg_CreditType] = 2
|
57
59
|
post[:sg_AuthCode] = auth
|
58
60
|
post[:sg_TransactionID] = transaction_id
|
@@ -74,8 +76,8 @@ module ActiveMerchant #:nodoc:
|
|
74
76
|
|
75
77
|
def void(authorization, options={})
|
76
78
|
post = {}
|
77
|
-
auth, transaction_id, token, exp_month, exp_year, original_amount = authorization.split("|")
|
78
|
-
add_transaction_data("Void", post, (original_amount.to_f * 100), options)
|
79
|
+
auth, transaction_id, token, exp_month, exp_year, original_amount, original_currency = authorization.split("|")
|
80
|
+
add_transaction_data("Void", post, (original_amount.to_f * 100), (options.merge!({currency: original_currency})))
|
79
81
|
post[:sg_CreditType] = 2
|
80
82
|
post[:sg_AuthCode] = auth
|
81
83
|
post[:sg_TransactionID] = transaction_id
|
@@ -125,6 +127,21 @@ module ActiveMerchant #:nodoc:
|
|
125
127
|
post[:sg_CVV2] = payment.verification_value
|
126
128
|
end
|
127
129
|
|
130
|
+
def add_customer_details(post, payment, options)
|
131
|
+
if address = options[:billing_address] || options[:address]
|
132
|
+
post[:sg_FirstName] = payment.first_name
|
133
|
+
post[:sg_LastName] = payment.last_name
|
134
|
+
post[:sg_Address] = address[:address1] if address[:address1]
|
135
|
+
post[:sg_City] = address[:city] if address[:city]
|
136
|
+
post[:sg_State] = address[:state] if address[:state]
|
137
|
+
post[:sg_Zip] = address[:zip] if address[:zip]
|
138
|
+
post[:sg_Country] = address[:country] if address[:country]
|
139
|
+
post[:sg_Phone] = address[:phone] if address[:phone]
|
140
|
+
end
|
141
|
+
|
142
|
+
post[:sg_Email] = options[:email]
|
143
|
+
end
|
144
|
+
|
128
145
|
def parse(xml)
|
129
146
|
response = {}
|
130
147
|
|
@@ -177,7 +194,8 @@ module ActiveMerchant #:nodoc:
|
|
177
194
|
response[:token],
|
178
195
|
parameters[:sg_ExpMonth],
|
179
196
|
parameters[:sg_ExpYear],
|
180
|
-
parameters[:sg_Amount]
|
197
|
+
parameters[:sg_Amount],
|
198
|
+
parameters[:sg_Currency]
|
181
199
|
].join("|")
|
182
200
|
end
|
183
201
|
|
@@ -0,0 +1,217 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class TrexleGateway < Gateway
|
4
|
+
self.test_url = 'https://core.trexle.com/api/v1'
|
5
|
+
self.live_url = 'https://core.trexle.com/api/v1'
|
6
|
+
|
7
|
+
self.default_currency = 'USD'
|
8
|
+
self.money_format = :cents
|
9
|
+
self.supported_countries = %w(AD AE AT AU BD BE BG BN CA CH CY CZ DE DK EE EG ES FI FR GB
|
10
|
+
GI GR HK HU ID IE IL IM IN IS IT JO KW LB LI LK LT LU LV MC
|
11
|
+
MT MU MV MX MY NL NO NZ OM PH PL PT QA RO SA SE SG SI SK SM
|
12
|
+
TR TT UM US VA VN ZA)
|
13
|
+
self.supported_cardtypes = [:visa, :master, :american_express]
|
14
|
+
self.homepage_url = 'https://trexle.com'
|
15
|
+
self.display_name = 'Trexle'
|
16
|
+
|
17
|
+
def initialize(options = {})
|
18
|
+
requires!(options, :api_key)
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
# Create a charge using a credit card, card token or customer token
|
23
|
+
#
|
24
|
+
# To charge a credit card: purchase([money], [creditcard hash], ...)
|
25
|
+
# To charge a customer: purchase([money], [token], ...)
|
26
|
+
def purchase(money, creditcard, options = {})
|
27
|
+
post = {}
|
28
|
+
|
29
|
+
add_amount(post, money, options)
|
30
|
+
add_customer_data(post, options)
|
31
|
+
add_invoice(post, options)
|
32
|
+
add_creditcard(post, creditcard)
|
33
|
+
add_address(post, creditcard, options)
|
34
|
+
commit(:post, 'charges', post, options)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Create a customer and associated credit card. The token that is returned
|
38
|
+
# can be used instead of a credit card parameter in the purchase method
|
39
|
+
def store(creditcard, options = {})
|
40
|
+
post = {}
|
41
|
+
|
42
|
+
add_creditcard(post, creditcard)
|
43
|
+
add_customer_data(post, options)
|
44
|
+
add_address(post, creditcard, options)
|
45
|
+
commit(:post, 'customers', post, options)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Refund a transaction
|
49
|
+
def refund(money, token, options = {})
|
50
|
+
commit(:post, "charges/#{CGI.escape(token)}/refunds", { amount: amount(money) }, options)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Authorize an amount on a credit card. Once authorized, you can later
|
54
|
+
# capture this charge using the charge token that is returned.
|
55
|
+
def authorize(money, creditcard, options = {})
|
56
|
+
post = {}
|
57
|
+
|
58
|
+
add_amount(post, money, options)
|
59
|
+
add_customer_data(post, options)
|
60
|
+
add_invoice(post, options)
|
61
|
+
add_creditcard(post, creditcard)
|
62
|
+
add_address(post, creditcard, options)
|
63
|
+
post[:capture] = false
|
64
|
+
commit(:post, 'charges', post, options)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Captures a previously authorized charge. Capturing only part of the original
|
68
|
+
# authorization is currently not supported.
|
69
|
+
def capture(money, token, options = {})
|
70
|
+
commit(:put, "charges/#{CGI.escape(token)}/capture", { amount: amount(money) }, options)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Updates the credit card for the customer.
|
74
|
+
def update(token, creditcard, options = {})
|
75
|
+
post = {}
|
76
|
+
|
77
|
+
add_creditcard(post, creditcard)
|
78
|
+
add_customer_data(post, options)
|
79
|
+
add_address(post, creditcard, options)
|
80
|
+
commit(:put, "customers/#{CGI.escape(token)}", post, options)
|
81
|
+
end
|
82
|
+
|
83
|
+
def supports_scrubbing
|
84
|
+
true
|
85
|
+
end
|
86
|
+
|
87
|
+
def scrub(transcript)
|
88
|
+
transcript.
|
89
|
+
gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
|
90
|
+
gsub(/(number\\?":\\?")(\d*)/, '\1[FILTERED]').
|
91
|
+
gsub(/(cvc\\?":\\?")(\d*)/, '\1[FILTERED]')
|
92
|
+
end
|
93
|
+
private
|
94
|
+
|
95
|
+
def add_amount(post, money, options)
|
96
|
+
post[:amount] = amount(money)
|
97
|
+
post[:currency] = (options[:currency] || currency(money))
|
98
|
+
post[:currency] = post[:currency].upcase if post[:currency]
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_customer_data(post, options)
|
102
|
+
post[:email] = options[:email] if options[:email]
|
103
|
+
post[:ip_address] = options[:ip] if options[:ip]
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_address(post, creditcard, options)
|
107
|
+
return if creditcard.kind_of?(String)
|
108
|
+
address = (options[:billing_address] || options[:address])
|
109
|
+
return unless address
|
110
|
+
|
111
|
+
post[:card] ||= {}
|
112
|
+
post[:card].merge!(
|
113
|
+
address_line1: address[:address1],
|
114
|
+
address_line2: address[:address_line2],
|
115
|
+
address_city: address[:city],
|
116
|
+
address_postcode: address[:zip],
|
117
|
+
address_state: address[:state],
|
118
|
+
address_country: address[:country]
|
119
|
+
)
|
120
|
+
end
|
121
|
+
|
122
|
+
def add_invoice(post, options)
|
123
|
+
post[:description] = options[:description] || "Active Merchant Purchase"
|
124
|
+
end
|
125
|
+
|
126
|
+
def add_creditcard(post, creditcard)
|
127
|
+
if creditcard.respond_to?(:number)
|
128
|
+
post[:card] ||= {}
|
129
|
+
|
130
|
+
post[:card].merge!(
|
131
|
+
number: creditcard.number,
|
132
|
+
expiry_month: creditcard.month,
|
133
|
+
expiry_year: creditcard.year,
|
134
|
+
cvc: creditcard.verification_value,
|
135
|
+
name: creditcard.name
|
136
|
+
)
|
137
|
+
elsif creditcard.kind_of?(String)
|
138
|
+
if creditcard =~ /^token_/
|
139
|
+
post[:card_token] = creditcard
|
140
|
+
else
|
141
|
+
post[:customer_token] = creditcard
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def headers(params = {})
|
147
|
+
result = {
|
148
|
+
"Content-Type" => "application/json",
|
149
|
+
"Authorization" => "Basic #{Base64.strict_encode64(options[:api_key] + ':').strip}"
|
150
|
+
}
|
151
|
+
|
152
|
+
result['X-Partner-Key'] = params[:partner_key] if params[:partner_key]
|
153
|
+
result['X-Safe-Card'] = params[:safe_card] if params[:safe_card]
|
154
|
+
result
|
155
|
+
end
|
156
|
+
|
157
|
+
def commit(method, action, params, options)
|
158
|
+
url = "#{test? ? test_url : live_url}/#{action}"
|
159
|
+
raw_response = ssl_request(method, url, post_data(params), headers(options))
|
160
|
+
parsed_response = parse(raw_response)
|
161
|
+
success_response(parsed_response)
|
162
|
+
rescue ResponseError => e
|
163
|
+
error_response(parse(e.response.body))
|
164
|
+
rescue JSON::ParserError
|
165
|
+
unparsable_response(raw_response)
|
166
|
+
end
|
167
|
+
|
168
|
+
def success_response(body)
|
169
|
+
return invalid_response unless body['response']
|
170
|
+
|
171
|
+
response = body['response']
|
172
|
+
Response.new(
|
173
|
+
true,
|
174
|
+
response['status_message'],
|
175
|
+
body,
|
176
|
+
authorization: token(response),
|
177
|
+
test: test?
|
178
|
+
)
|
179
|
+
end
|
180
|
+
|
181
|
+
def error_response(body)
|
182
|
+
return invalid_response unless body['error']
|
183
|
+
Response.new(
|
184
|
+
false,
|
185
|
+
body['error'],
|
186
|
+
body,
|
187
|
+
authorization: nil,
|
188
|
+
test: test?
|
189
|
+
)
|
190
|
+
end
|
191
|
+
|
192
|
+
def unparsable_response(raw_response)
|
193
|
+
message = "Invalid JSON response received from Trexle. Please contact support@trexle.com if you continue to receive this message."
|
194
|
+
message += " (The raw response returned by the API was #{raw_response.inspect})"
|
195
|
+
return Response.new(false, message)
|
196
|
+
end
|
197
|
+
|
198
|
+
def invalid_response
|
199
|
+
message = "Invalid response."
|
200
|
+
return Response.new(false, message)
|
201
|
+
end
|
202
|
+
|
203
|
+
def token(response)
|
204
|
+
response['token']
|
205
|
+
end
|
206
|
+
|
207
|
+
def parse(body)
|
208
|
+
return {} if body.blank?
|
209
|
+
JSON.parse(body)
|
210
|
+
end
|
211
|
+
|
212
|
+
def post_data(parameters = {})
|
213
|
+
parameters.to_json
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
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.68.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: 2017-06-
|
11
|
+
date: 2017-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -358,6 +358,7 @@ files:
|
|
358
358
|
- lib/active_merchant/billing/gateways/transact_pro.rb
|
359
359
|
- lib/active_merchant/billing/gateways/transax.rb
|
360
360
|
- lib/active_merchant/billing/gateways/transnational.rb
|
361
|
+
- lib/active_merchant/billing/gateways/trexle.rb
|
361
362
|
- lib/active_merchant/billing/gateways/trust_commerce.rb
|
362
363
|
- lib/active_merchant/billing/gateways/usa_epay.rb
|
363
364
|
- lib/active_merchant/billing/gateways/usa_epay_advanced.rb
|