activemerchant 1.8.0 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +9 -0
  3. data/CONTRIBUTORS +21 -1
  4. data/README.rdoc +16 -4
  5. data/lib/active_merchant.rb +2 -0
  6. data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
  7. data/lib/active_merchant/billing/gateways/paybox_direct.rb +205 -0
  8. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  9. data/lib/active_merchant/billing/integrations/bogus.rb +1 -1
  10. data/lib/active_merchant/billing/integrations/chronopay.rb +1 -1
  11. data/lib/active_merchant/billing/integrations/direc_pay.rb +37 -0
  12. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +188 -0
  13. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  14. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  15. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  16. data/lib/active_merchant/billing/integrations/gestpay.rb +1 -1
  17. data/lib/active_merchant/billing/integrations/helper.rb +8 -5
  18. data/lib/active_merchant/billing/integrations/hi_trust.rb +1 -1
  19. data/lib/active_merchant/billing/integrations/nochex.rb +1 -1
  20. data/lib/active_merchant/billing/integrations/paypal.rb +1 -1
  21. data/lib/active_merchant/billing/integrations/return.rb +4 -2
  22. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  23. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  24. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +109 -0
  25. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +204 -0
  26. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +27 -0
  27. data/lib/active_merchant/billing/integrations/two_checkout.rb +1 -1
  28. data/lib/active_merchant/version.rb +1 -1
  29. metadata +17 -4
  30. 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
+
@@ -14,7 +14,7 @@ module ActiveMerchant #:nodoc:
14
14
  Notification.new(post)
15
15
  end
16
16
 
17
- def self.return(query_string)
17
+ def self.return(query_string, options = {})
18
18
  Return.new(query_string)
19
19
  end
20
20
  end
@@ -14,7 +14,7 @@ module ActiveMerchant #:nodoc:
14
14
  Notification.new(post)
15
15
  end
16
16
 
17
- def self.return(query_string)
17
+ def self.return(query_string, options = {})
18
18
  Return.new(query_string)
19
19
  end
20
20
  end
@@ -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