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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/lib/offsite_payments.rb +1 -1
  4. data/lib/offsite_payments/integrations/a1agregator.rb +0 -8
  5. data/lib/offsite_payments/integrations/bit_pay.rb +11 -6
  6. data/lib/offsite_payments/integrations/citrus.rb +2 -2
  7. data/lib/offsite_payments/integrations/direc_pay.rb +1 -1
  8. data/lib/offsite_payments/integrations/easy_pay.rb +1 -1
  9. data/lib/offsite_payments/integrations/epay.rb +2 -2
  10. data/lib/offsite_payments/integrations/gestpay.rb +1 -1
  11. data/lib/offsite_payments/integrations/liqpay.rb +2 -2
  12. data/lib/offsite_payments/integrations/mollie_ideal.rb +1 -1
  13. data/lib/offsite_payments/integrations/mollie_mistercash.rb +1 -1
  14. data/lib/offsite_payments/integrations/pag_seguro.rb +1 -1
  15. data/lib/offsite_payments/integrations/paxum.rb +2 -2
  16. data/lib/offsite_payments/integrations/pay_fast.rb +1 -1
  17. data/lib/offsite_payments/integrations/payflow_link.rb +0 -4
  18. data/lib/offsite_payments/integrations/paytm.rb +2 -2
  19. data/lib/offsite_payments/integrations/payu_in.rb +3 -3
  20. data/lib/offsite_payments/integrations/platron.rb +1 -1
  21. data/lib/offsite_payments/integrations/quickpay.rb +1 -1
  22. data/lib/offsite_payments/integrations/quickpay_v10.rb +173 -0
  23. data/lib/offsite_payments/integrations/realex_offsite.rb +549 -15
  24. data/lib/offsite_payments/integrations/sage_pay_form.rb +1 -0
  25. data/lib/offsite_payments/integrations/universal.rb +0 -1
  26. data/lib/offsite_payments/integrations/web_pay.rb +1 -1
  27. data/lib/offsite_payments/integrations/webmoney.rb +1 -1
  28. data/lib/offsite_payments/version.rb +1 -1
  29. metadata +6 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51cf90edf6cc8aee813514a8c228ede8e2b7b816fbc16c626453f1329b65bdc3
4
- data.tar.gz: e31d47d8ba5e038c9f8b4d4d6212c51f417347bf63344fb54cdc7c57c4e42c78
3
+ metadata.gz: c97ad87cccef24116fe87f91ee89b4b9b407eb45d3e495de18ba2a1b5e33a0c0
4
+ data.tar.gz: 1dd21e00bcb3a717c04da06c9fa3052010f10e326809fe7582f89f3264476424
5
5
  SHA512:
6
- metadata.gz: 1b9eb62afb3ba07284b3d6017b9f70f561c1e98470b95b718514c4b0d85e76655398e6222a14547c5eae77904f523142a857877e0f8fee44209143ef8151a76f
7
- data.tar.gz: 1a08cdad7a12d4e4957059f601a96d0e6bff0c1a3d6a72bd4c9625efa1be4087f40e185ce159a2b60599e5c55f1ca5e8b065306c6c11799e98aeedca32c9e0be
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
- * [Realex](http://www.realexpayments.com)
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)
@@ -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', 'HUF', 'ISK', 'JPY', 'KMF', 'KRW', 'PYG', 'RWF', 'TWD', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF' ]
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.new(gross), currency)
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?( BigDecimal.new(order_amount) )
205
+ if @notification.invoice_ok?( order_id ) && @notification.amount_ok?(BigDecimal(order_amount))
206
206
  @notification.status
207
207
  else
208
208
  'Mismatch'
@@ -320,7 +320,7 @@ module OffsitePayments #:nodoc:
320
320
  data = ActiveUtils::PostData.new
321
321
  data[:requestparams] = parameters.join('|')
322
322
 
323
- response = ssl_get("#{url}?#{data.to_post_data}")
323
+ ssl_get("#{url}?#{data.to_post_data}")
324
324
  end
325
325
 
326
326
  def test?
@@ -101,7 +101,7 @@ module OffsitePayments #:nodoc:
101
101
  end
102
102
 
103
103
  def amount
104
- Money.from_amount(BigDecimal.new(gross), currency)
104
+ Money.from_amount(BigDecimal(gross), currency)
105
105
  end
106
106
 
107
107
  def item_id
@@ -125,7 +125,7 @@ module OffsitePayments #:nodoc:
125
125
  return false
126
126
  end
127
127
 
128
- %w(txnid orderid currency date time hash fraud payercountry issuercountry txnfee subscriptionid paymenttype cardno).each do |attr|
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, value = *line.scan( %r{^([A-Za-z0-9_.]+)\=(.*)$} ).flatten
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 => e
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.new(gross), currency)
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.new(gross)
159
+ BigDecimal(gross)
160
160
  end
161
161
 
162
162
  def item_id
@@ -133,7 +133,7 @@ module OffsitePayments #:nodoc:
133
133
  end
134
134
 
135
135
  def gross_cents
136
- (BigDecimal.new(@params['amount'], 2) * 100).to_i
136
+ (BigDecimal(@params['amount'], 2) * 100).to_i
137
137
  end
138
138
 
139
139
  def status
@@ -100,7 +100,7 @@ module OffsitePayments #:nodoc:
100
100
  end
101
101
 
102
102
  def gross_cents
103
- (BigDecimal.new(@params['amount'], 2) * 100).to_i
103
+ (BigDecimal(@params['amount'], 2) * 100).to_i
104
104
  end
105
105
 
106
106
  def status
@@ -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 => e
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.starts_with?("&")
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.starts_with?("&")
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.new(params['amount_net']), currency)
215
+ Money.from_amount(BigDecimal(params['amount_net']), currency)
216
216
  end
217
217
 
218
218
  # The name of the item being charged for.
@@ -138,10 +138,6 @@ module OffsitePayments #:nodoc:
138
138
  nil
139
139
  end
140
140
 
141
- def status
142
- params['RESPMSG']
143
- end
144
-
145
141
  # Id of this transaction (paypal number)
146
142
  def transaction_id
147
143
  params['PNREF']
@@ -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.new(original_gross) == order_amount
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.new(order_amount))
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.new( '0.0' ) )
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.new( original_gross ) == order_amount && parsed_discount == order_discount
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.new(order_amount) )
261
+ if @notification.invoice_ok?( order_id ) && @notification.amount_ok?( BigDecimal(order_amount) )
262
262
  @notification.status
263
263
  else
264
264
  'Mismatch'
@@ -120,7 +120,7 @@ module OffsitePayments #:nodoc:
120
120
  end
121
121
 
122
122
  def amount
123
- Money.from_amount(BigDecimal.new(params['pg_amount']), currency)
123
+ Money.from_amount(BigDecimal(params['pg_amount']), currency)
124
124
  end
125
125
 
126
126
  def secret
@@ -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://secure.quickpay.dk/form/'
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
- [extract_digits(params[:zip]), extract_digits(params[:address1])].join('|')
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
- add_field(mappings[:billing_address][:zip], extract_avs_code(params))
135
- add_field(mappings[:billing_address][:country], lookup_country_code(params[:country]))
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
- add_field(mappings[:shipping_address][:zip], extract_avs_code(params))
140
- add_field(mappings[:shipping_address][:country], lookup_country_code(params[:country]))
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
- mapping :shipping_address, :zip => 'SHIPPING_CODE',
168
- :country => 'SHIPPING_CO'
169
- mapping :billing_address, :zip => 'BILLING_CODE',
170
- :country => 'BILLING_CO'
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
@@ -72,6 +72,7 @@ module OffsitePayments #:nodoc:
72
72
  attr_reader :identifier
73
73
 
74
74
  def initialize(order, account, options={})
75
+ @shipping_address_set = nil
75
76
  super
76
77
  @identifier = rand(0..99999).to_s.rjust(5, '0')
77
78
  add_field 'VendorTxCode', "#{order}-#{@identifier}"
@@ -22,7 +22,6 @@ module OffsitePayments #:nodoc:
22
22
  'CVE' => 0,
23
23
  'DJF' => 0,
24
24
  'GNF' => 0,
25
- 'HUF' => 0,
26
25
  'ISK' => 0,
27
26
  'JPY' => 0,
28
27
  'KMF' => 0,
@@ -150,7 +150,7 @@ module OffsitePayments #:nodoc:
150
150
  end
151
151
 
152
152
  def amount
153
- Money.from_amount(BigDecimal.new(gross), currency)
153
+ Money.from_amount(BigDecimal(gross), currency)
154
154
  end
155
155
 
156
156
  def item_id
@@ -83,7 +83,7 @@ module OffsitePayments #:nodoc:
83
83
  end
84
84
 
85
85
  def amount
86
- Money.from_amount(BigDecimal.new(gross), currency)
86
+ Money.from_amount(BigDecimal(gross), currency)
87
87
  end
88
88
 
89
89
  def key_present?
@@ -1,3 +1,3 @@
1
1
  module OffsitePayments
2
- VERSION = "2.7.19"
2
+ VERSION = "2.7.26"
3
3
  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.19
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: 2019-07-11 00:00:00.000000000 Z
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
- rubyforge_project:
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.