activemerchant 1.3.2 → 1.4.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.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +58 -0
- data/CONTRIBUTERS +25 -0
- data/MIT-LICENSE +3 -3
- data/README +16 -10
- data/Rakefile +4 -3
- data/lib/active_merchant.rb +7 -1
- data/lib/active_merchant/billing/check.rb +16 -9
- data/lib/active_merchant/billing/gateway.rb +1 -1
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +702 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +102 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +233 -0
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
- data/lib/active_merchant/billing/gateways/braintree.rb +10 -1
- data/lib/active_merchant/billing/gateways/cyber_source.rb +26 -2
- data/lib/active_merchant/billing/gateways/data_cash.rb +255 -59
- data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +214 -0
- data/lib/active_merchant/billing/gateways/net_registry.rb +1 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +2 -2
- data/lib/active_merchant/billing/gateways/payflow_express.rb +3 -11
- data/lib/active_merchant/billing/gateways/payment_express.rb +2 -2
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +39 -21
- data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +3 -12
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +20 -0
- data/lib/active_merchant/billing/gateways/protx.rb +25 -25
- data/lib/active_merchant/billing/gateways/sage.rb +145 -0
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +110 -0
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +3 -1
- data/lib/active_merchant/billing/gateways/skip_jack.rb +2 -0
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +1 -1
- data/lib/active_merchant/billing/gateways/wirecard.rb +304 -0
- data/lib/active_merchant/billing/integrations.rb +8 -2
- data/lib/active_merchant/billing/integrations/action_view_helper.rb +18 -4
- data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +4 -2
- data/lib/active_merchant/billing/integrations/notification.rb +10 -1
- data/lib/active_merchant/lib/posts_data.rb +12 -3
- data/script/destroy +0 -0
- data/script/generate +0 -0
- data/test/extra/binding_of_caller.rb +0 -0
- data/test/extra/breakpoint.rb +0 -0
- data/test/fixtures.yml +24 -0
- data/test/remote/gateways/remote_authorize_net_cim_test.rb +459 -0
- data/test/remote/gateways/remote_beanstream_interac_test.rb +53 -0
- data/test/remote/gateways/remote_beanstream_test.rb +150 -0
- data/test/remote/gateways/remote_braintree_test.rb +22 -0
- data/test/remote/gateways/remote_cyber_source_test.rb +28 -3
- data/test/remote/gateways/remote_data_cash_test.rb +250 -48
- data/test/remote/gateways/remote_modern_payments_cim_test.rb +58 -0
- data/test/remote/gateways/remote_modern_payments_test.rb +43 -0
- data/test/remote/gateways/remote_sage_bankcard_test.rb +109 -0
- data/test/remote/gateways/remote_sage_test.rb +87 -0
- data/test/remote/gateways/remote_sage_virtual_check_test.rb +62 -0
- data/test/remote/gateways/remote_wirecard_test.rb +76 -0
- data/test/remote/integrations/remote_paypal_integration_test.rb +15 -3
- data/test/test_helper.rb +31 -13
- data/test/unit/check_test.rb +14 -2
- data/test/unit/credit_card_methods_test.rb +18 -0
- data/test/unit/gateways/authorize_net_cim_test.rb +641 -0
- data/test/unit/gateways/beanstream_interac_test.rb +51 -0
- data/test/unit/gateways/beanstream_test.rb +108 -0
- data/test/unit/gateways/braintree_test.rb +2 -5
- data/test/unit/gateways/cyber_source_test.rb +18 -0
- data/test/unit/gateways/data_cash_test.rb +32 -4
- data/test/unit/gateways/gateway_test.rb +8 -1
- data/test/unit/gateways/modern_payments_cim_test.rb +171 -0
- data/test/unit/gateways/net_registry_test.rb +6 -0
- data/test/unit/gateways/payflow_express_test.rb +18 -2
- data/test/unit/gateways/paypal_express_test.rb +154 -0
- data/test/unit/gateways/paypal_test.rb +140 -0
- data/test/unit/gateways/sage_bankcard_test.rb +162 -0
- data/test/unit/gateways/sage_virtual_check_test.rb +71 -0
- data/test/unit/gateways/secure_pay_au_test.rb +58 -1
- data/test/unit/gateways/skip_jack_test.rb +8 -0
- data/test/unit/gateways/verifi_test.rb +0 -1
- data/test/unit/gateways/wirecard_test.rb +232 -0
- data/test/unit/integrations/action_view_helper_test.rb +3 -0
- data/test/unit/integrations/notifications/hi_trust_notification_test.rb +23 -2
- data/test/unit/integrations/notifications/notification_test.rb +13 -0
- data/test/unit/posts_data_test.rb +20 -6
- metadata +40 -5
- metadata.gz.sig +0 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/sage_core'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
class SageVirtualCheckGateway < Gateway #:nodoc:
|
6
|
+
include SageCore
|
7
|
+
self.url = 'https://www.sagepayments.net/cgi-bin/eftVirtualCheck.dll?transaction'
|
8
|
+
self.source = 'virtual_check'
|
9
|
+
|
10
|
+
def purchase(money, credit_card, options = {})
|
11
|
+
post = {}
|
12
|
+
add_check(post, credit_card)
|
13
|
+
add_check_customer_data(post, options)
|
14
|
+
add_transaction_data(post, money, options)
|
15
|
+
commit(:purchase, post)
|
16
|
+
end
|
17
|
+
|
18
|
+
def void(reference, options = {})
|
19
|
+
post = {}
|
20
|
+
add_reference(post, reference)
|
21
|
+
commit(:void, post)
|
22
|
+
end
|
23
|
+
|
24
|
+
def credit(money, credit_card, options = {})
|
25
|
+
post = {}
|
26
|
+
add_check(post, credit_card)
|
27
|
+
add_check_customer_data(post, options)
|
28
|
+
add_transaction_data(post, money, options)
|
29
|
+
commit(:credit, post)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def add_check(post, check)
|
34
|
+
post[:C_first_name] = check.first_name
|
35
|
+
post[:C_last_name] = check.last_name
|
36
|
+
post[:C_rte] = check.routing_number
|
37
|
+
post[:C_acct] = check.account_number
|
38
|
+
post[:C_check_number] = check.number
|
39
|
+
post[:C_acct_type] = account_type(check)
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_check_customer_data(post, options)
|
43
|
+
# Required Customer Type – (NACHA Transaction Class)
|
44
|
+
# CCD for Commercial, Merchant Initiated
|
45
|
+
# PPD for Personal, Merchant Initiated
|
46
|
+
# WEB for Internet, Consumer Initiated
|
47
|
+
# RCK for Returned Checks
|
48
|
+
# ARC for Account Receivable Entry
|
49
|
+
# TEL for TelephoneInitiated
|
50
|
+
post[:C_customer_type] = "WEB"
|
51
|
+
|
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.
|
53
|
+
post[:C_originator_id] = options[:originator_id]
|
54
|
+
|
55
|
+
# Optional Transaction Addenda
|
56
|
+
post[:T_addenda] = options[:addenda]
|
57
|
+
|
58
|
+
# Required Check Writer Social Security Number ( Numbers Only, No Dashes )
|
59
|
+
post[:C_ssn] = options[:ssn].to_s.gsub(/[^\d]/, '')
|
60
|
+
|
61
|
+
post[:C_dl_state_code] = options[:drivers_license_state]
|
62
|
+
post[:C_dl_number] = options[:drivers_license_number]
|
63
|
+
post[:C_dob] = format_birth_date(options[:date_of_birth])
|
64
|
+
end
|
65
|
+
|
66
|
+
def format_birth_date(date)
|
67
|
+
date.respond_to?(:strftime) ? date.strftime("%m/%d/%Y") : date
|
68
|
+
end
|
69
|
+
|
70
|
+
# DDA for Checking
|
71
|
+
# SAV for Savings
|
72
|
+
def account_type(check)
|
73
|
+
case check.account_type
|
74
|
+
when 'checking' then 'DDA'
|
75
|
+
when 'savings' then 'SAV'
|
76
|
+
else raise ArgumentError, "Unknown account type #{check.account_type}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def parse(data)
|
81
|
+
response = {}
|
82
|
+
response[:success] = data[1,1]
|
83
|
+
response[:code] = data[2,6].strip
|
84
|
+
response[:message] = data[8,32].strip
|
85
|
+
response[:risk] = data[40, 2]
|
86
|
+
response[:reference] = data[42, 10]
|
87
|
+
|
88
|
+
extra_data = data[53...-1].split("\034")
|
89
|
+
response[:order_number] = extra_data[0]
|
90
|
+
response[:authentication_indicator] = extra_data[1]
|
91
|
+
response[:authentication_disclosure] = extra_data[2]
|
92
|
+
response
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
@@ -36,6 +36,8 @@ module ActiveMerchant #:nodoc:
|
|
36
36
|
:credit => 4
|
37
37
|
}
|
38
38
|
|
39
|
+
SUCCESS_CODES = [ '00', '08', '11', '16', '77' ]
|
40
|
+
|
39
41
|
def initialize(options = {})
|
40
42
|
requires!(options, :login, :password)
|
41
43
|
@options = options
|
@@ -109,7 +111,7 @@ module ActiveMerchant #:nodoc:
|
|
109
111
|
end
|
110
112
|
|
111
113
|
def success?(response)
|
112
|
-
response[:response_code]
|
114
|
+
SUCCESS_CODES.include?(response[:response_code])
|
113
115
|
end
|
114
116
|
|
115
117
|
def authorization_from(response)
|
@@ -265,7 +265,7 @@ module ActiveMerchant #:nodoc:
|
|
265
265
|
def store(creditcard, options = {})
|
266
266
|
parameters = {
|
267
267
|
:verify => options[:verify] || 'y',
|
268
|
-
:billingid => options[:billingid] || nil,
|
268
|
+
:billingid => options[:billingid] || options[:billing_id] || nil,
|
269
269
|
}
|
270
270
|
|
271
271
|
add_creditcard(parameters, creditcard)
|
@@ -0,0 +1,304 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
class WirecardGateway < Gateway
|
6
|
+
# Test server location
|
7
|
+
TEST_URL = 'https://c3-test.wirecard.com/secure/ssl-gateway'
|
8
|
+
|
9
|
+
# Live server location
|
10
|
+
LIVE_URL = 'https://c3.wirecard.com/secure/ssl-gateway'
|
11
|
+
|
12
|
+
# The Namespaces are not really needed, because it just tells the System, that there's actually no namespace used.
|
13
|
+
# It's just specified here for completeness.
|
14
|
+
ENVELOPE_NAMESPACES = {
|
15
|
+
'xmlns:xsi' => 'http://www.w3.org/1999/XMLSchema-instance',
|
16
|
+
'xsi:noNamespaceSchemaLocation' => 'wirecard.xsd'
|
17
|
+
}
|
18
|
+
|
19
|
+
PERMITTED_TRANSACTIONS = %w[ AUTHORIZATION CAPTURE_AUTHORIZATION PURCHASE ]
|
20
|
+
|
21
|
+
RETURN_CODES = %w[ ACK NOK ]
|
22
|
+
|
23
|
+
# The countries the gateway supports merchants from as 2 digit ISO country codes
|
24
|
+
# TODO: Check supported countries
|
25
|
+
self.supported_countries = ['DE']
|
26
|
+
|
27
|
+
# Wirecard supports all major credit and debit cards:
|
28
|
+
# Visa, Mastercard, American Express, Diners Club,
|
29
|
+
# JCB, Switch, VISA Carte Bancaire, Visa Electron and UATP cards.
|
30
|
+
# They also support the latest anti-fraud systems such as Verified by Visa or Master Secure Code.
|
31
|
+
self.supported_cardtypes = [
|
32
|
+
:visa, :master, :american_express, :diners_club, :jcb, :switch
|
33
|
+
]
|
34
|
+
|
35
|
+
# The homepage URL of the gateway
|
36
|
+
self.homepage_url = 'http://www.wirecard.com'
|
37
|
+
|
38
|
+
# The name of the gateway
|
39
|
+
self.display_name = 'Wirecard'
|
40
|
+
|
41
|
+
# The currency should normally be EUROs
|
42
|
+
self.default_currency = 'EUR'
|
43
|
+
|
44
|
+
# 100 is 1.00 Euro
|
45
|
+
self.money_format = :cents
|
46
|
+
|
47
|
+
def initialize(options = {})
|
48
|
+
# verify that username and password are supplied
|
49
|
+
requires!(options, :login, :password)
|
50
|
+
# unfortunately Wirecard also requires a BusinessCaseSignature in the XML request
|
51
|
+
requires!(options, :signature)
|
52
|
+
@options = options
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
# Should run against the test servers or not?
|
57
|
+
def test?
|
58
|
+
@options[:test] || super
|
59
|
+
end
|
60
|
+
|
61
|
+
# Authorization
|
62
|
+
def authorize(money, creditcard, options = {})
|
63
|
+
prepare_options_hash(options)
|
64
|
+
@options[:credit_card] = creditcard
|
65
|
+
request = build_request(:authorization, money, @options)
|
66
|
+
commit(request)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# Capture Authorization
|
71
|
+
def capture(money, authorization, options = {})
|
72
|
+
prepare_options_hash(options)
|
73
|
+
@options[:authorization] = authorization
|
74
|
+
request = build_request(:capture_authorization, money, @options)
|
75
|
+
commit(request)
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# Purchase
|
80
|
+
def purchase(money, creditcard, options = {})
|
81
|
+
prepare_options_hash(options)
|
82
|
+
@options[:credit_card] = creditcard
|
83
|
+
request = build_request(:purchase, money, @options)
|
84
|
+
commit(request)
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def prepare_options_hash(options)
|
90
|
+
@options.update(options)
|
91
|
+
setup_address_hash!(options)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Create all address hash key value pairs so that
|
95
|
+
# it still works if only provided with one or two of them
|
96
|
+
def setup_address_hash!(options)
|
97
|
+
options[:billing_address] = options[:billing_address] || options[:address] || {}
|
98
|
+
options[:shipping_address] = options[:shipping_address] || {}
|
99
|
+
# Include Email in address-hash from options-hash
|
100
|
+
options[:billing_address][:email] = options[:email] if options[:email]
|
101
|
+
end
|
102
|
+
|
103
|
+
# Contact WireCard, make the XML request, and parse the
|
104
|
+
# reply into a Response object
|
105
|
+
def commit(request)
|
106
|
+
headers = { 'Content-Type' => 'text/xml',
|
107
|
+
'Authorization' => encoded_credentials }
|
108
|
+
|
109
|
+
response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request, headers))
|
110
|
+
# Pending Status also means Acknowledged (as stated in their specification)
|
111
|
+
success = response[:FunctionResult] == "ACK" || response[:FunctionResult] == "PENDING"
|
112
|
+
message = response[:Message]
|
113
|
+
authorization = (success && @options[:action] == :authorization) ? response[:GuWID] : nil
|
114
|
+
|
115
|
+
Response.new(success, message, response,
|
116
|
+
:test => test?,
|
117
|
+
:authorization => authorization,
|
118
|
+
:avs_result => { :code => response[:avsCode] },
|
119
|
+
:cvv_result => response[:cvCode]
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Generates the complete xml-message, that gets sent to the gateway
|
124
|
+
def build_request(action, money, options = {})
|
125
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
126
|
+
xml.instruct!
|
127
|
+
xml.tag! 'WIRECARD_BXML' do
|
128
|
+
xml.tag! 'W_REQUEST' do
|
129
|
+
xml.tag! 'W_JOB' do
|
130
|
+
# TODO: OPTIONAL, check what value needs to be insert here
|
131
|
+
xml.tag! 'JobID', 'test dummy data'
|
132
|
+
# UserID for this transaction
|
133
|
+
xml.tag! 'BusinessCaseSignature', options[:signature] || options[:login]
|
134
|
+
# Create the whole rest of the message
|
135
|
+
add_transaction_data(xml, action, money, options)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
xml.target!
|
140
|
+
end
|
141
|
+
|
142
|
+
# Includes the whole transaction data (payment, creditcard, address)
|
143
|
+
def add_transaction_data(xml, action, money, options = {})
|
144
|
+
options[:action] = action
|
145
|
+
# TODO: require order_id instead of auto-generating it if not supplied
|
146
|
+
options[:order_id] ||= generate_unique_id
|
147
|
+
transaction_type = action.to_s.upcase
|
148
|
+
|
149
|
+
xml.tag! "FNC_CC_#{transaction_type}" do
|
150
|
+
# TODO: OPTIONAL, check which param should be used here
|
151
|
+
xml.tag! 'FunctionID', options[:description] || 'Test dummy FunctionID'
|
152
|
+
|
153
|
+
xml.tag! 'CC_TRANSACTION' do
|
154
|
+
xml.tag! 'TransactionID', options[:order_id]
|
155
|
+
if [:authorization, :purchase].include?(action)
|
156
|
+
add_invoice(xml, money, options)
|
157
|
+
add_creditcard(xml, options[:credit_card])
|
158
|
+
add_address(xml, options[:billing_address])
|
159
|
+
elsif action == :capture_authorization
|
160
|
+
xml.tag! 'GuWID', options[:authorization] if options[:authorization]
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Includes the payment (amount, currency, country) to the transaction-xml
|
167
|
+
def add_invoice(xml, money, options)
|
168
|
+
xml.tag! 'Amount', amount(money)
|
169
|
+
xml.tag! 'Currency', options[:currency] || currency(money)
|
170
|
+
xml.tag! 'CountryCode', options[:billing_address][:country]
|
171
|
+
xml.tag! 'RECURRING_TRANSACTION' do
|
172
|
+
xml.tag! 'Type', options[:recurring] || 'Single'
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Includes the credit-card data to the transaction-xml
|
177
|
+
def add_creditcard(xml, creditcard)
|
178
|
+
raise "Creditcard must be supplied!" if creditcard.nil?
|
179
|
+
xml.tag! 'CREDIT_CARD_DATA' do
|
180
|
+
xml.tag! 'CreditCardNumber', creditcard.number
|
181
|
+
xml.tag! 'CVC2', creditcard.verification_value
|
182
|
+
xml.tag! 'ExpirationYear', creditcard.year
|
183
|
+
xml.tag! 'ExpirationMonth', format(creditcard.month, :two_digits)
|
184
|
+
xml.tag! 'CardHolderName', [creditcard.first_name, creditcard.last_name].join(' ')
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# Includes the IP address of the customer to the transaction-xml
|
189
|
+
def add_customer_data(xml, options)
|
190
|
+
return unless options[:ip]
|
191
|
+
xml.tag! 'CONTACT_DATA' do
|
192
|
+
xml.tag! 'IPAddress', options[:ip]
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
# Includes the address to the transaction-xml
|
197
|
+
def add_address(xml, address)
|
198
|
+
return if address.nil?
|
199
|
+
xml.tag! 'CORPTRUSTCENTER_DATA' do
|
200
|
+
xml.tag! 'ADDRESS' do
|
201
|
+
xml.tag! 'Address1', address[:address1]
|
202
|
+
xml.tag! 'Address2', address[:address2] if address[:address2]
|
203
|
+
xml.tag! 'City', address[:city]
|
204
|
+
xml.tag! 'ZipCode', address[:zip]
|
205
|
+
xml.tag! 'State', address[:state].blank? ? 'N/A' : address[:state]
|
206
|
+
xml.tag! 'Country', address[:country]
|
207
|
+
xml.tag! 'Phone', address[:phone]
|
208
|
+
xml.tag! 'Email', address[:email]
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
# Read the XML message from the gateway and check if it was successful,
|
215
|
+
# and also extract required return values from the response.
|
216
|
+
def parse(xml)
|
217
|
+
basepath = '/WIRECARD_BXML/W_RESPONSE'
|
218
|
+
response = {}
|
219
|
+
|
220
|
+
xml = REXML::Document.new(xml)
|
221
|
+
if root = REXML::XPath.first(xml, "#{basepath}/W_JOB")
|
222
|
+
parse_response(response, root)
|
223
|
+
elsif root = REXML::XPath.first(xml, "/#{basepath}/ERROR")
|
224
|
+
parse_error(response, root)
|
225
|
+
else
|
226
|
+
response[:Message] = "No valid XML response message received. \
|
227
|
+
Propably wrong credentials supplied with HTTP header."
|
228
|
+
end
|
229
|
+
|
230
|
+
response
|
231
|
+
end
|
232
|
+
|
233
|
+
# Parse the <ProcessingStatus> Element which containts all important information
|
234
|
+
def parse_response(response, root)
|
235
|
+
status = nil
|
236
|
+
# get the root element for this Transaction
|
237
|
+
root.elements.to_a.each do |node|
|
238
|
+
if node.name =~ /FNC_CC_/
|
239
|
+
status = REXML::XPath.first(node, "CC_TRANSACTION/PROCESSING_STATUS")
|
240
|
+
end
|
241
|
+
end
|
242
|
+
# Get message
|
243
|
+
message = ''
|
244
|
+
if info = status.elements['Info']
|
245
|
+
message << info.text
|
246
|
+
end
|
247
|
+
# Get errors if available and append them to the message
|
248
|
+
errors = errors_to_string(status)
|
249
|
+
unless errors.strip.blank?
|
250
|
+
message << ' - ' unless message.strip.blank?
|
251
|
+
message << errors
|
252
|
+
end
|
253
|
+
response[:Message] = message
|
254
|
+
|
255
|
+
# Get basic response information
|
256
|
+
status.elements.to_a.each do |node|
|
257
|
+
response[node.name.to_sym] = (node.text || '').strip
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
# Parse a generic error response from the gateway
|
262
|
+
def parse_error(response, root)
|
263
|
+
# TODO: Implement parsing of more generic error messages
|
264
|
+
end
|
265
|
+
|
266
|
+
# Parses all <ERROR> elements in the response and converts the information
|
267
|
+
# to a single string
|
268
|
+
def errors_to_string(status)
|
269
|
+
# Get context error messages (can be 0..*)
|
270
|
+
errors = []
|
271
|
+
REXML::XPath.each(status, "ERROR") do |error_elem|
|
272
|
+
error = {}
|
273
|
+
error[:Advice] = []
|
274
|
+
error[:Message] = error_elem.elements['Message'].text
|
275
|
+
error_elem.elements.each('Advice') do |advice|
|
276
|
+
error[:Advice] << advice.text
|
277
|
+
end
|
278
|
+
errors << error
|
279
|
+
end
|
280
|
+
# Convert all messages to a single string
|
281
|
+
string = ''
|
282
|
+
errors.each do |error|
|
283
|
+
string << error[:Message]
|
284
|
+
error[:Advice].each_with_index do |advice, index|
|
285
|
+
string << ' (' if index == 0
|
286
|
+
string << "#{index+1}. #{advice}"
|
287
|
+
string << ' and ' if index < error[:Advice].size - 1
|
288
|
+
string << ')' if index == error[:Advice].size - 1
|
289
|
+
end
|
290
|
+
end
|
291
|
+
string
|
292
|
+
end
|
293
|
+
|
294
|
+
# Encode login and password in Base64 to supply as HTTP header
|
295
|
+
# (for http basic authentication)
|
296
|
+
def encoded_credentials
|
297
|
+
credentials = [@options[:login], @options[:password]].join(':')
|
298
|
+
"Basic " << Base64.encode64(credentials).strip
|
299
|
+
end
|
300
|
+
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
@@ -10,6 +10,12 @@ require 'active_merchant/billing/integrations/two_checkout'
|
|
10
10
|
require 'active_merchant/billing/integrations/hi_trust'
|
11
11
|
|
12
12
|
# make the bogus gateway be classified correctly by the inflector
|
13
|
-
Inflector
|
14
|
-
|
13
|
+
if defined?(ActiveSupport::Inflector)
|
14
|
+
ActiveSupport::Inflector.inflections do |inflect|
|
15
|
+
inflect.uncountable 'bogus'
|
16
|
+
end
|
17
|
+
else
|
18
|
+
Inflector.inflections do |inflect|
|
19
|
+
inflect.uncountable 'bogus'
|
20
|
+
end
|
15
21
|
end
|