offsite_payments 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +5 -6
- data/lib/offsite_payments/helper.rb +2 -2
- data/lib/offsite_payments/integrations/a1agregator.rb +1 -1
- data/lib/offsite_payments/integrations/chronopay.rb +2 -2
- data/lib/offsite_payments/integrations/coinbase.rb +166 -0
- data/lib/offsite_payments/integrations/direc_pay.rb +2 -2
- data/lib/offsite_payments/integrations/dotpay.rb +2 -2
- data/lib/offsite_payments/integrations/e_payment_plans.rb +1 -1
- data/lib/offsite_payments/integrations/gestpay.rb +2 -0
- data/lib/offsite_payments/integrations/ipay88.rb +17 -6
- data/lib/offsite_payments/integrations/mollie_ideal.rb +7 -4
- data/lib/offsite_payments/integrations/nochex.rb +1 -1
- data/lib/offsite_payments/integrations/pag_seguro.rb +27 -14
- data/lib/offsite_payments/integrations/pay_fast.rb +1 -1
- data/lib/offsite_payments/integrations/payflow_link.rb +1 -1
- data/lib/offsite_payments/integrations/paypal.rb +1 -1
- data/lib/offsite_payments/integrations/payu_in.rb +13 -3
- data/lib/offsite_payments/integrations/pxpay.rb +5 -3
- data/lib/offsite_payments/integrations/realex.rb +294 -0
- data/lib/offsite_payments/integrations/sage_pay_form.rb +3 -3
- data/lib/offsite_payments/integrations/two_checkout.rb +0 -3
- data/lib/offsite_payments/integrations/universal.rb +4 -3
- data/lib/offsite_payments/integrations/valitor.rb +1 -1
- data/lib/offsite_payments/notification.rb +1 -1
- data/lib/offsite_payments/version.rb +1 -1
- data/lib/offsite_payments.rb +3 -8
- data.tar.gz.sig +0 -0
- metadata +66 -16
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 657879b046bcb541ea2225eee85af0f5916a4d79
|
|
4
|
+
data.tar.gz: 73e5e75b10f09b131966a268697dd641dfc1bd93
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 697047cf3a0639a5093c1f1ba0c5a19c9040a4694405ea7ca515b0a2bcabb3a52527ac97e49919b8fcd42fd1c27b7f10ead8d55c9aea4597eb4cdcbc20308bc3
|
|
7
|
+
data.tar.gz: 22c3e6d5e428a00fd8943d15ad95ae3e811716d8cbbdf778cb7f881f16665b952a63223a786274b616c6741118ab1f00feef0dd87dbabb04d012ab966b4a3440
|
checksums.yaml.gz.sig
ADDED
|
Binary file
|
data/README.md
CHANGED
|
@@ -35,6 +35,7 @@ Or, if you're using Bundler, just add the following to your Gemfile:
|
|
|
35
35
|
* [A1Agregator](http://a1agregator.ru/) - RU
|
|
36
36
|
* [Authorize.Net SIM](http://developer.authorize.net/api/sim/) - US
|
|
37
37
|
* [Banca Sella GestPay](https://www.gestpay.it/)
|
|
38
|
+
* [BitPay](https://bitpay.com/)
|
|
38
39
|
* [Chronopay](http://www.chronopay.com)
|
|
39
40
|
* [DirecPay](http://www.timesofmoney.com/direcpay/jsp/home.jsp)
|
|
40
41
|
* [Direct-eBanking / sofortueberweisung.de by Payment-Networks AG](https://www.payment-network.com/deb_com_en/merchantarea/home) - DE, AT, CH, BE, UK, NL
|
|
@@ -49,6 +50,7 @@ Or, if you're using Bundler, just add the following to your Gemfile:
|
|
|
49
50
|
* [PagSeguro](http://www.pagseguro.com.br/) - BR
|
|
50
51
|
* [Paxum](https://www.paxum.com/)
|
|
51
52
|
* [PayPal Website Payments Standard](https://www.paypal.com/cgi-bin/webscr?cmd#_wp-standard-overview-outside)
|
|
53
|
+
* [PayDollar](http://www.paydollar.com)
|
|
52
54
|
* [Paysbuy](https://www.paysbuy.com/) - TH
|
|
53
55
|
* [Platron](https://www.platron.ru/) - RU
|
|
54
56
|
* [RBK Money](https://rbkmoney.ru/) - RU
|
|
@@ -61,10 +63,7 @@ Or, if you're using Bundler, just add the following to your Gemfile:
|
|
|
61
63
|
* [WebPay](http://webpay.by/)
|
|
62
64
|
* [WorldPay](http://www.worldpay.com)
|
|
63
65
|
|
|
64
|
-
##
|
|
66
|
+
## Misc.
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
git clone https://github.com/Shopify/offsite_payments.git
|
|
69
|
-
|
|
70
|
-
Please don't touch the CHANGELOG in your pull requests, we'll add the appropriate CHANGELOG entries at release time.
|
|
68
|
+
- This library is MIT licensed.
|
|
69
|
+
- We will gladly accept contributions. See **CONTRIBUTING.md** for more information.
|
|
@@ -90,9 +90,9 @@ module OffsitePayments #:nodoc:
|
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
def lookup_country_code(name_or_code, format = country_format)
|
|
93
|
-
country =
|
|
93
|
+
country = ActiveUtils::Country.find(name_or_code)
|
|
94
94
|
country.code(format).to_s
|
|
95
|
-
rescue
|
|
95
|
+
rescue ActiveUtils::InvalidCountryCodeError
|
|
96
96
|
name_or_code
|
|
97
97
|
end
|
|
98
98
|
|
|
@@ -117,10 +117,10 @@ module OffsitePayments #:nodoc:
|
|
|
117
117
|
private
|
|
118
118
|
|
|
119
119
|
def checkout_language_from_country(country_code)
|
|
120
|
-
country =
|
|
120
|
+
country = ActiveUtils::Country.find(country_code)
|
|
121
121
|
short_code = country.code(:alpha2).to_s
|
|
122
122
|
LANG_FOR_COUNTRY[short_code]
|
|
123
|
-
rescue
|
|
123
|
+
rescue ActiveUtils::InvalidCountryCodeError
|
|
124
124
|
'EN'
|
|
125
125
|
end
|
|
126
126
|
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
module OffsitePayments #:nodoc:
|
|
2
|
+
module Integrations #:nodoc:
|
|
3
|
+
module Coinbase
|
|
4
|
+
mattr_accessor :service_url
|
|
5
|
+
self.service_url = 'https://www.coinbase.com/checkouts/redirect'
|
|
6
|
+
|
|
7
|
+
mattr_accessor :buttoncreate_url
|
|
8
|
+
self.buttoncreate_url = 'https://api.coinbase.com/v1/buttons'
|
|
9
|
+
|
|
10
|
+
mattr_accessor :notification_confirmation_url
|
|
11
|
+
self.notification_confirmation_url = 'https://api.coinbase.com/v1/orders/%s'
|
|
12
|
+
|
|
13
|
+
# options should be { credential1: "your API key", credential2: "your API secret" }
|
|
14
|
+
def self.notification(post, options = {})
|
|
15
|
+
Notification.new(post, options)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.return(query_string, options = {})
|
|
19
|
+
Return.new(query_string, options)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Helper < OffsitePayments::Helper
|
|
23
|
+
# account should be a Coinbase API key; see https://coinbase.com/account/integrations
|
|
24
|
+
# options[:credential2] should be the corresponding API secret
|
|
25
|
+
def initialize(order_id, account, options)
|
|
26
|
+
super
|
|
27
|
+
|
|
28
|
+
@order = order_id
|
|
29
|
+
@account = account
|
|
30
|
+
@options = options
|
|
31
|
+
@options[:credential1] ||= ''
|
|
32
|
+
@options[:credential2] ||= ''
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
mapping :notify_url, 'notify_url'
|
|
36
|
+
mapping :return_url, 'return_url'
|
|
37
|
+
mapping :cancel_return_url, 'cancel_return_url'
|
|
38
|
+
|
|
39
|
+
def form_fields
|
|
40
|
+
uri = URI.parse(Coinbase.buttoncreate_url)
|
|
41
|
+
|
|
42
|
+
request_body = {
|
|
43
|
+
'button[auto_redirect]' => true,
|
|
44
|
+
'button[name]' => @options[:description] || "Your Order",
|
|
45
|
+
'button[price_string]' => @options[:amount],
|
|
46
|
+
'button[price_currency_iso]' => @options[:currency],
|
|
47
|
+
'button[custom]' => @order,
|
|
48
|
+
'button[callback_url]' => @fields['notify_url'],
|
|
49
|
+
'button[success_url]' => @fields['return_url'],
|
|
50
|
+
'button[cancel_url]' => @fields['cancel_return_url'],
|
|
51
|
+
'api_key' => @account
|
|
52
|
+
}.to_query
|
|
53
|
+
|
|
54
|
+
data = Coinbase.do_request(uri, @account, @options[:credential2], request_body)
|
|
55
|
+
json = JSON.parse(data)
|
|
56
|
+
|
|
57
|
+
raise ActionViewHelperError, "Error occured while contacting gateway : #{json['error']}" if json['error']
|
|
58
|
+
|
|
59
|
+
{'id' => json['button']['code']}
|
|
60
|
+
rescue JSON::ParserError
|
|
61
|
+
raise ActionViewHelperError, 'Invalid response from gateway. Please try again.'
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class Notification < OffsitePayments::Notification
|
|
66
|
+
|
|
67
|
+
def complete?
|
|
68
|
+
status == "Completed"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def item_id
|
|
72
|
+
params['custom']
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def transaction_id
|
|
76
|
+
params['id']
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def received_at
|
|
80
|
+
Time.iso8601(params['created_at']).to_time.to_i
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def gross
|
|
84
|
+
"%.2f" % (params['total_native']['cents'].to_f / 100)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def currency
|
|
88
|
+
params['total_native']['currency_iso']
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def status
|
|
92
|
+
case params['status']
|
|
93
|
+
when "completed"
|
|
94
|
+
"Completed"
|
|
95
|
+
else
|
|
96
|
+
"Failed"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Acknowledge the transaction to Coinbase. This method has to be called after a new
|
|
101
|
+
# apc arrives. Coinbase will verify that all the information we received are correct
|
|
102
|
+
# and will return a ok or a fail.
|
|
103
|
+
def acknowledge(authcode = {})
|
|
104
|
+
|
|
105
|
+
uri = URI.parse(Coinbase.notification_confirmation_url % transaction_id)
|
|
106
|
+
|
|
107
|
+
response = Coinbase.do_request(uri, @options[:credential1], @options[:credential2])
|
|
108
|
+
return false if response.nil?
|
|
109
|
+
|
|
110
|
+
posted_order = @params
|
|
111
|
+
parse(response)
|
|
112
|
+
|
|
113
|
+
%w(id custom total_native status).all? { |param| posted_order[param] == @params[param] }
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
private
|
|
117
|
+
|
|
118
|
+
def parse(post)
|
|
119
|
+
@raw = post.to_s
|
|
120
|
+
@params = JSON.parse(post)['order']
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class Return < OffsitePayments::Return
|
|
125
|
+
def initialize(query_string, options = {})
|
|
126
|
+
super
|
|
127
|
+
@notification = Notification.new(@params.to_json, options)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def parse(query_string)
|
|
131
|
+
parsed_hash = Rack::Utils.parse_nested_query(query_string)
|
|
132
|
+
|
|
133
|
+
if native_cents = parsed_hash['order'] && parsed_hash['order']['total_native'] && parsed_hash['order']['total_native']['cents']
|
|
134
|
+
parsed_hash['order']['total_native']['cents'] = native_cents.to_i
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
parsed_hash
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
protected
|
|
142
|
+
|
|
143
|
+
def self.do_request(uri, api_key, api_secret, post_body = nil)
|
|
144
|
+
nonce = (Time.now.to_f * 1e6).to_i
|
|
145
|
+
hmac_message = nonce.to_s + uri.to_s
|
|
146
|
+
|
|
147
|
+
if post_body
|
|
148
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
|
149
|
+
request.body = post_body
|
|
150
|
+
hmac_message = hmac_message + request.body
|
|
151
|
+
else
|
|
152
|
+
request = Net::HTTP::Get.new(uri.path)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
156
|
+
http.use_ssl = true
|
|
157
|
+
|
|
158
|
+
request['ACCESS_KEY'] = api_key
|
|
159
|
+
request['ACCESS_SIGNATURE'] = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), api_secret, hmac_message)
|
|
160
|
+
request['ACCESS_NONCE'] = nonce.to_s
|
|
161
|
+
|
|
162
|
+
http.request(request).body
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -309,7 +309,7 @@ module OffsitePayments #:nodoc:
|
|
|
309
309
|
end
|
|
310
310
|
|
|
311
311
|
class Status
|
|
312
|
-
include
|
|
312
|
+
include ActiveUtils::PostsData
|
|
313
313
|
|
|
314
314
|
STATUS_TEST_URL = 'https://test.direcpay.com/direcpay/secure/dpMerchantTransaction.jsp'
|
|
315
315
|
STATUS_LIVE_URL = 'https://www.timesofmoney.com/direcpay/secure/dpPullMerchAtrnDtls.jsp'
|
|
@@ -324,7 +324,7 @@ module OffsitePayments #:nodoc:
|
|
|
324
324
|
def update(authorization, notification_url)
|
|
325
325
|
url = test? ? STATUS_TEST_URL : STATUS_LIVE_URL
|
|
326
326
|
parameters = [ authorization, account, notification_url ]
|
|
327
|
-
data =
|
|
327
|
+
data = ActiveUtils::PostData.new
|
|
328
328
|
data[:requestparams] = parameters.join('|')
|
|
329
329
|
|
|
330
330
|
response = ssl_get("#{url}?#{data.to_post_data}")
|
|
@@ -75,9 +75,9 @@ module OffsitePayments #:nodoc:
|
|
|
75
75
|
private
|
|
76
76
|
|
|
77
77
|
def lookup_country_code(name_or_code, format = country_format)
|
|
78
|
-
country =
|
|
78
|
+
country = ActiveUtils::Country.find(name_or_code)
|
|
79
79
|
country.code(format).to_s
|
|
80
|
-
rescue
|
|
80
|
+
rescue ActiveUtils::InvalidCountryCodeError
|
|
81
81
|
name_or_code
|
|
82
82
|
end
|
|
83
83
|
end
|
|
@@ -50,6 +50,8 @@ module OffsitePayments #:nodoc:
|
|
|
50
50
|
site.use_ssl = true
|
|
51
51
|
site.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
52
52
|
site.get(path).body
|
|
53
|
+
rescue Timeout::Error, Errno::ECONNRESET, Errno::ETIMEDOUT
|
|
54
|
+
raise ActionViewHelperError, "Error occured while contacting payment gateway. Please try again."
|
|
53
55
|
end
|
|
54
56
|
end
|
|
55
57
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module OffsitePayments #:nodoc:
|
|
2
2
|
module Integrations #:nodoc:
|
|
3
3
|
module Ipay88
|
|
4
|
+
CANCELLED_ERROR_DESCRIPTION = 'Customer Cancel Transaction'
|
|
5
|
+
|
|
4
6
|
def self.service_url
|
|
5
7
|
"https://www.mobile88.com/epayment/entry.asp"
|
|
6
8
|
end
|
|
@@ -13,8 +15,12 @@ module OffsitePayments #:nodoc:
|
|
|
13
15
|
Return.new(query_string, options)
|
|
14
16
|
end
|
|
15
17
|
|
|
18
|
+
def self.notification(post, options = {})
|
|
19
|
+
Notification.new(post, options)
|
|
20
|
+
end
|
|
21
|
+
|
|
16
22
|
class Helper < OffsitePayments::Helper
|
|
17
|
-
include
|
|
23
|
+
include ActiveUtils::RequiresParameters
|
|
18
24
|
|
|
19
25
|
# Currencies supported
|
|
20
26
|
# MYR (Malaysian Ringgit - for all payment methods except China Union Pay and PayPal)
|
|
@@ -108,6 +114,7 @@ module OffsitePayments #:nodoc:
|
|
|
108
114
|
mapping :language, "Lang"
|
|
109
115
|
mapping :payment, "PaymentId"
|
|
110
116
|
mapping :return_url, "ResponseURL"
|
|
117
|
+
mapping :notify_url, "BackendURL"
|
|
111
118
|
mapping :signature, "Signature"
|
|
112
119
|
|
|
113
120
|
protected
|
|
@@ -123,10 +130,14 @@ module OffsitePayments #:nodoc:
|
|
|
123
130
|
end
|
|
124
131
|
|
|
125
132
|
class Notification < OffsitePayments::Notification
|
|
126
|
-
include
|
|
133
|
+
include ActiveUtils::PostsData
|
|
127
134
|
|
|
128
135
|
def status
|
|
129
|
-
params["Status"] == '1'
|
|
136
|
+
if params["Status"] == '1'
|
|
137
|
+
'Completed'
|
|
138
|
+
else
|
|
139
|
+
error == CANCELLED_ERROR_DESCRIPTION ? 'Cancelled' : 'Failed'
|
|
140
|
+
end
|
|
130
141
|
end
|
|
131
142
|
|
|
132
143
|
def complete?
|
|
@@ -138,7 +149,7 @@ module OffsitePayments #:nodoc:
|
|
|
138
149
|
end
|
|
139
150
|
|
|
140
151
|
def gross
|
|
141
|
-
params["Amount"]
|
|
152
|
+
params["Amount"].try(:gsub, /,(?=\d{3}\b)/, '')
|
|
142
153
|
end
|
|
143
154
|
|
|
144
155
|
def currency
|
|
@@ -182,7 +193,7 @@ module OffsitePayments #:nodoc:
|
|
|
182
193
|
end
|
|
183
194
|
|
|
184
195
|
def acknowledge
|
|
185
|
-
secure? && success?
|
|
196
|
+
secure? && (!success? || requery == "00")
|
|
186
197
|
end
|
|
187
198
|
|
|
188
199
|
protected
|
|
@@ -228,7 +239,7 @@ module OffsitePayments #:nodoc:
|
|
|
228
239
|
end
|
|
229
240
|
|
|
230
241
|
def cancelled?
|
|
231
|
-
params["ErrDesc"] ==
|
|
242
|
+
params["ErrDesc"] == CANCELLED_ERROR_DESCRIPTION
|
|
232
243
|
end
|
|
233
244
|
|
|
234
245
|
def message
|
|
@@ -2,7 +2,7 @@ module OffsitePayments #:nodoc:
|
|
|
2
2
|
module Integrations #:nodoc:
|
|
3
3
|
module MollieIdeal
|
|
4
4
|
class API
|
|
5
|
-
include
|
|
5
|
+
include ActiveUtils::PostsData
|
|
6
6
|
|
|
7
7
|
attr_reader :token
|
|
8
8
|
|
|
@@ -25,7 +25,7 @@ module OffsitePayments #:nodoc:
|
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
RedirectError = Class.new(
|
|
28
|
+
RedirectError = Class.new(ActiveUtils::ActiveUtilsError)
|
|
29
29
|
|
|
30
30
|
MOLLIE_API_V1_URI = 'https://api.mollie.nl/v1/'.freeze
|
|
31
31
|
|
|
@@ -137,10 +137,13 @@ module OffsitePayments #:nodoc:
|
|
|
137
137
|
|
|
138
138
|
def request_redirect
|
|
139
139
|
MollieIdeal.create_payment(token, redirect_paramaters)
|
|
140
|
-
rescue
|
|
141
|
-
|
|
140
|
+
rescue ActiveUtils::ResponseError => e
|
|
141
|
+
case e.response.code
|
|
142
|
+
when '401', '403', '422'
|
|
142
143
|
error = JSON.parse(e.response.body)['error']['message']
|
|
143
144
|
raise ActionViewHelperError, error
|
|
145
|
+
when '503'
|
|
146
|
+
raise ActionViewHelperError, 'Service temporarily unavailable. Please try again.'
|
|
144
147
|
else
|
|
145
148
|
raise
|
|
146
149
|
end
|
|
@@ -139,7 +139,7 @@ module OffsitePayments #:nodoc:
|
|
|
139
139
|
|
|
140
140
|
# Parser and handler for incoming Automatic Payment Confirmations from Nochex.
|
|
141
141
|
class Notification < OffsitePayments::Notification
|
|
142
|
-
include
|
|
142
|
+
include ActiveUtils::PostsData
|
|
143
143
|
|
|
144
144
|
def complete?
|
|
145
145
|
status == 'Completed'
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module OffsitePayments #:nodoc:
|
|
2
4
|
module Integrations #:nodoc:
|
|
3
5
|
module PagSeguro
|
|
@@ -60,17 +62,18 @@ module OffsitePayments #:nodoc:
|
|
|
60
62
|
|
|
61
63
|
mapping :order, 'reference'
|
|
62
64
|
|
|
63
|
-
mapping :billing_address, :city => 'shippingAddressCity',
|
|
64
|
-
:address1 => 'shippingAddressStreet',
|
|
65
|
-
:address2 => 'shippingAddressNumber',
|
|
66
|
-
:state => 'shippingAddressState',
|
|
67
|
-
:zip => 'shippingAddressPostalCode',
|
|
68
|
-
:country => 'shippingAddressCountry'
|
|
69
|
-
|
|
70
65
|
mapping :notify_url, 'notificationURL'
|
|
71
66
|
mapping :return_url, 'redirectURL'
|
|
72
67
|
mapping :description, 'itemDescription1'
|
|
73
68
|
|
|
69
|
+
def shipping_address(params = {})
|
|
70
|
+
add_field('shippingAddressCity', params[:city].slice(0, 60)) if params[:city]
|
|
71
|
+
add_field('shippingAddressStreet', params[:address1].slice(0, 80)) if params[:address1]
|
|
72
|
+
add_field('shippingAddressComplement', params[:address2].slice(0, 40)) if params[:address2]
|
|
73
|
+
add_field('shippingAddressState', params[:state])
|
|
74
|
+
add_field('shippingAddressPostalCode', params[:zip].delete("^0-9").slice(0, 8)) if params[:zip]
|
|
75
|
+
end
|
|
76
|
+
|
|
74
77
|
def form_fields
|
|
75
78
|
invoice_id = fetch_token
|
|
76
79
|
|
|
@@ -82,11 +85,13 @@ module OffsitePayments #:nodoc:
|
|
|
82
85
|
end
|
|
83
86
|
|
|
84
87
|
def customer(params = {})
|
|
85
|
-
phone = area_code_and_number(params[:phone])
|
|
86
88
|
full_name = remove_excessive_whitespace("#{params[:first_name]} #{params[:last_name]}")
|
|
87
89
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
if phone = area_code_and_number(params[:phone])
|
|
91
|
+
add_field("senderAreaCode", phone[0])
|
|
92
|
+
add_field("senderPhone", phone[1])
|
|
93
|
+
end
|
|
94
|
+
|
|
90
95
|
add_field("senderEmail", params[:email])
|
|
91
96
|
add_field('senderName', full_name)
|
|
92
97
|
end
|
|
@@ -106,11 +111,12 @@ module OffsitePayments #:nodoc:
|
|
|
106
111
|
check_for_errors(response, xml)
|
|
107
112
|
|
|
108
113
|
extract_token(xml)
|
|
109
|
-
rescue Timeout::Error, Errno::ECONNRESET => e
|
|
114
|
+
rescue Timeout::Error, Errno::ECONNRESET, Errno::ETIMEDOUT => e
|
|
110
115
|
raise ActionViewHelperError, "Erro ao conectar-se ao PagSeguro. Por favor, tente novamente."
|
|
111
116
|
end
|
|
112
117
|
|
|
113
118
|
def area_code_and_number(phone)
|
|
119
|
+
return if phone.nil?
|
|
114
120
|
phone.gsub!(/[^\d]/, '')
|
|
115
121
|
|
|
116
122
|
ddd = phone.slice(0..1)
|
|
@@ -128,7 +134,7 @@ module OffsitePayments #:nodoc:
|
|
|
128
134
|
when "401"
|
|
129
135
|
raise ActionViewHelperError, "Token do PagSeguro inválido."
|
|
130
136
|
else
|
|
131
|
-
raise
|
|
137
|
+
raise ActiveUtils::ResponseError, response
|
|
132
138
|
end
|
|
133
139
|
end
|
|
134
140
|
|
|
@@ -159,13 +165,19 @@ module OffsitePayments #:nodoc:
|
|
|
159
165
|
end
|
|
160
166
|
|
|
161
167
|
class Notification < OffsitePayments::Notification
|
|
168
|
+
class NotificationError < StandardError; end
|
|
169
|
+
|
|
162
170
|
def initialize(post, options = {})
|
|
171
|
+
@acknowledge = true
|
|
163
172
|
notify_code = parse_http_query(post)["notificationCode"]
|
|
164
173
|
email = options[:credential1]
|
|
165
174
|
token = options[:credential2]
|
|
166
175
|
|
|
167
176
|
uri = URI.join(PagSeguro.notification_url, notify_code)
|
|
168
177
|
parse_xml(web_get(uri, email: email, token: token))
|
|
178
|
+
|
|
179
|
+
rescue NotificationError
|
|
180
|
+
@acknowledge = false
|
|
169
181
|
end
|
|
170
182
|
|
|
171
183
|
def complete?
|
|
@@ -221,9 +233,8 @@ module OffsitePayments #:nodoc:
|
|
|
221
233
|
end
|
|
222
234
|
end
|
|
223
235
|
|
|
224
|
-
# There's no acknowledge for PagSeguro
|
|
225
236
|
def acknowledge
|
|
226
|
-
|
|
237
|
+
@acknowledge
|
|
227
238
|
end
|
|
228
239
|
|
|
229
240
|
private
|
|
@@ -232,6 +243,8 @@ module OffsitePayments #:nodoc:
|
|
|
232
243
|
uri.query = URI.encode_www_form(params)
|
|
233
244
|
|
|
234
245
|
response = Net::HTTP.get_response(uri)
|
|
246
|
+
raise NotificationError if response.code.to_i > 200
|
|
247
|
+
|
|
235
248
|
response.body
|
|
236
249
|
end
|
|
237
250
|
|
|
@@ -116,7 +116,7 @@ module OffsitePayments #:nodoc:
|
|
|
116
116
|
|
|
117
117
|
# Order amount should be equal to gross - discount
|
|
118
118
|
def amount_ok?( order_amount, order_discount = BigDecimal.new( '0.0' ) )
|
|
119
|
-
BigDecimal.new(
|
|
119
|
+
BigDecimal.new( original_gross ) == order_amount && BigDecimal.new( discount.to_s ) == order_discount
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
# Status of transaction return from the PayU. List of possible values:
|
|
@@ -162,10 +162,14 @@ module OffsitePayments #:nodoc:
|
|
|
162
162
|
end
|
|
163
163
|
|
|
164
164
|
# original amount send by merchant
|
|
165
|
-
def
|
|
165
|
+
def original_gross
|
|
166
166
|
params['amount']
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
+
def gross
|
|
170
|
+
parse_and_round_gross_amount(params['amount'])
|
|
171
|
+
end
|
|
172
|
+
|
|
169
173
|
# This is discount given to user - based on promotion set by merchants.
|
|
170
174
|
def discount
|
|
171
175
|
params['discount']
|
|
@@ -225,7 +229,7 @@ module OffsitePayments #:nodoc:
|
|
|
225
229
|
end
|
|
226
230
|
|
|
227
231
|
def checksum_ok?
|
|
228
|
-
checksum_fields = [transaction_status, *user_defined.reverse, customer_email, customer_first_name, product_info,
|
|
232
|
+
checksum_fields = [transaction_status, *user_defined.reverse, customer_email, customer_first_name, product_info, original_gross, invoice]
|
|
229
233
|
|
|
230
234
|
unless Digest::SHA512.hexdigest([@secret_key, *checksum_fields, @merchant_id].join("|")) == checksum
|
|
231
235
|
@message = 'Return checksum not matching the data provided'
|
|
@@ -233,6 +237,12 @@ module OffsitePayments #:nodoc:
|
|
|
233
237
|
end
|
|
234
238
|
true
|
|
235
239
|
end
|
|
240
|
+
|
|
241
|
+
private
|
|
242
|
+
def parse_and_round_gross_amount(amount)
|
|
243
|
+
rounded_amount = (amount.to_f * 100.0).round
|
|
244
|
+
sprintf("%.2f", rounded_amount / 100.00)
|
|
245
|
+
end
|
|
236
246
|
end
|
|
237
247
|
|
|
238
248
|
class Return < OffsitePayments::Return
|
|
@@ -16,7 +16,7 @@ module OffsitePayments #:nodoc:
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
class Helper < OffsitePayments::Helper
|
|
19
|
-
include
|
|
19
|
+
include ActiveUtils::PostsData
|
|
20
20
|
|
|
21
21
|
attr_reader :token_parameters, :redirect_parameters
|
|
22
22
|
|
|
@@ -58,6 +58,8 @@ module OffsitePayments #:nodoc:
|
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
url.to_s
|
|
61
|
+
rescue ActiveUtils::ConnectionError
|
|
62
|
+
raise ActionViewHelperError, "A connection error occurred while contacting the payment gateway. Please try again."
|
|
61
63
|
end
|
|
62
64
|
|
|
63
65
|
def form_method
|
|
@@ -102,8 +104,8 @@ module OffsitePayments #:nodoc:
|
|
|
102
104
|
end
|
|
103
105
|
|
|
104
106
|
class Notification < OffsitePayments::Notification
|
|
105
|
-
include
|
|
106
|
-
include
|
|
107
|
+
include ActiveUtils::PostsData
|
|
108
|
+
include ActiveUtils::RequiresParameters
|
|
107
109
|
|
|
108
110
|
def initialize(query_string, options={})
|
|
109
111
|
# PxPay appends ?result=...&userid=... to whatever return_url was specified, even if that URL ended with a ?query.
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
module OffsitePayments #:nodoc:
|
|
2
|
+
module Integrations #:nodoc:
|
|
3
|
+
module Realex
|
|
4
|
+
mattr_accessor :production_url
|
|
5
|
+
mattr_accessor :test_url
|
|
6
|
+
self.production_url = 'https://hpp.realexpayments.com/pay'
|
|
7
|
+
self.test_url = 'https://hpp.sandbox.realexpayments.com/pay'
|
|
8
|
+
|
|
9
|
+
def self.helper(order, account, options={})
|
|
10
|
+
Helper.new(order, account, options)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.notification(query_string, options={})
|
|
14
|
+
Notification.new(query_string, options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.return(query_string, options={})
|
|
18
|
+
Return.new(query_string, options)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.service_url
|
|
22
|
+
mode = OffsitePayments.mode
|
|
23
|
+
case mode
|
|
24
|
+
when :production
|
|
25
|
+
self.production_url
|
|
26
|
+
when :test
|
|
27
|
+
self.test_url
|
|
28
|
+
else
|
|
29
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module Common
|
|
34
|
+
CURRENCY_SPECIAL_MINOR_UNITS = {
|
|
35
|
+
'BIF' => 0,
|
|
36
|
+
'BYR' => 0,
|
|
37
|
+
'CLF' => 0,
|
|
38
|
+
'CLP' => 0,
|
|
39
|
+
'CVE' => 0,
|
|
40
|
+
'DJF' => 0,
|
|
41
|
+
'GNF' => 0,
|
|
42
|
+
'HUF' => 0,
|
|
43
|
+
'ISK' => 0,
|
|
44
|
+
'JPY' => 0,
|
|
45
|
+
'KMF' => 0,
|
|
46
|
+
'KRW' => 0,
|
|
47
|
+
'PYG' => 0,
|
|
48
|
+
'RWF' => 0,
|
|
49
|
+
'UGX' => 0,
|
|
50
|
+
'UYI' => 0,
|
|
51
|
+
'VND' => 0,
|
|
52
|
+
'VUV' => 0,
|
|
53
|
+
'XAF' => 0,
|
|
54
|
+
'XOF' => 0,
|
|
55
|
+
'XPF' => 0,
|
|
56
|
+
'BHD' => 3,
|
|
57
|
+
'IQD' => 3,
|
|
58
|
+
'JOD' => 3,
|
|
59
|
+
'KWD' => 3,
|
|
60
|
+
'LYD' => 3,
|
|
61
|
+
'OMR' => 3,
|
|
62
|
+
'TND' => 3,
|
|
63
|
+
'COU' => 4
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
def create_signature(fields, secret)
|
|
67
|
+
data = fields.join('.')
|
|
68
|
+
digest = Digest::SHA1.hexdigest(data)
|
|
69
|
+
signed = "#{digest}.#{secret}"
|
|
70
|
+
Digest::SHA1.hexdigest(signed)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Realex accepts currency amounts as an integer in the lowest value
|
|
74
|
+
# e.g.
|
|
75
|
+
# format_amount(110.56, 'GBP')
|
|
76
|
+
# => 11056
|
|
77
|
+
def format_amount(amount, currency)
|
|
78
|
+
units = CURRENCY_SPECIAL_MINOR_UNITS[currency] || 2
|
|
79
|
+
multiple = 10**units
|
|
80
|
+
return (amount.to_f * multiple.to_f).to_i
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Realex returns currency amount as an integer
|
|
84
|
+
def format_amount_as_float(amount, currency)
|
|
85
|
+
units = CURRENCY_SPECIAL_MINOR_UNITS[currency] || 2
|
|
86
|
+
divisor = 10**units
|
|
87
|
+
return (amount.to_f / divisor.to_f)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def extract_digits(value)
|
|
91
|
+
value.scan(/\d+/).join('')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def extract_avs_code(params={})
|
|
95
|
+
[extract_digits(params[:zip]), extract_digits(params[:address1])].join('|')
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
class Helper < OffsitePayments::Helper
|
|
101
|
+
include Common
|
|
102
|
+
|
|
103
|
+
def initialize(order, account, options = {})
|
|
104
|
+
@timestamp = Time.now.strftime('%Y%m%d%H%M%S')
|
|
105
|
+
@currency = options[:currency]
|
|
106
|
+
@merchant_id = account
|
|
107
|
+
@sub_account = options[:credential2]
|
|
108
|
+
@secret = options[:credential3]
|
|
109
|
+
super
|
|
110
|
+
# Credentials
|
|
111
|
+
add_field 'MERCHANT_ID', @merchant_id
|
|
112
|
+
add_field 'ACCOUNT', @sub_account
|
|
113
|
+
# Defaults
|
|
114
|
+
add_field 'AUTO_SETTLE_FLAG', '1'
|
|
115
|
+
add_field 'RETURN_TSS', '1'
|
|
116
|
+
add_field 'TIMESTAMP', @timestamp
|
|
117
|
+
# Realex does not send back CURRENCY param in response
|
|
118
|
+
# however it does echo any other param so we send it twice.
|
|
119
|
+
add_field 'X-CURRENCY', @currency
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def form_fields
|
|
123
|
+
sign_fields
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def amount=(amount)
|
|
127
|
+
add_field 'AMOUNT', format_amount(amount, @currency)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def billing_address(params={})
|
|
131
|
+
add_field(mappings[:billing_address][:zip], extract_avs_code(params))
|
|
132
|
+
add_field(mappings[:billing_address][:country], lookup_country_code(params[:country]))
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def shipping_address(params={})
|
|
136
|
+
add_field(mappings[:shipping_address][:zip], extract_avs_code(params))
|
|
137
|
+
add_field(mappings[:shipping_address][:country], lookup_country_code(params[:country]))
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def sign_fields
|
|
141
|
+
@fields.merge!('SHA1HASH' => generate_signature)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def generate_signature
|
|
145
|
+
fields_to_sign = []
|
|
146
|
+
['TIMESTAMP', 'MERCHANT_ID', 'ORDER_ID', 'AMOUNT', 'CURRENCY'].each do |field|
|
|
147
|
+
fields_to_sign << @fields[field]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
create_signature(fields_to_sign, @secret)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Realex Required Fields
|
|
154
|
+
mapping :currency, 'CURRENCY'
|
|
155
|
+
|
|
156
|
+
mapping :order, 'ORDER_ID'
|
|
157
|
+
mapping :amount, 'AMOUNT'
|
|
158
|
+
mapping :return_url, 'MERCHANT_RESPONSE_URL'
|
|
159
|
+
|
|
160
|
+
# Realex Optional fields
|
|
161
|
+
mapping :customer, :email => 'CUST_NUM'
|
|
162
|
+
|
|
163
|
+
mapping :shipping_address, :zip => 'SHIPPING_CODE',
|
|
164
|
+
:country => 'SHIPPING_CO'
|
|
165
|
+
mapping :billing_address, :zip => 'BILLING_CODE',
|
|
166
|
+
:country => 'BILLING_CO'
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
class Notification < OffsitePayments::Notification
|
|
170
|
+
include Common
|
|
171
|
+
def initialize(post, options={})
|
|
172
|
+
super
|
|
173
|
+
@secret = options[:credential3]
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Required Notification methods to define
|
|
177
|
+
def status
|
|
178
|
+
if result == '00'
|
|
179
|
+
'Completed'
|
|
180
|
+
else
|
|
181
|
+
'Invalid'
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Realex does not send back the currency param by default
|
|
186
|
+
# we have sent this additional parameter
|
|
187
|
+
def currency
|
|
188
|
+
params['X-CURRENCY']
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def gross
|
|
192
|
+
format_amount_as_float(params['AMOUNT'], currency)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def complete?
|
|
196
|
+
verified? && status == 'Completed'
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Fields for Realex signature verification
|
|
200
|
+
def timestamp
|
|
201
|
+
params['TIMESTAMP']
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def merchant_id
|
|
205
|
+
params['MERCHANT_ID']
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def order_id
|
|
209
|
+
params['ORDER_ID']
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def result
|
|
213
|
+
params['RESULT']
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def message
|
|
217
|
+
params['MESSAGE']
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def pasref
|
|
221
|
+
params['PASREF']
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def authcode
|
|
225
|
+
params['AUTHCODE']
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def signature
|
|
229
|
+
params['SHA1HASH']
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def calculated_signature
|
|
233
|
+
fields = [timestamp, merchant_id, order_id, result, message, pasref, authcode]
|
|
234
|
+
create_signature(fields, @secret)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def verified?
|
|
238
|
+
signature == calculated_signature
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Extra data (available from Realex)
|
|
242
|
+
def cvn_result
|
|
243
|
+
params['CVNRESULT']
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def avs_postcode_result
|
|
247
|
+
params['AVSPOSTCODERESULT']
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def avs_address_result
|
|
251
|
+
params['AVSADDRESSRESULT']
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def pasref
|
|
255
|
+
params['PASREF']
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def eci
|
|
259
|
+
params['ECI']
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def cavv
|
|
263
|
+
params['CAVV']
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def xid
|
|
267
|
+
params['XID']
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
class Return < OffsitePayments::Return
|
|
273
|
+
def initialize(data, options)
|
|
274
|
+
super
|
|
275
|
+
@notification = Notification.new(data, options)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def success?
|
|
279
|
+
notification.complete?
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# TODO: realex does not provide a separate cancelled endpoint
|
|
283
|
+
def cancelled?
|
|
284
|
+
false
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def message
|
|
288
|
+
notification.message
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
@@ -131,6 +131,8 @@ module OffsitePayments #:nodoc:
|
|
|
131
131
|
fields['BillingPostCode'] ||= "0000"
|
|
132
132
|
fields['DeliveryPostCode'] ||= "0000"
|
|
133
133
|
|
|
134
|
+
fields['ReferrerID'] = referrer_id if referrer_id
|
|
135
|
+
|
|
134
136
|
crypt_skip = ['Vendor', 'EncryptKey', 'SendEmail']
|
|
135
137
|
crypt_skip << 'BillingState' unless fields['BillingCountry'] == 'US'
|
|
136
138
|
crypt_skip << 'DeliveryState' unless fields['DeliveryCountry'] == 'US'
|
|
@@ -138,14 +140,12 @@ module OffsitePayments #:nodoc:
|
|
|
138
140
|
key = fields['EncryptKey']
|
|
139
141
|
@crypt ||= create_crypt_field(fields.except(*crypt_skip), key)
|
|
140
142
|
|
|
141
|
-
|
|
143
|
+
{
|
|
142
144
|
'VPSProtocol' => '3.00',
|
|
143
145
|
'TxType' => 'PAYMENT',
|
|
144
146
|
'Vendor' => @fields['Vendor'],
|
|
145
147
|
'Crypt' => @crypt
|
|
146
148
|
}
|
|
147
|
-
result['ReferrerID'] = referrer_id if referrer_id
|
|
148
|
-
result
|
|
149
149
|
end
|
|
150
150
|
|
|
151
151
|
private
|
|
@@ -82,9 +82,6 @@ module OffsitePayments #:nodoc:
|
|
|
82
82
|
# Overrides Approved URL for return process redirects
|
|
83
83
|
mapping :return_url, 'x_receipt_link_url'
|
|
84
84
|
|
|
85
|
-
# notifications are sent via static URLs in the Instant Notification Settings of 2Checkout admin
|
|
86
|
-
mapping :notify_url, 'notify_url'
|
|
87
|
-
|
|
88
85
|
# Allow seller to indicate the step of the checkout page
|
|
89
86
|
# Possible values: ‘review-cart’, ‘shipping-information’, ‘shipping-method’, ‘billing-information’ and ‘payment-method’
|
|
90
87
|
mapping :purchase_step, 'purchase_step'
|
|
@@ -10,7 +10,7 @@ module OffsitePayments #:nodoc:
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def self.sign(fields, key)
|
|
13
|
-
|
|
13
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, key, fields.sort.join)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
class Helper < OffsitePayments::Helper
|
|
@@ -129,7 +129,7 @@ module OffsitePayments #:nodoc:
|
|
|
129
129
|
end
|
|
130
130
|
|
|
131
131
|
def acknowledge(authcode = nil)
|
|
132
|
-
signature = @params
|
|
132
|
+
signature = @params['x_signature']
|
|
133
133
|
signature && signature.casecmp(generate_signature) == 0
|
|
134
134
|
end
|
|
135
135
|
|
|
@@ -161,7 +161,8 @@ module OffsitePayments #:nodoc:
|
|
|
161
161
|
private
|
|
162
162
|
|
|
163
163
|
def generate_signature
|
|
164
|
-
|
|
164
|
+
signature_params = @params.select { |k| k.start_with? 'x_' }.reject { |k| k == 'x_signature' }
|
|
165
|
+
Universal.sign(signature_params, @key)
|
|
165
166
|
end
|
|
166
167
|
end
|
|
167
168
|
|
data/lib/offsite_payments.rb
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
require 'securerandom'
|
|
2
2
|
require 'cgi'
|
|
3
|
+
require "timeout"
|
|
4
|
+
require "socket"
|
|
3
5
|
|
|
4
6
|
require 'active_support/core_ext/class/delegating_attributes'
|
|
5
7
|
|
|
6
|
-
require 'active_utils
|
|
7
|
-
require 'active_utils/common/connection'
|
|
8
|
-
require 'active_utils/common/requires_parameters'
|
|
9
|
-
require 'active_utils/common/country'
|
|
10
|
-
require 'active_utils/common/error'
|
|
11
|
-
require 'active_utils/common/post_data'
|
|
12
|
-
require 'active_utils/common/posts_data'
|
|
13
|
-
require 'active_utils/common/currency_code'
|
|
8
|
+
require 'active_utils'
|
|
14
9
|
|
|
15
10
|
require "offsite_payments/helper"
|
|
16
11
|
require "offsite_payments/notification"
|
data.tar.gz.sig
ADDED
|
Binary file
|
metadata
CHANGED
|
@@ -1,14 +1,36 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: offsite_payments
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tobias Luetke
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
|
-
cert_chain:
|
|
11
|
-
|
|
10
|
+
cert_chain:
|
|
11
|
+
- |
|
|
12
|
+
-----BEGIN CERTIFICATE-----
|
|
13
|
+
MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MQ8wDQYDVQQDDAZhZG1p
|
|
14
|
+
bnMxFzAVBgoJkiaJk/IsZAEZFgdzaG9waWZ5MRMwEQYKCZImiZPyLGQBGRYDY29t
|
|
15
|
+
MB4XDTE0MDUxNTIwMzM0OFoXDTE1MDUxNTIwMzM0OFowPzEPMA0GA1UEAwwGYWRt
|
|
16
|
+
aW5zMRcwFQYKCZImiZPyLGQBGRYHc2hvcGlmeTETMBEGCgmSJomT8ixkARkWA2Nv
|
|
17
|
+
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL0/81O3e1vh5smcwp2G
|
|
18
|
+
MpLQ6q0kejQLa65bPYPxdzWA1SYOKyGfw+yR9LdFzsuKpwWzKq6zX35lj1IckWS4
|
|
19
|
+
bNBEQzxmufUxU0XPM02haFB8fOfDJzdXsWte9Ge4IFwahwn68gpMqN+BvxL+KMYz
|
|
20
|
+
Iut9YmN44d4LZdsENEIO5vmybuG2vYDz7R56qB0PA+Q2P2CdhymsBad2DQs69FBo
|
|
21
|
+
uico9V6VMYYctL9lCYdzu9IXrOYNTt88suKIVzzAlHOKeN0Ng5qdztFoTR8sfxDr
|
|
22
|
+
Ydg3KHl5n47wlpgd8R0f/4b5gGxW+v9pyJCgQnLlRu7DedVSvv7+GMtj3g9r3nhJ
|
|
23
|
+
KqECAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFI/o
|
|
24
|
+
maf34HXbUOQsdoLHacEKQgunMB0GA1UdEQQWMBSBEmFkbWluc0BzaG9waWZ5LmNv
|
|
25
|
+
bTAdBgNVHRIEFjAUgRJhZG1pbnNAc2hvcGlmeS5jb20wDQYJKoZIhvcNAQEFBQAD
|
|
26
|
+
ggEBADkK9aj5T0HPExsov4EoMWFnO+G7RQ28C30VAfKxnL2UxG6i4XMHVs6Xi94h
|
|
27
|
+
qXFw1ec9Y2eDUqaolT3bviOk9BB197+A8Vz/k7MC6ci2NE+yDDB7HAC8zU6LAx8Y
|
|
28
|
+
Iqvw7B/PSZ/pz4bUVFlTATif4mi1vO3lidRkdHRtM7UePSn2rUpOi0gtXBP3bLu5
|
|
29
|
+
YjHJN7wx5cugMEyroKITG5gL0Nxtu21qtOlHX4Hc4KdE2JqzCPOsS4zsZGhgwhPs
|
|
30
|
+
fl3hbtVFTqbOlwL9vy1fudXcolIE/ZTcxQ+er07ZFZdKCXayR9PPs64heamfn0fp
|
|
31
|
+
TConQSX2BnZdhIEYW+cKzEC/bLc=
|
|
32
|
+
-----END CERTIFICATE-----
|
|
33
|
+
date: 2015-01-17 00:00:00.000000000 Z
|
|
12
34
|
dependencies:
|
|
13
35
|
- !ruby/object:Gem::Dependency
|
|
14
36
|
name: activesupport
|
|
@@ -48,6 +70,9 @@ dependencies:
|
|
|
48
70
|
name: money
|
|
49
71
|
requirement: !ruby/object:Gem::Requirement
|
|
50
72
|
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 5.0.0
|
|
51
76
|
- - "<"
|
|
52
77
|
- !ruby/object:Gem::Version
|
|
53
78
|
version: 7.0.0
|
|
@@ -55,6 +80,9 @@ dependencies:
|
|
|
55
80
|
prerelease: false
|
|
56
81
|
version_requirements: !ruby/object:Gem::Requirement
|
|
57
82
|
requirements:
|
|
83
|
+
- - ">="
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: 5.0.0
|
|
58
86
|
- - "<"
|
|
59
87
|
- !ruby/object:Gem::Version
|
|
60
88
|
version: 7.0.0
|
|
@@ -79,47 +107,53 @@ dependencies:
|
|
|
79
107
|
- !ruby/object:Gem::Version
|
|
80
108
|
version: 4.0.0
|
|
81
109
|
- !ruby/object:Gem::Dependency
|
|
82
|
-
name:
|
|
110
|
+
name: active_utils
|
|
83
111
|
requirement: !ruby/object:Gem::Requirement
|
|
84
112
|
requirements:
|
|
85
113
|
- - "~>"
|
|
86
114
|
- !ruby/object:Gem::Version
|
|
87
|
-
version:
|
|
115
|
+
version: 3.0.0
|
|
88
116
|
type: :runtime
|
|
89
117
|
prerelease: false
|
|
90
118
|
version_requirements: !ruby/object:Gem::Requirement
|
|
91
119
|
requirements:
|
|
92
120
|
- - "~>"
|
|
93
121
|
- !ruby/object:Gem::Version
|
|
94
|
-
version:
|
|
122
|
+
version: 3.0.0
|
|
95
123
|
- !ruby/object:Gem::Dependency
|
|
96
|
-
name:
|
|
124
|
+
name: nokogiri
|
|
97
125
|
requirement: !ruby/object:Gem::Requirement
|
|
98
126
|
requirements:
|
|
99
127
|
- - "~>"
|
|
100
128
|
- !ruby/object:Gem::Version
|
|
101
|
-
version:
|
|
129
|
+
version: '1.4'
|
|
102
130
|
type: :runtime
|
|
103
131
|
prerelease: false
|
|
104
132
|
version_requirements: !ruby/object:Gem::Requirement
|
|
105
133
|
requirements:
|
|
106
134
|
- - "~>"
|
|
107
135
|
- !ruby/object:Gem::Version
|
|
108
|
-
version:
|
|
136
|
+
version: '1.4'
|
|
109
137
|
- !ruby/object:Gem::Dependency
|
|
110
|
-
name:
|
|
138
|
+
name: actionpack
|
|
111
139
|
requirement: !ruby/object:Gem::Requirement
|
|
112
140
|
requirements:
|
|
113
|
-
- - "
|
|
141
|
+
- - ">="
|
|
114
142
|
- !ruby/object:Gem::Version
|
|
115
|
-
version:
|
|
143
|
+
version: 3.2.20
|
|
144
|
+
- - "<"
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: 5.0.0
|
|
116
147
|
type: :runtime
|
|
117
148
|
prerelease: false
|
|
118
149
|
version_requirements: !ruby/object:Gem::Requirement
|
|
119
150
|
requirements:
|
|
120
|
-
- - "
|
|
151
|
+
- - ">="
|
|
121
152
|
- !ruby/object:Gem::Version
|
|
122
|
-
version:
|
|
153
|
+
version: 3.2.20
|
|
154
|
+
- - "<"
|
|
155
|
+
- !ruby/object:Gem::Version
|
|
156
|
+
version: 5.0.0
|
|
123
157
|
- !ruby/object:Gem::Dependency
|
|
124
158
|
name: rake
|
|
125
159
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -134,20 +168,34 @@ dependencies:
|
|
|
134
168
|
- - ">="
|
|
135
169
|
- !ruby/object:Gem::Version
|
|
136
170
|
version: '0'
|
|
171
|
+
- !ruby/object:Gem::Dependency
|
|
172
|
+
name: test-unit
|
|
173
|
+
requirement: !ruby/object:Gem::Requirement
|
|
174
|
+
requirements:
|
|
175
|
+
- - "~>"
|
|
176
|
+
- !ruby/object:Gem::Version
|
|
177
|
+
version: '3.0'
|
|
178
|
+
type: :development
|
|
179
|
+
prerelease: false
|
|
180
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
181
|
+
requirements:
|
|
182
|
+
- - "~>"
|
|
183
|
+
- !ruby/object:Gem::Version
|
|
184
|
+
version: '3.0'
|
|
137
185
|
- !ruby/object:Gem::Dependency
|
|
138
186
|
name: mocha
|
|
139
187
|
requirement: !ruby/object:Gem::Requirement
|
|
140
188
|
requirements:
|
|
141
189
|
- - "~>"
|
|
142
190
|
- !ruby/object:Gem::Version
|
|
143
|
-
version:
|
|
191
|
+
version: '1.0'
|
|
144
192
|
type: :development
|
|
145
193
|
prerelease: false
|
|
146
194
|
version_requirements: !ruby/object:Gem::Requirement
|
|
147
195
|
requirements:
|
|
148
196
|
- - "~>"
|
|
149
197
|
- !ruby/object:Gem::Version
|
|
150
|
-
version:
|
|
198
|
+
version: '1.0'
|
|
151
199
|
- !ruby/object:Gem::Dependency
|
|
152
200
|
name: rails
|
|
153
201
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -198,6 +246,7 @@ files:
|
|
|
198
246
|
- lib/offsite_payments/integrations/bogus.rb
|
|
199
247
|
- lib/offsite_payments/integrations/chronopay.rb
|
|
200
248
|
- lib/offsite_payments/integrations/citrus.rb
|
|
249
|
+
- lib/offsite_payments/integrations/coinbase.rb
|
|
201
250
|
- lib/offsite_payments/integrations/direc_pay.rb
|
|
202
251
|
- lib/offsite_payments/integrations/directebanking.rb
|
|
203
252
|
- lib/offsite_payments/integrations/doku.rb
|
|
@@ -230,6 +279,7 @@ files:
|
|
|
230
279
|
- lib/offsite_payments/integrations/pxpay.rb
|
|
231
280
|
- lib/offsite_payments/integrations/quickpay.rb
|
|
232
281
|
- lib/offsite_payments/integrations/rbkmoney.rb
|
|
282
|
+
- lib/offsite_payments/integrations/realex.rb
|
|
233
283
|
- lib/offsite_payments/integrations/robokassa.rb
|
|
234
284
|
- lib/offsite_payments/integrations/sage_pay_form.rb
|
|
235
285
|
- lib/offsite_payments/integrations/two_checkout.rb
|
metadata.gz.sig
ADDED
|
Binary file
|