offsite_payments 2.0.1 → 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.tar.gz.sig +0 -0
- data/README.md +5 -6
- data/lib/offsite_payments.rb +1 -8
- 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 +25 -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
- metadata +44 -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
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
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.
|
data/lib/offsite_payments.rb
CHANGED
@@ -5,14 +5,7 @@ require "socket"
|
|
5
5
|
|
6
6
|
require 'active_support/core_ext/class/delegating_attributes'
|
7
7
|
|
8
|
-
require 'active_utils
|
9
|
-
require 'active_utils/common/connection'
|
10
|
-
require 'active_utils/common/requires_parameters'
|
11
|
-
require 'active_utils/common/country'
|
12
|
-
require 'active_utils/common/error'
|
13
|
-
require 'active_utils/common/post_data'
|
14
|
-
require 'active_utils/common/posts_data'
|
15
|
-
require 'active_utils/common/currency_code'
|
8
|
+
require 'active_utils'
|
16
9
|
|
17
10
|
require "offsite_payments/helper"
|
18
11
|
require "offsite_payments/notification"
|
@@ -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'
|
@@ -62,17 +62,18 @@ module OffsitePayments #:nodoc:
|
|
62
62
|
|
63
63
|
mapping :order, 'reference'
|
64
64
|
|
65
|
-
mapping :billing_address, :city => 'shippingAddressCity',
|
66
|
-
:address1 => 'shippingAddressStreet',
|
67
|
-
:address2 => 'shippingAddressNumber',
|
68
|
-
:state => 'shippingAddressState',
|
69
|
-
:zip => 'shippingAddressPostalCode',
|
70
|
-
:country => 'shippingAddressCountry'
|
71
|
-
|
72
65
|
mapping :notify_url, 'notificationURL'
|
73
66
|
mapping :return_url, 'redirectURL'
|
74
67
|
mapping :description, 'itemDescription1'
|
75
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
|
+
|
76
77
|
def form_fields
|
77
78
|
invoice_id = fetch_token
|
78
79
|
|
@@ -84,11 +85,13 @@ module OffsitePayments #:nodoc:
|
|
84
85
|
end
|
85
86
|
|
86
87
|
def customer(params = {})
|
87
|
-
phone = area_code_and_number(params[:phone])
|
88
88
|
full_name = remove_excessive_whitespace("#{params[:first_name]} #{params[:last_name]}")
|
89
89
|
|
90
|
-
|
91
|
-
|
90
|
+
if phone = area_code_and_number(params[:phone])
|
91
|
+
add_field("senderAreaCode", phone[0])
|
92
|
+
add_field("senderPhone", phone[1])
|
93
|
+
end
|
94
|
+
|
92
95
|
add_field("senderEmail", params[:email])
|
93
96
|
add_field('senderName', full_name)
|
94
97
|
end
|
@@ -108,11 +111,12 @@ module OffsitePayments #:nodoc:
|
|
108
111
|
check_for_errors(response, xml)
|
109
112
|
|
110
113
|
extract_token(xml)
|
111
|
-
rescue Timeout::Error, Errno::ECONNRESET => e
|
114
|
+
rescue Timeout::Error, Errno::ECONNRESET, Errno::ETIMEDOUT => e
|
112
115
|
raise ActionViewHelperError, "Erro ao conectar-se ao PagSeguro. Por favor, tente novamente."
|
113
116
|
end
|
114
117
|
|
115
118
|
def area_code_and_number(phone)
|
119
|
+
return if phone.nil?
|
116
120
|
phone.gsub!(/[^\d]/, '')
|
117
121
|
|
118
122
|
ddd = phone.slice(0..1)
|
@@ -130,7 +134,7 @@ module OffsitePayments #:nodoc:
|
|
130
134
|
when "401"
|
131
135
|
raise ActionViewHelperError, "Token do PagSeguro inválido."
|
132
136
|
else
|
133
|
-
raise
|
137
|
+
raise ActiveUtils::ResponseError, response
|
134
138
|
end
|
135
139
|
end
|
136
140
|
|
@@ -161,13 +165,19 @@ module OffsitePayments #:nodoc:
|
|
161
165
|
end
|
162
166
|
|
163
167
|
class Notification < OffsitePayments::Notification
|
168
|
+
class NotificationError < StandardError; end
|
169
|
+
|
164
170
|
def initialize(post, options = {})
|
171
|
+
@acknowledge = true
|
165
172
|
notify_code = parse_http_query(post)["notificationCode"]
|
166
173
|
email = options[:credential1]
|
167
174
|
token = options[:credential2]
|
168
175
|
|
169
176
|
uri = URI.join(PagSeguro.notification_url, notify_code)
|
170
177
|
parse_xml(web_get(uri, email: email, token: token))
|
178
|
+
|
179
|
+
rescue NotificationError
|
180
|
+
@acknowledge = false
|
171
181
|
end
|
172
182
|
|
173
183
|
def complete?
|
@@ -223,9 +233,8 @@ module OffsitePayments #:nodoc:
|
|
223
233
|
end
|
224
234
|
end
|
225
235
|
|
226
|
-
# There's no acknowledge for PagSeguro
|
227
236
|
def acknowledge
|
228
|
-
|
237
|
+
@acknowledge
|
229
238
|
end
|
230
239
|
|
231
240
|
private
|
@@ -234,6 +243,8 @@ module OffsitePayments #:nodoc:
|
|
234
243
|
uri.query = URI.encode_www_form(params)
|
235
244
|
|
236
245
|
response = Net::HTTP.get_response(uri)
|
246
|
+
raise NotificationError if response.code.to_i > 200
|
247
|
+
|
237
248
|
response.body
|
238
249
|
end
|
239
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
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: offsite_payments
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Luetke
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
fl3hbtVFTqbOlwL9vy1fudXcolIE/ZTcxQ+er07ZFZdKCXayR9PPs64heamfn0fp
|
31
31
|
TConQSX2BnZdhIEYW+cKzEC/bLc=
|
32
32
|
-----END CERTIFICATE-----
|
33
|
-
date:
|
33
|
+
date: 2015-01-17 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: activesupport
|
@@ -70,6 +70,9 @@ dependencies:
|
|
70
70
|
name: money
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 5.0.0
|
73
76
|
- - "<"
|
74
77
|
- !ruby/object:Gem::Version
|
75
78
|
version: 7.0.0
|
@@ -77,6 +80,9 @@ dependencies:
|
|
77
80
|
prerelease: false
|
78
81
|
version_requirements: !ruby/object:Gem::Requirement
|
79
82
|
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 5.0.0
|
80
86
|
- - "<"
|
81
87
|
- !ruby/object:Gem::Version
|
82
88
|
version: 7.0.0
|
@@ -101,47 +107,53 @@ dependencies:
|
|
101
107
|
- !ruby/object:Gem::Version
|
102
108
|
version: 4.0.0
|
103
109
|
- !ruby/object:Gem::Dependency
|
104
|
-
name:
|
110
|
+
name: active_utils
|
105
111
|
requirement: !ruby/object:Gem::Requirement
|
106
112
|
requirements:
|
107
113
|
- - "~>"
|
108
114
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
115
|
+
version: 3.0.0
|
110
116
|
type: :runtime
|
111
117
|
prerelease: false
|
112
118
|
version_requirements: !ruby/object:Gem::Requirement
|
113
119
|
requirements:
|
114
120
|
- - "~>"
|
115
121
|
- !ruby/object:Gem::Version
|
116
|
-
version:
|
122
|
+
version: 3.0.0
|
117
123
|
- !ruby/object:Gem::Dependency
|
118
|
-
name:
|
124
|
+
name: nokogiri
|
119
125
|
requirement: !ruby/object:Gem::Requirement
|
120
126
|
requirements:
|
121
127
|
- - "~>"
|
122
128
|
- !ruby/object:Gem::Version
|
123
|
-
version:
|
129
|
+
version: '1.4'
|
124
130
|
type: :runtime
|
125
131
|
prerelease: false
|
126
132
|
version_requirements: !ruby/object:Gem::Requirement
|
127
133
|
requirements:
|
128
134
|
- - "~>"
|
129
135
|
- !ruby/object:Gem::Version
|
130
|
-
version:
|
136
|
+
version: '1.4'
|
131
137
|
- !ruby/object:Gem::Dependency
|
132
|
-
name:
|
138
|
+
name: actionpack
|
133
139
|
requirement: !ruby/object:Gem::Requirement
|
134
140
|
requirements:
|
135
|
-
- - "
|
141
|
+
- - ">="
|
136
142
|
- !ruby/object:Gem::Version
|
137
|
-
version:
|
143
|
+
version: 3.2.20
|
144
|
+
- - "<"
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 5.0.0
|
138
147
|
type: :runtime
|
139
148
|
prerelease: false
|
140
149
|
version_requirements: !ruby/object:Gem::Requirement
|
141
150
|
requirements:
|
142
|
-
- - "
|
151
|
+
- - ">="
|
143
152
|
- !ruby/object:Gem::Version
|
144
|
-
version:
|
153
|
+
version: 3.2.20
|
154
|
+
- - "<"
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: 5.0.0
|
145
157
|
- !ruby/object:Gem::Dependency
|
146
158
|
name: rake
|
147
159
|
requirement: !ruby/object:Gem::Requirement
|
@@ -156,20 +168,34 @@ dependencies:
|
|
156
168
|
- - ">="
|
157
169
|
- !ruby/object:Gem::Version
|
158
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'
|
159
185
|
- !ruby/object:Gem::Dependency
|
160
186
|
name: mocha
|
161
187
|
requirement: !ruby/object:Gem::Requirement
|
162
188
|
requirements:
|
163
189
|
- - "~>"
|
164
190
|
- !ruby/object:Gem::Version
|
165
|
-
version:
|
191
|
+
version: '1.0'
|
166
192
|
type: :development
|
167
193
|
prerelease: false
|
168
194
|
version_requirements: !ruby/object:Gem::Requirement
|
169
195
|
requirements:
|
170
196
|
- - "~>"
|
171
197
|
- !ruby/object:Gem::Version
|
172
|
-
version:
|
198
|
+
version: '1.0'
|
173
199
|
- !ruby/object:Gem::Dependency
|
174
200
|
name: rails
|
175
201
|
requirement: !ruby/object:Gem::Requirement
|
@@ -220,6 +246,7 @@ files:
|
|
220
246
|
- lib/offsite_payments/integrations/bogus.rb
|
221
247
|
- lib/offsite_payments/integrations/chronopay.rb
|
222
248
|
- lib/offsite_payments/integrations/citrus.rb
|
249
|
+
- lib/offsite_payments/integrations/coinbase.rb
|
223
250
|
- lib/offsite_payments/integrations/direc_pay.rb
|
224
251
|
- lib/offsite_payments/integrations/directebanking.rb
|
225
252
|
- lib/offsite_payments/integrations/doku.rb
|
@@ -252,6 +279,7 @@ files:
|
|
252
279
|
- lib/offsite_payments/integrations/pxpay.rb
|
253
280
|
- lib/offsite_payments/integrations/quickpay.rb
|
254
281
|
- lib/offsite_payments/integrations/rbkmoney.rb
|
282
|
+
- lib/offsite_payments/integrations/realex.rb
|
255
283
|
- lib/offsite_payments/integrations/robokassa.rb
|
256
284
|
- lib/offsite_payments/integrations/sage_pay_form.rb
|
257
285
|
- lib/offsite_payments/integrations/two_checkout.rb
|
@@ -285,7 +313,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
285
313
|
version: '0'
|
286
314
|
requirements: []
|
287
315
|
rubyforge_project:
|
288
|
-
rubygems_version: 2.2.
|
316
|
+
rubygems_version: 2.2.2
|
289
317
|
signing_key:
|
290
318
|
specification_version: 4
|
291
319
|
summary: Framework and tools for dealing with offsite (hosted) payment pages.
|
metadata.gz.sig
CHANGED
Binary file
|