koffsite_payments 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +13 -0
  4. data/lib/offsite_payments.rb +48 -0
  5. data/lib/offsite_payments/action_view_helper.rb +72 -0
  6. data/lib/offsite_payments/helper.rb +119 -0
  7. data/lib/offsite_payments/integrations.rb +14 -0
  8. data/lib/offsite_payments/integrations/a1agregator.rb +245 -0
  9. data/lib/offsite_payments/integrations/authorize_net_sim.rb +580 -0
  10. data/lib/offsite_payments/integrations/bit_pay.rb +150 -0
  11. data/lib/offsite_payments/integrations/bogus.rb +32 -0
  12. data/lib/offsite_payments/integrations/chronopay.rb +283 -0
  13. data/lib/offsite_payments/integrations/citrus.rb +227 -0
  14. data/lib/offsite_payments/integrations/coinbase.rb +166 -0
  15. data/lib/offsite_payments/integrations/direc_pay.rb +339 -0
  16. data/lib/offsite_payments/integrations/directebanking.rb +237 -0
  17. data/lib/offsite_payments/integrations/doku.rb +171 -0
  18. data/lib/offsite_payments/integrations/dotpay.rb +166 -0
  19. data/lib/offsite_payments/integrations/dwolla.rb +160 -0
  20. data/lib/offsite_payments/integrations/e_payment_plans.rb +146 -0
  21. data/lib/offsite_payments/integrations/easy_pay.rb +137 -0
  22. data/lib/offsite_payments/integrations/epay.rb +161 -0
  23. data/lib/offsite_payments/integrations/first_data.rb +133 -0
  24. data/lib/offsite_payments/integrations/gestpay.rb +203 -0
  25. data/lib/offsite_payments/integrations/hi_trust.rb +179 -0
  26. data/lib/offsite_payments/integrations/ipay88.rb +251 -0
  27. data/lib/offsite_payments/integrations/klarna.rb +291 -0
  28. data/lib/offsite_payments/integrations/liqpay.rb +216 -0
  29. data/lib/offsite_payments/integrations/maksuturva.rb +231 -0
  30. data/lib/offsite_payments/integrations/mollie_ideal.rb +216 -0
  31. data/lib/offsite_payments/integrations/moneybookers.rb +199 -0
  32. data/lib/offsite_payments/integrations/nochex.rb +228 -0
  33. data/lib/offsite_payments/integrations/pag_seguro.rb +268 -0
  34. data/lib/offsite_payments/integrations/paxum.rb +114 -0
  35. data/lib/offsite_payments/integrations/pay_fast.rb +269 -0
  36. data/lib/offsite_payments/integrations/pay_u_latam.rb +246 -0
  37. data/lib/offsite_payments/integrations/paydollar.rb +142 -0
  38. data/lib/offsite_payments/integrations/payflow_link.rb +194 -0
  39. data/lib/offsite_payments/integrations/paypal.rb +362 -0
  40. data/lib/offsite_payments/integrations/paypal_payments_advanced.rb +23 -0
  41. data/lib/offsite_payments/integrations/paysbuy.rb +71 -0
  42. data/lib/offsite_payments/integrations/payu_in.rb +266 -0
  43. data/lib/offsite_payments/integrations/payu_in_paisa.rb +46 -0
  44. data/lib/offsite_payments/integrations/platron.rb +153 -0
  45. data/lib/offsite_payments/integrations/pxpay.rb +273 -0
  46. data/lib/offsite_payments/integrations/quickpay.rb +232 -0
  47. data/lib/offsite_payments/integrations/rbkmoney.rb +110 -0
  48. data/lib/offsite_payments/integrations/robokassa.rb +154 -0
  49. data/lib/offsite_payments/integrations/sage_pay_form.rb +425 -0
  50. data/lib/offsite_payments/integrations/two_checkout.rb +329 -0
  51. data/lib/offsite_payments/integrations/universal.rb +181 -0
  52. data/lib/offsite_payments/integrations/valitor.rb +200 -0
  53. data/lib/offsite_payments/integrations/verkkomaksut.rb +143 -0
  54. data/lib/offsite_payments/integrations/web_pay.rb +186 -0
  55. data/lib/offsite_payments/integrations/webmoney.rb +119 -0
  56. data/lib/offsite_payments/integrations/wirecard_checkout_page.rb +359 -0
  57. data/lib/offsite_payments/integrations/world_pay.rb +273 -0
  58. data/lib/offsite_payments/notification.rb +71 -0
  59. data/lib/offsite_payments/return.rb +37 -0
  60. data/lib/offsite_payments/version.rb +3 -0
  61. 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