activemerchant 1.8.0 → 1.9.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 +9 -0
- data/CONTRIBUTORS +21 -1
- data/README.rdoc +16 -4
- data/lib/active_merchant.rb +2 -0
- data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
- data/lib/active_merchant/billing/gateways/paybox_direct.rb +205 -0
- data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
- data/lib/active_merchant/billing/integrations/bogus.rb +1 -1
- data/lib/active_merchant/billing/integrations/chronopay.rb +1 -1
- data/lib/active_merchant/billing/integrations/direc_pay.rb +37 -0
- data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +188 -0
- data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
- data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
- data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
- data/lib/active_merchant/billing/integrations/gestpay.rb +1 -1
- data/lib/active_merchant/billing/integrations/helper.rb +8 -5
- data/lib/active_merchant/billing/integrations/hi_trust.rb +1 -1
- data/lib/active_merchant/billing/integrations/nochex.rb +1 -1
- data/lib/active_merchant/billing/integrations/paypal.rb +1 -1
- data/lib/active_merchant/billing/integrations/return.rb +4 -2
- data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +109 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +204 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +27 -0
- data/lib/active_merchant/billing/integrations/two_checkout.rb +1 -1
- data/lib/active_merchant/version.rb +1 -1
- metadata +17 -4
- metadata.gz.sig +0 -0
@@ -0,0 +1,330 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class SecureNetGateway < Gateway
|
4
|
+
|
5
|
+
API_VERSION = "4.0"
|
6
|
+
|
7
|
+
TRANSACTIONS = {
|
8
|
+
:auth_only => "0000", #
|
9
|
+
:partial_auth_only => "0001",
|
10
|
+
:auth_capture => "0100", #
|
11
|
+
:partial_auth_capture => "0101",
|
12
|
+
:prior_auth_capture => "0200",
|
13
|
+
:capture_only => "0300", #
|
14
|
+
:void => "0400", #
|
15
|
+
:partial_void => "0401",
|
16
|
+
:credit => "0500", #
|
17
|
+
:credit_authonly => "0501",
|
18
|
+
:credit_priorauthcapture => "0502",
|
19
|
+
:force_credit => "0600",
|
20
|
+
:force_credit_authonly => "0601",
|
21
|
+
:force_credit_priorauthcapture => "0602",
|
22
|
+
:verification => "0700",
|
23
|
+
:auth_increment => "0800",
|
24
|
+
:issue => "0900",
|
25
|
+
:activate => "0901",
|
26
|
+
:redeem => "0902",
|
27
|
+
:redeem_partial => "0903",
|
28
|
+
:deactivate => "0904",
|
29
|
+
:reactivate => "0905",
|
30
|
+
:inquiry_balance => "0906"
|
31
|
+
}
|
32
|
+
|
33
|
+
XML_ATTRIBUTES = { 'xmlns' => "http://gateway.securenet.com/API/Contracts",
|
34
|
+
'xmlns:i' => "http://www.w3.org/2001/XMLSchema-instance"
|
35
|
+
}
|
36
|
+
NIL_ATTRIBUTE = { 'i:nil' => "true" }
|
37
|
+
|
38
|
+
# SUCCESS = "true"
|
39
|
+
# SENSITIVE_FIELDS = [ :verification_str2, :expiry_date, :card_number ]
|
40
|
+
|
41
|
+
self.supported_countries = ['US']
|
42
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
43
|
+
self.homepage_url = 'http://www.securenet.com/'
|
44
|
+
self.display_name = 'SecureNet'
|
45
|
+
# self.wiredump_device = STDOUT
|
46
|
+
|
47
|
+
# TEST_URL = 'https://certify.securenet.com/api/Gateway.svc'
|
48
|
+
TEST_URL = 'https://certify.securenet.com/API/gateway.svc/webHttp/ProcessTransaction'
|
49
|
+
LIVE_URL = 'https://gateway.securenet.com/api/Gateway.svc'
|
50
|
+
|
51
|
+
APPROVED, DECLINED, ERROR = 1, 2, 3
|
52
|
+
|
53
|
+
RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT = 0, 2, 3
|
54
|
+
AVS_RESULT_CODE, CARD_CODE_RESPONSE_CODE, TRANSACTION_ID = 5, 6, 8
|
55
|
+
|
56
|
+
CARD_CODE_ERRORS = %w( N S )
|
57
|
+
AVS_ERRORS = %w( A E N R W Z )
|
58
|
+
|
59
|
+
def initialize(options = {})
|
60
|
+
requires!(options, :login, :password)
|
61
|
+
@options = options
|
62
|
+
super
|
63
|
+
end
|
64
|
+
|
65
|
+
def authorize(money, creditcard, options = {})
|
66
|
+
commit(build_sale_or_authorization_request(creditcard, options, :auth_only), money)
|
67
|
+
end
|
68
|
+
|
69
|
+
def purchase(money, creditcard, options = {})
|
70
|
+
commit(build_sale_or_authorization_request(creditcard, options, :auth_capture), money)
|
71
|
+
end
|
72
|
+
|
73
|
+
def capture(money, creditcard, authorization, options = {})
|
74
|
+
commit(build_capture_request(authorization, creditcard, options, :prior_auth_capture), money)
|
75
|
+
end
|
76
|
+
|
77
|
+
def void(money, creditcard, authorization, options = {})
|
78
|
+
commit(build_void_request(authorization, creditcard, options, :void), money)
|
79
|
+
end
|
80
|
+
|
81
|
+
def credit(money, creditcard, authorization, options = {})
|
82
|
+
commit(build_credit_request(authorization, creditcard, options, :credit), money)
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
def commit(request, money)
|
87
|
+
xml = build_request(request, money)
|
88
|
+
data = ssl_post(TEST_URL, xml, "Content-Type" => "text/xml")
|
89
|
+
response = parse(data)
|
90
|
+
|
91
|
+
test_mode = test?
|
92
|
+
Response.new(success?(response), message_from(response), response,
|
93
|
+
:test => test_mode,
|
94
|
+
:authorization => response[:transactionid],
|
95
|
+
:avs_result => { :code => response[:avs_result_code] },
|
96
|
+
:cvv_result => response[:card_code_response_code]
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
def build_request(request, money)
|
101
|
+
xml = Builder::XmlMarkup.new
|
102
|
+
|
103
|
+
xml.instruct!
|
104
|
+
xml.tag!("TRANSACTION", XML_ATTRIBUTES) do
|
105
|
+
xml.tag! 'AMOUNT', amount(money)
|
106
|
+
xml << request
|
107
|
+
end
|
108
|
+
|
109
|
+
xml.target!
|
110
|
+
end
|
111
|
+
|
112
|
+
def build_sale_or_authorization_request(creditcard, options, action)
|
113
|
+
xml = Builder::XmlMarkup.new
|
114
|
+
|
115
|
+
add_credit_card(xml, creditcard)
|
116
|
+
xml.tag! 'CODE', TRANSACTIONS[action]
|
117
|
+
add_customer_data(xml, options)
|
118
|
+
add_address(xml, creditcard, options)
|
119
|
+
xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
|
120
|
+
xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
|
121
|
+
add_invoice(xml, options)
|
122
|
+
add_merchant_key(xml, options)
|
123
|
+
xml.tag! 'METHOD', 'CC'
|
124
|
+
xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id]
|
125
|
+
xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
|
126
|
+
xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!?
|
127
|
+
xml.tag! 'TEST', 'TRUE'
|
128
|
+
xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0
|
129
|
+
xml.tag! 'TRANSACTION_SERVICE', 0
|
130
|
+
|
131
|
+
xml.target!
|
132
|
+
end
|
133
|
+
|
134
|
+
def build_capture_or_credit_request(identification, options)
|
135
|
+
xml = Builder::XmlMarkup.new
|
136
|
+
|
137
|
+
add_identification(xml, identification)
|
138
|
+
add_customer_data(xml, options)
|
139
|
+
|
140
|
+
xml.target!
|
141
|
+
end
|
142
|
+
|
143
|
+
def build_capture_request(authorization, creditcard, options, action)
|
144
|
+
xml = Builder::XmlMarkup.new
|
145
|
+
|
146
|
+
add_credit_card(xml, creditcard)
|
147
|
+
xml.tag! 'CODE', TRANSACTIONS[action]
|
148
|
+
add_customer_data(xml, options)
|
149
|
+
xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
|
150
|
+
xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
|
151
|
+
add_merchant_key(xml, options)
|
152
|
+
xml.tag! 'METHOD', 'CC'
|
153
|
+
xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id]
|
154
|
+
xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
|
155
|
+
xml.tag! 'REF_TRANSID', authorization
|
156
|
+
xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!?
|
157
|
+
xml.tag! 'TEST', 'TRUE'
|
158
|
+
xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0
|
159
|
+
xml.tag! 'TRANSACTION_SERVICE', 0
|
160
|
+
|
161
|
+
xml.target!
|
162
|
+
end
|
163
|
+
|
164
|
+
def build_credit_request(authorization, creditcard, options, action)
|
165
|
+
# requires!(options, :card_number)
|
166
|
+
xml = Builder::XmlMarkup.new
|
167
|
+
|
168
|
+
add_credit_card(xml, creditcard)
|
169
|
+
xml.tag! 'CODE', TRANSACTIONS[action]
|
170
|
+
add_customer_data(xml, options)
|
171
|
+
xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
|
172
|
+
xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
|
173
|
+
add_merchant_key(xml, options)
|
174
|
+
xml.tag! 'METHOD', 'CC'
|
175
|
+
xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id]
|
176
|
+
xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
|
177
|
+
xml.tag! 'REF_TRANSID', authorization
|
178
|
+
xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!?
|
179
|
+
xml.tag! 'TEST', 'TRUE'
|
180
|
+
xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0
|
181
|
+
xml.tag! 'TRANSACTION_SERVICE', 0
|
182
|
+
|
183
|
+
xml.target!
|
184
|
+
end
|
185
|
+
|
186
|
+
def build_void_request(authorization, creditcard, options, action)
|
187
|
+
xml = Builder::XmlMarkup.new
|
188
|
+
|
189
|
+
add_credit_card(xml, creditcard)
|
190
|
+
xml.tag! 'CODE', TRANSACTIONS[action]
|
191
|
+
add_customer_data(xml, options)
|
192
|
+
xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
|
193
|
+
xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
|
194
|
+
add_merchant_key(xml, options)
|
195
|
+
xml.tag! 'METHOD', 'CC'
|
196
|
+
xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id]
|
197
|
+
xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
|
198
|
+
xml.tag! 'REF_TRANSID', authorization
|
199
|
+
xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!?
|
200
|
+
xml.tag! 'TEST', 'TRUE'
|
201
|
+
xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0
|
202
|
+
xml.tag! 'TRANSACTION_SERVICE', 0
|
203
|
+
|
204
|
+
xml.target!
|
205
|
+
end
|
206
|
+
|
207
|
+
#########################################################################
|
208
|
+
# FUNCTIONS RELATED TO BUILDING THE XML
|
209
|
+
#########################################################################
|
210
|
+
def add_credit_card(xml, creditcard)
|
211
|
+
xml.tag!("CARD") do
|
212
|
+
xml.tag! 'CARDCODE', creditcard.verification_value if creditcard.verification_value?
|
213
|
+
xml.tag! 'CARDNUMBER', creditcard.number
|
214
|
+
xml.tag! 'EXPDATE', expdate(creditcard)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def expdate(creditcard)
|
219
|
+
year = sprintf("%.4i", creditcard.year)
|
220
|
+
month = sprintf("%.2i", creditcard.month)
|
221
|
+
|
222
|
+
"#{month}#{year[-2..-1]}"
|
223
|
+
end
|
224
|
+
|
225
|
+
def add_customer_data(xml, options)
|
226
|
+
if options.has_key? :customer
|
227
|
+
xml.tag! 'CUSTOMERID', options[:customer]
|
228
|
+
end
|
229
|
+
|
230
|
+
if options.has_key? :ip
|
231
|
+
xml.tag! 'CUSTOMERIP', options[:ip]
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def add_address(xml, creditcard, options)
|
236
|
+
|
237
|
+
if address = options[:billing_address] || options[:address]
|
238
|
+
xml.tag!("CUSTOMER_BILL") do
|
239
|
+
xml.tag! 'ADDRESS', address[:address1].to_s
|
240
|
+
xml.tag! 'CITY', address[:city].to_s
|
241
|
+
xml.tag! 'COMPANY', address[:company].to_s
|
242
|
+
xml.tag! 'COUNTRY', address[:country].to_s
|
243
|
+
if options.has_key? :email
|
244
|
+
xml.tag! 'EMAIL', options[:email]
|
245
|
+
# xml.tag! 'EMAIL', 'myemail@yahoo.com'
|
246
|
+
xml.tag! 'EMAILRECEIPT', 'FALSE'
|
247
|
+
end
|
248
|
+
xml.tag! 'FIRSTNAME', creditcard.first_name
|
249
|
+
xml.tag! 'LASTNAME', creditcard.last_name
|
250
|
+
xml.tag! 'PHONE', address[:phone].to_s
|
251
|
+
xml.tag! 'STATE', address[:state].blank? ? 'n/a' : address[:state]
|
252
|
+
xml.tag! 'ZIP', address[:zip].to_s
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
if address = options[:shipping_address]
|
257
|
+
xml.tag!("CUSTOMER_SHIP") do
|
258
|
+
xml.tag! 'ADDRESS', address[:address1].to_s
|
259
|
+
xml.tag! 'CITY', address[:city].to_s
|
260
|
+
xml.tag! 'COMPANY', address[:company].to_s
|
261
|
+
xml.tag! 'COUNTRY', address[:country].to_s
|
262
|
+
xml.tag! 'FIRSTNAME', address[:first_name].to_s
|
263
|
+
xml.tag! 'LASTNAME', address[:last_name].to_s
|
264
|
+
xml.tag! 'STATE', address[:state].blank? ? 'n/a' : address[:state]
|
265
|
+
xml.tag! 'ZIP', address[:zip].to_s
|
266
|
+
end
|
267
|
+
else
|
268
|
+
xml.tag!('CUSTOMER_SHIP', NIL_ATTRIBUTE) do
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
273
|
+
|
274
|
+
def add_invoice(xml, options)
|
275
|
+
xml.tag! 'INVOICEDESC', options[:description]
|
276
|
+
xml.tag! 'INVOICENUM', 'inv-8'
|
277
|
+
end
|
278
|
+
|
279
|
+
def add_merchant_key(xml, options)
|
280
|
+
xml.tag!("MERCHANT_KEY") do
|
281
|
+
xml.tag! 'GROUPID', 0
|
282
|
+
xml.tag! 'SECUREKEY', @options[:password]
|
283
|
+
xml.tag! 'SECURENETID', @options[:login]
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
#########################################################################
|
288
|
+
# FUNCTIONS RELATED TO THE RESPONSE
|
289
|
+
#########################################################################
|
290
|
+
def success?(response)
|
291
|
+
response[:response_code].to_i == APPROVED
|
292
|
+
end
|
293
|
+
|
294
|
+
def message_from(response)
|
295
|
+
if response[:response_code].to_i == DECLINED
|
296
|
+
return CVVResult.messages[ response[:card_code_response_code] ] if CARD_CODE_ERRORS.include?(response[:card_code_response_code])
|
297
|
+
return AVSResult.messages[ response[:avs_result_code] ] if AVS_ERRORS.include?(response[:avs_result_code])
|
298
|
+
end
|
299
|
+
|
300
|
+
return response[:response_reason_text].nil? ? '' : response[:response_reason_text][0..-1]
|
301
|
+
end
|
302
|
+
|
303
|
+
def parse(xml)
|
304
|
+
response = {}
|
305
|
+
xml = REXML::Document.new(xml)
|
306
|
+
root = REXML::XPath.first(xml, "//GATEWAYRESPONSE")# ||
|
307
|
+
# root = REXML::XPath.first(xml, "//ProcessTransactionResponse")# ||
|
308
|
+
# REXML::XPath.first(xml, "//ErrorResponse")
|
309
|
+
if root
|
310
|
+
root.elements.to_a.each do |node|
|
311
|
+
recurring_parse_element(response, node)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
response
|
316
|
+
end
|
317
|
+
|
318
|
+
def recurring_parse_element(response, node)
|
319
|
+
if node.has_elements?
|
320
|
+
node.elements.each{|e| recurring_parse_element(response, e) }
|
321
|
+
else
|
322
|
+
response[node.name.underscore.to_sym] = node.text
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module DirecPay
|
5
|
+
autoload :Helper, File.dirname(__FILE__) + '/direc_pay/helper.rb'
|
6
|
+
autoload :Return, File.dirname(__FILE__) + '/direc_pay/return.rb'
|
7
|
+
autoload :Notification, File.dirname(__FILE__) + '/direc_pay/notification.rb'
|
8
|
+
autoload :Status, File.dirname(__FILE__) + '/direc_pay/status.rb'
|
9
|
+
|
10
|
+
mattr_accessor :production_url, :test_url
|
11
|
+
|
12
|
+
self.production_url = "https://www.timesofmoney.com/direcpay/secure/dpMerchantTransaction.jsp"
|
13
|
+
self.test_url = "https://test.timesofmoney.com/direcpay/secure/dpMerchantTransaction.jsp"
|
14
|
+
|
15
|
+
def self.service_url
|
16
|
+
mode = ActiveMerchant::Billing::Base.integration_mode
|
17
|
+
case mode
|
18
|
+
when :production
|
19
|
+
self.production_url
|
20
|
+
when :test
|
21
|
+
self.test_url
|
22
|
+
else
|
23
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.notification(post)
|
28
|
+
Notification.new(post)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.return(query_string)
|
32
|
+
Return.new(query_string)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module DirecPay
|
5
|
+
class Helper < ActiveMerchant::Billing::Integrations::Helper
|
6
|
+
mapping :account, 'MID'
|
7
|
+
mapping :order, 'Merchant Order No'
|
8
|
+
mapping :amount, 'Amount'
|
9
|
+
mapping :currency, 'Currency'
|
10
|
+
mapping :country, 'Country'
|
11
|
+
|
12
|
+
mapping :billing_address, :city => 'custCity',
|
13
|
+
:address1 => 'custAddress',
|
14
|
+
:state => 'custState',
|
15
|
+
:zip => 'custPinCode',
|
16
|
+
:country => 'custCountry',
|
17
|
+
:phone2 => 'custMobileNo'
|
18
|
+
|
19
|
+
mapping :shipping_address, :name => 'deliveryName',
|
20
|
+
:city => 'deliveryCity',
|
21
|
+
:address1 => 'deliveryAddress',
|
22
|
+
:state => 'deliveryState',
|
23
|
+
:zip => 'deliveryPinCode',
|
24
|
+
:country => 'deliveryCountry',
|
25
|
+
:phone2 => 'deliveryMobileNo'
|
26
|
+
|
27
|
+
mapping :customer, :name => 'custName',
|
28
|
+
:email => 'custEmailId'
|
29
|
+
|
30
|
+
mapping :description, 'otherNotes'
|
31
|
+
mapping :edit_allowed, 'editAllowed'
|
32
|
+
|
33
|
+
mapping :return_url, 'Success URL'
|
34
|
+
mapping :failure_url, 'Failure URL'
|
35
|
+
|
36
|
+
mapping :operating_mode, 'Operating Mode'
|
37
|
+
mapping :other_details, 'Other Details'
|
38
|
+
mapping :collaborator, 'Collaborator'
|
39
|
+
|
40
|
+
OPERATING_MODE = 'DOM'
|
41
|
+
COUNTRY = 'IND'
|
42
|
+
CURRENCY = 'INR'
|
43
|
+
OTHER_DETAILS = 'NULL'
|
44
|
+
EDIT_ALLOWED = 'N'
|
45
|
+
|
46
|
+
PHONE_CODES = {
|
47
|
+
'IN' => '91',
|
48
|
+
'US' => '01',
|
49
|
+
'CA' => '01'
|
50
|
+
}
|
51
|
+
|
52
|
+
ENCODED_PARAMS = [ :account, :operating_mode, :country, :currency, :amount, :order, :other_details, :return_url, :failure_url, :collaborator ]
|
53
|
+
|
54
|
+
|
55
|
+
def initialize(order, account, options = {})
|
56
|
+
super
|
57
|
+
collaborator = ActiveMerchant::Billing::Base.integration_mode == :test || options[:test] ? 'TOML' : 'DirecPay'
|
58
|
+
add_field(mappings[:collaborator], collaborator)
|
59
|
+
add_field(mappings[:country], 'IND')
|
60
|
+
add_field(mappings[:operating_mode], OPERATING_MODE)
|
61
|
+
add_field(mappings[:other_details], OTHER_DETAILS)
|
62
|
+
add_field(mappings[:edit_allowed], EDIT_ALLOWED)
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def customer(params = {})
|
67
|
+
full_name = "#{params[:first_name]} #{params[:last_name]}"
|
68
|
+
add_field(mappings[:customer][:name], full_name)
|
69
|
+
add_field(mappings[:customer][:email], params[:email])
|
70
|
+
end
|
71
|
+
|
72
|
+
# Need to format the amount to have 2 decimal places
|
73
|
+
def amount=(money)
|
74
|
+
cents = money.respond_to?(:cents) ? money.cents : money
|
75
|
+
if money.is_a?(String) or cents.to_i <= 0
|
76
|
+
raise ArgumentError, 'money amount must be either a Money object or a positive integer in cents.'
|
77
|
+
end
|
78
|
+
add_field(mappings[:amount], sprintf("%.2f", cents.to_f/100))
|
79
|
+
end
|
80
|
+
|
81
|
+
def shipping_address(params = {})
|
82
|
+
add_street_address!(params)
|
83
|
+
super(params.dup)
|
84
|
+
add_field(mappings[:shipping_address][:name], fields[mappings[:customer][:name]]) if fields[mappings[:shipping_address][:name]].blank?
|
85
|
+
add_phone_for!(:shipping_address, params)
|
86
|
+
end
|
87
|
+
|
88
|
+
def billing_address(params = {})
|
89
|
+
add_street_address!(params)
|
90
|
+
super(params.dup)
|
91
|
+
add_phone_for!(:billing_address, params)
|
92
|
+
end
|
93
|
+
|
94
|
+
def form_fields
|
95
|
+
add_failure_url
|
96
|
+
add_request_parameters
|
97
|
+
|
98
|
+
unencoded_parameters
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def add_request_parameters
|
105
|
+
params = ENCODED_PARAMS.map{ |param| fields[mappings[param]] }
|
106
|
+
encoded = encode_value(params.join('|'))
|
107
|
+
|
108
|
+
add_field('requestparameter', encoded)
|
109
|
+
end
|
110
|
+
|
111
|
+
def unencoded_parameters
|
112
|
+
params = fields.dup
|
113
|
+
# remove all encoded params from exported fields
|
114
|
+
ENCODED_PARAMS.each{ |param| params.delete(mappings[param]) }
|
115
|
+
# remove all special characters from each field value
|
116
|
+
params = params.collect{|name, value| [name, remove_special_characters(value)] }
|
117
|
+
Hash[params]
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_failure_url
|
121
|
+
if fields[mappings[:failure_url]].nil?
|
122
|
+
add_field(mappings[:failure_url], fields[mappings[:return_url]])
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def add_street_address!(params)
|
127
|
+
address = params[:address1]
|
128
|
+
address << " #{params[:address2]}" if params[:address2]
|
129
|
+
params.merge!(:address1 => address)
|
130
|
+
end
|
131
|
+
|
132
|
+
def add_phone_for!(address_type, params)
|
133
|
+
address_field = address_type == :billing_address ? 'custPhoneNo' : 'deliveryPhNo'
|
134
|
+
|
135
|
+
if params.has_key?(:phone)
|
136
|
+
country = fields[mappings[address_type][:country]]
|
137
|
+
phone = params[:phone].to_s
|
138
|
+
# Remove all non digits
|
139
|
+
phone.gsub!(/[^\d ]+/, '')
|
140
|
+
|
141
|
+
phone_country_code, phone_area_code, phone_number = nil
|
142
|
+
|
143
|
+
if country == 'IN' && phone =~ /(91)? *(\d{3}) *(\d{4,})$/
|
144
|
+
phone_country_code, phone_area_code, phone_number = $1, $2, $3
|
145
|
+
else
|
146
|
+
numbers = phone.split(' ')
|
147
|
+
case numbers.size
|
148
|
+
when 3
|
149
|
+
phone_country_code, phone_area_code, phone_number = numbers
|
150
|
+
when 2
|
151
|
+
phone_area_code, phone_number = numbers
|
152
|
+
else
|
153
|
+
phone =~ /(\d{3})(\d+)$/
|
154
|
+
phone_area_code, phone_number = $1, $2
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
add_field("#{address_field}1", phone_country_code || phone_code_for_country(country) || '91')
|
159
|
+
add_field("#{address_field}2", phone_area_code)
|
160
|
+
add_field("#{address_field}3", phone_number)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Special characters are NOT allowed while posting transaction parameters on DirecPay system
|
165
|
+
def remove_special_characters(string)
|
166
|
+
string.gsub(/[~"'&#%]/, '-')
|
167
|
+
end
|
168
|
+
|
169
|
+
def encode_value(value)
|
170
|
+
encoded = ActiveSupport::Base64.encode64s(value)
|
171
|
+
string_to_encode = encoded[0, 1] + "T" + encoded[1, encoded.length]
|
172
|
+
ActiveSupport::Base64.encode64s(string_to_encode)
|
173
|
+
end
|
174
|
+
|
175
|
+
def decode_value(value)
|
176
|
+
decoded = ActiveSupport::Base64.decode64(value)
|
177
|
+
string_to_decode = decoded[0, 1] + decoded[2, decoded.length]
|
178
|
+
ActiveSupport::Base64.decode64(string_to_decode)
|
179
|
+
end
|
180
|
+
|
181
|
+
def phone_code_for_country(country)
|
182
|
+
PHONE_CODES[country]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|