activemerchant 1.42.2 → 1.42.3
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 +8 -8
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG +32 -0
- data/CONTRIBUTORS +12 -0
- data/README.md +3 -0
- data/lib/active_merchant/billing/base.rb +9 -2
- data/lib/active_merchant/billing/credit_card_methods.rb +1 -1
- data/lib/active_merchant/billing/gateway.rb +1 -1
- data/lib/active_merchant/billing/gateways/authorize_net.rb +3 -2
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +8 -8
- data/lib/active_merchant/billing/gateways/balanced.rb +7 -2
- data/lib/active_merchant/billing/gateways/beanstream.rb +1 -1
- data/lib/active_merchant/billing/gateways/bogus.rb +32 -22
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +124 -39
- data/lib/active_merchant/billing/gateways/cyber_source.rb +2 -2
- data/lib/active_merchant/billing/gateways/litle.rb +1 -1
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -2
- data/lib/active_merchant/billing/gateways/moneris.rb +1 -1
- data/lib/active_merchant/billing/gateways/moneris_us.rb +1 -1
- data/lib/active_merchant/billing/gateways/nab_transact.rb +3 -1
- data/lib/active_merchant/billing/gateways/netpay.rb +1 -1
- data/lib/active_merchant/billing/gateways/pay_junction.rb +7 -7
- data/lib/active_merchant/billing/gateways/payex.rb +402 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +41 -11
- data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
- data/lib/active_merchant/billing/gateways/paymill.rb +55 -3
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
- data/lib/active_merchant/billing/gateways/payscout.rb +171 -0
- data/lib/active_merchant/billing/gateways/pin.rb +1 -1
- data/lib/active_merchant/billing/gateways/realex.rb +1 -1
- data/lib/active_merchant/billing/gateways/redsys.rb +1 -1
- data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +23 -25
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +26 -15
- data/lib/active_merchant/billing/gateways/webpay.rb +27 -11
- data/lib/active_merchant/billing/gateways/wirecard.rb +1 -1
- data/lib/active_merchant/billing/integrations/bit_pay/helper.rb +1 -1
- data/lib/active_merchant/billing/integrations/ipay88.rb +4 -0
- data/lib/active_merchant/billing/integrations/ipay88/helper.rb +1 -1
- data/lib/active_merchant/billing/integrations/ipay88/notification.rb +103 -0
- data/lib/active_merchant/billing/integrations/ipay88/return.rb +8 -74
- data/lib/active_merchant/billing/integrations/pay_fast/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/paypal/helper.rb +1 -1
- data/lib/active_merchant/billing/integrations/payu_in.rb +2 -9
- data/lib/active_merchant/billing/integrations/payu_in/helper.rb +15 -13
- data/lib/active_merchant/billing/integrations/payu_in/notification.rb +9 -20
- data/lib/active_merchant/billing/integrations/payu_in_paisa/helper.rb +1 -1
- data/lib/active_merchant/billing/integrations/payu_in_paisa/notification.rb +0 -10
- data/lib/active_merchant/billing/integrations/payu_in_paisa/return.rb +1 -1
- data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +1 -1
- data/lib/active_merchant/billing/integrations/valitor/helper.rb +3 -3
- data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +2 -2
- data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/wirecard_checkout_page.rb +1 -1
- data/lib/active_merchant/billing/integrations/world_pay/helper.rb +2 -2
- data/lib/active_merchant/version.rb +1 -1
- metadata +7 -3
- metadata.gz.sig +0 -0
@@ -19,20 +19,23 @@ module ActiveMerchant #:nodoc:
|
|
19
19
|
commit(request, options)
|
20
20
|
end
|
21
21
|
|
22
|
-
def purchase(money,
|
23
|
-
request = build_sale_or_authorization_request(:purchase, money,
|
22
|
+
def purchase(money, funding_source, options = {})
|
23
|
+
request = build_sale_or_authorization_request(:purchase, money, funding_source, options)
|
24
24
|
|
25
25
|
commit(request, options)
|
26
26
|
end
|
27
27
|
|
28
|
-
def credit(money,
|
29
|
-
if
|
28
|
+
def credit(money, funding_source, options = {})
|
29
|
+
if funding_source.is_a?(String)
|
30
30
|
deprecated CREDIT_DEPRECATION_MESSAGE
|
31
31
|
# Perform referenced credit
|
32
|
-
refund(money,
|
33
|
-
|
32
|
+
refund(money, funding_source, options)
|
33
|
+
elsif card_brand(funding_source) == 'check'
|
34
34
|
# Perform non-referenced credit
|
35
|
-
request =
|
35
|
+
request = build_check_request(:credit, money, funding_source, options)
|
36
|
+
commit(request, options)
|
37
|
+
else
|
38
|
+
request = build_credit_card_request(:credit, money, funding_source, options)
|
36
39
|
commit(request, options)
|
37
40
|
end
|
38
41
|
end
|
@@ -76,11 +79,13 @@ module ActiveMerchant #:nodoc:
|
|
76
79
|
end
|
77
80
|
|
78
81
|
private
|
79
|
-
def build_sale_or_authorization_request(action, money,
|
80
|
-
if
|
81
|
-
build_reference_sale_or_authorization_request(action, money,
|
82
|
+
def build_sale_or_authorization_request(action, money, funding_source, options)
|
83
|
+
if funding_source.is_a?(String)
|
84
|
+
build_reference_sale_or_authorization_request(action, money, funding_source, options)
|
85
|
+
elsif card_brand(funding_source) == 'check'
|
86
|
+
build_check_request(action, money, funding_source, options)
|
82
87
|
else
|
83
|
-
build_credit_card_request(action, money,
|
88
|
+
build_credit_card_request(action, money, funding_source, options)
|
84
89
|
end
|
85
90
|
end
|
86
91
|
|
@@ -147,6 +152,31 @@ module ActiveMerchant #:nodoc:
|
|
147
152
|
xml.target!
|
148
153
|
end
|
149
154
|
|
155
|
+
def build_check_request(action, money, check, options)
|
156
|
+
xml = Builder::XmlMarkup.new
|
157
|
+
xml.tag! TRANSACTIONS[action] do
|
158
|
+
xml.tag! 'PayData' do
|
159
|
+
xml.tag! 'Invoice' do
|
160
|
+
xml.tag! 'CustIP', options[:ip] unless options[:ip].blank?
|
161
|
+
xml.tag! 'InvNum', options[:order_id].to_s.gsub(/[^\w.]/, '') unless options[:order_id].blank?
|
162
|
+
xml.tag! 'Description', options[:description] unless options[:description].blank?
|
163
|
+
xml.tag! 'BillTo' do
|
164
|
+
xml.tag! 'Name', check.name
|
165
|
+
end
|
166
|
+
xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
|
167
|
+
end
|
168
|
+
xml.tag! 'Tender' do
|
169
|
+
xml.tag! 'ACH' do
|
170
|
+
xml.tag! 'AcctType', check.account_type == 'checking' ? 'C' : 'S'
|
171
|
+
xml.tag! 'AcctNum', check.account_number
|
172
|
+
xml.tag! 'ABA', check.routing_number
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
xml.target!
|
178
|
+
end
|
179
|
+
|
150
180
|
def add_credit_card(xml, credit_card)
|
151
181
|
xml.tag! 'Card' do
|
152
182
|
xml.tag! 'CardType', credit_card_type(credit_card)
|
@@ -227,7 +227,7 @@ module ActiveMerchant #:nodoc:
|
|
227
227
|
end
|
228
228
|
|
229
229
|
# The options hash may contain optional data which will be passed
|
230
|
-
# through the
|
230
|
+
# through the specialized optional fields at PaymentExpress
|
231
231
|
# as follows:
|
232
232
|
#
|
233
233
|
# {
|
@@ -67,7 +67,7 @@ module ActiveMerchant #:nodoc:
|
|
67
67
|
raw_response = ssl_request(method, "https://api.paymill.com/v2/#{url}", post_data(parameters), headers)
|
68
68
|
rescue ResponseError => e
|
69
69
|
parsed = JSON.parse(e.response.body)
|
70
|
-
return Response.new(false, parsed
|
70
|
+
return Response.new(false, response_message(parsed), parsed, {})
|
71
71
|
end
|
72
72
|
|
73
73
|
response_from(raw_response)
|
@@ -75,13 +75,13 @@ module ActiveMerchant #:nodoc:
|
|
75
75
|
|
76
76
|
def response_from(raw_response)
|
77
77
|
parsed = JSON.parse(raw_response)
|
78
|
-
|
79
78
|
options = {
|
80
79
|
:authorization => authorization_from(parsed),
|
81
80
|
:test => (parsed['mode'] == 'test'),
|
82
81
|
}
|
83
82
|
|
84
|
-
|
83
|
+
succeeded = (parsed['data'] == []) || (parsed['data']['response_code'] == 20000)
|
84
|
+
Response.new(succeeded, response_message(parsed), parsed, options)
|
85
85
|
end
|
86
86
|
|
87
87
|
def authorization_from(parsed_response)
|
@@ -175,6 +175,58 @@ module ActiveMerchant #:nodoc:
|
|
175
175
|
authorization.split(';').first
|
176
176
|
end
|
177
177
|
|
178
|
+
RESPONSE_CODES = {
|
179
|
+
10001 => "General undefined response.",
|
180
|
+
10002 => "Still waiting on something.",
|
181
|
+
|
182
|
+
20000 => "General success response.",
|
183
|
+
|
184
|
+
40000 => "General problem with data.",
|
185
|
+
40001 => "General problem with payment data.",
|
186
|
+
40100 => "Problem with credit card data.",
|
187
|
+
40101 => "Problem with cvv.",
|
188
|
+
40102 => "Card expired or not yet valid.",
|
189
|
+
40103 => "Limit exceeded.",
|
190
|
+
40104 => "Card invalid.",
|
191
|
+
40105 => "Expiry date not valid.",
|
192
|
+
40106 => "Credit card brand required.",
|
193
|
+
40200 => "Problem with bank account data.",
|
194
|
+
40201 => "Bank account data combination mismatch.",
|
195
|
+
40202 => "User authentication failed.",
|
196
|
+
40300 => "Problem with 3d secure data.",
|
197
|
+
40301 => "Currency / amount mismatch",
|
198
|
+
40400 => "Problem with input data.",
|
199
|
+
40401 => "Amount too low or zero.",
|
200
|
+
40402 => "Usage field too long.",
|
201
|
+
40403 => "Currency not allowed.",
|
202
|
+
|
203
|
+
50000 => "General problem with backend.",
|
204
|
+
50001 => "Country blacklisted.",
|
205
|
+
50100 => "Technical error with credit card.",
|
206
|
+
50101 => "Error limit exceeded.",
|
207
|
+
50102 => "Card declined by authorization system.",
|
208
|
+
50103 => "Manipulation or stolen card.",
|
209
|
+
50104 => "Card restricted.",
|
210
|
+
50105 => "Invalid card configuration data.",
|
211
|
+
50200 => "Technical error with bank account.",
|
212
|
+
50201 => "Card blacklisted.",
|
213
|
+
50300 => "Technical error with 3D secure.",
|
214
|
+
50400 => "Decline because of risk issues.",
|
215
|
+
50500 => "General timeout.",
|
216
|
+
50501 => "Timeout on side of the acquirer.",
|
217
|
+
50502 => "Risk management transaction timeout.",
|
218
|
+
50600 => "Duplicate transaction."
|
219
|
+
}
|
220
|
+
|
221
|
+
def response_message(parsed_response)
|
222
|
+
return parsed_response["error"] if parsed_response["error"]
|
223
|
+
return "Transaction approved." if (parsed_response['data'] == [])
|
224
|
+
|
225
|
+
code = parsed_response["data"]["response_code"]
|
226
|
+
RESPONSE_CODES[code] || code.to_s
|
227
|
+
end
|
228
|
+
|
229
|
+
|
178
230
|
class ResponseParser
|
179
231
|
def initialize(raw_response="", options={})
|
180
232
|
@raw_response = raw_response
|
@@ -242,7 +242,7 @@ module ActiveMerchant #:nodoc:
|
|
242
242
|
commit 'DoAuthorization', build_do_authorize(transaction_id, money, options)
|
243
243
|
end
|
244
244
|
|
245
|
-
# The ManagePendingTransactionStatus API operation accepts or
|
245
|
+
# The ManagePendingTransactionStatus API operation accepts or denies a
|
246
246
|
# pending transaction held by Fraud Management Filters.
|
247
247
|
#
|
248
248
|
# ==== Parameters:
|
@@ -0,0 +1,171 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class PayscoutGateway < Gateway
|
4
|
+
self.live_url = self.test_url = 'https://secure.payscout.com/api/transact.php'
|
5
|
+
|
6
|
+
self.supported_countries = ['US']
|
7
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
8
|
+
self.default_currency = 'USD'
|
9
|
+
self.homepage_url = 'http://www.payscout.com/'
|
10
|
+
self.display_name = 'Payscout'
|
11
|
+
|
12
|
+
self.ssl_version = 'SSLv3'
|
13
|
+
|
14
|
+
def initialize(options = {})
|
15
|
+
requires!(options, :username, :password)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def authorize(money, creditcard, options = {})
|
20
|
+
post = {}
|
21
|
+
add_invoice(post, options)
|
22
|
+
add_creditcard(post, creditcard)
|
23
|
+
add_currency(post, money, options)
|
24
|
+
add_address(post, options)
|
25
|
+
|
26
|
+
commit('auth', money, post)
|
27
|
+
end
|
28
|
+
|
29
|
+
def purchase(money, creditcard, options = {})
|
30
|
+
post = {}
|
31
|
+
add_invoice(post, options)
|
32
|
+
add_creditcard(post, creditcard)
|
33
|
+
add_currency(post, money, options)
|
34
|
+
add_address(post, options)
|
35
|
+
|
36
|
+
commit('sale', money, post)
|
37
|
+
end
|
38
|
+
|
39
|
+
def capture(money, authorization, options = {})
|
40
|
+
post = {}
|
41
|
+
post[:transactionid] = authorization
|
42
|
+
|
43
|
+
commit('capture', money, post)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def refund(money, authorization, options = {})
|
48
|
+
post = {}
|
49
|
+
post[:transactionid] = authorization
|
50
|
+
|
51
|
+
commit('refund', money, post)
|
52
|
+
end
|
53
|
+
|
54
|
+
def void(authorization, options = {})
|
55
|
+
post = {}
|
56
|
+
post[:transactionid] = authorization
|
57
|
+
|
58
|
+
commit('void', nil, post)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def add_address(post, options)
|
64
|
+
if address = options[:billing_address] || options[:address]
|
65
|
+
post[:address1] = address[:address1].to_s
|
66
|
+
post[:address2] = address[:address2].to_s
|
67
|
+
post[:city] = address[:city].to_s
|
68
|
+
post[:state] = (address[:state].blank? ? 'n/a' : address[:state])
|
69
|
+
post[:zip] = address[:zip].to_s
|
70
|
+
post[:country] = address[:country].to_s
|
71
|
+
post[:phone] = address[:phone].to_s
|
72
|
+
post[:fax] = address[:fax].to_s
|
73
|
+
post[:email] = address[:email].to_s
|
74
|
+
end
|
75
|
+
|
76
|
+
if address = options[:shipping_address]
|
77
|
+
post[:shipping_firstname] = address[:first_name].to_s
|
78
|
+
post[:shipping_lastname] = address[:last_name].to_s
|
79
|
+
post[:shipping_company] = address[:company].to_s
|
80
|
+
post[:shipping_address1] = address[:address1].to_s
|
81
|
+
post[:shipping_address2] = address[:address2].to_s
|
82
|
+
post[:shipping_city] = address[:city].to_s
|
83
|
+
post[:shipping_country] = address[:country].to_s
|
84
|
+
post[:shipping_state] = (address[:state].blank? ? 'n/a' : address[:state])
|
85
|
+
post[:shipping_zip] = address[:zip].to_s
|
86
|
+
post[:shipping_email] = address[:email].to_s
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def add_currency(post, money, options)
|
91
|
+
post[:currency] = options[:currency] || currency(money)
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_invoice(post, options)
|
95
|
+
post[:orderdescription] = options[:description]
|
96
|
+
post[:orderid] = options[:order_id]
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_creditcard(post, creditcard)
|
100
|
+
post[:ccnumber] = creditcard.number
|
101
|
+
post[:cvv] = creditcard.verification_value if creditcard.verification_value?
|
102
|
+
post[:ccexp] = expdate(creditcard)
|
103
|
+
post[:firstname] = creditcard.first_name
|
104
|
+
post[:lastname] = creditcard.last_name
|
105
|
+
end
|
106
|
+
|
107
|
+
def parse(body)
|
108
|
+
Hash[body.split('&').map{|x|x.split('=')}]
|
109
|
+
end
|
110
|
+
|
111
|
+
def commit(action, money, parameters)
|
112
|
+
parameters[:amount] = amount(money) unless action == 'void'
|
113
|
+
url = (test? ? self.test_url : self.live_url)
|
114
|
+
data = ssl_post(url, post_data(action, parameters))
|
115
|
+
|
116
|
+
response = parse(data)
|
117
|
+
response[:action] = action
|
118
|
+
|
119
|
+
message = message_from(response)
|
120
|
+
test_mode = (test? || message =~ /TESTMODE/)
|
121
|
+
Response.new(success?(response), message, response,
|
122
|
+
:test => test_mode,
|
123
|
+
:authorization => response['transactionid'],
|
124
|
+
:fraud_review => fraud_review?(response),
|
125
|
+
:avs_result => { :code => response['avsresponse'] },
|
126
|
+
:cvv_result => response['cvvresponse']
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
def message_from(response)
|
131
|
+
case response['response']
|
132
|
+
when '1'
|
133
|
+
'The transaction has been approved'
|
134
|
+
when '2'
|
135
|
+
'The transaction has been declined'
|
136
|
+
when '3'
|
137
|
+
response['responsetext']
|
138
|
+
else
|
139
|
+
'There was an error processing the transaction'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def fraud_review?(response)
|
144
|
+
false
|
145
|
+
end
|
146
|
+
|
147
|
+
def success?(response)
|
148
|
+
(response['response'] == '1')
|
149
|
+
end
|
150
|
+
|
151
|
+
def post_data(action, parameters = {})
|
152
|
+
post = {}
|
153
|
+
|
154
|
+
post[:username] = @options[:username]
|
155
|
+
post[:password] = @options[:password]
|
156
|
+
post[:type] = action
|
157
|
+
|
158
|
+
request = post.merge(parameters).collect { |key, value| "#{key}=#{URI.escape(value.to_s)}" }.join("&")
|
159
|
+
request
|
160
|
+
end
|
161
|
+
|
162
|
+
def expdate(creditcard)
|
163
|
+
year = sprintf("%.4i", creditcard.year)
|
164
|
+
month = sprintf("%.2i", creditcard.month)
|
165
|
+
|
166
|
+
"#{month}#{year[-2..-1]}"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
@@ -90,7 +90,7 @@ module ActiveMerchant #:nodoc:
|
|
90
90
|
:expiry_month => creditcard.month,
|
91
91
|
:expiry_year => creditcard.year,
|
92
92
|
:cvc => creditcard.verification_value,
|
93
|
-
:name =>
|
93
|
+
:name => creditcard.name
|
94
94
|
)
|
95
95
|
elsif creditcard.kind_of?(String)
|
96
96
|
if creditcard =~ /^card_/
|
@@ -12,7 +12,7 @@ module ActiveMerchant
|
|
12
12
|
# login - The unique id of the merchant
|
13
13
|
# password - The secret is used to digitally sign the request
|
14
14
|
# account - This is an optional third part of the authentication process
|
15
|
-
# and is used if the merchant wishes do
|
15
|
+
# and is used if the merchant wishes do distinguish cc traffic from the different sources
|
16
16
|
# by using a different account. This must be created in advance
|
17
17
|
#
|
18
18
|
# the Realex team decided to make the orderid unique per request,
|
@@ -49,7 +49,7 @@ module ActiveMerchant #:nodoc:
|
|
49
49
|
self.default_currency = 'EUR'
|
50
50
|
self.money_format = :cents
|
51
51
|
|
52
|
-
# Not all card types may be
|
52
|
+
# Not all card types may be activated by the bank!
|
53
53
|
self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :diners_club]
|
54
54
|
|
55
55
|
# Homepage URL of the gateway for reference
|
@@ -0,0 +1,194 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class SoEasyPayGateway < Gateway
|
4
|
+
self.live_url = self.test_url = 'https://secure.soeasypay.com/gateway.asmx'
|
5
|
+
self.money_format = :cents
|
6
|
+
|
7
|
+
self.supported_countries = [
|
8
|
+
'US', 'CA', 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE',
|
9
|
+
'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU',
|
10
|
+
'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'GB',
|
11
|
+
'IS', 'NO', 'CH'
|
12
|
+
]
|
13
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :maestro, :jcb, :solo, :diners_club]
|
14
|
+
self.homepage_url = 'http://www.soeasypay.com/'
|
15
|
+
self.display_name = 'SoEasyPay'
|
16
|
+
|
17
|
+
def initialize(options = {})
|
18
|
+
requires!(options, :login, :password)
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def authorize(money, payment_source, options = {})
|
23
|
+
if payment_source.respond_to?(:number)
|
24
|
+
commit('AuthorizeTransaction', do_authorization(money, payment_source, options), options)
|
25
|
+
else
|
26
|
+
commit('ReauthorizeTransaction', do_reauthorization(money, payment_source, options), options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def purchase(money, payment_source, options = {})
|
31
|
+
if payment_source.respond_to?(:number)
|
32
|
+
commit('SaleTransaction', do_sale(money, payment_source, options), options)
|
33
|
+
else
|
34
|
+
commit('RebillTransaction', do_rebill(money, payment_source, options), options)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def capture(money, authorization, options = {})
|
39
|
+
commit('CaptureTransaction', do_capture(money, authorization, options), options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def refund(money, authorization, options={})
|
43
|
+
commit('RefundTransaction', do_refund(money, authorization, options), options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def void(authorization, options={})
|
47
|
+
commit('CancelTransaction', do_void(authorization, options), options)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def do_authorization(money, card, options)
|
53
|
+
build_soap('AuthorizeTransaction') do |soap|
|
54
|
+
fill_credentials(soap, options)
|
55
|
+
fill_order_info(soap, money, options)
|
56
|
+
fill_cardholder(soap, card, options)
|
57
|
+
fill_card(soap, card)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def do_sale(money, card, options)
|
62
|
+
build_soap('SaleTransaction') do |soap|
|
63
|
+
fill_credentials(soap, options)
|
64
|
+
fill_order_info(soap, money, options)
|
65
|
+
fill_cardholder(soap, card, options)
|
66
|
+
fill_card(soap, card)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def do_reauthorization(money, authorization, options)
|
71
|
+
build_soap('ReauthorizeTransaction') do |soap|
|
72
|
+
fill_credentials(soap, options)
|
73
|
+
fill_order_info(soap, money, options)
|
74
|
+
fill_transaction_id(soap, authorization)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def do_rebill(money, authorization, options)
|
79
|
+
build_soap('RebillTransaction') do |soap|
|
80
|
+
fill_credentials(soap, options)
|
81
|
+
fill_order_info(soap, money, options)
|
82
|
+
fill_transaction_id(soap, authorization)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def do_capture(money, authorization, options)
|
87
|
+
build_soap('CaptureTransaction') do |soap|
|
88
|
+
fill_credentials(soap, options)
|
89
|
+
fill_order_info(soap, money, options, :no_currency)
|
90
|
+
fill_transaction_id(soap, authorization)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def do_refund(money, authorization, options)
|
95
|
+
build_soap('RefundTransaction') do |soap|
|
96
|
+
fill_credentials(soap, options)
|
97
|
+
fill_order_info(soap, money, options, :no_currency)
|
98
|
+
fill_transaction_id(soap, authorization)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def do_void(authorization, options)
|
103
|
+
build_soap('CancelTransaction') do |soap|
|
104
|
+
fill_credentials(soap, options)
|
105
|
+
fill_transaction_id(soap, authorization)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def fill_credentials(soap, options)
|
110
|
+
soap.tag!('websiteID', @options[:login].to_s)
|
111
|
+
soap.tag!('password', @options[:password].to_s)
|
112
|
+
end
|
113
|
+
|
114
|
+
def fill_cardholder(soap, card, options)
|
115
|
+
ch_info = options[:billing_address] || options[:address]
|
116
|
+
|
117
|
+
soap.tag!('customerIP',options[:ip].to_s)
|
118
|
+
name = card.name || ch_info[:name]
|
119
|
+
soap.tag!('cardHolderName', name.to_s)
|
120
|
+
address = ch_info[:address1] || ''
|
121
|
+
address << ch_info[:address2] if ch_info[:address2]
|
122
|
+
soap.tag!('cardHolderAddress', address.to_s)
|
123
|
+
soap.tag!('cardHolderZipcode', ch_info[:zip].to_s)
|
124
|
+
soap.tag!('cardHolderCity', ch_info[:city].to_s)
|
125
|
+
soap.tag!('cardHolderState', ch_info[:state].to_s)
|
126
|
+
soap.tag!('cardHolderCountryCode', ch_info[:country].to_s)
|
127
|
+
soap.tag!('cardHolderPhone', ch_info[:phone].to_s)
|
128
|
+
soap.tag!('cardHolderEmail', options[:email].to_s)
|
129
|
+
end
|
130
|
+
|
131
|
+
def fill_transaction_id(soap, transaction_id)
|
132
|
+
soap.tag!('transactionID', transaction_id.to_s)
|
133
|
+
end
|
134
|
+
|
135
|
+
def fill_card(soap, card)
|
136
|
+
soap.tag!('cardNumber', card.number.to_s)
|
137
|
+
soap.tag!('cardSecurityCode', card.verification_value.to_s)
|
138
|
+
soap.tag!('cardExpireMonth', card.month.to_s.rjust(2, "0"))
|
139
|
+
soap.tag!('cardExpireYear', card.year.to_s)
|
140
|
+
end
|
141
|
+
|
142
|
+
def fill_order_info(soap, money, options, skip_currency=false)
|
143
|
+
soap.tag!('orderID', options[:order_id].to_s)
|
144
|
+
soap.tag!('orderDescription', "Order #{options[:order_id]}")
|
145
|
+
soap.tag!('amount', amount(money).to_s)
|
146
|
+
soap.tag!('currency', (options[:currency] || currency(money)).to_s) unless skip_currency
|
147
|
+
end
|
148
|
+
|
149
|
+
def parse(response, action)
|
150
|
+
result = {}
|
151
|
+
document = REXML::Document.new(response)
|
152
|
+
response_element = document.root.get_elements("//[@xsi:type='tns:#{action}Response']").first
|
153
|
+
response_element.elements.each do |element|
|
154
|
+
result[element.name.underscore] = element.text
|
155
|
+
end
|
156
|
+
result
|
157
|
+
end
|
158
|
+
|
159
|
+
def commit(soap_action, soap, options)
|
160
|
+
headers = {"SOAPAction" => "\"urn:Interface##{soap_action}\"",
|
161
|
+
"Content-Type" => "text/xml; charset=utf-8"}
|
162
|
+
response_string = ssl_post(test? ? self.test_url : self.live_url, soap, headers)
|
163
|
+
response = parse(response_string, soap_action)
|
164
|
+
return Response.new(response['errorcode'] == '000',
|
165
|
+
response['errormessage'],
|
166
|
+
response,
|
167
|
+
:test => test?,
|
168
|
+
:authorization => response['transaction_id'])
|
169
|
+
end
|
170
|
+
|
171
|
+
def build_soap(request)
|
172
|
+
retval = Builder::XmlMarkup.new(:indent => 2)
|
173
|
+
retval.instruct!(:xml, :version => '1.0', :encoding => 'utf-8')
|
174
|
+
retval.tag!('soap:Envelope', {
|
175
|
+
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
176
|
+
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
|
177
|
+
'xmlns:soapenc' => 'http://schemas.xmlsoap.org/soap/encoding/',
|
178
|
+
'xmlns:tns' => 'urn:Interface',
|
179
|
+
'xmlns:types' => 'urn:Interface/encodedTypes',
|
180
|
+
'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/'}) do
|
181
|
+
retval.tag!('soap:Body', {'soap:encodingStyle'=>'http://schemas.xmlsoap.org/soap/encoding/'}) do
|
182
|
+
retval.tag!("tns:#{request}") do
|
183
|
+
retval.tag!("#{request}Request", {'xsi:type'=>"tns:#{request}Request"}) do
|
184
|
+
yield retval
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
retval.target!
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|