koffsite_payments 3.0.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +13 -0
- data/lib/offsite_payments.rb +48 -0
- data/lib/offsite_payments/action_view_helper.rb +72 -0
- data/lib/offsite_payments/helper.rb +119 -0
- data/lib/offsite_payments/integrations.rb +14 -0
- data/lib/offsite_payments/integrations/a1agregator.rb +245 -0
- data/lib/offsite_payments/integrations/authorize_net_sim.rb +580 -0
- data/lib/offsite_payments/integrations/bit_pay.rb +150 -0
- data/lib/offsite_payments/integrations/bogus.rb +32 -0
- data/lib/offsite_payments/integrations/chronopay.rb +283 -0
- data/lib/offsite_payments/integrations/citrus.rb +227 -0
- data/lib/offsite_payments/integrations/coinbase.rb +166 -0
- data/lib/offsite_payments/integrations/direc_pay.rb +339 -0
- data/lib/offsite_payments/integrations/directebanking.rb +237 -0
- data/lib/offsite_payments/integrations/doku.rb +171 -0
- data/lib/offsite_payments/integrations/dotpay.rb +166 -0
- data/lib/offsite_payments/integrations/dwolla.rb +160 -0
- data/lib/offsite_payments/integrations/e_payment_plans.rb +146 -0
- data/lib/offsite_payments/integrations/easy_pay.rb +137 -0
- data/lib/offsite_payments/integrations/epay.rb +161 -0
- data/lib/offsite_payments/integrations/first_data.rb +133 -0
- data/lib/offsite_payments/integrations/gestpay.rb +203 -0
- data/lib/offsite_payments/integrations/hi_trust.rb +179 -0
- data/lib/offsite_payments/integrations/ipay88.rb +251 -0
- data/lib/offsite_payments/integrations/klarna.rb +291 -0
- data/lib/offsite_payments/integrations/liqpay.rb +216 -0
- data/lib/offsite_payments/integrations/maksuturva.rb +231 -0
- data/lib/offsite_payments/integrations/mollie_ideal.rb +216 -0
- data/lib/offsite_payments/integrations/moneybookers.rb +199 -0
- data/lib/offsite_payments/integrations/nochex.rb +228 -0
- data/lib/offsite_payments/integrations/pag_seguro.rb +268 -0
- data/lib/offsite_payments/integrations/paxum.rb +114 -0
- data/lib/offsite_payments/integrations/pay_fast.rb +269 -0
- data/lib/offsite_payments/integrations/pay_u_latam.rb +246 -0
- data/lib/offsite_payments/integrations/paydollar.rb +142 -0
- data/lib/offsite_payments/integrations/payflow_link.rb +194 -0
- data/lib/offsite_payments/integrations/paypal.rb +362 -0
- data/lib/offsite_payments/integrations/paypal_payments_advanced.rb +23 -0
- data/lib/offsite_payments/integrations/paysbuy.rb +71 -0
- data/lib/offsite_payments/integrations/payu_in.rb +266 -0
- data/lib/offsite_payments/integrations/payu_in_paisa.rb +46 -0
- data/lib/offsite_payments/integrations/platron.rb +153 -0
- data/lib/offsite_payments/integrations/pxpay.rb +273 -0
- data/lib/offsite_payments/integrations/quickpay.rb +232 -0
- data/lib/offsite_payments/integrations/rbkmoney.rb +110 -0
- data/lib/offsite_payments/integrations/robokassa.rb +154 -0
- data/lib/offsite_payments/integrations/sage_pay_form.rb +425 -0
- data/lib/offsite_payments/integrations/two_checkout.rb +329 -0
- data/lib/offsite_payments/integrations/universal.rb +181 -0
- data/lib/offsite_payments/integrations/valitor.rb +200 -0
- data/lib/offsite_payments/integrations/verkkomaksut.rb +143 -0
- data/lib/offsite_payments/integrations/web_pay.rb +186 -0
- data/lib/offsite_payments/integrations/webmoney.rb +119 -0
- data/lib/offsite_payments/integrations/wirecard_checkout_page.rb +359 -0
- data/lib/offsite_payments/integrations/world_pay.rb +273 -0
- data/lib/offsite_payments/notification.rb +71 -0
- data/lib/offsite_payments/return.rb +37 -0
- data/lib/offsite_payments/version.rb +3 -0
- metadata +268 -0
@@ -0,0 +1,114 @@
|
|
1
|
+
module OffsitePayments #:nodoc:
|
2
|
+
module Integrations #:nodoc:
|
3
|
+
# Documentation:
|
4
|
+
# https://www.paxum.com/payment_docs/page.php?name=apiIntroduction
|
5
|
+
module Paxum
|
6
|
+
mattr_accessor :test_url
|
7
|
+
self.test_url = 'https://paxum.com/payment/phrame.php?action=displayProcessPaymentLogin'
|
8
|
+
|
9
|
+
mattr_accessor :production_url
|
10
|
+
self.production_url = 'https://paxum.com/payment/phrame.php?action=displayProcessPaymentLogin'
|
11
|
+
|
12
|
+
mattr_accessor :signature_parameter_name
|
13
|
+
self.signature_parameter_name = 'key'
|
14
|
+
|
15
|
+
def self.service_url
|
16
|
+
mode = OffsitePayments.mode
|
17
|
+
case mode
|
18
|
+
when :production
|
19
|
+
self.production_url
|
20
|
+
when :test
|
21
|
+
self.test_url
|
22
|
+
else
|
23
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.helper(order, account, options = {})
|
28
|
+
Helper.new(order, account, options)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.notification(query_string, options = {})
|
32
|
+
Notification.new(query_string, options)
|
33
|
+
end
|
34
|
+
|
35
|
+
module Common
|
36
|
+
def generate_signature_string
|
37
|
+
@raw_post.slice!(0) if @raw_post.starts_with?("&")
|
38
|
+
@raw_post = CGI.unescape(@raw_post)
|
39
|
+
@raw_post = "&#{@raw_post}" unless @raw_post.starts_with?("&")
|
40
|
+
arr = @raw_post.split('&')
|
41
|
+
arr.delete(arr.last)
|
42
|
+
data = arr.join('&')
|
43
|
+
|
44
|
+
(data + secret)
|
45
|
+
end
|
46
|
+
|
47
|
+
def generate_signature
|
48
|
+
Digest::MD5.hexdigest(generate_signature_string)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Helper < OffsitePayments::Helper
|
53
|
+
include Common
|
54
|
+
|
55
|
+
def initialize(order, account, options = {})
|
56
|
+
@paxum_options = options.dup
|
57
|
+
options.delete(:description)
|
58
|
+
options.delete(:fail_url)
|
59
|
+
options.delete(:success_url)
|
60
|
+
options.delete(:result_url)
|
61
|
+
super
|
62
|
+
add_field "button_type_id", "1"
|
63
|
+
add_field "variables", "notify_url=#{@paxum_options[:result_url]}"
|
64
|
+
@paxum_options.each do |key, value|
|
65
|
+
add_field mappings[key], value
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def form_fields
|
70
|
+
@fields
|
71
|
+
end
|
72
|
+
|
73
|
+
def params
|
74
|
+
@fields
|
75
|
+
end
|
76
|
+
|
77
|
+
mapping :account, 'business_email'
|
78
|
+
mapping :amount, 'amount'
|
79
|
+
mapping :currency, 'currency'
|
80
|
+
mapping :order, 'item_id'
|
81
|
+
mapping :description, 'item_name'
|
82
|
+
mapping :fail_url, 'cancel_url'
|
83
|
+
mapping :success_url, 'finish_url'
|
84
|
+
mapping :result_url, 'notify_url'
|
85
|
+
end
|
86
|
+
|
87
|
+
class Notification < OffsitePayments::Notification
|
88
|
+
include Common
|
89
|
+
|
90
|
+
def initialize(post, options = {})
|
91
|
+
@raw_post = post.dup
|
92
|
+
post.slice!(0)
|
93
|
+
super
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.recognizes?(params)
|
97
|
+
(params.has_key?('transaction_item_id') && params.has_key?('transaction_amount'))
|
98
|
+
end
|
99
|
+
|
100
|
+
def security_key
|
101
|
+
params["key"]
|
102
|
+
end
|
103
|
+
|
104
|
+
def secret
|
105
|
+
@options[:secret]
|
106
|
+
end
|
107
|
+
|
108
|
+
def acknowledge(authcode = nil)
|
109
|
+
(security_key == generate_signature)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
module OffsitePayments #:nodoc:
|
2
|
+
module Integrations #:nodoc:
|
3
|
+
# Documentation:
|
4
|
+
# https://www.payfast.co.za/s/std/integration-guide
|
5
|
+
module PayFast
|
6
|
+
# Overwrite this if you want to change the PayFast sandbox url
|
7
|
+
mattr_accessor :process_test_url
|
8
|
+
self.process_test_url = 'https://sandbox.payfast.co.za/eng/process'
|
9
|
+
|
10
|
+
# Overwrite this if you want to change the PayFast production url
|
11
|
+
mattr_accessor :process_production_url
|
12
|
+
self.process_production_url = 'https://www.payfast.co.za/eng/process'
|
13
|
+
|
14
|
+
# Overwrite this if you want to change the PayFast sandbox url
|
15
|
+
mattr_accessor :validate_test_url
|
16
|
+
self.validate_test_url = 'https://sandbox.payfast.co.za/eng/query/validate'
|
17
|
+
|
18
|
+
# Overwrite this if you want to change the PayFast production url
|
19
|
+
mattr_accessor :validate_production_url
|
20
|
+
self.validate_production_url = 'https://www.payfast.co.za/eng/query/validate'
|
21
|
+
|
22
|
+
mattr_accessor :signature_parameter_name
|
23
|
+
self.signature_parameter_name = 'signature'
|
24
|
+
|
25
|
+
def self.service_url
|
26
|
+
mode = OffsitePayments.mode
|
27
|
+
case mode
|
28
|
+
when :production
|
29
|
+
self.process_production_url
|
30
|
+
when :test
|
31
|
+
self.process_test_url
|
32
|
+
else
|
33
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.validate_service_url
|
38
|
+
mode = OffsitePayments.mode
|
39
|
+
case mode
|
40
|
+
when :production
|
41
|
+
self.validate_production_url
|
42
|
+
when :test
|
43
|
+
self.validate_test_url
|
44
|
+
else
|
45
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.helper(order, account, options = {})
|
50
|
+
Helper.new(order, account, options)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.notification(query_string, options = {})
|
54
|
+
Notification.new(query_string, options)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.return(post, options = {})
|
58
|
+
Return.new(post, options)
|
59
|
+
end
|
60
|
+
|
61
|
+
module Common
|
62
|
+
def generate_signature(type)
|
63
|
+
string = case type
|
64
|
+
when :request
|
65
|
+
request_signature_string
|
66
|
+
when :notify
|
67
|
+
notify_signature_string
|
68
|
+
end
|
69
|
+
|
70
|
+
Digest::MD5.hexdigest(string)
|
71
|
+
end
|
72
|
+
|
73
|
+
def request_attributes
|
74
|
+
[:merchant_id, :merchant_key, :return_url, :cancel_url,
|
75
|
+
:notify_url, :name_first, :name_last, :email_address,
|
76
|
+
:payment_id, :amount, :item_name, :item_description,
|
77
|
+
:custom_str1, :custom_str2, :custom_str3, :custom_str4,
|
78
|
+
:custom_str5, :custom_int1, :custom_int2, :custom_int3,
|
79
|
+
:custom_int4, :custom_int5, :email_confirmation,
|
80
|
+
:confirmation_address]
|
81
|
+
end
|
82
|
+
|
83
|
+
def request_signature_string
|
84
|
+
request_attributes.map do |attr|
|
85
|
+
"#{mappings[attr]}=#{CGI.escape(@fields[mappings[attr]])}" if @fields[mappings[attr]].present?
|
86
|
+
end.compact.join('&')
|
87
|
+
end
|
88
|
+
|
89
|
+
def notify_signature_string
|
90
|
+
params.map do |key, value|
|
91
|
+
"#{key}=#{CGI.escape(value)}" unless key == PayFast.signature_parameter_name
|
92
|
+
end.compact.join('&')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class Helper < OffsitePayments::Helper
|
97
|
+
include Common
|
98
|
+
|
99
|
+
def initialize(order, account, options = {})
|
100
|
+
super
|
101
|
+
add_field('merchant_id', account)
|
102
|
+
add_field('merchant_key', options.delete(:credential2))
|
103
|
+
add_field('m_payment_id', order)
|
104
|
+
end
|
105
|
+
|
106
|
+
def form_fields
|
107
|
+
@fields
|
108
|
+
end
|
109
|
+
|
110
|
+
def params
|
111
|
+
@fields
|
112
|
+
end
|
113
|
+
|
114
|
+
mapping :merchant_id, 'merchant_id'
|
115
|
+
mapping :merchant_key, 'merchant_key'
|
116
|
+
mapping :return_url, 'return_url'
|
117
|
+
mapping :cancel_return_url, 'cancel_url'
|
118
|
+
mapping :notify_url, 'notify_url'
|
119
|
+
mapping :name_first, 'name_first'
|
120
|
+
mapping :name_last, 'name_last'
|
121
|
+
mapping :email_address, 'email_address'
|
122
|
+
mapping :payment_id, 'm_payment_id'
|
123
|
+
mapping :amount, 'amount'
|
124
|
+
mapping :item_name, 'item_name'
|
125
|
+
mapping :description, 'item_name'
|
126
|
+
|
127
|
+
mapping :customer, :first_name => 'name_first',
|
128
|
+
:last_name => 'name_last',
|
129
|
+
:email => 'email_address',
|
130
|
+
:phone => 'phone'
|
131
|
+
|
132
|
+
5.times { |i| mapping :"custom_str#{i}", "custom_str#{i}" }
|
133
|
+
5.times { |i| mapping :"custom_int#{i}", "custom_int#{i}" }
|
134
|
+
|
135
|
+
mapping :email_confirmation, 'email_confirmation'
|
136
|
+
mapping :confirmation_address, 'confirmation_address'
|
137
|
+
end
|
138
|
+
|
139
|
+
# Parser and handler for incoming ITN from PayFast.
|
140
|
+
# The Example shows a typical handler in a rails application.
|
141
|
+
#
|
142
|
+
# Example
|
143
|
+
#
|
144
|
+
# class BackendController < ApplicationController
|
145
|
+
# include OffsitePayments::Integrations
|
146
|
+
#
|
147
|
+
# def pay_fast_itn
|
148
|
+
# notify = PayFast::Notification.new(request.raw_post)
|
149
|
+
#
|
150
|
+
# order = Order.find(notify.item_id)
|
151
|
+
#
|
152
|
+
# if notify.acknowledge
|
153
|
+
# begin
|
154
|
+
#
|
155
|
+
# if notify.complete? and order.total == notify.amount
|
156
|
+
# order.status = 'success'
|
157
|
+
#
|
158
|
+
# shop.ship(order)
|
159
|
+
# else
|
160
|
+
# logger.error("Failed to verify Paypal's notification, please investigate")
|
161
|
+
# end
|
162
|
+
#
|
163
|
+
# rescue => e
|
164
|
+
# order.status = 'failed'
|
165
|
+
# raise
|
166
|
+
# ensure
|
167
|
+
# order.save
|
168
|
+
# end
|
169
|
+
# end
|
170
|
+
#
|
171
|
+
# render :nothing
|
172
|
+
# end
|
173
|
+
# end
|
174
|
+
class Notification < OffsitePayments::Notification
|
175
|
+
include ActiveMerchant::PostsData
|
176
|
+
include Common
|
177
|
+
|
178
|
+
# Was the transaction complete?
|
179
|
+
def complete?
|
180
|
+
status == "Completed"
|
181
|
+
end
|
182
|
+
|
183
|
+
# Status of transaction. List of possible values:
|
184
|
+
# <tt>COMPLETE</tt>::
|
185
|
+
def status
|
186
|
+
if params['payment_status'] == "COMPLETE"
|
187
|
+
"Completed"
|
188
|
+
else
|
189
|
+
"Failed"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Id of this transaction (uniq PayFast transaction id)
|
194
|
+
def transaction_id
|
195
|
+
params['pf_payment_id']
|
196
|
+
end
|
197
|
+
|
198
|
+
# Id of this transaction (uniq Shopify transaction id)
|
199
|
+
def item_id
|
200
|
+
params['m_payment_id']
|
201
|
+
end
|
202
|
+
|
203
|
+
# The total amount which the payer paid.
|
204
|
+
def gross
|
205
|
+
params['amount_gross']
|
206
|
+
end
|
207
|
+
|
208
|
+
# The total in fees which was deducted from the amount.
|
209
|
+
def fee
|
210
|
+
params['amount_fee']
|
211
|
+
end
|
212
|
+
|
213
|
+
# The net amount credited to the receiver's account.
|
214
|
+
def amount
|
215
|
+
params['amount_net']
|
216
|
+
end
|
217
|
+
|
218
|
+
# The name of the item being charged for.
|
219
|
+
def item_name
|
220
|
+
params['item_name']
|
221
|
+
end
|
222
|
+
|
223
|
+
# The Merchant ID as given by the PayFast system. Used to uniquely identify the receiver's account.
|
224
|
+
def merchant_id
|
225
|
+
params['merchant_id']
|
226
|
+
end
|
227
|
+
|
228
|
+
def currency
|
229
|
+
nil
|
230
|
+
end
|
231
|
+
|
232
|
+
# Generated hash depends on params order so use OrderedHash instead of Hash
|
233
|
+
def empty!
|
234
|
+
super
|
235
|
+
@params = ActiveSupport::OrderedHash.new
|
236
|
+
end
|
237
|
+
|
238
|
+
# Acknowledge the transaction to PayFast. This method has to be called after a new
|
239
|
+
# ITN arrives. PayFast will verify that all the information we received are correct and will return a
|
240
|
+
# VERIFIED or INVALID status.
|
241
|
+
#
|
242
|
+
# Example:
|
243
|
+
#
|
244
|
+
# def pay_fast_itn
|
245
|
+
# notify = PayFastNotification.new(request.raw_post)
|
246
|
+
#
|
247
|
+
# if notify.acknowledge
|
248
|
+
# ... process order ... if notify.complete?
|
249
|
+
# else
|
250
|
+
# ... log possible hacking attempt ...
|
251
|
+
# end
|
252
|
+
def acknowledge(authcode = nil)
|
253
|
+
if params[PayFast.signature_parameter_name] == generate_signature(:notify)
|
254
|
+
response = ssl_post(PayFast.validate_service_url, notify_signature_string,
|
255
|
+
'Content-Type' => "application/x-www-form-urlencoded",
|
256
|
+
'Content-Length' => "#{notify_signature_string.size}"
|
257
|
+
)
|
258
|
+
raise StandardError.new("Faulty PayFast result: #{response}") unless ['VALID', 'INVALID'].include?(response)
|
259
|
+
|
260
|
+
response == "VALID"
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
class Return < OffsitePayments::Return
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
@@ -0,0 +1,246 @@
|
|
1
|
+
require 'builder'
|
2
|
+
|
3
|
+
module OffsitePayments #:nodoc:
|
4
|
+
module Integrations #:nodoc:
|
5
|
+
module PayULatam
|
6
|
+
|
7
|
+
mattr_accessor :test_url
|
8
|
+
self.test_url = 'https://stg.api.payulatam.com/payments-api/4.0/service.cgi'
|
9
|
+
|
10
|
+
mattr_accessor :production_url
|
11
|
+
self.production_url = 'https://api.payulatam.com/payments-api/4.0/service.cgi'
|
12
|
+
|
13
|
+
QUERIES_API_TEST_URL = 'https://stg.api.payulatam.com/reports-api/4.0/service.cgi'
|
14
|
+
QUERIES_API_LIVE_URL = 'https://api.payulatam.com/reports-api/4.0/service.cgi'
|
15
|
+
|
16
|
+
QUERY_COMMANDS = {
|
17
|
+
:orderId => 'ORDER_DETAIL',
|
18
|
+
:referenceCode => 'ORDER_DETAIL_BY_REFERENCE_CODE',
|
19
|
+
:transactionId => 'TRANSACTION_RESPONSE_DETAIL',
|
20
|
+
}
|
21
|
+
|
22
|
+
def self.service_url
|
23
|
+
mode = OffsitePayments.mode
|
24
|
+
case mode
|
25
|
+
when :production
|
26
|
+
self.production_url
|
27
|
+
when :test
|
28
|
+
self.test_url
|
29
|
+
else
|
30
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.queries_url
|
35
|
+
mode = OffsitePayments.mode
|
36
|
+
case mode
|
37
|
+
when :production
|
38
|
+
QUERIES_API_LIVE_URL
|
39
|
+
when :test
|
40
|
+
QUERIES_API_TEST_URL
|
41
|
+
else
|
42
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.helper(order, account, options = {})
|
47
|
+
Helper.new(order, account, options)
|
48
|
+
end
|
49
|
+
|
50
|
+
class Helper < OffsitePayments::Helper
|
51
|
+
|
52
|
+
mapping :customer,
|
53
|
+
:name => 'name',
|
54
|
+
:email => 'email',
|
55
|
+
:phone => 'phone',
|
56
|
+
:dni_number => 'dniNumber'
|
57
|
+
|
58
|
+
mapping :billing_address,
|
59
|
+
:address1 => 'address1',
|
60
|
+
:city => 'city',
|
61
|
+
:state => 'state',
|
62
|
+
:country => 'country'
|
63
|
+
|
64
|
+
mapping :amount, 'amount'
|
65
|
+
mapping :currency, 'currency'
|
66
|
+
mapping :order, 'order'
|
67
|
+
mapping :description, 'description'
|
68
|
+
|
69
|
+
mapping :language, 'language'
|
70
|
+
mapping :payment_method, 'paymentMethod'
|
71
|
+
mapping :expiration_date, 'expirationDate'
|
72
|
+
|
73
|
+
# These credentials are mandatory:
|
74
|
+
#
|
75
|
+
# credential2: api_login
|
76
|
+
# credential3: api_key
|
77
|
+
# credential4: account_id
|
78
|
+
def initialize(order, merchant_id, options = {})
|
79
|
+
super
|
80
|
+
@merchant_id = merchant_id
|
81
|
+
@options = options
|
82
|
+
|
83
|
+
add_field 'language', 'en'
|
84
|
+
end
|
85
|
+
|
86
|
+
def api_login
|
87
|
+
@options[:credential2]
|
88
|
+
end
|
89
|
+
|
90
|
+
def api_key
|
91
|
+
@options[:credential3]
|
92
|
+
end
|
93
|
+
|
94
|
+
def account_id
|
95
|
+
@options[:credential4]
|
96
|
+
end
|
97
|
+
|
98
|
+
def merchant_id
|
99
|
+
@merchant_id
|
100
|
+
end
|
101
|
+
|
102
|
+
def form_method
|
103
|
+
'GET'
|
104
|
+
end
|
105
|
+
|
106
|
+
def form_fields
|
107
|
+
cash_request = send_request(PayULatam.service_url, build_cash_request)
|
108
|
+
|
109
|
+
raise ActionViewHelperError, "Invalid response: #{cash_request}" unless success_cash_request_response?(cash_request)
|
110
|
+
|
111
|
+
{
|
112
|
+
:order_id => cash_request['transactionResponse']['orderId'],
|
113
|
+
:transaction_id => cash_request['transactionResponse']['transactionId'],
|
114
|
+
:url => cash_request['transactionResponse']['extraParameters']['URL_PAYMENT_RECEIPT_HTML'],
|
115
|
+
:expiration_date => cash_request['transactionResponse']['extraParameters']['EXPIRATION_DATE'],
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
def order_status(order_id)
|
120
|
+
request_status = send_request(PayULatam.queries_url, build_query_request(:orderId, order_id))
|
121
|
+
|
122
|
+
raise ActionViewHelperError, "Invalid response: #{request_status}" unless success_response?(request_status)
|
123
|
+
# Not found?
|
124
|
+
return nil if request_status['result'].nil? or request_status['result']['payload'].nil?
|
125
|
+
|
126
|
+
{
|
127
|
+
:order_id => request_status['result']['payload']['id'],
|
128
|
+
:status => request_status['result']['payload']['status'],
|
129
|
+
:reference_code => request_status['result']['payload']['referenceCode'],
|
130
|
+
:description => request_status['result']['payload']['description']
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
134
|
+
def transaction_status(transaction_id)
|
135
|
+
request_status = send_request(PayULatam.queries_url, build_query_request(:transactionId, transaction_id))
|
136
|
+
|
137
|
+
raise ActionViewHelperError, "Invalid response: #{request_status}" unless success_response?(request_status)
|
138
|
+
# Not found?
|
139
|
+
return nil if request_status['result'].nil? or request_status['result']['payload'].nil?
|
140
|
+
|
141
|
+
{
|
142
|
+
:status => request_status['result']['payload']['state'],
|
143
|
+
:traceability_code => request_status['result']['payload']['trazabilityCode'],
|
144
|
+
:authorization => request_status['result']['payload']['authorizationCode']
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
def orders_statuses(reference_code)
|
149
|
+
request_status = send_request(PayULatam.queries_url, build_query_request(:referenceCode, reference_code))
|
150
|
+
|
151
|
+
raise ActionViewHelperError, "Invalid response: #{request_status}" unless success_response?(request_status)
|
152
|
+
# Not found?
|
153
|
+
return nil if request_status['result'].nil?
|
154
|
+
|
155
|
+
request_status['result']['payload']
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
def send_request(url, request_body)
|
161
|
+
uri = URI.parse(url)
|
162
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
163
|
+
http.use_ssl = true
|
164
|
+
# PayULatam's test server has an improperly installed cert
|
165
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if test?
|
166
|
+
|
167
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
168
|
+
request['Accept'] = 'application/json'
|
169
|
+
request.content_type = 'application/json'
|
170
|
+
request.body = request_body
|
171
|
+
|
172
|
+
response = http.request(request)
|
173
|
+
JSON.parse(response.body)
|
174
|
+
rescue JSON::ParserError
|
175
|
+
response.body
|
176
|
+
end
|
177
|
+
|
178
|
+
def build_cash_request
|
179
|
+
shipping_address = {}
|
180
|
+
shipping_address[:street1] = @fields['address1'] unless @fields['address1'].nil?
|
181
|
+
shipping_address[:city] = @fields['city'] unless @fields['city'].nil?
|
182
|
+
shipping_address[:state] = @fields['state'] unless @fields['state'].nil?
|
183
|
+
shipping_address[:country] = @fields['country'] unless @fields['country'].nil?
|
184
|
+
shipping_address[:phone] = @fields['phone'] unless @fields['phone'].nil?
|
185
|
+
|
186
|
+
buyer = {}
|
187
|
+
buyer[:fullName] = @fields['name'] unless @fields['name'].nil?
|
188
|
+
buyer[:emailAddress] = @fields['email'] unless @fields['email'].nil?
|
189
|
+
buyer[:dniNumber] = @fields['dniNumber'] unless @fields['dniNumber'].nil?
|
190
|
+
buyer[:shippingAddress] = shipping_address
|
191
|
+
|
192
|
+
order = {}
|
193
|
+
order[:accountId] = account_id
|
194
|
+
order[:referenceCode] = @fields['order']
|
195
|
+
order[:description] = @fields['description']
|
196
|
+
order[:language] = @fields['language']
|
197
|
+
order[:signature] = signature
|
198
|
+
order[:shippingAddress] = {:country => @fields['country']} unless @fields['country'].nil?
|
199
|
+
order[:buyer] = buyer
|
200
|
+
order[:additionalValues] = {:TX_VALUE => {:value => @fields['amount'].to_i, :currency => @fields['currency']}}
|
201
|
+
|
202
|
+
transaction = {}
|
203
|
+
transaction[:order] = order
|
204
|
+
transaction[:type] = 'AUTHORIZATION_AND_CAPTURE'
|
205
|
+
transaction[:paymentMethod] = @fields['paymentMethod']
|
206
|
+
transaction[:expirationDate] = @fields['expirationDate'] unless @fields['expirationDate'].nil?
|
207
|
+
|
208
|
+
request = build_base_request('SUBMIT_TRANSACTION')
|
209
|
+
request[:transaction] = transaction
|
210
|
+
|
211
|
+
request.to_json
|
212
|
+
end
|
213
|
+
|
214
|
+
def build_query_request(key, value)
|
215
|
+
request = build_base_request(QUERY_COMMANDS[key])
|
216
|
+
request[:details] = {key => value}
|
217
|
+
|
218
|
+
request.to_json
|
219
|
+
end
|
220
|
+
|
221
|
+
def build_base_request(command)
|
222
|
+
request = {}
|
223
|
+
request[:language] = @fields['language']
|
224
|
+
request[:command] = command
|
225
|
+
# Should always be false, even in test mode
|
226
|
+
request[:test] = 'false'
|
227
|
+
request[:merchant] = {:apiLogin => api_login, :apiKey => api_key}
|
228
|
+
request
|
229
|
+
end
|
230
|
+
|
231
|
+
def signature
|
232
|
+
raw = "#{api_key}~#{merchant_id}~#{@fields['order']}~#{@fields['amount']}~#{@fields['currency']}"
|
233
|
+
Digest::MD5.hexdigest(raw)
|
234
|
+
end
|
235
|
+
|
236
|
+
def success_cash_request_response?(cash_request_response)
|
237
|
+
success_response?(cash_request_response) and cash_request_response['transactionResponse'].is_a?(Hash) and cash_request_response['transactionResponse']['errorCode'].nil?
|
238
|
+
end
|
239
|
+
|
240
|
+
def success_response?(response)
|
241
|
+
response.is_a?(Hash) and response['code'] == 'SUCCESS' and response['error'].nil?
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|