better_offsite_payments 2.3.0

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