activemerchant 1.65.0 → 1.66.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 +9 -0
- data/lib/active_merchant/billing/gateways/iveri.rb +251 -0
- data/lib/active_merchant/billing/gateways/pro_pay.rb +326 -0
- data/lib/active_merchant/billing/gateways/safe_charge.rb +9 -0
- data/lib/active_merchant/billing/gateways/wepay.rb +11 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5c4bbd0ee52bf39713dad270b4e4b923d24d193c
|
|
4
|
+
data.tar.gz: 304ee11c40f4c5c68d108ccbab8a6eceaddb0315
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 69f9b2b2082147a44ec23c987b1f6ffaf139b44a2773e84c4c30e70b18812e02677c37714f36de005db44ebe66237b1617ddce74f58fae8731544d990accf216
|
|
7
|
+
data.tar.gz: 394bc190204e8e3cb01b1b1b5f5a27c6af430672c51767a760b2f816d0c07e29ef5cb0d9bb3346a616a0ba3083d954d43034d7d8333b721a5ce44bb06ef5e940
|
data/CHANGELOG
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
== HEAD
|
|
4
4
|
|
|
5
|
+
== Version 1.66.0 (May 4, 2017)
|
|
6
|
+
* Support Rails 5.1 [jhawthorn] #2407
|
|
7
|
+
* ProPay: Add Canada as supported country [davidsantoso]
|
|
8
|
+
* ProPay: Add gateway support [davidsantoso] #2405
|
|
9
|
+
* SafeCharge: Support credit transactions [shasum] #2404
|
|
10
|
+
* WePay: Add scrub method [shasum] #2406
|
|
11
|
+
* iVeri: Add gateway support [curiousepic] #2400
|
|
12
|
+
* iVeri: Support 3DSecure data fields [davidsantoso] #2412
|
|
13
|
+
|
|
5
14
|
== Version 1.65.0 (April 26, 2017)
|
|
6
15
|
* Adyen: Add Adyen v18 gateway [adyenpayments] #2272
|
|
7
16
|
* Authorize.Net: Force refund of unsettled payments via void [bizla] #2399
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
require 'nokogiri'
|
|
2
|
+
|
|
3
|
+
module ActiveMerchant #:nodoc:
|
|
4
|
+
module Billing #:nodoc:
|
|
5
|
+
class IveriGateway < Gateway
|
|
6
|
+
self.live_url = self.test_url = 'https://portal.nedsecure.co.za/iVeriWebService/Service.asmx'
|
|
7
|
+
|
|
8
|
+
self.supported_countries = ['US', 'ZA', 'GB']
|
|
9
|
+
self.default_currency = 'ZAR'
|
|
10
|
+
self.money_format = :cents
|
|
11
|
+
self.supported_cardtypes = [:visa, :master, :american_express]
|
|
12
|
+
|
|
13
|
+
self.homepage_url = 'http://www.iveri.com'
|
|
14
|
+
self.display_name = 'iVeri'
|
|
15
|
+
|
|
16
|
+
def initialize(options={})
|
|
17
|
+
requires!(options, :app_id, :cert_id)
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def purchase(money, payment_method, options={})
|
|
22
|
+
post = build_vxml_request('Debit', options) do |xml|
|
|
23
|
+
add_auth_purchase_params(xml, money, payment_method, options)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
commit(post)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def authorize(money, payment_method, options={})
|
|
30
|
+
post = build_vxml_request('Authorisation', options) do |xml|
|
|
31
|
+
add_auth_purchase_params(xml, money, payment_method, options)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
commit(post)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def capture(money, authorization, options={})
|
|
38
|
+
post = build_vxml_request('Debit', options) do |xml|
|
|
39
|
+
add_authorization(xml, authorization, options)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
commit(post)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def refund(money, authorization, options={})
|
|
46
|
+
post = build_vxml_request('Credit', options) do |xml|
|
|
47
|
+
add_amount(xml, money, options)
|
|
48
|
+
add_authorization(xml, authorization, options)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
commit(post)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def void(authorization, options={})
|
|
55
|
+
post = build_vxml_request('Void', options) do |xml|
|
|
56
|
+
add_authorization(xml, authorization, options)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
commit(post)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def verify(credit_card, options={})
|
|
63
|
+
authorize(0, credit_card, options)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def verify_credentials
|
|
67
|
+
void = void('', options)
|
|
68
|
+
return true if void.message == 'Missing OriginalMerchantTrace'
|
|
69
|
+
false
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def supports_scrubbing?
|
|
73
|
+
true
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def scrub(transcript)
|
|
77
|
+
transcript.
|
|
78
|
+
gsub(%r((CertificateID=\\\")[^\\]*), '\1[FILTERED]').
|
|
79
|
+
gsub(%r((<PAN>)[^&]*), '\1[FILTERED]').
|
|
80
|
+
gsub(%r((<CardSecurityCode>)[^&]*), '\1[FILTERED]')
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def build_xml_envelope(vxml)
|
|
86
|
+
builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
|
|
87
|
+
xml[:soap].Envelope 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema', 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/' do
|
|
88
|
+
xml[:soap].Body do
|
|
89
|
+
xml.Execute 'xmlns' => 'http://iveri.com/' do
|
|
90
|
+
xml.validateRequest 'true'
|
|
91
|
+
xml.protocol 'V_XML'
|
|
92
|
+
xml.protocolVersion '2.0'
|
|
93
|
+
xml.request vxml
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
builder.to_xml
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def build_vxml_request(action, options)
|
|
103
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
|
104
|
+
xml.V_XML('Version' => '2.0', 'CertificateID' => @options[:cert_id], 'Direction' => 'Request') do
|
|
105
|
+
xml.Transaction('ApplicationID' => @options[:app_id], 'Command' => action, 'Mode' => mode) do
|
|
106
|
+
yield(xml)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
builder.doc.root.to_xml
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def add_auth_purchase_params(post, money, payment_method, options)
|
|
115
|
+
add_card_holder_authentication(post, options)
|
|
116
|
+
add_amount(post, money, options)
|
|
117
|
+
add_electronic_commerce_indicator(post, options)
|
|
118
|
+
add_payment_method(post, payment_method, options)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def add_amount(post, money, options)
|
|
122
|
+
post.Amount(amount(money))
|
|
123
|
+
post.Currency(options[:currency] || default_currency)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def add_electronic_commerce_indicator(post, options)
|
|
127
|
+
post.ElectronicCommerceIndicator(options[:eci]) if options[:eci]
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def add_authorization(post, authorization, options)
|
|
131
|
+
post.MerchantReference(split_auth(authorization)[2])
|
|
132
|
+
post.TransactionIndex(split_auth(authorization)[1])
|
|
133
|
+
post.OriginalRequestID(split_auth(authorization)[0])
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def add_payment_method(post, payment_method, options)
|
|
137
|
+
post.ExpiryDate("#{format(payment_method.month, :two_digits)}#{payment_method.year}")
|
|
138
|
+
add_new_reference(post, options)
|
|
139
|
+
post.CardSecurityCode(payment_method.verification_value)
|
|
140
|
+
post.PAN(payment_method.number)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def add_new_reference(post, options)
|
|
144
|
+
post.MerchantReference(options[:order_id] || generate_unique_id)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def add_card_holder_authentication(post, options)
|
|
148
|
+
post.CardHolderAuthenticationID(options[:xid]) if options[:xid]
|
|
149
|
+
post.CardHolderAuthenticationData(options[:cavv]) if options[:cavv]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def commit(post)
|
|
153
|
+
raw_response = begin
|
|
154
|
+
ssl_post(live_url, build_xml_envelope(post), headers(post))
|
|
155
|
+
rescue ActiveMerchant::ResponseError => e
|
|
156
|
+
e.response.body
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
parsed = parse(raw_response)
|
|
160
|
+
succeeded = success_from(parsed)
|
|
161
|
+
|
|
162
|
+
Response.new(
|
|
163
|
+
succeeded,
|
|
164
|
+
message_from(parsed, succeeded),
|
|
165
|
+
parsed,
|
|
166
|
+
authorization: authorization_from(parsed),
|
|
167
|
+
error_code: error_code_from(parsed, succeeded),
|
|
168
|
+
test: test?
|
|
169
|
+
)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def mode
|
|
173
|
+
test? ? 'Test' : 'Live'
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def headers(post)
|
|
177
|
+
{
|
|
178
|
+
"Content-Type" => "text/xml; charset=utf-8",
|
|
179
|
+
"Content-Length" => post.size.to_s,
|
|
180
|
+
"SOAPAction" => "http://iveri.com/Execute"
|
|
181
|
+
}
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def parse(body)
|
|
185
|
+
parsed = {}
|
|
186
|
+
|
|
187
|
+
vxml = Nokogiri::XML(body).remove_namespaces!.xpath("//Envelope/Body/ExecuteResponse/ExecuteResult").inner_text
|
|
188
|
+
doc = Nokogiri::XML(vxml)
|
|
189
|
+
doc.xpath("*").each do |node|
|
|
190
|
+
if (node.elements.empty?)
|
|
191
|
+
parsed[underscore(node.name)] = node.text
|
|
192
|
+
else
|
|
193
|
+
node.elements.each do |childnode|
|
|
194
|
+
parse_element(parsed, childnode)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
parsed
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def parse_element(parsed, node)
|
|
202
|
+
if !node.attributes.empty?
|
|
203
|
+
node.attributes.each do |a|
|
|
204
|
+
parsed[underscore(node.name)+ "_" + underscore(a[1].name)] = a[1].value
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
if !node.elements.empty?
|
|
209
|
+
node.elements.each {|e| parse_element(parsed, e) }
|
|
210
|
+
else
|
|
211
|
+
parsed[underscore(node.name)] = node.text
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def success_from(response)
|
|
216
|
+
response['result_status'] == '0'
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def message_from(response, succeeded)
|
|
220
|
+
if succeeded
|
|
221
|
+
"Succeeded"
|
|
222
|
+
else
|
|
223
|
+
response['result_description'] || response['result_acquirer_description']
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def authorization_from(response)
|
|
228
|
+
"#{response['transaction_request_id']}|#{response['transaction_index']}|#{response['merchant_reference']}"
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def split_auth(authorization)
|
|
232
|
+
request_id, transaction_index, merchant_reference = authorization.to_s.split('|')
|
|
233
|
+
[request_id, transaction_index, merchant_reference]
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def error_code_from(response, succeeded)
|
|
237
|
+
unless succeeded
|
|
238
|
+
response['result_code']
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def underscore(camel_cased_word)
|
|
243
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
|
244
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
|
245
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
|
246
|
+
tr("-", "_").
|
|
247
|
+
downcase
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
require 'nokogiri'
|
|
2
|
+
|
|
3
|
+
module ActiveMerchant #:nodoc:
|
|
4
|
+
module Billing #:nodoc:
|
|
5
|
+
class ProPayGateway < Gateway
|
|
6
|
+
self.test_url = 'https://xmltest.propay.com/API/PropayAPI.aspx'
|
|
7
|
+
self.live_url = 'https://epay.propay.com/api/propayapi.aspx'
|
|
8
|
+
|
|
9
|
+
self.supported_countries = ['US', 'CA']
|
|
10
|
+
self.default_currency = 'USD'
|
|
11
|
+
self.money_format = :cents
|
|
12
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
|
13
|
+
|
|
14
|
+
self.homepage_url = 'https://www.propay.com/'
|
|
15
|
+
self.display_name = 'ProPay'
|
|
16
|
+
|
|
17
|
+
STATUS_RESPONSE_CODES = {
|
|
18
|
+
"00" => "Success",
|
|
19
|
+
"20" => "Invalid username",
|
|
20
|
+
"21" => "Invalid transType",
|
|
21
|
+
"22" => "Invalid Currency Code",
|
|
22
|
+
"23" => "Invalid accountType",
|
|
23
|
+
"24" => "Invalid sourceEmail",
|
|
24
|
+
"25" => "Invalid firstName",
|
|
25
|
+
"26" => "Invalid mInitial",
|
|
26
|
+
"27" => "Invalid lastName",
|
|
27
|
+
"28" => "Invalid billAddr",
|
|
28
|
+
"29" => "Invalid aptNum",
|
|
29
|
+
"30" => "Invalid city",
|
|
30
|
+
"31" => "Invalid state",
|
|
31
|
+
"32" => "Invalid billZip",
|
|
32
|
+
"33" => "Invalid mailAddr",
|
|
33
|
+
"34" => "Invalid mailApt",
|
|
34
|
+
"35" => "Invalid mailCity",
|
|
35
|
+
"36" => "Invalid mailState",
|
|
36
|
+
"37" => "Invalid mailZip",
|
|
37
|
+
"38" => "Invalid dayPhone",
|
|
38
|
+
"39" => "Invalid evenPhone",
|
|
39
|
+
"40" => "Invalid ssn",
|
|
40
|
+
"41" => "Invalid dob",
|
|
41
|
+
"42" => "Invalid recEmail",
|
|
42
|
+
"43" => "Invalid knownAccount",
|
|
43
|
+
"44" => "Invalid amount",
|
|
44
|
+
"45" => "Invalid invNum",
|
|
45
|
+
"46" => "Invalid rtNum",
|
|
46
|
+
"47" => "Invalid accntNum",
|
|
47
|
+
"48" => "Invalid ccNum",
|
|
48
|
+
"49" => "Invalid expDate",
|
|
49
|
+
"50" => "Invalid cvv2",
|
|
50
|
+
"51" => "Invalid transNum and/or Unable to act perform actions on transNum due to funding",
|
|
51
|
+
"52" => "Invalid splitNum",
|
|
52
|
+
"53" => "A ProPay account with this email address already exists AND/OR User has no account number",
|
|
53
|
+
"54" => "A ProPay account with this social security number already exists",
|
|
54
|
+
"55" => "The email address provided does not correspond to a ProPay account.",
|
|
55
|
+
"56" => "Recipient’s email address shouldn’t have a ProPay account and does",
|
|
56
|
+
"57" => "Cannot settle transaction because it already expired",
|
|
57
|
+
"58" => "Credit card declined",
|
|
58
|
+
"59" => "Invalid Credential or IP address not allowed",
|
|
59
|
+
"60" => "Credit card authorization timed out; retry at a later time",
|
|
60
|
+
"61" => "Amount exceeds single transaction limit",
|
|
61
|
+
"62" => "Amount exceeds monthly volume limit",
|
|
62
|
+
"63" => "Insufficient funds in account",
|
|
63
|
+
"64" => "Over credit card use limit",
|
|
64
|
+
"65" => "Miscellaneous error",
|
|
65
|
+
"66" => "Denied a ProPay account",
|
|
66
|
+
"67" => "Unauthorized service requested",
|
|
67
|
+
"68" => "Account not affiliated",
|
|
68
|
+
"69" => "Duplicate invoice number (The same card was charged for the same amount with the same invoice number (including blank invoices) in a 1 minute period. Details about the original transaction are included whenever a 69 response is returned. These details include a repeat of the auth code, the original AVS response, and the original CVV response.)",
|
|
69
|
+
"70" => "Duplicate external ID",
|
|
70
|
+
"71" => "Account previously set up, but problem affiliating it with partner",
|
|
71
|
+
"72" => "The ProPay Account has already been upgraded to a Premium Account",
|
|
72
|
+
"73" => "Invalid Destination Account",
|
|
73
|
+
"74" => "Account or Trans Error",
|
|
74
|
+
"75" => "Money already pulled",
|
|
75
|
+
"76" => "Not Premium (used only for push/pull transactions)",
|
|
76
|
+
"77" => "Empty results",
|
|
77
|
+
"78" => "Invalid Authentication",
|
|
78
|
+
"79" => "Generic account status error",
|
|
79
|
+
"80" => "Invalid Password",
|
|
80
|
+
"81" => "Account Expired",
|
|
81
|
+
"82" => "InvalidUserID",
|
|
82
|
+
"83" => "BatchTransCountError",
|
|
83
|
+
"84" => "InvalidBeginDate",
|
|
84
|
+
"85" => "InvalidEndDate",
|
|
85
|
+
"86" => "InvalidExternalID",
|
|
86
|
+
"87" => "DuplicateUserID",
|
|
87
|
+
"88" => "Invalid track 1",
|
|
88
|
+
"89" => "Invalid track 2",
|
|
89
|
+
"90" => "Transaction already refunded",
|
|
90
|
+
"91" => "Duplicate Batch ID"
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
TRANSACTION_RESPONSE_CODES = {
|
|
94
|
+
"00" => "Success",
|
|
95
|
+
"1" => "Transaction blocked by issuer",
|
|
96
|
+
"4" => "Pick up card and deny transaction",
|
|
97
|
+
"5" => "Problem with the account",
|
|
98
|
+
"6" => "Customer requested stop to recurring payment",
|
|
99
|
+
"7" => "Customer requested stop to all recurring payments",
|
|
100
|
+
"8" => "Honor with ID only",
|
|
101
|
+
"9" => "Unpaid items on customer account",
|
|
102
|
+
"12" => "Invalid transaction",
|
|
103
|
+
"13" => "Amount Error",
|
|
104
|
+
"14" => "Invalid card number",
|
|
105
|
+
"15" => "No such issuer. Could not route transaction",
|
|
106
|
+
"16" => "Refund error",
|
|
107
|
+
"17" => "Over limit",
|
|
108
|
+
"19" => "Reenter transaction or the merchant account may be boarded incorrectly",
|
|
109
|
+
"25" => "Invalid terminal 41 Lost card",
|
|
110
|
+
"43" => "Stolen card",
|
|
111
|
+
"51" => "Insufficient funds",
|
|
112
|
+
"52" => "No such account",
|
|
113
|
+
"54" => "Expired card",
|
|
114
|
+
"55" => "Incorrect PIN",
|
|
115
|
+
"57" => "Bank does not allow this type of purchase",
|
|
116
|
+
"58" => "Credit card network does not allow this type of purchase for your merchant account.",
|
|
117
|
+
"61" => "Exceeds issuer withdrawal limit",
|
|
118
|
+
"62" => "Issuer does not allow this card to be charged for your business.",
|
|
119
|
+
"63" => "Security Violation",
|
|
120
|
+
"65" => "Activity limit exceeded",
|
|
121
|
+
"75" => "PIN tries exceeded",
|
|
122
|
+
"76" => "Unable to locate account",
|
|
123
|
+
"78" => "Account not recognized",
|
|
124
|
+
"80" => "Invalid Date",
|
|
125
|
+
"82" => "Invalid CVV2",
|
|
126
|
+
"83" => "Cannot verify the PIN",
|
|
127
|
+
"85" => "Service not supported for this card",
|
|
128
|
+
"93" => "Cannot complete transaction. Customer should call 800 number.",
|
|
129
|
+
"95" => "Misc Error Transaction failure",
|
|
130
|
+
"96" => "Issuer system malfunction or timeout.",
|
|
131
|
+
"97" => "Approved for a lesser amount. ProPay will not settle and consider this a decline.",
|
|
132
|
+
"98" => "Failure HV",
|
|
133
|
+
"99" => "Generic decline or unable to parse issuer response code"
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
def initialize(options={})
|
|
137
|
+
requires!(options, :cert_str)
|
|
138
|
+
super
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def purchase(money, payment, options={})
|
|
142
|
+
request = build_xml_request do |xml|
|
|
143
|
+
add_invoice(xml, money, options)
|
|
144
|
+
add_payment(xml, payment, options)
|
|
145
|
+
add_address(xml, options)
|
|
146
|
+
add_account(xml, options)
|
|
147
|
+
add_recurring(xml, options)
|
|
148
|
+
xml.transType "04"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
commit(request)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def authorize(money, payment, options={})
|
|
155
|
+
request = build_xml_request do |xml|
|
|
156
|
+
add_invoice(xml, money, options)
|
|
157
|
+
add_payment(xml, payment, options)
|
|
158
|
+
add_address(xml, options)
|
|
159
|
+
add_account(xml, options)
|
|
160
|
+
add_recurring(xml, options)
|
|
161
|
+
xml.transType "05"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
commit(request)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def capture(money, authorization, options={})
|
|
168
|
+
request = build_xml_request do |xml|
|
|
169
|
+
add_invoice(xml, money, options)
|
|
170
|
+
add_account(xml, options)
|
|
171
|
+
xml.transNum authorization
|
|
172
|
+
xml.transType "06"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
commit(request)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def refund(money, authorization, options={})
|
|
179
|
+
request = build_xml_request do |xml|
|
|
180
|
+
add_invoice(xml, money, options)
|
|
181
|
+
add_account(xml, options)
|
|
182
|
+
xml.transNum authorization
|
|
183
|
+
xml.transType "07"
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
commit(request)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def void(authorization, options={})
|
|
190
|
+
refund(nil, authorization, options)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def credit(money, payment, options={})
|
|
194
|
+
request = build_xml_request do |xml|
|
|
195
|
+
add_invoice(xml, money, options)
|
|
196
|
+
add_payment(xml, payment, options)
|
|
197
|
+
add_account(xml, options)
|
|
198
|
+
xml.transType "35"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
commit(request)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def verify(credit_card, options={})
|
|
205
|
+
MultiResponse.run(:use_first_response) do |r|
|
|
206
|
+
r.process { authorize(100, credit_card, options) }
|
|
207
|
+
r.process(:ignore_result) { void(r.authorization, options) }
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def supports_scrubbing?
|
|
212
|
+
true
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def scrub(transcript)
|
|
216
|
+
transcript.
|
|
217
|
+
gsub(%r((<certStr>).+(</certStr>)), '\1[FILTERED]\2').
|
|
218
|
+
gsub(%r((<ccNum>).+(</ccNum>)), '\1[FILTERED]\2').
|
|
219
|
+
gsub(%r((<CVV2>).+(</CVV2>)), '\1[FILTERED]\2')
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
private
|
|
223
|
+
|
|
224
|
+
def add_payment(xml, payment, options)
|
|
225
|
+
xml.ccNum payment.number
|
|
226
|
+
xml.expDate "#{format(payment.month, :two_digits)}#{format(payment.year, :two_digits)}"
|
|
227
|
+
xml.CVV2 payment.verification_value
|
|
228
|
+
xml.cardholderName payment.name
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def add_address(xml, options)
|
|
232
|
+
if address = options[:billing_address] || options[:address]
|
|
233
|
+
xml.addr address[:address1]
|
|
234
|
+
xml.aptNum address[:address2]
|
|
235
|
+
xml.city address[:city]
|
|
236
|
+
xml.state address[:state]
|
|
237
|
+
xml.zip address[:zip]
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def add_account(xml, options)
|
|
242
|
+
xml.accountNum options[:account_num]
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def add_invoice(xml, money, options)
|
|
246
|
+
xml.amount amount(money)
|
|
247
|
+
xml.currencyCode options[:currency] || currency(money)
|
|
248
|
+
xml.invNum options[:order_id] || SecureRandom.hex(25)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def add_recurring(xml, options)
|
|
252
|
+
xml.recurringPayment options[:recurring_payment]
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def parse(body)
|
|
256
|
+
results = {}
|
|
257
|
+
xml = Nokogiri::XML(body)
|
|
258
|
+
resp = xml.xpath("//XMLResponse/XMLTrans")
|
|
259
|
+
resp.children.each do |element|
|
|
260
|
+
results[element.name.underscore.downcase.to_sym] = element.text
|
|
261
|
+
end
|
|
262
|
+
results
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def commit(parameters)
|
|
266
|
+
url = (test? ? test_url : live_url)
|
|
267
|
+
response = parse(ssl_post(url, parameters))
|
|
268
|
+
|
|
269
|
+
Response.new(
|
|
270
|
+
success_from(response),
|
|
271
|
+
message_from(response),
|
|
272
|
+
response,
|
|
273
|
+
authorization: authorization_from(response),
|
|
274
|
+
avs_result: AVSResult.new(code: response[:avs]),
|
|
275
|
+
cvv_result: CVVResult.new(response[:cvv2_resp]),
|
|
276
|
+
test: test?,
|
|
277
|
+
error_code: error_code_from(response)
|
|
278
|
+
)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def success_from(response)
|
|
282
|
+
response[:status] == "00"
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def message_from(response)
|
|
286
|
+
return "Success" if success_from(response)
|
|
287
|
+
message = STATUS_RESPONSE_CODES[response[:status]]
|
|
288
|
+
message += " - #{TRANSACTION_RESPONSE_CODES[response[:response_code]]}" if response[:response_code]
|
|
289
|
+
|
|
290
|
+
message
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def authorization_from(response)
|
|
294
|
+
response[:trans_num]
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def error_code_from(response)
|
|
298
|
+
unless success_from(response)
|
|
299
|
+
response[:status]
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def build_xml_request
|
|
304
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
|
305
|
+
xml.XMLRequest do
|
|
306
|
+
xml.certStr @options[:cert_str]
|
|
307
|
+
xml.class_ "partner"
|
|
308
|
+
xml.XMLTrans do
|
|
309
|
+
yield(xml)
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
builder.to_xml
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def underscore(camel_cased_word)
|
|
319
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
|
320
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
|
321
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
|
322
|
+
tr("-", "_").
|
|
323
|
+
downcase
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
end
|
|
@@ -63,6 +63,15 @@ module ActiveMerchant #:nodoc:
|
|
|
63
63
|
commit(post)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
def credit(money, payment, options={})
|
|
67
|
+
post = {}
|
|
68
|
+
add_payment(post, payment)
|
|
69
|
+
add_transaction_data("Credit", post, money, options)
|
|
70
|
+
post[:sg_CreditType] = 1
|
|
71
|
+
|
|
72
|
+
commit(post)
|
|
73
|
+
end
|
|
74
|
+
|
|
66
75
|
def void(authorization, options={})
|
|
67
76
|
post = {}
|
|
68
77
|
auth, transaction_id, token, exp_month, exp_year, original_amount = authorization.split("|")
|
|
@@ -108,6 +108,17 @@ module ActiveMerchant #:nodoc:
|
|
|
108
108
|
end
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
+
def supports_scrubbing?
|
|
112
|
+
true
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def scrub(transcript)
|
|
116
|
+
transcript.
|
|
117
|
+
gsub(%r((\\?"cc_number\\?":\\?")[^\\"]+(\\?"))i, '\1[FILTERED]\2').
|
|
118
|
+
gsub(%r((\\?"cvv\\?":\\?")[^\\"]+(\\?"))i, '\1[FILTERED]\2').
|
|
119
|
+
gsub(%r((Authorization: Bearer )\w+)i, '\1[FILTERED]\2')
|
|
120
|
+
end
|
|
121
|
+
|
|
111
122
|
private
|
|
112
123
|
|
|
113
124
|
def authorize_with_token(post, money, token, options)
|
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.66.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-04
|
|
11
|
+
date: 2017-05-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -19,7 +19,7 @@ dependencies:
|
|
|
19
19
|
version: 3.2.14
|
|
20
20
|
- - "<"
|
|
21
21
|
- !ruby/object:Gem::Version
|
|
22
|
-
version:
|
|
22
|
+
version: 6.x
|
|
23
23
|
type: :runtime
|
|
24
24
|
prerelease: false
|
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -29,7 +29,7 @@ dependencies:
|
|
|
29
29
|
version: 3.2.14
|
|
30
30
|
- - "<"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version:
|
|
32
|
+
version: 6.x
|
|
33
33
|
- !ruby/object:Gem::Dependency
|
|
34
34
|
name: i18n
|
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -242,6 +242,7 @@ files:
|
|
|
242
242
|
- lib/active_merchant/billing/gateways/ipp.rb
|
|
243
243
|
- lib/active_merchant/billing/gateways/iridium.rb
|
|
244
244
|
- lib/active_merchant/billing/gateways/itransact.rb
|
|
245
|
+
- lib/active_merchant/billing/gateways/iveri.rb
|
|
245
246
|
- lib/active_merchant/billing/gateways/jetpay.rb
|
|
246
247
|
- lib/active_merchant/billing/gateways/komoju.rb
|
|
247
248
|
- lib/active_merchant/billing/gateways/kushki.rb
|
|
@@ -319,6 +320,7 @@ files:
|
|
|
319
320
|
- lib/active_merchant/billing/gateways/payway.rb
|
|
320
321
|
- lib/active_merchant/billing/gateways/pin.rb
|
|
321
322
|
- lib/active_merchant/billing/gateways/plugnpay.rb
|
|
323
|
+
- lib/active_merchant/billing/gateways/pro_pay.rb
|
|
322
324
|
- lib/active_merchant/billing/gateways/psigate.rb
|
|
323
325
|
- lib/active_merchant/billing/gateways/psl_card.rb
|
|
324
326
|
- lib/active_merchant/billing/gateways/qbms.rb
|