better_offsite_payments 2.3.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.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +76 -0
  4. data/lib/offsite_payments.rb +39 -0
  5. data/lib/offsite_payments/action_view_helper.rb +72 -0
  6. data/lib/offsite_payments/helper.rb +120 -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 +172 -0
  15. data/lib/offsite_payments/integrations/direc_pay.rb +332 -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 +205 -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 +275 -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/megakassa.rb +184 -0
  31. data/lib/offsite_payments/integrations/mollie.rb +32 -0
  32. data/lib/offsite_payments/integrations/mollie_ideal.rb +194 -0
  33. data/lib/offsite_payments/integrations/mollie_mistercash.rb +143 -0
  34. data/lib/offsite_payments/integrations/molpay.rb +193 -0
  35. data/lib/offsite_payments/integrations/moneybookers.rb +199 -0
  36. data/lib/offsite_payments/integrations/nochex.rb +228 -0
  37. data/lib/offsite_payments/integrations/pag_seguro.rb +268 -0
  38. data/lib/offsite_payments/integrations/paxum.rb +114 -0
  39. data/lib/offsite_payments/integrations/pay_fast.rb +269 -0
  40. data/lib/offsite_payments/integrations/paydollar.rb +142 -0
  41. data/lib/offsite_payments/integrations/payflow_link.rb +194 -0
  42. data/lib/offsite_payments/integrations/paypal.rb +362 -0
  43. data/lib/offsite_payments/integrations/paypal_payments_advanced.rb +23 -0
  44. data/lib/offsite_payments/integrations/paysbuy.rb +71 -0
  45. data/lib/offsite_payments/integrations/payu_in.rb +276 -0
  46. data/lib/offsite_payments/integrations/payu_in_paisa.rb +46 -0
  47. data/lib/offsite_payments/integrations/platron.rb +153 -0
  48. data/lib/offsite_payments/integrations/pxpay.rb +273 -0
  49. data/lib/offsite_payments/integrations/quickpay.rb +232 -0
  50. data/lib/offsite_payments/integrations/rbkmoney.rb +110 -0
  51. data/lib/offsite_payments/integrations/realex_offsite.rb +317 -0
  52. data/lib/offsite_payments/integrations/robokassa.rb +154 -0
  53. data/lib/offsite_payments/integrations/sage_pay_form.rb +431 -0
  54. data/lib/offsite_payments/integrations/two_checkout.rb +329 -0
  55. data/lib/offsite_payments/integrations/universal.rb +190 -0
  56. data/lib/offsite_payments/integrations/valitor.rb +200 -0
  57. data/lib/offsite_payments/integrations/verkkomaksut.rb +143 -0
  58. data/lib/offsite_payments/integrations/web_pay.rb +186 -0
  59. data/lib/offsite_payments/integrations/webmoney.rb +119 -0
  60. data/lib/offsite_payments/integrations/wirecard_checkout_page.rb +359 -0
  61. data/lib/offsite_payments/integrations/world_pay.rb +280 -0
  62. data/lib/offsite_payments/integrations/yandex_money.rb +175 -0
  63. data/lib/offsite_payments/notification.rb +71 -0
  64. data/lib/offsite_payments/return.rb +37 -0
  65. data/lib/offsite_payments/version.rb +3 -0
  66. metadata +297 -0
@@ -0,0 +1,32 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ module Mollie
4
+ class API
5
+ include ActiveUtils::PostsData
6
+
7
+ attr_reader :token
8
+
9
+ MOLLIE_API_V1_URI = 'https://api.mollie.nl/v1/'.freeze
10
+
11
+ def initialize(token)
12
+ @token = token
13
+ end
14
+
15
+ def get_request(resource, params = nil)
16
+ uri = URI.parse(MOLLIE_API_V1_URI + resource)
17
+ uri.query = params.map { |k,v| "#{CGI.escape(k)}=#{CGI.escape(v)}}"}.join('&') if params
18
+ headers = { "Authorization" => "Bearer #{token}", "Content-Type" => "application/json" }
19
+ JSON.parse(ssl_get(uri.to_s, headers))
20
+ end
21
+
22
+ def post_request(resource, params = nil)
23
+ uri = URI.parse(MOLLIE_API_V1_URI + resource)
24
+ headers = { "Authorization" => "Bearer #{token}", "Content-Type" => "application/json" }
25
+ data = params.nil? ? nil : JSON.dump(params)
26
+ JSON.parse(ssl_post(uri.to_s, data, headers))
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,194 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ module MollieIdeal
4
+ include Mollie
5
+
6
+ mattr_accessor :live_issuers
7
+ self.live_issuers = [
8
+ ["ABN AMRO", "ideal_ABNANL2A"],
9
+ ["ASN Bank", "ideal_ASNBNL21"],
10
+ ["Friesland Bank", "ideal_FRBKNL2L"],
11
+ ["ING", "ideal_INGBNL2A"],
12
+ ["Knab", "ideal_KNABNL2H"],
13
+ ["Rabobank", "ideal_RABONL2U"],
14
+ ["RegioBank", "ideal_RBRBNL21"],
15
+ ["SNS Bank", "ideal_SNSBNL2A"],
16
+ ["Triodos Bank", "ideal_TRIONL2U"],
17
+ ["van Lanschot", "ideal_FVLBNL22"]
18
+ ]
19
+
20
+ mattr_accessor :test_issuers
21
+ self.test_issuers = [
22
+ ["TBM Bank", "ideal_TESTNL99"]
23
+ ]
24
+
25
+ def self.redirect_param_label
26
+ "Select your bank"
27
+ end
28
+
29
+ def self.redirect_param_options(options = {})
30
+ return test_issuers if options[:credential1].blank?
31
+ options[:credential1].start_with?('live_') ? live_issuers : test_issuers
32
+ end
33
+
34
+ def self.retrieve_issuers(token)
35
+ response = API.new(token).get_request("issuers")
36
+ response['data']
37
+ .select { |issuer| issuer['method'] == 'ideal' }
38
+ .map { |issuer| [issuer['name'], issuer['id']] }
39
+ end
40
+
41
+ RedirectError = Class.new(ActiveUtils::ActiveUtilsError)
42
+
43
+ MOLLIE_API_V1_URI = 'https://api.mollie.nl/v1/'.freeze
44
+
45
+ def self.notification(post, options = {})
46
+ Notification.new(post, options)
47
+ end
48
+
49
+ def self.return(post, options = {})
50
+ Return.new(post, options)
51
+ end
52
+
53
+ def self.live?
54
+ OffsitePayments.mode == :production
55
+ end
56
+
57
+ def self.create_payment(token, params)
58
+ API.new(token).post_request('payments', params)
59
+ end
60
+
61
+ def self.check_payment_status(token, payment_id)
62
+ API.new(token).get_request("payments/#{payment_id}")
63
+ end
64
+
65
+ def self.requires_redirect_param?
66
+ true
67
+ end
68
+
69
+ class Helper < OffsitePayments::Helper
70
+ attr_reader :transaction_id, :redirect_parameters, :token
71
+
72
+ def initialize(order, account, options = {})
73
+ @token = account
74
+ @redirect_parameters = {
75
+ :amount => options[:amount],
76
+ :description => options[:description],
77
+ :issuer => options[:redirect_param],
78
+ :redirectUrl => options[:return_url],
79
+ :method => 'ideal',
80
+ :metadata => { :order => order }
81
+ }
82
+
83
+ @redirect_parameters[:webhookUrl] = options[:notify_url] if options[:notify_url]
84
+
85
+ super
86
+
87
+ raise ArgumentError, "The redirect_param option needs to be set to the bank_id the customer selected." if options[:redirect_param].blank?
88
+ raise ArgumentError, "The return_url option needs to be set." if options[:return_url].blank?
89
+ raise ArgumentError, "The description option needs to be set." if options[:description].blank?
90
+ end
91
+
92
+ def credential_based_url
93
+ response = request_redirect
94
+ @transaction_id = response['id']
95
+
96
+ uri = URI.parse(response['links']['paymentUrl'])
97
+ set_form_fields_for_redirect(uri)
98
+ uri.query = ''
99
+ uri.to_s.sub(/\?\z/, '')
100
+ end
101
+
102
+ def form_method
103
+ "GET"
104
+ end
105
+
106
+ def set_form_fields_for_redirect(uri)
107
+ CGI.parse(uri.query).each do |key, value|
108
+ if value.is_a?(Array) && value.length == 1
109
+ add_field(key, value.first)
110
+ else
111
+ add_field(key, value)
112
+ end
113
+ end
114
+ end
115
+
116
+ def request_redirect
117
+ MollieIdeal.create_payment(token, redirect_parameters)
118
+ rescue ActiveUtils::ResponseError => e
119
+ case e.response.code
120
+ when '401', '403', '422'
121
+ error = JSON.parse(e.response.body)['error']['message']
122
+ raise ActionViewHelperError, error
123
+ when '503'
124
+ raise ActionViewHelperError, 'Service temporarily unavailable. Please try again.'
125
+ else
126
+ raise
127
+ end
128
+ end
129
+ end
130
+
131
+ class Notification < OffsitePayments::Notification
132
+ def initialize(post_arguments, options = {})
133
+ super
134
+
135
+ raise ArgumentError, "The transaction_id needs to be included in the query string." if transaction_id.nil?
136
+ raise ArgumentError, "The credential1 option needs to be set to the Mollie API key." if api_key.blank?
137
+ end
138
+
139
+ def complete?
140
+ true
141
+ end
142
+
143
+ def item_id
144
+ params['metadata']['order']
145
+ end
146
+
147
+ def transaction_id
148
+ params['id']
149
+ end
150
+
151
+ def api_key
152
+ @options[:credential1]
153
+ end
154
+
155
+ def currency
156
+ "EUR"
157
+ end
158
+
159
+ # the money amount we received in X.2 decimal.
160
+ def gross
161
+ @params['amount']
162
+ end
163
+
164
+ def gross_cents
165
+ (BigDecimal.new(@params['amount'], 2) * 100).to_i
166
+ end
167
+
168
+ def status
169
+ case @params['status']
170
+ when 'open'; 'Pending'
171
+ when 'paidout', 'paid'; 'Completed'
172
+ else 'Failed'
173
+ end
174
+ end
175
+
176
+ def test?
177
+ @params['mode'] == 'test'
178
+ end
179
+
180
+ def acknowledge(authcode = nil)
181
+ @params = check_payment_status(transaction_id)
182
+ true
183
+ end
184
+
185
+ def check_payment_status(transaction_id)
186
+ MollieIdeal.check_payment_status(@options[:credential1], transaction_id)
187
+ end
188
+ end
189
+
190
+ class Return < OffsitePayments::Return
191
+ end
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,143 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ module MollieMistercash
4
+ include Mollie
5
+
6
+ RedirectError = Class.new(ActiveUtils::ActiveUtilsError)
7
+
8
+ def self.notification(post, options = {})
9
+ Notification.new(post, options)
10
+ end
11
+
12
+ def self.return(post, options = {})
13
+ Return.new(post, options)
14
+ end
15
+
16
+ def self.live?
17
+ OffsitePayments.mode == :production
18
+ end
19
+
20
+ def self.create_payment(token, params)
21
+ API.new(token).post_request('payments', params)
22
+ end
23
+
24
+ def self.check_payment_status(token, payment_id)
25
+ API.new(token).get_request("payments/#{payment_id}")
26
+ end
27
+
28
+ def self.requires_redirect_param?
29
+ false
30
+ end
31
+
32
+ class Helper < OffsitePayments::Helper
33
+ attr_reader :transaction_id, :redirect_parameters, :token
34
+
35
+ def initialize(order, account, options = {})
36
+ @token = account
37
+ @redirect_parameters = {
38
+ :amount => options[:amount],
39
+ :description => options[:description],
40
+ :redirectUrl => options[:return_url],
41
+ :method => 'mistercash',
42
+ :metadata => { :order => order }
43
+ }
44
+
45
+ @redirect_parameters[:webhookUrl] = options[:notify_url] if options[:notify_url]
46
+
47
+ super
48
+
49
+ raise ArgumentError, "The return_url option needs to be set." if options[:return_url].blank?
50
+ raise ArgumentError, "The description option needs to be set." if options[:description].blank?
51
+ end
52
+
53
+ def credential_based_url
54
+ response = request_redirect
55
+ uri = URI.parse(response['links']['paymentUrl'])
56
+ uri.to_s
57
+ end
58
+
59
+ def form_method
60
+ "GET"
61
+ end
62
+
63
+ def request_redirect
64
+ MollieMistercash.create_payment(token, redirect_parameters)
65
+ rescue ActiveUtils::ResponseError => e
66
+ case e.response.code
67
+ when '401', '403', '422'
68
+ error = JSON.parse(e.response.body)['error']['message']
69
+ raise ActionViewHelperError, error
70
+ when '503'
71
+ raise ActionViewHelperError, 'Service temporarily unavailable. Please try again.'
72
+ else
73
+ raise
74
+ end
75
+ end
76
+
77
+ end
78
+
79
+ class Notification < OffsitePayments::Notification
80
+ def initialize(post_arguments, options = {})
81
+ super
82
+
83
+ raise ArgumentError, "The transaction_id needs to be included in the query string." if transaction_id.nil?
84
+ raise ArgumentError, "The credential1 option needs to be set to the Mollie API key." if api_key.blank?
85
+ end
86
+
87
+ def complete?
88
+ true
89
+ end
90
+
91
+ def item_id
92
+ params['metadata']['order']
93
+ end
94
+
95
+ def transaction_id
96
+ params['id']
97
+ end
98
+
99
+ def api_key
100
+ @options[:credential1]
101
+ end
102
+
103
+ def currency
104
+ "EUR"
105
+ end
106
+
107
+ # the money amount we received in X.2 decimal.
108
+ def gross
109
+ @params['amount']
110
+ end
111
+
112
+ def gross_cents
113
+ (BigDecimal.new(@params['amount'], 2) * 100).to_i
114
+ end
115
+
116
+ def status
117
+ case @params['status']
118
+ when 'open'; 'Pending'
119
+ when 'paidout', 'paid'; 'Completed'
120
+ else 'Failed'
121
+ end
122
+ end
123
+
124
+ def test?
125
+ @params['mode'] == 'test'
126
+ end
127
+
128
+ def acknowledge(authcode = nil)
129
+ @params = check_payment_status(transaction_id)
130
+ true
131
+ end
132
+
133
+ def check_payment_status(transaction_id)
134
+ MollieMistercash.check_payment_status(@options[:credential1], transaction_id)
135
+ end
136
+ end
137
+
138
+ class Return < OffsitePayments::Return
139
+ end
140
+
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,193 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ module Molpay
4
+ mattr_accessor :acknowledge_url
5
+ self.acknowledge_url = 'https://www.onlinepayment.com.my/MOLPay/API/chkstat/returnipn.php'
6
+
7
+ def self.notification(post, options = {})
8
+ Notification.new(post, options)
9
+ end
10
+
11
+ def self.return(query_string, options={})
12
+ Return.new(query_string, options)
13
+ end
14
+
15
+ # (Optional Parameter) = channel //will generate URL to go directly to specific channel, e.g maybank2u, cimb
16
+ # Please refer MOLPay API spec for the channel routing
17
+ class Helper < OffsitePayments::Helper
18
+ include ActiveUtils::RequiresParameters
19
+
20
+ SUPPORTED_CURRENCIES = ['MYR', 'USD', 'SGD', 'PHP', 'VND', 'IDR', 'AUD', 'CNY', 'THB', 'GBP', 'EUR', 'HKD']
21
+
22
+ # Defaults to en
23
+ SUPPORTED_LANGUAGES = ['en', 'cn']
24
+
25
+ SERVICE_URL = 'https://www.onlinepayment.com.my/MOLPay/pay/'.freeze
26
+
27
+ mapping :account, 'merchantid'
28
+ mapping :amount, 'amount'
29
+ mapping :order, 'orderid'
30
+ mapping :customer, :name => 'bill_name',
31
+ :email => 'bill_email',
32
+ :phone => 'bill_mobile'
33
+
34
+ mapping :description, 'bill_desc'
35
+ mapping :language, 'langcode'
36
+ mapping :country, 'country'
37
+ mapping :currency, 'cur'
38
+ mapping :return_url, 'returnurl'
39
+ mapping :notify_url, 'callbackurl'
40
+ mapping :signature, 'vcode'
41
+
42
+ attr_reader :amount_in_cents, :verify_key, :channel
43
+
44
+ def credential_based_url
45
+ service_url = SERVICE_URL + @fields[mappings[:account]] + "/"
46
+ service_url = service_url + @channel if @channel
47
+ service_url
48
+ end
49
+
50
+ def initialize(order, account, options = {})
51
+ requires!(options, :amount, :currency, :credential2)
52
+ @verify_key = options[:credential2] if options[:credential2]
53
+ @amount_in_cents = options[:amount]
54
+ @channel = options.delete(:channel)
55
+ super
56
+ end
57
+
58
+ def form_fields
59
+ add_field mappings[:signature], signature
60
+ @fields
61
+ end
62
+
63
+ def amount=(money)
64
+ unless money > 0
65
+ raise ArgumentError, "amount must be greater than $0.00."
66
+ end
67
+ add_field mappings[:amount], sprintf("%.2f", money.to_f)
68
+ end
69
+
70
+ def currency=(cur)
71
+ raise ArgumentError, "unsupported currency" unless SUPPORTED_CURRENCIES.include?(cur)
72
+ add_field mappings[:currency], cur
73
+ end
74
+
75
+ def language=(lang)
76
+ raise ArgumentError, "unsupported language" unless SUPPORTED_LANGUAGES.include?(lang)
77
+ add_field mappings[:language], lang
78
+ end
79
+
80
+ private
81
+
82
+ def signature
83
+ Digest::MD5.hexdigest("#{@fields[mappings[:amount]]}#{@fields[mappings[:account]]}#{@fields[mappings[:order]]}#{@verify_key}")
84
+ end
85
+ end
86
+
87
+ class Notification < OffsitePayments::Notification
88
+ include ActiveUtils::PostsData
89
+
90
+ def status
91
+ case params['status']
92
+ when '00'
93
+ 'Completed'
94
+ when '11'
95
+ 'Failed'
96
+ when '22'
97
+ 'Pending'
98
+ end
99
+ end
100
+
101
+ def complete?
102
+ status == 'Completed'
103
+ end
104
+
105
+ def item_id
106
+ params['orderid']
107
+ end
108
+
109
+ def transaction_id
110
+ params['tranID']
111
+ end
112
+
113
+ def account
114
+ params["domain"]
115
+ end
116
+
117
+ # the money amount we received in X.2 decimal.
118
+ def gross
119
+ params['amount']
120
+ end
121
+
122
+ def currency
123
+ params['currency']
124
+ end
125
+
126
+ def channel
127
+ params['channel']
128
+ end
129
+
130
+ # When was this payment received by the client.
131
+ def received_at
132
+ params['paydate']
133
+ end
134
+
135
+ def auth_code
136
+ params['appcode']
137
+ end
138
+
139
+ def error_code
140
+ params['error_code']
141
+ end
142
+
143
+ def error_desc
144
+ params['error_desc']
145
+ end
146
+
147
+ def security_key
148
+ params['skey']
149
+ end
150
+
151
+ def test?
152
+ gross.blank? && auth_code.blank? && error_code.blank? && error_desc.blank? && security_key.blank?
153
+ end
154
+
155
+ def status_orig
156
+ params['status']
157
+ end
158
+
159
+ def acknowledge(authcode = nil)
160
+ payload = raw + '&treq=1'
161
+ ssl_post(Molpay.acknowledge_url, payload,
162
+ 'Content-Length' => "#{payload.size}",
163
+ 'User-Agent' => "Shopify/OffsitePayments"
164
+ )
165
+
166
+ status == 'Completed' && security_key == generate_signature
167
+ end
168
+
169
+ protected
170
+
171
+ def generate_signature
172
+ key0 = Digest::MD5.hexdigest("#{transaction_id}#{item_id}#{status_orig}#{account}#{gross}#{currency}")
173
+ Digest::MD5.hexdigest("#{received_at}#{account}#{key0}#{auth_code}#{@options[:credential2]}")
174
+ end
175
+ end
176
+
177
+ class Return < OffsitePayments::Return
178
+ def initialize(query_string, options = {})
179
+ super
180
+ @notification = Notification.new(query_string, options)
181
+ end
182
+
183
+ def success?
184
+ @notification.acknowledge
185
+ end
186
+
187
+ def pending?
188
+ @notification.status == 'Pending'
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end