offsite_payments 2.7.19 → 2.7.26
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/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.
|