activemerchant 1.32.1 → 1.33.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +41 -0
- data/CONTRIBUTORS +8 -0
- data/README.md +6 -4
- data/lib/active_merchant/billing/check.rb +4 -3
- data/lib/active_merchant/billing/credit_card.rb +7 -3
- data/lib/active_merchant/billing/gateways/authorize_net.rb +27 -7
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +8 -1
- data/lib/active_merchant/billing/gateways/blue_pay.rb +201 -185
- data/lib/active_merchant/billing/gateways/bogus.rb +1 -1
- data/lib/active_merchant/billing/gateways/card_stream_modern.rb +155 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +94 -12
- data/lib/active_merchant/billing/gateways/litle.rb +41 -11
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +27 -6
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -2
- data/lib/active_merchant/billing/gateways/net_registry.rb +8 -3
- data/lib/active_merchant/billing/gateways/netaxept.rb +65 -117
- data/lib/active_merchant/billing/gateways/orbital.rb +181 -48
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +12 -10
- data/lib/active_merchant/billing/gateways/paymill.rb +5 -5
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +11 -6
- data/lib/active_merchant/billing/gateways/paypal_express.rb +25 -7
- data/lib/active_merchant/billing/gateways/pin.rb +5 -5
- data/lib/active_merchant/billing/gateways/sage.rb +10 -5
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +16 -11
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +1 -1
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +21 -16
- data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -0
- data/lib/active_merchant/billing/gateways/transnational.rb +239 -0
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +8 -3
- data/lib/active_merchant/billing/integrations/direc_pay.rb +1 -1
- data/lib/active_merchant/billing/integrations/direc_pay/status.rb +1 -1
- data/lib/active_merchant/billing/integrations/dwolla.rb +5 -12
- data/lib/active_merchant/billing/integrations/dwolla/common.rb +21 -0
- data/lib/active_merchant/billing/integrations/dwolla/helper.rb +15 -6
- data/lib/active_merchant/billing/integrations/dwolla/notification.rb +11 -6
- data/lib/active_merchant/billing/integrations/dwolla/return.rb +12 -4
- data/lib/active_merchant/billing/integrations/notification.rb +13 -8
- data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +13 -1
- data/lib/active_merchant/billing/integrations/payu_in.rb +43 -0
- data/lib/active_merchant/billing/integrations/payu_in/helper.rb +74 -0
- data/lib/active_merchant/billing/integrations/payu_in/notification.rb +167 -0
- data/lib/active_merchant/billing/integrations/payu_in/return.rb +53 -0
- data/lib/active_merchant/billing/integrations/quickpay/notification.rb +68 -5
- data/lib/active_merchant/billing/integrations/rbkmoney.rb +17 -0
- data/lib/active_merchant/billing/integrations/rbkmoney/helper.rb +23 -0
- data/lib/active_merchant/billing/integrations/rbkmoney/notification.rb +91 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +14 -4
- metadata.gz.sig +0 -0
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'nokogiri'
|
1
2
|
module ActiveMerchant #:nodoc:
|
2
3
|
module Billing #:nodoc:
|
3
4
|
module PayflowCommonAPI
|
@@ -140,17 +141,18 @@ module ActiveMerchant #:nodoc:
|
|
140
141
|
|
141
142
|
def parse(data)
|
142
143
|
response = {}
|
143
|
-
xml =
|
144
|
-
|
144
|
+
xml = Nokogiri::XML(data)
|
145
|
+
xml.remove_namespaces!
|
146
|
+
root = xml.xpath("//ResponseData")
|
145
147
|
|
146
148
|
# REXML::XPath in Ruby 1.8.6 is now unable to match nodes based on their attributes
|
147
|
-
tx_result =
|
149
|
+
tx_result = root.xpath(".//TransactionResult").first
|
148
150
|
|
149
|
-
if tx_result && tx_result.attributes['Duplicate'] == "true"
|
151
|
+
if tx_result && tx_result.attributes['Duplicate'].to_s == "true"
|
150
152
|
response[:duplicate] = true
|
151
153
|
end
|
152
154
|
|
153
|
-
root.
|
155
|
+
root.xpath(".//*").each do |node|
|
154
156
|
parse_element(response, node)
|
155
157
|
end
|
156
158
|
|
@@ -166,14 +168,14 @@ module ActiveMerchant #:nodoc:
|
|
166
168
|
# in an RPPaymentResults element so we'll come here multiple times
|
167
169
|
response[node_name] ||= []
|
168
170
|
response[node_name] << ( payment_result_response = {} )
|
169
|
-
node.
|
170
|
-
when node.
|
171
|
-
node.
|
171
|
+
node.xpath(".//*").each{ |e| parse_element(payment_result_response, e) }
|
172
|
+
when node.xpath(".//*").to_a.any?
|
173
|
+
node.xpath(".//*").each{|e| parse_element(response, e) }
|
172
174
|
when node_name.to_s =~ /amt$/
|
173
175
|
# *Amt elements don't put the value in the #text - instead they use a Currency attribute
|
174
|
-
response[node_name] = node.attributes['Currency']
|
176
|
+
response[node_name] = node.attributes['Currency'].to_s
|
175
177
|
when node_name == :ext_data
|
176
|
-
response[node.attributes['Name'].underscore.to_sym] = node.attributes['Value']
|
178
|
+
response[node.attributes['Name'].to_s.underscore.to_sym] = node.attributes['Value'].to_s
|
177
179
|
else
|
178
180
|
response[node_name] = node.text
|
179
181
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Billing #:nodoc:
|
3
3
|
class PaymillGateway < Gateway
|
4
|
-
self.supported_countries = %w(AD AT BE CY CZ DE DK EE ES FI FO FR GB GR
|
5
|
-
HU IE IL IS IT LI LT LU LV MT NL NO PL PT
|
6
|
-
|
4
|
+
self.supported_countries = %w(AD AT BE CH CY CZ DE DK EE ES FI FO FR GB GR
|
5
|
+
HU IE IL IS IT LI LT LU LV MT NL NO PL PT SE
|
6
|
+
SI SK TR VA)
|
7
7
|
|
8
8
|
self.supported_cardtypes = [:visa, :master]
|
9
9
|
self.homepage_url = 'https://paymill.com'
|
10
|
-
self.display_name = '
|
10
|
+
self.display_name = 'PAYMILL'
|
11
11
|
self.money_format = :cents
|
12
12
|
self.default_currency = 'EUR'
|
13
13
|
|
@@ -154,7 +154,7 @@ module ActiveMerchant #:nodoc:
|
|
154
154
|
end
|
155
155
|
|
156
156
|
def save_card_url
|
157
|
-
(test? ? 'https://test-token.paymill.com' : 'https://token-v2.paymill.
|
157
|
+
(test? ? 'https://test-token.paymill.com' : 'https://token-v2.paymill.de')
|
158
158
|
end
|
159
159
|
|
160
160
|
def post_data(params)
|
@@ -617,11 +617,11 @@ module ActiveMerchant #:nodoc:
|
|
617
617
|
response = parse(action, ssl_post(endpoint_url, build_request(request), @options[:headers]))
|
618
618
|
|
619
619
|
build_response(successful?(response), message_from(response), response,
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
620
|
+
:test => test?,
|
621
|
+
:authorization => authorization_from(response),
|
622
|
+
:fraud_review => fraud_review?(response),
|
623
|
+
:avs_result => { :code => response[:avs_code] },
|
624
|
+
:cvv_result => response[:cvv2_code]
|
625
625
|
)
|
626
626
|
end
|
627
627
|
|
@@ -630,7 +630,12 @@ module ActiveMerchant #:nodoc:
|
|
630
630
|
end
|
631
631
|
|
632
632
|
def authorization_from(response)
|
633
|
-
|
633
|
+
(
|
634
|
+
response[:transaction_id] ||
|
635
|
+
response[:authorization_id] ||
|
636
|
+
response[:refund_transaction_id] ||
|
637
|
+
response[:billing_agreement_id]
|
638
|
+
)
|
634
639
|
end
|
635
640
|
|
636
641
|
def successful?(response)
|
@@ -59,9 +59,19 @@ module ActiveMerchant #:nodoc:
|
|
59
59
|
commit 'DoExpressCheckoutPayment', build_sale_or_authorization_request('Sale', money, options)
|
60
60
|
end
|
61
61
|
|
62
|
-
def
|
62
|
+
def store(token, options = {})
|
63
|
+
commit 'CreateBillingAgreement', build_create_billing_agreement_request(token, options)
|
64
|
+
end
|
65
|
+
|
66
|
+
def authorize_reference_transaction(money, options = {})
|
63
67
|
requires!(options, :reference_id, :payment_type, :invoice_id, :description, :ip)
|
64
68
|
|
69
|
+
commit 'DoReferenceTransaction', build_reference_transaction_request('Authorization', money, options)
|
70
|
+
end
|
71
|
+
|
72
|
+
def reference_transaction(money, options = {})
|
73
|
+
requires!(options, :reference_id)
|
74
|
+
|
65
75
|
commit 'DoReferenceTransaction', build_reference_transaction_request('Sale', money, options)
|
66
76
|
end
|
67
77
|
|
@@ -142,7 +152,7 @@ module ActiveMerchant #:nodoc:
|
|
142
152
|
end
|
143
153
|
xml.tag! 'n2:CallbackURL', options[:callback_url] unless options[:callback_url].blank?
|
144
154
|
|
145
|
-
add_payment_details(xml,
|
155
|
+
add_payment_details(xml, money, currency_code, options)
|
146
156
|
if options[:shipping_options]
|
147
157
|
options[:shipping_options].each do |shipping_option|
|
148
158
|
xml.tag! 'n2:FlatRateShippingOptions' do
|
@@ -166,6 +176,18 @@ module ActiveMerchant #:nodoc:
|
|
166
176
|
xml.target!
|
167
177
|
end
|
168
178
|
|
179
|
+
def build_create_billing_agreement_request(token, options = {})
|
180
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
181
|
+
xml.tag! 'CreateBillingAgreementReq', 'xmlns' => PAYPAL_NAMESPACE do
|
182
|
+
xml.tag! 'CreateBillingAgreementRequest', 'xmlns:n2' => EBAY_NAMESPACE do
|
183
|
+
xml.tag! 'n2:Version', API_VERSION
|
184
|
+
xml.tag! 'Token', token
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
xml.target!
|
189
|
+
end
|
190
|
+
|
169
191
|
def build_reference_transaction_request(action, money, options)
|
170
192
|
currency_code = options[:currency] || currency(money)
|
171
193
|
|
@@ -179,7 +201,7 @@ module ActiveMerchant #:nodoc:
|
|
179
201
|
xml.tag! 'n2:ReferenceID', options[:reference_id]
|
180
202
|
xml.tag! 'n2:PaymentAction', action
|
181
203
|
xml.tag! 'n2:PaymentType', options[:payment_type] || 'Any'
|
182
|
-
add_payment_details(xml,
|
204
|
+
add_payment_details(xml, money, currency_code, options)
|
183
205
|
xml.tag! 'n2:IPAddress', options[:ip]
|
184
206
|
end
|
185
207
|
end
|
@@ -192,10 +214,6 @@ module ActiveMerchant #:nodoc:
|
|
192
214
|
PaypalExpressResponse.new(success, message, response, options)
|
193
215
|
end
|
194
216
|
|
195
|
-
def with_money_default(money)
|
196
|
-
amount(money).to_f.zero? ? 100 : money
|
197
|
-
end
|
198
|
-
|
199
217
|
def locale_code(country_code)
|
200
218
|
NON_STANDARD_LOCALE_CODES[country_code] || country_code
|
201
219
|
end
|
@@ -29,7 +29,7 @@ module ActiveMerchant #:nodoc:
|
|
29
29
|
add_creditcard(post, creditcard)
|
30
30
|
add_address(post, creditcard, options)
|
31
31
|
|
32
|
-
commit('charges', post)
|
32
|
+
commit('charges', post, options)
|
33
33
|
end
|
34
34
|
|
35
35
|
# Create a customer and associated credit card. The token that is returned
|
@@ -40,14 +40,14 @@ module ActiveMerchant #:nodoc:
|
|
40
40
|
add_creditcard(post, creditcard)
|
41
41
|
add_customer_data(post, options)
|
42
42
|
add_address(post, creditcard, options)
|
43
|
-
commit('customers', post)
|
43
|
+
commit('customers', post, options)
|
44
44
|
end
|
45
45
|
|
46
46
|
# Refund a transaction, note that the money attribute is ignored at the
|
47
47
|
# moment as the API does not support partial refunds. The parameter is
|
48
48
|
# kept for compatibility reasons
|
49
49
|
def refund(money, token, options = {})
|
50
|
-
commit("charges/#{CGI.escape(token)}/refunds", :amount => amount(money))
|
50
|
+
commit("charges/#{CGI.escape(token)}/refunds", { :amount => amount(money) }, options)
|
51
51
|
end
|
52
52
|
|
53
53
|
private
|
@@ -112,11 +112,11 @@ module ActiveMerchant #:nodoc:
|
|
112
112
|
result
|
113
113
|
end
|
114
114
|
|
115
|
-
def commit(action, params)
|
115
|
+
def commit(action, params, options)
|
116
116
|
url = "#{test? ? test_url : live_url}/#{action}"
|
117
117
|
|
118
118
|
begin
|
119
|
-
body = parse(ssl_post(url, post_data(params), headers(
|
119
|
+
body = parse(ssl_post(url, post_data(params), headers(options)))
|
120
120
|
rescue ResponseError => e
|
121
121
|
body = parse(e.response.body)
|
122
122
|
end
|
@@ -119,17 +119,22 @@ module ActiveMerchant #:nodoc:
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
|
122
|
+
def credit(money, source, options = {})
|
123
|
+
deprecated CREDIT_DEPRECATION_MESSAGE
|
124
|
+
refund(money, source, options)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Performs a refund transaction.
|
123
128
|
#
|
124
129
|
# ==== Parameters
|
125
130
|
#
|
126
131
|
# * <tt>money</tt> - The amount to be authorized as an integer value in cents.
|
127
|
-
# * <tt>source</tt> - The CreditCard or Check object to be used as the target for the
|
128
|
-
def
|
132
|
+
# * <tt>source</tt> - The CreditCard or Check object to be used as the target for the refund.
|
133
|
+
def refund(money, source, options = {})
|
129
134
|
if card_brand(source) == "check"
|
130
|
-
virtual_check.
|
135
|
+
virtual_check.refund(money, source, options)
|
131
136
|
else
|
132
|
-
bankcard.
|
137
|
+
bankcard.refund(money, source, options)
|
133
138
|
end
|
134
139
|
end
|
135
140
|
|
@@ -6,7 +6,7 @@ module ActiveMerchant #:nodoc:
|
|
6
6
|
include SageCore
|
7
7
|
self.live_url = 'https://www.sagepayments.net/cgi-bin/eftBankcard.dll?transaction'
|
8
8
|
self.source = 'bankcard'
|
9
|
-
|
9
|
+
|
10
10
|
# Credit cards supported by Sage
|
11
11
|
# * VISA
|
12
12
|
# * MasterCard
|
@@ -17,42 +17,47 @@ module ActiveMerchant #:nodoc:
|
|
17
17
|
# * JCB
|
18
18
|
# * Sears
|
19
19
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
|
20
|
-
|
20
|
+
|
21
21
|
def authorize(money, credit_card, options = {})
|
22
22
|
post = {}
|
23
23
|
add_credit_card(post, credit_card)
|
24
24
|
add_transaction_data(post, money, options)
|
25
25
|
commit(:authorization, post)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def purchase(money, credit_card, options = {})
|
29
29
|
post = {}
|
30
30
|
add_credit_card(post, credit_card)
|
31
31
|
add_transaction_data(post, money, options)
|
32
32
|
commit(:purchase, post)
|
33
|
-
end
|
34
|
-
|
35
|
-
# The +money+ amount is not used. The entire amount of the
|
33
|
+
end
|
34
|
+
|
35
|
+
# The +money+ amount is not used. The entire amount of the
|
36
36
|
# initial authorization will be captured.
|
37
37
|
def capture(money, reference, options = {})
|
38
38
|
post = {}
|
39
39
|
add_reference(post, reference)
|
40
40
|
commit(:capture, post)
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def void(reference, options = {})
|
44
44
|
post = {}
|
45
45
|
add_reference(post, reference)
|
46
46
|
commit(:void, post)
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def credit(money, credit_card, options = {})
|
50
|
+
deprecated CREDIT_DEPRECATION_MESSAGE
|
51
|
+
refund(money, credit_card, options)
|
52
|
+
end
|
53
|
+
|
54
|
+
def refund(money, credit_card, options = {})
|
50
55
|
post = {}
|
51
56
|
add_credit_card(post, credit_card)
|
52
57
|
add_transaction_data(post, money, options)
|
53
58
|
commit(:credit, post)
|
54
59
|
end
|
55
|
-
|
60
|
+
|
56
61
|
private
|
57
62
|
def exp_date(credit_card)
|
58
63
|
year = sprintf("%.4i", credit_card.year)
|
@@ -67,7 +72,7 @@ module ActiveMerchant #:nodoc:
|
|
67
72
|
post[:C_exp] = exp_date(credit_card)
|
68
73
|
post[:C_cvv] = credit_card.verification_value if credit_card.verification_value?
|
69
74
|
end
|
70
|
-
|
75
|
+
|
71
76
|
def parse(data)
|
72
77
|
response = {}
|
73
78
|
response[:success] = data[1,1]
|
@@ -78,7 +83,7 @@ module ActiveMerchant #:nodoc:
|
|
78
83
|
response[:avs_result] = data[43, 1].strip
|
79
84
|
response[:risk] = data[44, 2]
|
80
85
|
response[:reference] = data[46, 10]
|
81
|
-
|
86
|
+
|
82
87
|
response[:order_number], response[:recurring] = data[57...-1].split("\034")
|
83
88
|
response
|
84
89
|
end
|
@@ -45,7 +45,7 @@ module ActiveMerchant #:nodoc:
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def add_customer_data(post, options)
|
48
|
-
post[:T_customer_number] = options[:customer]
|
48
|
+
post[:T_customer_number] = options[:customer] if Float(options[:customer]) rescue nil
|
49
49
|
end
|
50
50
|
|
51
51
|
def add_addresses(post, options)
|
@@ -6,7 +6,7 @@ module ActiveMerchant #:nodoc:
|
|
6
6
|
include SageCore
|
7
7
|
self.live_url = 'https://www.sagepayments.net/cgi-bin/eftVirtualCheck.dll?transaction'
|
8
8
|
self.source = 'virtual_check'
|
9
|
-
|
9
|
+
|
10
10
|
def purchase(money, credit_card, options = {})
|
11
11
|
post = {}
|
12
12
|
add_check(post, credit_card)
|
@@ -14,21 +14,26 @@ module ActiveMerchant #:nodoc:
|
|
14
14
|
add_transaction_data(post, money, options)
|
15
15
|
commit(:purchase, post)
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def void(reference, options = {})
|
19
19
|
post = {}
|
20
20
|
add_reference(post, reference)
|
21
21
|
commit(:void, post)
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def credit(money, credit_card, options = {})
|
25
|
+
deprecated CREDIT_DEPRECATION_MESSAGE
|
26
|
+
refund(money, source, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def refund(money, credit_card, options = {})
|
25
30
|
post = {}
|
26
31
|
add_check(post, credit_card)
|
27
32
|
add_check_customer_data(post, options)
|
28
33
|
add_transaction_data(post, money, options)
|
29
34
|
commit(:credit, post)
|
30
35
|
end
|
31
|
-
|
36
|
+
|
32
37
|
private
|
33
38
|
def add_check(post, check)
|
34
39
|
post[:C_first_name] = check.first_name
|
@@ -38,37 +43,37 @@ module ActiveMerchant #:nodoc:
|
|
38
43
|
post[:C_check_number] = check.number
|
39
44
|
post[:C_acct_type] = account_type(check)
|
40
45
|
end
|
41
|
-
|
46
|
+
|
42
47
|
def add_check_customer_data(post, options)
|
43
48
|
# Required Customer Type – (NACHA Transaction Class)
|
44
|
-
# CCD for Commercial, Merchant Initiated
|
49
|
+
# CCD for Commercial, Merchant Initiated
|
45
50
|
# PPD for Personal, Merchant Initiated
|
46
|
-
# WEB for Internet, Consumer Initiated
|
47
|
-
# RCK for Returned Checks
|
48
|
-
# ARC for Account Receivable Entry
|
51
|
+
# WEB for Internet, Consumer Initiated
|
52
|
+
# RCK for Returned Checks
|
53
|
+
# ARC for Account Receivable Entry
|
49
54
|
# TEL for TelephoneInitiated
|
50
55
|
post[:C_customer_type] = "WEB"
|
51
56
|
|
52
|
-
# Optional 10 Digit Originator ID – Assigned By for each transaction class or business purpose. If not provided, the default Originator ID for the specific Customer Type will be applied.
|
57
|
+
# Optional 10 Digit Originator ID – Assigned By for each transaction class or business purpose. If not provided, the default Originator ID for the specific Customer Type will be applied.
|
53
58
|
post[:C_originator_id] = options[:originator_id]
|
54
59
|
|
55
60
|
# Optional Transaction Addenda
|
56
61
|
post[:T_addenda] = options[:addenda]
|
57
62
|
|
58
|
-
# Required Check Writer Social Security Number ( Numbers Only, No Dashes )
|
63
|
+
# Required Check Writer Social Security Number ( Numbers Only, No Dashes )
|
59
64
|
post[:C_ssn] = options[:ssn].to_s.gsub(/[^\d]/, '')
|
60
65
|
|
61
66
|
post[:C_dl_state_code] = options[:drivers_license_state]
|
62
67
|
post[:C_dl_number] = options[:drivers_license_number]
|
63
68
|
post[:C_dob] = format_birth_date(options[:date_of_birth])
|
64
69
|
end
|
65
|
-
|
70
|
+
|
66
71
|
def format_birth_date(date)
|
67
72
|
date.respond_to?(:strftime) ? date.strftime("%m/%d/%Y") : date
|
68
73
|
end
|
69
74
|
|
70
|
-
# DDA for Checking
|
71
|
-
# SAV for Savings
|
75
|
+
# DDA for Checking
|
76
|
+
# SAV for Savings
|
72
77
|
def account_type(check)
|
73
78
|
case check.account_type
|
74
79
|
when 'checking' then 'DDA'
|
@@ -76,7 +81,7 @@ module ActiveMerchant #:nodoc:
|
|
76
81
|
else raise ArgumentError, "Unknown account type #{check.account_type}"
|
77
82
|
end
|
78
83
|
end
|
79
|
-
|
84
|
+
|
80
85
|
def parse(data)
|
81
86
|
response = {}
|
82
87
|
response[:success] = data[1,1]
|
@@ -84,7 +89,7 @@ module ActiveMerchant #:nodoc:
|
|
84
89
|
response[:message] = data[8,32].strip
|
85
90
|
response[:risk] = data[40, 2]
|
86
91
|
response[:reference] = data[42, 10]
|
87
|
-
|
92
|
+
|
88
93
|
extra_data = data[53...-1].split("\034")
|
89
94
|
response[:order_number] = extra_data[0]
|
90
95
|
response[:authentication_indicator] = extra_data[1]
|
@@ -160,6 +160,7 @@ module ActiveMerchant #:nodoc:
|
|
160
160
|
|
161
161
|
def add_optional_data(post, options)
|
162
162
|
add_pair(post, :GiftAidPayment, options[:gift_aid_payment]) unless options[:gift_aid_payment].blank?
|
163
|
+
add_pair(post, :Apply3DSecure, options[:apply_3d_secure]) unless options[:apply_3d_secure].blank?
|
163
164
|
end
|
164
165
|
|
165
166
|
def add_address(post, options)
|
@@ -0,0 +1,239 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class TransnationalGateway < Gateway
|
4
|
+
self.live_url = self.test_url = 'https://secure.networkmerchants.com/api/transact.php'
|
5
|
+
|
6
|
+
self.supported_countries = ['US']
|
7
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
8
|
+
|
9
|
+
self.homepage_url = 'http://www.tnbci.com/'
|
10
|
+
self.display_name = 'Transnational'
|
11
|
+
|
12
|
+
self.money_format = :dollars
|
13
|
+
self.default_currency = 'USD'
|
14
|
+
|
15
|
+
def initialize(options = {})
|
16
|
+
requires!(options, :login, :password)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def authorize(money, creditcard_or_vault_id, options = {})
|
21
|
+
post = build_auth_post(money, creditcard_or_vault_id, options)
|
22
|
+
commit('auth', post)
|
23
|
+
end
|
24
|
+
|
25
|
+
def purchase(money, creditcard_or_vault_id, options = {})
|
26
|
+
post = build_purchase_post(money, creditcard_or_vault_id, options)
|
27
|
+
commit('sale', post)
|
28
|
+
end
|
29
|
+
|
30
|
+
def capture(money, authorization, options = {})
|
31
|
+
post = build_capture_post(money, authorization, options)
|
32
|
+
commit('capture', post)
|
33
|
+
end
|
34
|
+
|
35
|
+
def void(authorization, options = {})
|
36
|
+
post = build_void_post(authorization, options)
|
37
|
+
commit('void', post)
|
38
|
+
end
|
39
|
+
|
40
|
+
def refund(money, authorization, options = {})
|
41
|
+
post = build_refund_post(money, authorization, options)
|
42
|
+
commit('refund', post)
|
43
|
+
end
|
44
|
+
|
45
|
+
def store(creditcard, options = {})
|
46
|
+
post = build_store_post(creditcard, options)
|
47
|
+
commit_vault('add_customer', post)
|
48
|
+
end
|
49
|
+
|
50
|
+
def unstore(customer_vault_id, options = {})
|
51
|
+
post = build_unstore_post(customer_vault_id, options)
|
52
|
+
commit_vault('delete_customer', post)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def build_auth_post(money, creditcard_or_vault_id, options)
|
58
|
+
post = {}
|
59
|
+
add_order(post, options)
|
60
|
+
add_address(post, options)
|
61
|
+
add_shipping_address(post, options)
|
62
|
+
add_payment_method(post, creditcard_or_vault_id, options)
|
63
|
+
add_amount(post, money)
|
64
|
+
post
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_purchase_post(money, creditcard, options)
|
68
|
+
build_auth_post(money, creditcard, options)
|
69
|
+
end
|
70
|
+
|
71
|
+
def build_capture_post(money, authorization, option)
|
72
|
+
post = {}
|
73
|
+
post[:transactionid] = authorization
|
74
|
+
add_amount(post, money)
|
75
|
+
post
|
76
|
+
end
|
77
|
+
|
78
|
+
def build_void_post(authorization, options)
|
79
|
+
post = {}
|
80
|
+
post[:transactionid] = authorization
|
81
|
+
post
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_refund_post(money, authorization, options)
|
85
|
+
post = {}
|
86
|
+
post[:transactionid] = authorization
|
87
|
+
add_amount(post, money)
|
88
|
+
post
|
89
|
+
end
|
90
|
+
|
91
|
+
def build_store_post(creditcard_or_check, options)
|
92
|
+
post = {}
|
93
|
+
add_address(post, options)
|
94
|
+
add_shipping_address(post, options)
|
95
|
+
add_payment_method(post, creditcard_or_check, options)
|
96
|
+
post
|
97
|
+
end
|
98
|
+
|
99
|
+
def build_unstore_post(customer_vault_id, options)
|
100
|
+
post = {}
|
101
|
+
post['customer_vault_id'] = customer_vault_id
|
102
|
+
post
|
103
|
+
end
|
104
|
+
|
105
|
+
def add_order(post, options)
|
106
|
+
post[:orderid] = options[:order_id]
|
107
|
+
post[:orderdescription] = options[:description]
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_address(post, options)
|
111
|
+
post[:email] = options[:email]
|
112
|
+
post[:ipaddress] = options[:ip]
|
113
|
+
|
114
|
+
address = options[:billing_address] || options[:address] || {}
|
115
|
+
post[:address1] = address[:address1]
|
116
|
+
post[:address2] = address[:address2]
|
117
|
+
post[:city] = address[:city]
|
118
|
+
post[:state] = address[:state]
|
119
|
+
post[:zip] = address[:zip]
|
120
|
+
post[:country] = address[:country]
|
121
|
+
post[:phone] = address[:phone]
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_shipping_address(post, options)
|
125
|
+
shipping_address = options[:shipping_address] || {}
|
126
|
+
post[:shipping_address1] = shipping_address[:address1]
|
127
|
+
post[:shipping_address2] = shipping_address[:address2]
|
128
|
+
post[:shipping_city] = shipping_address[:city]
|
129
|
+
post[:shipping_state] = shipping_address[:state]
|
130
|
+
post[:shipping_zip] = shipping_address[:zip]
|
131
|
+
post[:shipping_country] = shipping_address[:country]
|
132
|
+
end
|
133
|
+
|
134
|
+
def add_swipe_data(post, options)
|
135
|
+
# unencrypted tracks
|
136
|
+
post[:track_1] = options[:track_1]
|
137
|
+
post[:track_2] = options[:track_2]
|
138
|
+
post[:track_3] = options[:track_3]
|
139
|
+
|
140
|
+
# encrypted tracks
|
141
|
+
post[:magnesafe_track_1] = options[:magnesafe_track_1]
|
142
|
+
post[:magnesafe_track_2] = options[:magnesafe_track_2]
|
143
|
+
post[:magnesafe_track_3] = options[:magnesafe_track_3]
|
144
|
+
post[:magnesafe_magneprint] = options[:magnesafe_magneprint]
|
145
|
+
post[:magnesafe_ksn] = options[:magnesafe_ksn]
|
146
|
+
post[:magnesafe_magneprint_status] = options[:magnesafe_magneprint_status]
|
147
|
+
end
|
148
|
+
|
149
|
+
def add_payment_method(post, creditcard_or_check_or_vault_id, options)
|
150
|
+
post[:processor_id] = options[:processor_id]
|
151
|
+
post[:customer_vault] = 'add_customer' if options[:store]
|
152
|
+
|
153
|
+
add_swipe_data(post, options)
|
154
|
+
|
155
|
+
# creditcard_or_check can be blank if using swipe data
|
156
|
+
if creditcard_or_check_or_vault_id.is_a?(CreditCard) # creditcard or check
|
157
|
+
creditcard = creditcard_or_check_or_vault_id
|
158
|
+
post[:firstname] = creditcard.first_name
|
159
|
+
post[:lastname] = creditcard.last_name
|
160
|
+
post[:ccnumber] = creditcard.number
|
161
|
+
post[:ccexp] = format(creditcard.month, :two_digits) + format(creditcard.year, :two_digits)
|
162
|
+
post[:cvv] = creditcard.verification_value
|
163
|
+
post[:payment] = 'creditcard'
|
164
|
+
elsif creditcard_or_check_or_vault_id.is_a?(Check)
|
165
|
+
check = creditcard_or_check_or_vault_id
|
166
|
+
post[:firstname] = check.first_name
|
167
|
+
post[:lastname] = check.last_name
|
168
|
+
post[:checkname] = check.name
|
169
|
+
post[:checkaba] = check.routing_number
|
170
|
+
post[:checkaccount] = check.account_number
|
171
|
+
post[:account_type] = check.account_type
|
172
|
+
post[:account_holder_type] = check.account_holder_type
|
173
|
+
post[:payment] = 'check'
|
174
|
+
else
|
175
|
+
post[:customer_vault_id] = creditcard_or_check_or_vault_id
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def add_login(post)
|
180
|
+
post[:username] = @options[:login]
|
181
|
+
post[:password] = @options[:password]
|
182
|
+
end
|
183
|
+
|
184
|
+
def add_amount(post, money)
|
185
|
+
post[:currency] = options[:currency] || currency(money)
|
186
|
+
post[:amount] = amount(money)
|
187
|
+
end
|
188
|
+
|
189
|
+
def commit_vault(action, parameters)
|
190
|
+
commit(nil, parameters.merge(:customer_vault => action))
|
191
|
+
end
|
192
|
+
|
193
|
+
def commit(action, parameters)
|
194
|
+
raw = parse(ssl_post(self.live_url, build_request(action, parameters)))
|
195
|
+
|
196
|
+
success = (raw['response'] == ResponseCodes::APPROVED)
|
197
|
+
|
198
|
+
authorization = authorization_from(success, parameters, raw)
|
199
|
+
|
200
|
+
Response.new(success, raw['responsetext'], raw,
|
201
|
+
:test => test?,
|
202
|
+
:authorization => authorization,
|
203
|
+
:avs_result => { :code => raw['avsresponse']},
|
204
|
+
:cvv_result => raw['cvvresponse']
|
205
|
+
)
|
206
|
+
end
|
207
|
+
|
208
|
+
def build_request(action, parameters)
|
209
|
+
parameters[:type] = action if action
|
210
|
+
add_login(parameters)
|
211
|
+
parameters.to_query
|
212
|
+
end
|
213
|
+
|
214
|
+
def authorization_from(success, parameters, response)
|
215
|
+
return nil unless success
|
216
|
+
|
217
|
+
authorization = response['transactionid']
|
218
|
+
if(parameters[:customer_vault] && (authorization.nil? || authorization.empty?))
|
219
|
+
authorization = response['customer_vault_id']
|
220
|
+
end
|
221
|
+
|
222
|
+
authorization
|
223
|
+
end
|
224
|
+
|
225
|
+
class ResponseCodes
|
226
|
+
APPROVED = '1'
|
227
|
+
DENIED = '2'
|
228
|
+
ERROR = '3'
|
229
|
+
end
|
230
|
+
|
231
|
+
def parse(raw_response)
|
232
|
+
rsp = CGI.parse(raw_response)
|
233
|
+
rsp.keys.each { |k| rsp[k] = rsp[k].first } # flatten out the values
|
234
|
+
rsp
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|