offsite_payments 2.7.19 → 2.7.26
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/offsite_payments.rb +1 -1
- data/lib/offsite_payments/integrations/a1agregator.rb +0 -8
- data/lib/offsite_payments/integrations/bit_pay.rb +11 -6
- data/lib/offsite_payments/integrations/citrus.rb +2 -2
- data/lib/offsite_payments/integrations/direc_pay.rb +1 -1
- data/lib/offsite_payments/integrations/easy_pay.rb +1 -1
- data/lib/offsite_payments/integrations/epay.rb +2 -2
- data/lib/offsite_payments/integrations/gestpay.rb +1 -1
- data/lib/offsite_payments/integrations/liqpay.rb +2 -2
- data/lib/offsite_payments/integrations/mollie_ideal.rb +1 -1
- data/lib/offsite_payments/integrations/mollie_mistercash.rb +1 -1
- data/lib/offsite_payments/integrations/pag_seguro.rb +1 -1
- data/lib/offsite_payments/integrations/paxum.rb +2 -2
- data/lib/offsite_payments/integrations/pay_fast.rb +1 -1
- data/lib/offsite_payments/integrations/payflow_link.rb +0 -4
- data/lib/offsite_payments/integrations/paytm.rb +2 -2
- data/lib/offsite_payments/integrations/payu_in.rb +3 -3
- data/lib/offsite_payments/integrations/platron.rb +1 -1
- data/lib/offsite_payments/integrations/quickpay.rb +1 -1
- data/lib/offsite_payments/integrations/quickpay_v10.rb +173 -0
- data/lib/offsite_payments/integrations/realex_offsite.rb +549 -15
- data/lib/offsite_payments/integrations/sage_pay_form.rb +1 -0
- data/lib/offsite_payments/integrations/universal.rb +0 -1
- data/lib/offsite_payments/integrations/web_pay.rb +1 -1
- data/lib/offsite_payments/integrations/webmoney.rb +1 -1
- data/lib/offsite_payments/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c97ad87cccef24116fe87f91ee89b4b9b407eb45d3e495de18ba2a1b5e33a0c0
|
4
|
+
data.tar.gz: 1dd21e00bcb3a717c04da06c9fa3052010f10e326809fe7582f89f3264476424
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acb62c7c223c6e07c47b8c911745feec5cbf7d31e1ce735519af0623f72cb4c2286ecc56facf46f0af14d4f18614d3715d80c57c4cb0b8b862f245c747df7d22
|
7
|
+
data.tar.gz: dc0c0a7871376e7496c9bcf4aff180c4c305f2ad85e827388b45f0634607310bf1c93c32c0364eb1ddd6b6f3032cbc858499ee50c7d31ce6afae8b6fe9c1d40a
|
data/README.md
CHANGED
@@ -67,6 +67,7 @@ one.
|
|
67
67
|
* [Dwolla](https://www.dwolla.com/default.aspx)
|
68
68
|
* [ePay](http://www.epay.dk/epay-payment-solutions/)
|
69
69
|
* [First Data](https://firstdata.zendesk.com/entries/407522-first-data-global-gateway-e4sm-payment-pages-integration-manual)
|
70
|
+
* [Realex](https://www.globalpaymentsinc.com)
|
70
71
|
* [HiTRUST](http://www.hitrust.com.hk/)
|
71
72
|
* [MOLPay](http://www.molpay.com/v2/) - MY, SG, ID, TH, VN, PH, CN, AU
|
72
73
|
* [Moneybookers](http://www.moneybookers.com)
|
@@ -77,7 +78,7 @@ one.
|
|
77
78
|
* [PayDollar](http://www.paydollar.com)
|
78
79
|
* [Paysbuy](https://www.paysbuy.com/) - TH
|
79
80
|
* [Platron](https://www.platron.ru/) - RU
|
80
|
-
* [
|
81
|
+
* [QuickPay](http://quickpay.net/dk/) - AT, DE, DK, EE, LT, LV, FO, NL, NO, SE, UK
|
81
82
|
* [RBK Money](https://rbkmoney.ru/) - RU
|
82
83
|
* [Robokassa](http://robokassa.ru/) - RU
|
83
84
|
* [SagePay Form](http://www.sagepay.com/products_services/sage_pay_go/integration/form)
|
data/lib/offsite_payments.rb
CHANGED
@@ -40,5 +40,5 @@ module OffsitePayments
|
|
40
40
|
self.mode == :test
|
41
41
|
end
|
42
42
|
|
43
|
-
CURRENCIES_WITHOUT_FRACTIONS = [ 'BIF', 'BYR', 'CLP', 'CVE', 'DJF', 'GNF', '
|
43
|
+
CURRENCIES_WITHOUT_FRACTIONS = [ 'BIF', 'BYR', 'CLP', 'CVE', 'DJF', 'GNF', 'ISK', 'JPY', 'KMF', 'KRW', 'PYG', 'RWF', 'TWD', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF' ]
|
44
44
|
end
|
@@ -93,14 +93,6 @@ module OffsitePayments #:nodoc:
|
|
93
93
|
params['type']
|
94
94
|
end
|
95
95
|
|
96
|
-
def partner_income
|
97
|
-
params['partner_income']
|
98
|
-
end
|
99
|
-
|
100
|
-
def system_income
|
101
|
-
params['system_income']
|
102
|
-
end
|
103
|
-
|
104
96
|
# Additional notification request params:
|
105
97
|
# tid
|
106
98
|
# name
|
@@ -73,9 +73,18 @@ module OffsitePayments #:nodoc:
|
|
73
73
|
|
74
74
|
{ "id" => extract_invoice_id(invoice) }
|
75
75
|
end
|
76
|
-
|
77
76
|
private
|
78
77
|
|
78
|
+
def add_plugin_info(request)
|
79
|
+
#add plugin info for v1 and v2 tokens
|
80
|
+
if BitPay.v2_api_token?(@account)
|
81
|
+
request.add_field("x-bitpay-plugin-info", "BitPay_AM" + application_id + "_Client_v2.0.1909")
|
82
|
+
else
|
83
|
+
request.add_field("x-bitpay-plugin-info", "BitPay_AM" + application_id + "_Client_v1.0.1909")
|
84
|
+
request.basic_auth @account, ''
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
79
88
|
def create_invoice
|
80
89
|
uri = URI.parse(BitPay.invoicing_url(@account))
|
81
90
|
http = Net::HTTP.new(uri.host, uri.port)
|
@@ -84,11 +93,7 @@ module OffsitePayments #:nodoc:
|
|
84
93
|
request = Net::HTTP::Post.new(uri.request_uri)
|
85
94
|
request.content_type = "application/json"
|
86
95
|
request.body = @fields.to_json
|
87
|
-
|
88
|
-
unless BitPay.v2_api_token?(@account)
|
89
|
-
request.add_field("x-bitpay-plugin-info", "BitPay_Shopify_Client_v2.0.1906")
|
90
|
-
request.basic_auth @account, ''
|
91
|
-
end
|
96
|
+
add_plugin_info(request)
|
92
97
|
|
93
98
|
response = http.request(request)
|
94
99
|
JSON.parse(response.body)
|
@@ -119,7 +119,7 @@ module OffsitePayments
|
|
119
119
|
end
|
120
120
|
|
121
121
|
def amount
|
122
|
-
Money.from_amount(BigDecimal
|
122
|
+
Money.from_amount(BigDecimal(gross), currency)
|
123
123
|
end
|
124
124
|
|
125
125
|
def transaction_id
|
@@ -202,7 +202,7 @@ module OffsitePayments
|
|
202
202
|
end
|
203
203
|
|
204
204
|
def status( order_id, order_amount )
|
205
|
-
if @notification.invoice_ok?( order_id ) && @notification.amount_ok?(
|
205
|
+
if @notification.invoice_ok?( order_id ) && @notification.amount_ok?(BigDecimal(order_amount))
|
206
206
|
@notification.status
|
207
207
|
else
|
208
208
|
'Mismatch'
|
@@ -125,7 +125,7 @@ module OffsitePayments #:nodoc:
|
|
125
125
|
return false
|
126
126
|
end
|
127
127
|
|
128
|
-
%w(txnid orderid
|
128
|
+
%w(txnid orderid date time hash fraud payercountry issuercountry txnfee subscriptionid paymenttype cardno).each do |attr|
|
129
129
|
define_method(attr) do
|
130
130
|
params[attr]
|
131
131
|
end
|
@@ -138,7 +138,7 @@ module OffsitePayments #:nodoc:
|
|
138
138
|
def generate_md5string
|
139
139
|
md5string = String.new
|
140
140
|
for line in @raw.split('&')
|
141
|
-
key,
|
141
|
+
key, _ = *line.scan( %r{^([A-Za-z0-9_.]+)\=(.*)$} ).flatten
|
142
142
|
md5string += params[key] if key != 'hash'
|
143
143
|
end
|
144
144
|
return md5string + @options[:credential3]
|
@@ -189,7 +189,7 @@ module OffsitePayments #:nodoc:
|
|
189
189
|
response = ssl_get(Gestpay.service_url, decryption_query_string(shop_login, encrypted_string))
|
190
190
|
encoded_response = parse_response(response)
|
191
191
|
parse_delimited_string(encoded_response, DELIMITER, true)
|
192
|
-
rescue GestpayEncryptionResponseError
|
192
|
+
rescue GestpayEncryptionResponseError
|
193
193
|
{ 'PAY1_TRANSACTIONRESULT' => 'Error' }
|
194
194
|
end
|
195
195
|
|
@@ -80,7 +80,7 @@ module OffsitePayments #:nodoc:
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def amount
|
83
|
-
Money.from_amount(BigDecimal
|
83
|
+
Money.from_amount(BigDecimal(gross), currency)
|
84
84
|
end
|
85
85
|
|
86
86
|
def item_id
|
@@ -156,7 +156,7 @@ module OffsitePayments #:nodoc:
|
|
156
156
|
end
|
157
157
|
|
158
158
|
def amount
|
159
|
-
BigDecimal
|
159
|
+
BigDecimal(gross)
|
160
160
|
end
|
161
161
|
|
162
162
|
def item_id
|
@@ -111,7 +111,7 @@ module OffsitePayments #:nodoc:
|
|
111
111
|
check_for_errors(response, xml)
|
112
112
|
|
113
113
|
extract_token(xml)
|
114
|
-
rescue Timeout::Error, Errno::ECONNRESET, Errno::ETIMEDOUT
|
114
|
+
rescue Timeout::Error, Errno::ECONNRESET, Errno::ETIMEDOUT
|
115
115
|
raise ActionViewHelperError, "Erro ao conectar-se ao PagSeguro. Por favor, tente novamente."
|
116
116
|
end
|
117
117
|
|
@@ -34,9 +34,9 @@ module OffsitePayments #:nodoc:
|
|
34
34
|
|
35
35
|
module Common
|
36
36
|
def generate_signature_string
|
37
|
-
@raw_post.slice!(0) if @raw_post.
|
37
|
+
@raw_post.slice!(0) if @raw_post.start_with?("&")
|
38
38
|
@raw_post = CGI.unescape(@raw_post)
|
39
|
-
@raw_post = "&#{@raw_post}" unless @raw_post.
|
39
|
+
@raw_post = "&#{@raw_post}" unless @raw_post.start_with?("&")
|
40
40
|
arr = @raw_post.split('&')
|
41
41
|
arr.delete(arr.last)
|
42
42
|
data = arr.join('&')
|
@@ -212,7 +212,7 @@ module OffsitePayments #:nodoc:
|
|
212
212
|
|
213
213
|
# The net amount credited to the receiver's account.
|
214
214
|
def amount
|
215
|
-
Money.from_amount(BigDecimal
|
215
|
+
Money.from_amount(BigDecimal(params['amount_net']), currency)
|
216
216
|
end
|
217
217
|
|
218
218
|
# The name of the item being charged for.
|
@@ -136,7 +136,7 @@ module OffsitePayments #:nodoc:
|
|
136
136
|
|
137
137
|
# Order amount should be equal to gross
|
138
138
|
def amount_ok?(order_amount)
|
139
|
-
BigDecimal
|
139
|
+
BigDecimal(original_gross) == order_amount
|
140
140
|
end
|
141
141
|
|
142
142
|
# Status of transaction return from the Paytm. List of possible values:
|
@@ -245,7 +245,7 @@ module OffsitePayments #:nodoc:
|
|
245
245
|
end
|
246
246
|
|
247
247
|
def status(order_id, order_amount)
|
248
|
-
if @notification.invoice_ok?(order_id) && @notification.amount_ok?(BigDecimal
|
248
|
+
if @notification.invoice_ok?(order_id) && @notification.amount_ok?(BigDecimal(order_amount))
|
249
249
|
@notification.status
|
250
250
|
else
|
251
251
|
'Mismatch'
|
@@ -116,9 +116,9 @@ module OffsitePayments #:nodoc:
|
|
116
116
|
end
|
117
117
|
|
118
118
|
# Order amount should be equal to gross - discount
|
119
|
-
def amount_ok?( order_amount, order_discount = BigDecimal
|
119
|
+
def amount_ok?( order_amount, order_discount = BigDecimal( '0.0' ) )
|
120
120
|
parsed_discount = discount.nil? ? 0.to_d : discount.to_d
|
121
|
-
BigDecimal
|
121
|
+
BigDecimal( original_gross ) == order_amount && parsed_discount == order_discount
|
122
122
|
end
|
123
123
|
|
124
124
|
# Status of transaction return from the PayU. List of possible values:
|
@@ -258,7 +258,7 @@ module OffsitePayments #:nodoc:
|
|
258
258
|
end
|
259
259
|
|
260
260
|
def status( order_id, order_amount )
|
261
|
-
if @notification.invoice_ok?( order_id ) && @notification.amount_ok?( BigDecimal
|
261
|
+
if @notification.invoice_ok?( order_id ) && @notification.amount_ok?( BigDecimal(order_amount) )
|
262
262
|
@notification.status
|
263
263
|
else
|
264
264
|
'Mismatch'
|
@@ -2,7 +2,7 @@ module OffsitePayments #:nodoc:
|
|
2
2
|
module Integrations #:nodoc:
|
3
3
|
module Quickpay
|
4
4
|
mattr_accessor :service_url
|
5
|
-
self.service_url = 'https://
|
5
|
+
self.service_url = 'https://legacy-proxy.quickpay.net/form/'
|
6
6
|
|
7
7
|
def self.notification(post, options = {})
|
8
8
|
Notification.new(post, options)
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
module OffsitePayments #:nodoc:
|
4
|
+
module Integrations #:nodoc:
|
5
|
+
module QuickpayV10
|
6
|
+
mattr_accessor :service_url
|
7
|
+
self.service_url = 'https://payment.quickpay.net'
|
8
|
+
|
9
|
+
def self.notification(post, options = {})
|
10
|
+
Notification.new(post)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.return(post, options = {})
|
14
|
+
Return.new(post, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
# credential2: Payment window API key
|
18
|
+
class Helper < OffsitePayments::Helper
|
19
|
+
def initialize(order, account, options = {})
|
20
|
+
payment_window_api_key options.delete(:credential2)
|
21
|
+
super
|
22
|
+
add_field('version', 'v10')
|
23
|
+
add_field('type', 'payment')
|
24
|
+
add_field('language', 'da')
|
25
|
+
add_field('autocapture', 0)
|
26
|
+
add_field('order_id', format_order_number(order))
|
27
|
+
end
|
28
|
+
|
29
|
+
def payment_window_api_key(value)
|
30
|
+
@payment_window_api_key = value
|
31
|
+
end
|
32
|
+
|
33
|
+
def form_fields
|
34
|
+
@fields.merge('checksum' => generate_checksum)
|
35
|
+
end
|
36
|
+
|
37
|
+
def flatten_params(obj, result = {}, path = [])
|
38
|
+
case obj
|
39
|
+
when Hash
|
40
|
+
obj.each do |k, v|
|
41
|
+
flatten_params(v, result, [*path, k])
|
42
|
+
end
|
43
|
+
when Array
|
44
|
+
obj.each_with_index do |v, i|
|
45
|
+
flatten_params(v, result, [*path, i])
|
46
|
+
end
|
47
|
+
else
|
48
|
+
result[path.map{|p| "[#{p}]"}.join.to_sym] = obj
|
49
|
+
end
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
def generate_checksum
|
54
|
+
flattened_params = flatten_params(@fields)
|
55
|
+
values = flattened_params.sort.map { |_, value| value }
|
56
|
+
base = values.join(' ')
|
57
|
+
OpenSSL::HMAC.hexdigest('sha256', @payment_window_api_key, base)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Limited to 20 digits max
|
61
|
+
def format_order_number(number)
|
62
|
+
number.to_s.gsub(/[^\w]/, '').rjust(4, "0")[0...20]
|
63
|
+
end
|
64
|
+
|
65
|
+
mapping :version, 'version'
|
66
|
+
mapping :type, 'type'
|
67
|
+
mapping :account, 'merchant_id'
|
68
|
+
mapping :language, 'language'
|
69
|
+
mapping :amount, 'amount'
|
70
|
+
mapping :currency, 'currency'
|
71
|
+
|
72
|
+
mapping :return_url, 'continueurl'
|
73
|
+
mapping :cancel_return_url, 'cancelurl'
|
74
|
+
mapping :notify_url, 'callbackurl'
|
75
|
+
|
76
|
+
mapping :autocapture, 'autocapture'
|
77
|
+
mapping :autofee, 'autofee'
|
78
|
+
|
79
|
+
mapping :description, 'description'
|
80
|
+
mapping :payment_methods, 'payment_methods'
|
81
|
+
mapping :acquirer, 'acquirer'
|
82
|
+
mapping :branding_id, 'branding_id'
|
83
|
+
mapping :google_analytics_tracking_id, 'google_analytics_tracking_id'
|
84
|
+
mapping :google_analytics_client_id, 'google_analytics_client_id'
|
85
|
+
mapping :variables, 'variables'
|
86
|
+
mapping :text_on_statement, 'text_on_statement'
|
87
|
+
mapping :customer_email, 'customer_email'
|
88
|
+
|
89
|
+
mapping :splitpayment, 'splitpayment'
|
90
|
+
mapping :forcemobile, 'forcemobile'
|
91
|
+
mapping :deadline, 'deadline'
|
92
|
+
mapping :cardhash, 'cardhash'
|
93
|
+
|
94
|
+
mapping :invoice_address, {}
|
95
|
+
mapping :billing_address, {}
|
96
|
+
end
|
97
|
+
|
98
|
+
# credential3: private key
|
99
|
+
# checksum_header: QuickPay-Checksum-Sha256 request header value
|
100
|
+
class Notification < OffsitePayments::Notification
|
101
|
+
# http://tech.quickpay.net/appendixes/errors/
|
102
|
+
def complete?
|
103
|
+
status == '20000'
|
104
|
+
end
|
105
|
+
|
106
|
+
def item_id
|
107
|
+
params['order_id']
|
108
|
+
end
|
109
|
+
|
110
|
+
def transaction_id
|
111
|
+
params['id']
|
112
|
+
end
|
113
|
+
|
114
|
+
def received_at
|
115
|
+
Time.iso8601(params['created_at'])
|
116
|
+
end
|
117
|
+
|
118
|
+
def gross
|
119
|
+
"%.2f" % (gross_cents / 100.0)
|
120
|
+
end
|
121
|
+
|
122
|
+
def gross_cents
|
123
|
+
last_operation['amount']
|
124
|
+
end
|
125
|
+
|
126
|
+
def last_operation
|
127
|
+
params['operations'].last
|
128
|
+
end
|
129
|
+
|
130
|
+
def status
|
131
|
+
last_operation['qp_status_code'] if last_operation
|
132
|
+
end
|
133
|
+
|
134
|
+
# Provide access to raw fields from quickpay
|
135
|
+
%w(
|
136
|
+
accepted
|
137
|
+
test_mode
|
138
|
+
branding_id
|
139
|
+
variables
|
140
|
+
acquirer
|
141
|
+
operations
|
142
|
+
metadata
|
143
|
+
balance
|
144
|
+
currency
|
145
|
+
).each do |attr|
|
146
|
+
define_method(attr) do
|
147
|
+
params[attr]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def generate_checksum
|
152
|
+
OpenSSL::HMAC.hexdigest('sha256', @options[:credential3], @raw)
|
153
|
+
end
|
154
|
+
|
155
|
+
def checksum_header
|
156
|
+
@options[:checksum_header]
|
157
|
+
end
|
158
|
+
|
159
|
+
# Quickpay doesn't do acknowledgements of callback notifications
|
160
|
+
# Instead it provides a SHA256 checksum header
|
161
|
+
def acknowledge(authcode = nil)
|
162
|
+
generate_checksum == checksum_header
|
163
|
+
end
|
164
|
+
|
165
|
+
# Take the posted data and move the relevant data into a hash
|
166
|
+
def parse(post)
|
167
|
+
@raw = post.to_s
|
168
|
+
@params = JSON.parse(post)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -63,6 +63,335 @@ module OffsitePayments #:nodoc:
|
|
63
63
|
'COU' => 4
|
64
64
|
}
|
65
65
|
|
66
|
+
CANADIAN_STATES = {
|
67
|
+
'AB' => 'Alberta',
|
68
|
+
'BC' => 'British Columbia',
|
69
|
+
'MB' => 'Manitoba',
|
70
|
+
'NB' => 'New Brunswick',
|
71
|
+
'NL' => 'Newfoundland',
|
72
|
+
'NS' => 'Nova Scotia',
|
73
|
+
'NU' => 'Nunavut',
|
74
|
+
'NT' => 'Northwest Territories',
|
75
|
+
'ON' => 'Ontario',
|
76
|
+
'PE' => 'Prince Edward Island',
|
77
|
+
'QC' => 'Quebec',
|
78
|
+
'SK' => 'Saskatchewan',
|
79
|
+
'YT' => 'Yukon'
|
80
|
+
}
|
81
|
+
|
82
|
+
US_STATES = {
|
83
|
+
'AL' => 'Alabama',
|
84
|
+
'AK' => 'Alaska',
|
85
|
+
'AS' => 'American Samoa',
|
86
|
+
'AZ' => 'Arizona',
|
87
|
+
'AR' => 'Arkansas',
|
88
|
+
'CA' => 'California',
|
89
|
+
'CO' => 'Colorado',
|
90
|
+
'CT' => 'Connecticut',
|
91
|
+
'DE' => 'Delaware',
|
92
|
+
'DC' => 'District Of Columbia',
|
93
|
+
'FM' => 'Federated States Of Micronesia',
|
94
|
+
'FL' => 'Florida',
|
95
|
+
'GA' => 'Georgia',
|
96
|
+
'GU' => 'Guam',
|
97
|
+
'HI' => 'Hawaii',
|
98
|
+
'ID' => 'Idaho',
|
99
|
+
'IL' => 'Illinois',
|
100
|
+
'IN' => 'Indiana',
|
101
|
+
'IA' => 'Iowa',
|
102
|
+
'KS' => 'Kansas',
|
103
|
+
'KY' => 'Kentucky',
|
104
|
+
'LA' => 'Louisiana',
|
105
|
+
'ME' => 'Maine',
|
106
|
+
'MH' => 'Marshall Islands',
|
107
|
+
'MD' => 'Maryland',
|
108
|
+
'MA' => 'Massachusetts',
|
109
|
+
'MI' => 'Michigan',
|
110
|
+
'MN' => 'Minnesota',
|
111
|
+
'MS' => 'Mississippi',
|
112
|
+
'MO' => 'Missouri',
|
113
|
+
'MT' => 'Montana',
|
114
|
+
'NE' => 'Nebraska',
|
115
|
+
'NV' => 'Nevada',
|
116
|
+
'NH' => 'New Hampshire',
|
117
|
+
'NJ' => 'New Jersey',
|
118
|
+
'NM' => 'New Mexico',
|
119
|
+
'NY' => 'New York',
|
120
|
+
'NC' => 'North Carolina',
|
121
|
+
'ND' => 'North Dakota',
|
122
|
+
'MP' => 'Northern Mariana Islands',
|
123
|
+
'OH' => 'Ohio',
|
124
|
+
'OK' => 'Oklahoma',
|
125
|
+
'OR' => 'Oregon',
|
126
|
+
'PW' => 'Palau',
|
127
|
+
'PA' => 'Pennsylvania',
|
128
|
+
'PR' => 'Puerto Rico',
|
129
|
+
'RI' => 'Rhode Island',
|
130
|
+
'SC' => 'South Carolina',
|
131
|
+
'SD' => 'South Dakota',
|
132
|
+
'TN' => 'Tennessee',
|
133
|
+
'TX' => 'Texas',
|
134
|
+
'UT' => 'Utah',
|
135
|
+
'VT' => 'Vermont',
|
136
|
+
'VI' => 'Virgin Islands',
|
137
|
+
'VA' => 'Virginia',
|
138
|
+
'WA' => 'Washington',
|
139
|
+
'WV' => 'West Virginia',
|
140
|
+
'WI' => 'Wisconsin',
|
141
|
+
'WY' => 'Wyoming'
|
142
|
+
}
|
143
|
+
|
144
|
+
COUNTRY_PHONE_NUMBERS = {
|
145
|
+
'AD' => { :code => '376', :length => [6, 7, 8, 9] },
|
146
|
+
'AE' => { :code => '971', :length => [7, 8, 9] },
|
147
|
+
'AF' => { :code => '93', :length => [8, 9] },
|
148
|
+
'AG' => { :code => '1', :length => [10] },
|
149
|
+
'AI' => { :code => '1', :length => [10] },
|
150
|
+
'AL' => { :code => '355', :length => [7, 8, 9] },
|
151
|
+
'AM' => { :code => '374', :length => [8] },
|
152
|
+
'AO' => { :code => '244', :length => [9] },
|
153
|
+
'AQ' => { :code => '672', :length => [] },
|
154
|
+
'AR' => { :code => '54', :length => [8, 9] },
|
155
|
+
'AS' => { :code => '1', :length => [10] },
|
156
|
+
'AT' => { :code => '43', :length => [7, 8, 9, 10, 11, 12, 13] },
|
157
|
+
'AU' => { :code => '61', :length => [9] },
|
158
|
+
'AW' => { :code => '297', :length => [7] },
|
159
|
+
'AX' => { :code => '358', :length => [] },
|
160
|
+
'AZ' => { :code => '994', :length => [8, 9] },
|
161
|
+
'BA' => { :code => '387', :length => [8] },
|
162
|
+
'BB' => { :code => '1', :length => [10] },
|
163
|
+
'BD' => { :code => '880', :length => [10] },
|
164
|
+
'BE' => { :code => '32', :length => [8, 9] },
|
165
|
+
'BF' => { :code => '226', :length => [8] },
|
166
|
+
'BG' => { :code => '359', :length => [8, 9, 10] },
|
167
|
+
'BH' => { :code => '973', :length => [8] },
|
168
|
+
'BI' => { :code => '257', :length => [8] },
|
169
|
+
'BJ' => { :code => '229', :length => [8] },
|
170
|
+
'BL' => { :code => '590', :length => [] },
|
171
|
+
'BM' => { :code => '1', :length => [10] },
|
172
|
+
'BN' => { :code => '673', :length => [7] },
|
173
|
+
'BO' => { :code => '591', :length => [8] },
|
174
|
+
'BQ' => { :code => '599', :length => [7] },
|
175
|
+
'BR' => { :code => '55', :length => [10, 11] },
|
176
|
+
'BS' => { :code => '1', :length => [10] },
|
177
|
+
'BT' => { :code => '975', :length => [7, 8] },
|
178
|
+
'BV' => { :code => '47', :length => [] },
|
179
|
+
'BW' => { :code => '267', :length => [7] },
|
180
|
+
'BY' => { :code => '375', :length => [9] },
|
181
|
+
'BZ' => { :code => '501', :length => [7] },
|
182
|
+
'CA' => { :code => '1', :length => [10] },
|
183
|
+
'CC' => { :code => '61', :length => [9] },
|
184
|
+
'CD' => { :code => '243', :length => [8] },
|
185
|
+
'CF' => { :code => '236', :length => [8] },
|
186
|
+
'CG' => { :code => '242', :length => [7] },
|
187
|
+
'CH' => { :code => '41', :length => [9, 10] },
|
188
|
+
'CI' => { :code => '225', :length => [8] },
|
189
|
+
'CK' => { :code => '682', :length => [5] },
|
190
|
+
'CL' => { :code => '56', :length => [8, 9] },
|
191
|
+
'CM' => { :code => '237', :length => [8] },
|
192
|
+
'CN' => { :code => '86', :length => [7, 8, 9, 10, 11] },
|
193
|
+
'CO' => { :code => '57', :length => [9, 10] },
|
194
|
+
'CR' => { :code => '506', :length => [8] },
|
195
|
+
'CU' => { :code => '53', :length => [8] },
|
196
|
+
'CV' => { :code => '238', :length => [7] },
|
197
|
+
'CW' => { :code => '599', :length => [7] },
|
198
|
+
'CX' => { :code => '61', :length => [] },
|
199
|
+
'CY' => { :code => '357', :length => [8] },
|
200
|
+
'CZ' => { :code => '420', :length => [9] },
|
201
|
+
'DE' => { :code => '49', :length => [6, 7, 8, 9, 10, 11] },
|
202
|
+
'DJ' => { :code => '253', :length => [6] },
|
203
|
+
'DK' => { :code => '45', :length => [8] },
|
204
|
+
'DM' => { :code => '1', :length => [10] },
|
205
|
+
'DO' => { :code => '1', :length => [10] },
|
206
|
+
'DZ' => { :code => '213', :length => [8] },
|
207
|
+
'EC' => { :code => '593', :length => [8, 9] },
|
208
|
+
'EE' => { :code => '372', :length => [7, 8] },
|
209
|
+
'EG' => { :code => '20', :length => [9] },
|
210
|
+
'EH' => { :code => '212', :length => [] },
|
211
|
+
'ER' => { :code => '291', :length => [7] },
|
212
|
+
'ES' => { :code => '34', :length => [9] },
|
213
|
+
'ET' => { :code => '251', :length => [9] },
|
214
|
+
'FI' => { :code => '358', :length => [9] },
|
215
|
+
'FJ' => { :code => '679', :length => [7] },
|
216
|
+
'FK' => { :code => '500', :length => [5] },
|
217
|
+
'FM' => { :code => '691', :length => [7] },
|
218
|
+
'FO' => { :code => '298', :length => [6] },
|
219
|
+
'FR' => { :code => '33', :length => [9, 10] },
|
220
|
+
'GA' => { :code => '241', :length => [6, 7, 8] },
|
221
|
+
'GB' => { :code => '44', :length => [10, 11] },
|
222
|
+
'GD' => { :code => '1', :length => [10] },
|
223
|
+
'GE' => { :code => '995', :length => [9] },
|
224
|
+
'GF' => { :code => '594', :length => [10] },
|
225
|
+
'GG' => { :code => '44', :length => [] },
|
226
|
+
'GH' => { :code => '233', :length => [5, 6, 7, 8] },
|
227
|
+
'GI' => { :code => '350', :length => [8] },
|
228
|
+
'GL' => { :code => '299', :length => [6] },
|
229
|
+
'GM' => { :code => '220', :length => [7] },
|
230
|
+
'GN' => { :code => '224', :length => [8] },
|
231
|
+
'GP' => { :code => '590', :length => [10] },
|
232
|
+
'GQ' => { :code => '240', :length => [6] },
|
233
|
+
'GR' => { :code => '30', :length => [10] },
|
234
|
+
'GS' => { :code => '500', :length => [] },
|
235
|
+
'GT' => { :code => '502', :length => [8] },
|
236
|
+
'GU' => { :code => '1', :length => [10] },
|
237
|
+
'GW' => { :code => '245', :length => [7] },
|
238
|
+
'GY' => { :code => '592', :length => [6, 7] },
|
239
|
+
'HK' => { :code => '852', :length => [8] },
|
240
|
+
'HN' => { :code => '504', :length => [7, 8] },
|
241
|
+
'HR' => { :code => '385', :length => [8] },
|
242
|
+
'HT' => { :code => '509', :length => [8] },
|
243
|
+
'HU' => { :code => '36', :length => [8, 9] },
|
244
|
+
'ID' => { :code => '62', :length => [8, 9, 10, 11] },
|
245
|
+
'IE' => { :code => '353', :length => [9] },
|
246
|
+
'IL' => { :code => '972', :length => [7, 8, 9] },
|
247
|
+
'IM' => { :code => '44', :length => [] },
|
248
|
+
'IN' => { :code => '91', :length => [10] },
|
249
|
+
'IO' => { :code => '246', :length => [] },
|
250
|
+
'IQ' => { :code => '964', :length => [8, 9, 10] },
|
251
|
+
'IR' => { :code => '98', :length => [10] },
|
252
|
+
'IS' => { :code => '354', :length => [7, 8, 9] },
|
253
|
+
'IT' => { :code => '39', :length => [9, 11] },
|
254
|
+
'JE' => { :code => '44', :length => [] },
|
255
|
+
'JM' => { :code => '1', :length => [10] },
|
256
|
+
'JO' => { :code => '962', :length => [8, 9] },
|
257
|
+
'JP' => { :code => '81', :length => [9, 10] },
|
258
|
+
'KE' => { :code => '254', :length => [9] },
|
259
|
+
'KG' => { :code => '996', :length => [9] },
|
260
|
+
'KH' => { :code => '855', :length => [8] },
|
261
|
+
'KI' => { :code => '686', :length => [5] },
|
262
|
+
'KM' => { :code => '269', :length => [7] },
|
263
|
+
'KN' => { :code => '1', :length => [10] },
|
264
|
+
'KP' => { :code => '850', :length => [8, 9] },
|
265
|
+
'KR' => { :code => '82', :length => [8, 9] },
|
266
|
+
'KW' => { :code => '965', :length => [7] },
|
267
|
+
'KY' => { :code => '1', :length => [10] },
|
268
|
+
'KZ' => { :code => '7', :length => [10] },
|
269
|
+
'LA' => { :code => '856', :length => [8] },
|
270
|
+
'LB' => { :code => '961', :length => [8] },
|
271
|
+
'LC' => { :code => '1', :length => [10] },
|
272
|
+
'LI' => { :code => '423', :length => [7] },
|
273
|
+
'LK' => { :code => '94', :length => [10] },
|
274
|
+
'LR' => { :code => '231', :length => [6, 7, 8] },
|
275
|
+
'LS' => { :code => '266', :length => [8] },
|
276
|
+
'LT' => { :code => '370', :length => [8] },
|
277
|
+
'LU' => { :code => '352', :length => [9] },
|
278
|
+
'LV' => { :code => '371', :length => [8] },
|
279
|
+
'LY' => { :code => '218', :length => [8, 9] },
|
280
|
+
'MA' => { :code => '212', :length => [8] },
|
281
|
+
'MC' => { :code => '377', :length => [8, 9] },
|
282
|
+
'MD' => { :code => '373', :length => [8] },
|
283
|
+
'ME' => { :code => '382', :length => [8] },
|
284
|
+
'MF' => { :code => '590', :length => [] },
|
285
|
+
'MG' => { :code => '261', :length => [9] },
|
286
|
+
'MH' => { :code => '692', :length => [7] },
|
287
|
+
'MK' => { :code => '389', :length => [7, 8] },
|
288
|
+
'ML' => { :code => '223', :length => [8] },
|
289
|
+
'MM' => { :code => '95', :length => [7, 8] },
|
290
|
+
'MN' => { :code => '976', :length => [7, 8, 9, 10] },
|
291
|
+
'MO' => { :code => '853', :length => [8] },
|
292
|
+
'MP' => { :code => '1', :length => [10] },
|
293
|
+
'MQ' => { :code => '596', :length => [10] },
|
294
|
+
'MR' => { :code => '222', :length => [7] },
|
295
|
+
'MS' => { :code => '1', :length => [10] },
|
296
|
+
'MT' => { :code => '356', :length => [8] },
|
297
|
+
'MU' => { :code => '230', :length => [7] },
|
298
|
+
'MV' => { :code => '960', :length => [7] },
|
299
|
+
'MW' => { :code => '265', :length => [8] },
|
300
|
+
'MX' => { :code => '52', :length => [8, 9, 10] },
|
301
|
+
'MY' => { :code => '60', :length => [9, 10] },
|
302
|
+
'MZ' => { :code => '258', :length => [8, 9] },
|
303
|
+
'NA' => { :code => '264', :length => [6, 7] },
|
304
|
+
'NC' => { :code => '687', :length => [6] },
|
305
|
+
'NE' => { :code => '227', :length => [8] },
|
306
|
+
'NF' => { :code => '672', :length => [6] },
|
307
|
+
'NG' => { :code => '234', :length => [7, 8] },
|
308
|
+
'NI' => { :code => '505', :length => [8] },
|
309
|
+
'NL' => { :code => '31', :length => [9] },
|
310
|
+
'NO' => { :code => '47', :length => [8] },
|
311
|
+
'NP' => { :code => '977', :length => [7, 8] },
|
312
|
+
'NR' => { :code => '674', :length => [7] },
|
313
|
+
'NU' => { :code => '683', :length => [4] },
|
314
|
+
'NZ' => { :code => '64', :length => [8, 9] },
|
315
|
+
'OM' => { :code => '968', :length => [8] },
|
316
|
+
'PA' => { :code => '507', :length => [7] },
|
317
|
+
'PE' => { :code => '51', :length => [8, 9] },
|
318
|
+
'PF' => { :code => '689', :length => [6] },
|
319
|
+
'PG' => { :code => '675', :length => [7] },
|
320
|
+
'PH' => { :code => '63', :length => [8, 9, 10] },
|
321
|
+
'PK' => { :code => '92', :length => [9, 10] },
|
322
|
+
'PL' => { :code => '48', :length => [9] },
|
323
|
+
'PM' => { :code => '508', :length => [6] },
|
324
|
+
'PN' => { :code => '64', :length => [9] },
|
325
|
+
'PR' => { :code => '1', :length => [10] },
|
326
|
+
'PS' => { :code => '970', :length => [8] },
|
327
|
+
'PT' => { :code => '351', :length => [9] },
|
328
|
+
'PW' => { :code => '680', :length => [7] },
|
329
|
+
'PY' => { :code => '595', :length => [9] },
|
330
|
+
'QA' => { :code => '974', :length => [7] },
|
331
|
+
'RE' => { :code => '262', :length => [10] },
|
332
|
+
'RO' => { :code => '40', :length => [9] },
|
333
|
+
'RS' => { :code => '381', :length => [9] },
|
334
|
+
'RU' => { :code => '7', :length => [10] },
|
335
|
+
'RW' => { :code => '250', :length => [8, 9] },
|
336
|
+
'SA' => { :code => '966', :length => [8, 9] },
|
337
|
+
'SB' => { :code => '677', :length => [5] },
|
338
|
+
'SC' => { :code => '248', :length => [6] },
|
339
|
+
'SD' => { :code => '249', :length => [9] },
|
340
|
+
'SE' => { :code => '46', :length => [9] },
|
341
|
+
'SG' => { :code => '65', :length => [8, 9] },
|
342
|
+
'SH' => { :code => '290', :length => [4] },
|
343
|
+
'SI' => { :code => '386', :length => [8] },
|
344
|
+
'SJ' => { :code => '47', :length => [8] },
|
345
|
+
'SK' => { :code => '421', :length => [9] },
|
346
|
+
'SL' => { :code => '232', :length => [8] },
|
347
|
+
'SM' => { :code => '378', :length => [9, 10, 11, 12] },
|
348
|
+
'SN' => { :code => '221', :length => [7] },
|
349
|
+
'SO' => { :code => '252', :length => [7, 8] },
|
350
|
+
'SR' => { :code => '597', :length => [6] },
|
351
|
+
'SS' => { :code => '211', :length => [9] },
|
352
|
+
'ST' => { :code => '239', :length => [6, 7] },
|
353
|
+
'SV' => { :code => '503', :length => [8] },
|
354
|
+
'SX' => { :code => '1', :length => [10] },
|
355
|
+
'SY' => { :code => '963', :length => [7, 8] },
|
356
|
+
'SZ' => { :code => '268', :length => [7] },
|
357
|
+
'TC' => { :code => '1', :length => [10] },
|
358
|
+
'TD' => { :code => '235', :length => [7] },
|
359
|
+
'TF' => { :code => '262', :length => [] },
|
360
|
+
'TG' => { :code => '228', :length => [7] },
|
361
|
+
'TH' => { :code => '66', :length => [9, 10] },
|
362
|
+
'TJ' => { :code => '992', :length => [9] },
|
363
|
+
'TK' => { :code => '690', :length => [4] },
|
364
|
+
'TL' => { :code => '670', :length => [7] },
|
365
|
+
'TM' => { :code => '993', :length => [8] },
|
366
|
+
'TN' => { :code => '216', :length => [8] },
|
367
|
+
'TO' => { :code => '676', :length => [5, 6, 7] },
|
368
|
+
'TR' => { :code => '90', :length => [10] },
|
369
|
+
'TT' => { :code => '1', :length => [10] },
|
370
|
+
'TV' => { :code => '688', :length => [5] },
|
371
|
+
'TW' => { :code => '886', :length => [7, 8] },
|
372
|
+
'TZ' => { :code => '255', :length => [9] },
|
373
|
+
'UA' => { :code => '380', :length => [8, 9] },
|
374
|
+
'UG' => { :code => '256', :length => [9] },
|
375
|
+
'UM' => { :code => '1', :length => [] },
|
376
|
+
'US' => { :code => '1', :length => [10] },
|
377
|
+
'UY' => { :code => '598', :length => [7, 8] },
|
378
|
+
'UZ' => { :code => '998', :length => [9] },
|
379
|
+
'VA' => { :code => '39', :length => [9] },
|
380
|
+
'VC' => { :code => '1', :length => [10] },
|
381
|
+
'VE' => { :code => '58', :length => [10] },
|
382
|
+
'VG' => { :code => '1', :length => [10] },
|
383
|
+
'VI' => { :code => '1', :length => [10] },
|
384
|
+
'VN' => { :code => '84', :length => [7, 8, 9, 10] },
|
385
|
+
'VU' => { :code => '678', :length => [5, 6, 7] },
|
386
|
+
'WF' => { :code => '681', :length => [6] },
|
387
|
+
'WS' => { :code => '685', :length => [6, 7] },
|
388
|
+
'YE' => { :code => '967', :length => [7, 8, 9] },
|
389
|
+
'YT' => { :code => '262', :length => [7] },
|
390
|
+
'ZA' => { :code => '27', :length => [9] },
|
391
|
+
'ZM' => { :code => '260', :length => [9] },
|
392
|
+
'ZW' => { :code => '263', :length => [8, 9, 10, 11] }
|
393
|
+
}
|
394
|
+
|
66
395
|
def create_signature(fields, secret)
|
67
396
|
data = fields.join('.')
|
68
397
|
digest = Digest::SHA1.hexdigest(data)
|
@@ -92,15 +421,135 @@ module OffsitePayments #:nodoc:
|
|
92
421
|
value.scan(/\d+/).join('')
|
93
422
|
end
|
94
423
|
|
424
|
+
# This method is used for generating the "BILLING_CODE" field,
|
425
|
+
# this field is generated by concatenating the zip field and
|
426
|
+
# the first line of address with a pipe(|) between them
|
427
|
+
# if the country is GB, we remove the non-numeric characters
|
95
428
|
def extract_avs_code(params={})
|
96
|
-
|
429
|
+
return unless params[:zip] && params[:address1]
|
430
|
+
code = [params[:zip], params[:address1]]
|
431
|
+
code = code.collect{|p| extract_digits(p) } if params[:country] == 'GB'
|
432
|
+
code.reject{|p| p.empty? }.join('|')
|
433
|
+
end
|
434
|
+
|
435
|
+
def extract_address_match_indicator(value)
|
436
|
+
value ? 'TRUE' : 'FALSE'
|
437
|
+
end
|
438
|
+
|
439
|
+
def adjust_phone_number_length(country_calling_code, phone_number)
|
440
|
+
country_calling_code[0...3] + '|' + phone_number[0...15]
|
441
|
+
end
|
442
|
+
|
443
|
+
# The home phone number provided by the Cardholder. Should be In format:
|
444
|
+
# of 'CountryCallingCode|Number' for example, '1|123456789'.
|
445
|
+
def format_phone_number(phone_number, country_code)
|
446
|
+
return nil if phone_number.nil?
|
447
|
+
|
448
|
+
country_number = COUNTRY_PHONE_NUMBERS[country_code] || { :code => '0', :length => [] }
|
449
|
+
|
450
|
+
# Remove non-digit characters
|
451
|
+
processed_number = phone_number.gsub(/\D/, '')
|
452
|
+
return '0|0' if [[], ['0']].include? processed_number.chars.uniq
|
453
|
+
|
454
|
+
# Allow Italy and Ivory Coast to have leading zero, as they use it as a part of some phone numbers
|
455
|
+
if ['IT', 'CI'].include?(country_code) && /\A0[1-9]\d*/.match(processed_number)
|
456
|
+
return adjust_phone_number_length(country_number[:code], processed_number)
|
457
|
+
end
|
458
|
+
|
459
|
+
return '0|0' if processed_number == country_number[:code]
|
460
|
+
|
461
|
+
# Remove leading zero(s)
|
462
|
+
processed_number = processed_number.gsub(/\A0*/, '')
|
463
|
+
|
464
|
+
# Check if the potential Singapore calling code is not the local prefix
|
465
|
+
if country_code == 'SG' &&
|
466
|
+
processed_number.start_with?(country_number[:code]) &&
|
467
|
+
country_number[:length].include?(processed_number.length)
|
468
|
+
then
|
469
|
+
return adjust_phone_number_length(country_number[:code], processed_number)
|
470
|
+
end
|
471
|
+
|
472
|
+
# Remove country calling code from the processed number and try to fix trivial mistakes
|
473
|
+
if processed_number.start_with?(country_number[:code]) ||
|
474
|
+
(!(country_number[:length].include?(processed_number.length)) &&
|
475
|
+
country_number[:length].include?(processed_number.length - country_number[:code].length) &&
|
476
|
+
(country_number[:code].chars.sort == processed_number[0...country_number[:code].length].chars.sort))
|
477
|
+
then
|
478
|
+
processed_number = processed_number[country_number[:code].length..-1]
|
479
|
+
end
|
480
|
+
|
481
|
+
# Limit returned string to 3 characters + | + 15 characters
|
482
|
+
adjust_phone_number_length(country_number[:code], processed_number)
|
483
|
+
end
|
484
|
+
|
485
|
+
def lookup_state_code(country_code, state)
|
486
|
+
case country_code
|
487
|
+
when 'CA'
|
488
|
+
state_code = CANADIAN_STATES.find { |code, state_name| state_name.downcase == state.downcase}
|
489
|
+
state_code ? state_code.first : state
|
490
|
+
when 'US'
|
491
|
+
state_code = US_STATES.find { |code, state_name| state_name.downcase == state.downcase}
|
492
|
+
state_code ? state_code.first : state
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
# if HPP_ADDRESS_MATCH_INDICATOR is set to TRUE
|
497
|
+
# HPP requires the shipping address to be sent from the billing address
|
498
|
+
def copy_billing_address
|
499
|
+
@fields.select { |k, _| k.start_with? 'HPP_BILLING_' }
|
500
|
+
.each do |k, v|
|
501
|
+
add_field("HPP_SHIPPING_#{k.split('HPP_BILLING_')[1]}", v)
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
# Validations
|
506
|
+
def get_pattern(key)
|
507
|
+
case key
|
508
|
+
when 'HPP_CUSTOMER_EMAIL' then /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,24})*$/
|
509
|
+
when 'HPP_CUSTOMER_PHONENUMBER_MOBILE' then /^([0-9 +]){1,3}(\|){0,1}([0-9 +]){1,15}$/
|
510
|
+
when 'HPP_BILLING_STREET1', 'HPP_SHIPPING_STREET1', 'HPP_BILLING_STREET2', 'HPP_SHIPPING_STREET2' then /^[\p{L}\p{M}\p{Blank}\p{N}\/\.\-\_\'\,]{1,50}$/
|
511
|
+
when 'HPP_BILLING_CITY', 'HPP_SHIPPING_CITY' then /^[\p{L}\p{M}\p{Blank}\p{N}\/\.\-\_\'\,]{1,40}$/
|
512
|
+
when 'HPP_BILLING_COUNTRY', 'HPP_SHIPPING_COUNTRY' then /^([0-9])*$/
|
513
|
+
when 'HPP_BILLING_POSTALCODE', 'HPP_SHIPPING_POSTALCODE' then /^[a-zA-Z0-9\-\s]{1,16}$/
|
514
|
+
when 'HPP_BILLING_STATE', 'HPP_SHIPPING_STATE' then /^([A-Z])*$/
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
def get_message(key)
|
519
|
+
case key
|
520
|
+
when 'HPP_CUSTOMER_EMAIL' then 'Invalid E-mail address.'
|
521
|
+
when 'HPP_CUSTOMER_PHONENUMBER_MOBILE' then 'Invalid Telephone. The selected payment method only allows numbers, spaces or punctuation (+, |), and no more than 19 characters.'
|
522
|
+
when 'HPP_BILLING_STREET1', 'HPP_SHIPPING_STREET1', 'HPP_BILLING_STREET2', 'HPP_SHIPPING_STREET2' then 'Invalid Street address. The selected payment method only allows letters, numbers, spaces or punctuation, and no more than 50 characters per line.'
|
523
|
+
when 'HPP_BILLING_CITY', 'HPP_SHIPPING_CITY' then 'Invalid City. The selected payment method only allows letters, numbers, spaces or punctuation, and no more than 40 characters.'
|
524
|
+
when 'HPP_BILLING_COUNTRY', 'HPP_SHIPPING_COUNTRY' then 'Invalid Country code.'
|
525
|
+
when 'HPP_BILLING_POSTALCODE', 'HPP_SHIPPING_POSTALCODE' then 'Invalid Zip/Postal Code. The selected payment method only allows letters, numbers, spaces or punctuation, and no more than 16 characters.'
|
526
|
+
when 'HPP_BILLING_STATE', 'HPP_SHIPPING_STATE' then 'Invalid State.'
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
def validate(key, value)
|
531
|
+
pattern = get_pattern(key)
|
532
|
+
|
533
|
+
return value unless pattern.present?
|
534
|
+
|
535
|
+
if value =~pattern
|
536
|
+
return value
|
537
|
+
else
|
538
|
+
raise ArgumentError, get_message(key)
|
539
|
+
end
|
97
540
|
end
|
98
541
|
|
542
|
+
def add_field(name, value)
|
543
|
+
return if name.blank? || value.blank?
|
544
|
+
@fields[name.to_s] = validate(name.to_s, value.to_s)
|
545
|
+
end
|
99
546
|
end
|
100
547
|
|
101
548
|
class Helper < OffsitePayments::Helper
|
102
549
|
include Common
|
103
550
|
|
551
|
+
self.country_format = :numeric
|
552
|
+
|
104
553
|
def initialize(order, account, options = {})
|
105
554
|
@timestamp = Time.now.strftime('%Y%m%d%H%M%S')
|
106
555
|
@currency = options[:currency]
|
@@ -115,11 +564,13 @@ module OffsitePayments #:nodoc:
|
|
115
564
|
add_field 'AUTO_SETTLE_FLAG', '1'
|
116
565
|
add_field 'RETURN_TSS', '1'
|
117
566
|
add_field 'TIMESTAMP', @timestamp
|
567
|
+
add_field 'HPP_VERSION', '2'
|
118
568
|
# Realex does not send back CURRENCY param in response
|
119
569
|
# however it does echo any other param so we send it twice.
|
120
570
|
add_field 'X-CURRENCY', @currency
|
121
571
|
add_field 'X-TEST', @test.to_s
|
122
572
|
add_field 'ORDER_ID', "#{order}#{@timestamp.to_i}"
|
573
|
+
add_field 'COMMENT1', application_id
|
123
574
|
end
|
124
575
|
|
125
576
|
def form_fields
|
@@ -131,13 +582,82 @@ module OffsitePayments #:nodoc:
|
|
131
582
|
end
|
132
583
|
|
133
584
|
def billing_address(params={})
|
134
|
-
|
135
|
-
|
585
|
+
country = params[:country]
|
586
|
+
country_code = lookup_country_code(country, :alpha2)
|
587
|
+
avs_code = extract_avs_code(params)
|
588
|
+
params[:state] = lookup_state_code(country_code, params[:state])
|
589
|
+
|
590
|
+
super
|
591
|
+
|
592
|
+
add_field(mappings[:billing_address][:country], lookup_country_code(country))
|
593
|
+
add_field(mappings[:billing_address][:code], avs_code)
|
594
|
+
|
595
|
+
unless ['US', 'CA'].include?(country_code)
|
596
|
+
# HPP_BILLING_STATE is required only for US and CA, otherwise is deleted
|
597
|
+
@fields.delete_if do |k, _|
|
598
|
+
k == 'HPP_BILLING_STATE'
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
if @fields[mappings[:customer][:phone]]
|
603
|
+
add_field(mappings[:customer][:phone], format_phone_number(@phone_number, country_code))
|
604
|
+
end
|
136
605
|
end
|
137
606
|
|
138
607
|
def shipping_address(params={})
|
139
|
-
|
140
|
-
|
608
|
+
country = params[:country]
|
609
|
+
country_code = lookup_country_code(country, :alpha2)
|
610
|
+
params[:state] = lookup_state_code(country_code, params[:state])
|
611
|
+
|
612
|
+
super
|
613
|
+
|
614
|
+
add_field(mappings[:shipping_address][:country], lookup_country_code(country))
|
615
|
+
# the mapping for 'SHIPPING_CODE' field, which has the same value as the 'HPP_SHIPPING_POSTALCODE'
|
616
|
+
add_field(mappings[:shipping_address][:code], params[:zip])
|
617
|
+
|
618
|
+
unless ['US', 'CA'].include?(country_code)
|
619
|
+
# HPP_SHIPPING_STATE is required only for US and CA, otherwise is deleted
|
620
|
+
@fields.delete_if do |k, _|
|
621
|
+
k == 'HPP_SHIPPING_STATE'
|
622
|
+
end
|
623
|
+
end
|
624
|
+
|
625
|
+
if @fields[mappings[:customer][:phone]]&.[](0..1) == '0|'
|
626
|
+
add_field(mappings[:customer][:phone], format_phone_number(@phone_number, country_code))
|
627
|
+
end
|
628
|
+
end
|
629
|
+
|
630
|
+
def customer(params={})
|
631
|
+
country = @fields[mappings[:billing_address][:country]]
|
632
|
+
@phone_number = params[:phone]
|
633
|
+
params[:phone] = format_phone_number(@phone_number, lookup_country_code(country, :alpha2))
|
634
|
+
|
635
|
+
super
|
636
|
+
end
|
637
|
+
|
638
|
+
def addresses_match(address_match = nil)
|
639
|
+
return if address_match.nil?
|
640
|
+
|
641
|
+
add_field(
|
642
|
+
mappings[:addresses_match],
|
643
|
+
extract_address_match_indicator(address_match)
|
644
|
+
)
|
645
|
+
|
646
|
+
copy_billing_address if address_match
|
647
|
+
end
|
648
|
+
|
649
|
+
def comment(comment = nil)
|
650
|
+
add_field(mappings[:comment], comment)
|
651
|
+
end
|
652
|
+
|
653
|
+
# HPP does not want shipping address and HPP_ADDRESS_MATCH_INDICATOR to be sent
|
654
|
+
# if the product does not require shipping
|
655
|
+
def require_shipping(require_shipping = nil)
|
656
|
+
return unless require_shipping == false
|
657
|
+
|
658
|
+
@fields.delete_if do |k, _|
|
659
|
+
k.start_with?('HPP_SHIPPING_') || k == 'HPP_ADDRESS_MATCH_INDICATOR'
|
660
|
+
end
|
141
661
|
end
|
142
662
|
|
143
663
|
def sign_fields
|
@@ -161,13 +681,31 @@ module OffsitePayments #:nodoc:
|
|
161
681
|
mapping :notify_url, 'MERCHANT_RESPONSE_URL'
|
162
682
|
mapping :return_url, 'MERCHANT_RETURN_URL'
|
163
683
|
|
164
|
-
# Realex Optional fields
|
165
|
-
mapping :customer, :email => 'CUST_NUM'
|
166
684
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
685
|
+
# Realex Optional fields
|
686
|
+
mapping :customer, :email => 'HPP_CUSTOMER_EMAIL',
|
687
|
+
:phone => 'HPP_CUSTOMER_PHONENUMBER_MOBILE'
|
688
|
+
|
689
|
+
mapping :shipping_address, :zip => 'HPP_SHIPPING_POSTALCODE',
|
690
|
+
:country => 'HPP_SHIPPING_COUNTRY',
|
691
|
+
:address1 => 'HPP_SHIPPING_STREET1',
|
692
|
+
:address2 => 'HPP_SHIPPING_STREET2',
|
693
|
+
:address3 => 'HPP_SHIPPING_STREET3',
|
694
|
+
:city => 'HPP_SHIPPING_CITY',
|
695
|
+
:state => 'HPP_SHIPPING_STATE',
|
696
|
+
:code => 'SHIPPING_CODE'
|
697
|
+
|
698
|
+
mapping :billing_address, :zip => 'HPP_BILLING_POSTALCODE',
|
699
|
+
:country => 'HPP_BILLING_COUNTRY',
|
700
|
+
:address1 => 'HPP_BILLING_STREET1',
|
701
|
+
:address2 => 'HPP_BILLING_STREET2',
|
702
|
+
:address3 => 'HPP_BILLING_STREET3',
|
703
|
+
:city => 'HPP_BILLING_CITY',
|
704
|
+
:state => 'HPP_BILLING_STATE',
|
705
|
+
:code => 'BILLING_CODE'
|
706
|
+
|
707
|
+
mapping :addresses_match, 'HPP_ADDRESS_MATCH_INDICATOR'
|
708
|
+
mapping :comment, 'COMMENT2'
|
171
709
|
end
|
172
710
|
|
173
711
|
class Notification < OffsitePayments::Notification
|
@@ -241,10 +779,6 @@ module OffsitePayments #:nodoc:
|
|
241
779
|
params['MESSAGE']
|
242
780
|
end
|
243
781
|
|
244
|
-
def pasref
|
245
|
-
params['PASREF']
|
246
|
-
end
|
247
|
-
|
248
782
|
def authcode
|
249
783
|
params['AUTHCODE']
|
250
784
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: offsite_payments
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.7.
|
4
|
+
version: 2.7.26
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Luetke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -257,6 +257,7 @@ files:
|
|
257
257
|
- lib/offsite_payments/integrations/platron.rb
|
258
258
|
- lib/offsite_payments/integrations/pxpay.rb
|
259
259
|
- lib/offsite_payments/integrations/quickpay.rb
|
260
|
+
- lib/offsite_payments/integrations/quickpay_v10.rb
|
260
261
|
- lib/offsite_payments/integrations/rbkmoney.rb
|
261
262
|
- lib/offsite_payments/integrations/realex_offsite.rb
|
262
263
|
- lib/offsite_payments/integrations/robokassa.rb
|
@@ -275,7 +276,8 @@ files:
|
|
275
276
|
homepage: https://github.com/activemerchant/offsite_payments
|
276
277
|
licenses:
|
277
278
|
- MIT
|
278
|
-
metadata:
|
279
|
+
metadata:
|
280
|
+
allowed_push_host: https://rubygems.org
|
279
281
|
post_install_message: "\n In order to use `offsite_payments` gem, you need to either
|
280
282
|
install or add to your Gemfile\n one of the two options for Money gem:\n -
|
281
283
|
`gem 'money'`\n - `gem 'shopify-money', require: 'money'`\n\n Regardless
|
@@ -299,8 +301,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
299
301
|
- !ruby/object:Gem::Version
|
300
302
|
version: '0'
|
301
303
|
requirements: []
|
302
|
-
|
303
|
-
rubygems_version: 2.7.6
|
304
|
+
rubygems_version: 3.0.3
|
304
305
|
signing_key:
|
305
306
|
specification_version: 4
|
306
307
|
summary: Framework and tools for dealing with offsite (hosted) payment pages.
|