offsite_payments 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|