solidus_open_pay 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +61 -0
  3. data/.github/stale.yml +1 -0
  4. data/.gitignore +22 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +249 -0
  7. data/Gemfile +49 -0
  8. data/LICENSE +26 -0
  9. data/README.md +37 -0
  10. data/Rakefile +11 -0
  11. data/app/assets/images/solidus_open_pay/.gitkeep +0 -0
  12. data/app/assets/javascripts/spree/backend/solidus_open_pay.js +2 -0
  13. data/app/assets/javascripts/spree/frontend/solidus_open_pay.js +2 -0
  14. data/app/assets/stylesheets/spree/backend/solidus_openpay.css +3 -0
  15. data/app/assets/stylesheets/spree/frontend/solidus_openpay.css +3 -0
  16. data/app/models/concerns/solidus_open_pay/attributes_access.rb +83 -0
  17. data/app/models/solidus_open_pay/builders/charge.rb +72 -0
  18. data/app/models/solidus_open_pay/gateway.rb +98 -0
  19. data/app/models/solidus_open_pay/payment_method.rb +30 -0
  20. data/app/models/solidus_open_pay/payment_source.rb +25 -0
  21. data/app/models/solidus_open_pay/response.rb +63 -0
  22. data/app/views/checkouts/payment/_open_pay.html.erb +171 -0
  23. data/app/views/spree/admin/payments/source_views/_open_pay.html.erb +21 -0
  24. data/app/views/spree/api/payments/source_views/_open_pay.json.jbuilder +3 -0
  25. data/app/views/spree/checkout/payment/_open_pay.html.erb +183 -0
  26. data/bin/console +17 -0
  27. data/bin/rails +7 -0
  28. data/bin/rails-engine +13 -0
  29. data/bin/rails-sandbox +16 -0
  30. data/bin/rake +7 -0
  31. data/bin/sandbox +86 -0
  32. data/bin/setup +8 -0
  33. data/config/locales/en.yml +44 -0
  34. data/config/locales/es-MX.yml +44 -0
  35. data/config/locales/es.yml +44 -0
  36. data/config/routes.rb +7 -0
  37. data/db/migrate/20241120003957_add_open_pay_sources.rb +23 -0
  38. data/lib/generators/solidus_open_pay/install/install_generator.rb +113 -0
  39. data/lib/generators/solidus_open_pay/install/templates/config/initializers/solidus_open_pay.rb +6 -0
  40. data/lib/solidus_open_pay/configuration.rb +27 -0
  41. data/lib/solidus_open_pay/engine.rb +38 -0
  42. data/lib/solidus_open_pay/testing_support/factories.rb +34 -0
  43. data/lib/solidus_open_pay/version.rb +5 -0
  44. data/lib/solidus_open_pay.rb +5 -0
  45. data/lib/tasks/solidus_openpay_tasks.rake +6 -0
  46. data/solidus_open_pay.gemspec +39 -0
  47. data/spec/models/solidus_open_pay/payment_method_spec.rb +417 -0
  48. data/spec/solidus_open_pay_spec_helper.rb +5 -0
  49. data/spec/spec_helper.rb +34 -0
  50. data/spec/support/factory_bot.rb +10 -0
  51. data/spec/support/solidus.rb +18 -0
  52. data/spec/support/solidus_open_pay/gateway_helpers.rb +27 -0
  53. metadata +197 -0
@@ -0,0 +1,417 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ # rubocop:disable Style/HashSyntax
6
+ RSpec.describe SolidusOpenPay::PaymentMethod, type: :model do
7
+ let(:user) { create(:user) }
8
+ let(:address) do
9
+ create(:address)
10
+ end
11
+ let(:open_pay_payment_method) do
12
+ create(:open_pay_payment_method)
13
+ end
14
+ let(:source) do
15
+ create(
16
+ :open_pay_payment_source,
17
+ payment_method: open_pay_payment_method
18
+ )
19
+ end
20
+ let(:order) do
21
+ create(
22
+ :order_with_line_items,
23
+ user: user,
24
+ ship_address: address,
25
+ bill_address: address
26
+ )
27
+ end
28
+ let(:payment) do
29
+ order.payments.create!(
30
+ payment_method: open_pay_payment_method,
31
+ source: source,
32
+ amount: 55
33
+ )
34
+ end
35
+
36
+ describe 'preferences' do
37
+ describe 'saving preference hashes as strings' do
38
+ context 'with valid hash syntax' do
39
+ let(:update_params) do
40
+ {
41
+ :server => 'test',
42
+ :test_mode => true,
43
+ :merchant_id => '1',
44
+ :private_key => 'sk_xxxx1',
45
+ :public_key => 'pk_xxxx1',
46
+ :country => '',
47
+ :test => true
48
+ }
49
+ end
50
+
51
+ before do
52
+ open_pay_payment_method.update(preferences: update_params)
53
+ end
54
+
55
+ it 'successfully updates the preference' do
56
+ expect(open_pay_payment_method.preferred_merchant_id)
57
+ .to eq('1')
58
+ expect(open_pay_payment_method.preferred_private_key)
59
+ .to eq('sk_xxxx1')
60
+ expect(open_pay_payment_method.preferred_public_key)
61
+ .to eq('pk_xxxx1')
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ describe '#authorize' do
68
+ let(:authorization_response) do
69
+ {
70
+ 'id' => 'triitam7thhlqfvunpsd',
71
+ 'authorization' => '801585',
72
+ 'operation_type' => 'in',
73
+ 'transaction_type' => 'charge',
74
+ 'status' => 'in_progress',
75
+ 'conciliated' => false,
76
+ 'creation_date' => '2024-11-22T13:58:05-06:00',
77
+ 'operation_date' => '2024-11-22T13:58:05-06:00',
78
+ 'description' => 'Cargo inicial',
79
+ 'error_message' => nil,
80
+ 'order_id' => 'R709462453-YBR2C8GT',
81
+ 'card' => {
82
+ 'type' => 'credit',
83
+ 'brand' => 'visa',
84
+ 'address' => nil,
85
+ 'card_number' => '424242XXXXXX4242',
86
+ 'holder_name' => 'User Test',
87
+ 'expiration_year' => '29',
88
+ 'expiration_month' => '09',
89
+ 'allows_charges' => true,
90
+ 'allows_payouts' => false,
91
+ 'bank_name' => 'BANCOMER',
92
+ 'points_type' => 'bancomer',
93
+ 'card_business_type' => nil,
94
+ 'dcc' => nil,
95
+ 'bank_code' => '012',
96
+ 'points_card' => true
97
+ },
98
+ 'gateway_card_present' => 'BANCOMER',
99
+ 'amount' => 10.0,
100
+ 'customer' => {
101
+ 'name' => 'User',
102
+ 'last_name' => 'Test',
103
+ 'email' => 'admin@example.com',
104
+ 'phone_number' => nil,
105
+ 'address' => nil,
106
+ 'creation_date' => '2024-11-22T13:58:05-06:00',
107
+ 'external_id' => nil,
108
+ 'clabe' => nil
109
+ },
110
+ 'currency' => 'MXN',
111
+ 'method' => 'card'
112
+ }
113
+ end
114
+
115
+ before do
116
+ allow_any_instance_of(OpenpayApi).to receive(:create)
117
+ .with(:charges) { Charges.new({}, nil, nil) }
118
+ allow_any_instance_of(Charges)
119
+ .to receive(:create) { authorization_response }
120
+ end
121
+
122
+ it 'sends an authorize request to open pay' do
123
+ response = open_pay_payment_method.authorize(
124
+ 1000,
125
+ source,
126
+ {
127
+ order_id: order.number,
128
+ email: user.email
129
+ }
130
+ )
131
+
132
+ expect(response).to be_success
133
+ expect(response.class).to be(SolidusOpenPay::Response)
134
+ end
135
+ end
136
+
137
+ describe '#capture' do
138
+ let(:capture_response) do
139
+ {
140
+ 'id' => 'triitam7thhlqfvunpsd',
141
+ 'authorization' => '801585',
142
+ 'operation_type' => 'in',
143
+ 'transaction_type' => 'charge',
144
+ 'status' => 'completed',
145
+ 'conciliated' => false,
146
+ 'creation_date' => '2024-11-22T13:58:05-06:00',
147
+ 'operation_date' => '2024-11-22T14:01:19-06:00',
148
+ 'description' => 'Cargo inicial',
149
+ 'error_message' => nil,
150
+ 'order_id' => 'R709462453-YBR2C8GT',
151
+ 'card' => {
152
+ 'type' => 'credit',
153
+ 'brand' => 'visa',
154
+ 'address' => nil,
155
+ 'card_number' => '424242XXXXXX4242',
156
+ 'holder_name' => 'User Test',
157
+ 'expiration_year' => '29',
158
+ 'expiration_month' => '09',
159
+ 'allows_charges' => true,
160
+ 'allows_payouts' => false,
161
+ 'bank_name' => 'BANCOMER',
162
+ 'points_type' => 'bancomer',
163
+ 'card_business_type' => nil,
164
+ 'dcc' => nil,
165
+ 'bank_code' => '012',
166
+ 'points_card' => true
167
+ },
168
+ 'fee' => {
169
+ 'amount' => 2.79,
170
+ 'tax' => 0.4464,
171
+ 'surcharge' => nil,
172
+ 'base_commission' => nil,
173
+ 'currency' => 'MXN'
174
+ },
175
+ 'amount' => 10.0,
176
+ 'customer' => {
177
+ 'name' => 'User',
178
+ 'last_name' => 'Test',
179
+ 'email' => 'admin@example.com',
180
+ 'phone_number' => nil,
181
+ 'address' => nil,
182
+ 'creation_date' => '2024-11-22T13:58:06-06:00',
183
+ 'external_id' => nil,
184
+ 'clabe' => nil
185
+ },
186
+ 'currency' => 'MXN',
187
+ 'method' => 'card'
188
+ }
189
+ end
190
+
191
+ before do
192
+ allow_any_instance_of(Charges)
193
+ .to receive(:capture) { RestClient::Response.new }
194
+ allow_any_instance_of(RestClient::Response)
195
+ .to receive(:body) { capture_response.to_json }
196
+ end
197
+
198
+ it 'sends an capture request to open pay' do
199
+ response = open_pay_payment_method.capture(
200
+ 1000,
201
+ 'triitam7thhlqfvunpsd',
202
+ {
203
+ order_id: order.number,
204
+ email: user.email
205
+ }
206
+ )
207
+
208
+ expect(response).to be_success
209
+ expect(response.class).to be(SolidusOpenPay::Response)
210
+ end
211
+ end
212
+
213
+ describe '#purchase' do
214
+ let(:purchase_response) do
215
+ {
216
+ 'id' => 'tr6jtfjrksvqe1ifqpvy',
217
+ 'authorization' => '801585',
218
+ 'operation_type' => 'in',
219
+ 'transaction_type' => 'charge',
220
+ 'status' => 'completed',
221
+ 'conciliated' => false,
222
+ 'creation_date' => '2024-11-26T16:26:08-06:00',
223
+ 'operation_date' => '2024-11-26T16:26:25-06:00',
224
+ 'description' => 'Cargo inicial',
225
+ 'error_message' => nil,
226
+ 'order_id' => 'R069147136-8AK5U5HC',
227
+ 'card' => {
228
+ 'type' => 'credit',
229
+ 'brand' => 'visa',
230
+ 'address' => nil,
231
+ 'card_number' => '424242XXXXXX4242',
232
+ 'holder_name' => 'User Test',
233
+ 'expiration_year' => '29',
234
+ 'expiration_month' => '09',
235
+ 'allows_charges' => true,
236
+ 'allows_payouts' => false,
237
+ 'bank_name' => 'BANCOMER',
238
+ 'points_type' => 'bancomer',
239
+ 'card_business_type' => nil,
240
+ 'dcc' => nil,
241
+ 'points_card' => true,
242
+ 'bank_code' => '012'
243
+ },
244
+ 'amount' => 10.0,
245
+ 'currency' => 'MXN',
246
+ 'customer' => {
247
+ 'name' => 'User',
248
+ 'last_name' => 'Test',
249
+ 'email' => 'pedidos@donmanolito.com',
250
+ 'phone_number' => nil,
251
+ 'address' => nil,
252
+ 'creation_date' => '2024-11-26T16:26:08-06:00',
253
+ 'external_id' => nil,
254
+ 'clabe' => nil
255
+ },
256
+ 'fee' => {
257
+ 'amount' => 2.79,
258
+ 'tax' => 0.4464,
259
+ 'surcharge' => nil,
260
+ 'base_commission' => nil,
261
+ 'currency' => 'MXN'
262
+ },
263
+ 'method' => 'card'
264
+ }
265
+ end
266
+
267
+ before do
268
+ allow_any_instance_of(OpenpayApi).to receive(:create)
269
+ .with(:charges) { Charges.new({}, nil, nil) }
270
+ allow_any_instance_of(Charges)
271
+ .to receive(:create) { purchase_response }
272
+ end
273
+
274
+ it 'sends an purchase request to open pay' do
275
+ response = open_pay_payment_method.purchase(
276
+ 1000,
277
+ source,
278
+ {
279
+ order_id: order.number,
280
+ email: user.email
281
+ }
282
+ )
283
+
284
+ expect(response).to be_success
285
+ expect(response.class).to be(SolidusOpenPay::Response)
286
+ end
287
+ end
288
+
289
+ describe '#void' do
290
+ let(:void_response) do
291
+ {
292
+ 'id' => 'trhp1prb21hweym5zoxq',
293
+ 'authorization' => '801585',
294
+ 'operation_type' => 'in',
295
+ 'transaction_type' => 'charge',
296
+ 'status' => 'cancelled',
297
+ 'conciliated' => true,
298
+ 'creation_date' => '2024-11-22T22:20:28-06:00',
299
+ 'operation_date' => '2024-11-22T22:21:05-06:00',
300
+ 'description' => 'Cargo inicial',
301
+ 'error_message' => nil,
302
+ 'order_id' => 'R161167589-DBHXWAP6',
303
+ 'card' =>
304
+ {
305
+ 'type' => 'credit',
306
+ 'brand' => 'visa',
307
+ 'address' => nil,
308
+ 'card_number' => '424242XXXXXX4242',
309
+ 'holder_name' => 'User Test',
310
+ 'expiration_year' => '29',
311
+ 'expiration_month' => '09',
312
+ 'allows_charges' => true,
313
+ 'allows_payouts' => false,
314
+ 'bank_name' => 'BANCOMER',
315
+ 'points_type' => 'bancomer',
316
+ 'card_business_type' => nil,
317
+ 'dcc' => nil,
318
+ 'points_card' => true,
319
+ 'bank_code' => '012'
320
+ },
321
+ 'customer' => {
322
+ 'name' => 'User',
323
+ 'last_name' => 'Test',
324
+ 'email' => 'pedidos@donmanolito.com',
325
+ 'phone_number' => nil,
326
+ 'address' => nil,
327
+ 'creation_date' => '2024-11-22T22:20:29-06:00',
328
+ 'external_id' => nil,
329
+ 'clabe' => nil
330
+ },
331
+ 'amount' => 10.0,
332
+ 'currency' => 'MXN',
333
+ 'method' => 'card'
334
+ }
335
+ end
336
+
337
+ before do
338
+ allow_any_instance_of(Charges)
339
+ .to receive(:refund) { void_response }
340
+ end
341
+
342
+ it 'sends an void request to open pay' do
343
+ response = open_pay_payment_method.void(
344
+ 'triitam7thhlqfvunpsd',
345
+ {}
346
+ )
347
+
348
+ expect(response).to be_success
349
+ expect(response.class).to be(SolidusOpenPay::Response)
350
+ end
351
+ end
352
+
353
+ describe '#credit' do
354
+ let(:credit_response) do
355
+ {
356
+ 'id' => 'trhp1prb21hweym5zoxq',
357
+ 'authorization' => '801585',
358
+ 'operation_type' => 'in',
359
+ 'transaction_type' => 'charge',
360
+ 'status' => 'cancelled',
361
+ 'conciliated' => true,
362
+ 'creation_date' => '2024-11-22T22:20:28-06:00',
363
+ 'operation_date' => '2024-11-22T22:21:05-06:00',
364
+ 'description' => 'Cargo inicial',
365
+ 'error_message' => nil,
366
+ 'order_id' => 'R161167589-DBHXWAP6',
367
+ 'card' =>
368
+ {
369
+ 'type' => 'credit',
370
+ 'brand' => 'visa',
371
+ 'address' => nil,
372
+ 'card_number' => '424242XXXXXX4242',
373
+ 'holder_name' => 'User Test',
374
+ 'expiration_year' => '29',
375
+ 'expiration_month' => '09',
376
+ 'allows_charges' => true,
377
+ 'allows_payouts' => false,
378
+ 'bank_name' => 'BANCOMER',
379
+ 'points_type' => 'bancomer',
380
+ 'card_business_type' => nil,
381
+ 'dcc' => nil,
382
+ 'points_card' => true,
383
+ 'bank_code' => '012'
384
+ },
385
+ 'customer' => {
386
+ 'name' => 'User',
387
+ 'last_name' => 'Test',
388
+ 'email' => 'pedidos@donmanolito.com',
389
+ 'phone_number' => nil,
390
+ 'address' => nil,
391
+ 'creation_date' => '2024-11-22T22:20:29-06:00',
392
+ 'external_id' => nil,
393
+ 'clabe' => nil
394
+ },
395
+ 'amount' => 10.0,
396
+ 'currency' => 'MXN',
397
+ 'method' => 'card'
398
+ }
399
+ end
400
+
401
+ before do
402
+ allow_any_instance_of(Charges)
403
+ .to receive(:refund) { credit_response }
404
+ end
405
+
406
+ it 'sends an credit request to open pay' do
407
+ response = open_pay_payment_method.credit(
408
+ 'triitam7thhlqfvunpsd',
409
+ {}
410
+ )
411
+
412
+ expect(response).to be_success
413
+ expect(response.class).to be(SolidusOpenPay::Response)
414
+ end
415
+ end
416
+ end
417
+ # rubocop:enable Style/HashSyntax
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openpay'
4
+
5
+ Dir["#{__dir__}/support/solidus_open_pay/**/*.rb"].sort.each { |f| require f }
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Configure Rails Environment
4
+ ENV['RAILS_ENV'] = 'test'
5
+
6
+ require 'openpay'
7
+ require 'rails-controller-testing'
8
+
9
+ # Run Coverage report
10
+ require 'solidus_dev_support/rspec/coverage'
11
+
12
+ # Create the dummy app if it's still missing.
13
+ dummy_env = "#{__dir__}/dummy/config/environment.rb"
14
+ system 'bin/rake extension:test_app' unless File.exist? dummy_env
15
+ require dummy_env
16
+
17
+ # Requires factories and other useful helpers defined in spree_core.
18
+ require 'solidus_dev_support/rspec/feature_helper'
19
+
20
+ # Requires supporting ruby files with custom matchers and macros, etc,
21
+ # in spec/support/ and its subdirectories.
22
+ Dir["#{__dir__}/support/**/*.rb"].sort.each { |f| require f }
23
+
24
+ # Requires factories defined in lib/solidus_open_pay/testing_support/factories.rb
25
+ SolidusDevSupport::TestingSupport::Factories.load_for(SolidusOpenPay::Engine)
26
+
27
+ RSpec.configure do |config|
28
+ config.infer_spec_type_from_file_location!
29
+ config.use_transactional_fixtures = false
30
+
31
+ if Spree.solidus_gem_version < Gem::Version.new('2.11')
32
+ config.extend Spree::TestingSupport::AuthorizationHelpers::Request, type: :system
33
+ end
34
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'factory_bot'
4
+ require 'spree/testing_support/factory_bot'
5
+
6
+ Spree::TestingSupport::FactoryBot.add_paths_and_load!
7
+
8
+ RSpec.configure do |config|
9
+ config.include FactoryBot::Syntax::Methods
10
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spree/testing_support/flash'
4
+ require 'spree/testing_support/url_helpers'
5
+ require 'spree/testing_support/controller_requests'
6
+ require 'spree/testing_support/authorization_helpers'
7
+ require 'spree/testing_support/translations'
8
+ require 'spree/testing_support/order_walkthrough'
9
+
10
+ RSpec.configure do |config|
11
+ config.include Spree::TestingSupport::Flash
12
+ config.include Spree::TestingSupport::UrlHelpers
13
+ config.include Spree::TestingSupport::Translations
14
+ config.include Spree::TestingSupport::ControllerRequests, type: :controller
15
+
16
+ config.include Rails.application.routes.url_helpers
17
+ config.include Spree::Core::Engine.routes.url_helpers
18
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusOpenPay
4
+ module GatewayHelpers
5
+ def new_gateway(opts = {})
6
+ SolidusOpenPay::Gateway.new({
7
+ name: 'OpenPay',
8
+ preferences: {
9
+ environment: 'sandbox',
10
+ public_key: 'dummy_public_key',
11
+ private_key: 'dummy_private_key',
12
+ merchant_id: 'dummy_merchant_id',
13
+ country: nil,
14
+ test_mode: true
15
+ }
16
+ }.merge(opts))
17
+ end
18
+
19
+ def create_gateway(opts = {})
20
+ new_gateway(opts).tap(&:save!)
21
+ end
22
+ end
23
+ end
24
+
25
+ RSpec.configure do |config|
26
+ config.include SolidusOpenPay::GatewayHelpers
27
+ end