workarea-klarna 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +20 -0
  3. data/.eslintrc.json +36 -0
  4. data/.github/workflows/ci.yml +61 -0
  5. data/.gitignore +24 -0
  6. data/.rubocop.yml +2 -0
  7. data/.stylelintrc.json +8 -0
  8. data/.yardopts +1 -0
  9. data/CHANGELOG.md +81 -0
  10. data/Gemfile +17 -0
  11. data/LICENSE +52 -0
  12. data/README.md +79 -0
  13. data/Rakefile +56 -0
  14. data/app/assets/javascripts/workarea/storefront/klarna/modules/klarna_widget.js +99 -0
  15. data/app/controllers/workarea/storefront/checkout/addresses_controller.decorator +8 -0
  16. data/app/controllers/workarea/storefront/checkout/place_order_controller.decorator +9 -0
  17. data/app/controllers/workarea/storefront/checkouts_controller.decorator +13 -0
  18. data/app/models/workarea/checkout/steps/payment.decorator +22 -0
  19. data/app/models/workarea/order.decorator +7 -0
  20. data/app/models/workarea/payment.decorator +34 -0
  21. data/app/models/workarea/payment/authorize/klarna.rb +21 -0
  22. data/app/models/workarea/payment/capture/klarna.rb +21 -0
  23. data/app/models/workarea/payment/klarna_session.rb +18 -0
  24. data/app/models/workarea/payment/purchase/klarna.rb +21 -0
  25. data/app/models/workarea/payment/refund/klarna.rb +18 -0
  26. data/app/models/workarea/payment/tender/klarna.rb +53 -0
  27. data/app/services/workarea/setup_klarna_session.rb +24 -0
  28. data/app/view_models/workarea/storefront/checkout/payment_view_model.decorator +41 -0
  29. data/app/views/workarea/admin/orders/tenders/_klarna.html.haml +4 -0
  30. data/app/views/workarea/storefront/checkouts/_klarna_payments.html.haml +22 -0
  31. data/app/views/workarea/storefront/klarna/_sdk.html.haml +2 -0
  32. data/app/views/workarea/storefront/order_mailer/tenders/_klarna.html.haml +2 -0
  33. data/app/views/workarea/storefront/orders/tenders/_klarna.html.haml +6 -0
  34. data/bin/rails +20 -0
  35. data/config/initializers/appends.rb +14 -0
  36. data/config/initializers/configuration.rb +32 -0
  37. data/config/initializers/fields.rb +43 -0
  38. data/config/locales/en.yml +30 -0
  39. data/config/routes.rb +2 -0
  40. data/lib/workarea/klarna.rb +30 -0
  41. data/lib/workarea/klarna/bogus_gateway.rb +19 -0
  42. data/lib/workarea/klarna/engine.rb +10 -0
  43. data/lib/workarea/klarna/gateway.rb +92 -0
  44. data/lib/workarea/klarna/gateway/cancel_request.rb +16 -0
  45. data/lib/workarea/klarna/gateway/capture_request.rb +24 -0
  46. data/lib/workarea/klarna/gateway/create_session_request.rb +22 -0
  47. data/lib/workarea/klarna/gateway/order.rb +249 -0
  48. data/lib/workarea/klarna/gateway/place_order_request.rb +34 -0
  49. data/lib/workarea/klarna/gateway/refund_request.rb +24 -0
  50. data/lib/workarea/klarna/gateway/release_request.rb +16 -0
  51. data/lib/workarea/klarna/gateway/request.rb +91 -0
  52. data/lib/workarea/klarna/gateway/response.rb +38 -0
  53. data/lib/workarea/klarna/gateway/update_session_request.rb +30 -0
  54. data/lib/workarea/klarna/version.rb +5 -0
  55. data/package.json +9 -0
  56. data/test/dummy/Rakefile +6 -0
  57. data/test/dummy/app/assets/config/manifest.js +4 -0
  58. data/test/dummy/app/assets/javascripts/application.js +13 -0
  59. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  60. data/test/dummy/app/controllers/application_controller.rb +3 -0
  61. data/test/dummy/app/helpers/application_helper.rb +2 -0
  62. data/test/dummy/app/jobs/application_job.rb +2 -0
  63. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  64. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  65. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  66. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  67. data/test/dummy/bin/bundle +3 -0
  68. data/test/dummy/bin/rails +4 -0
  69. data/test/dummy/bin/rake +4 -0
  70. data/test/dummy/bin/setup +34 -0
  71. data/test/dummy/bin/update +29 -0
  72. data/test/dummy/config.ru +5 -0
  73. data/test/dummy/config/application.rb +24 -0
  74. data/test/dummy/config/boot.rb +5 -0
  75. data/test/dummy/config/cable.yml +9 -0
  76. data/test/dummy/config/environment.rb +5 -0
  77. data/test/dummy/config/environments/development.rb +54 -0
  78. data/test/dummy/config/environments/production.rb +86 -0
  79. data/test/dummy/config/environments/test.rb +43 -0
  80. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  81. data/test/dummy/config/initializers/assets.rb +11 -0
  82. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  83. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  84. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  85. data/test/dummy/config/initializers/inflections.rb +16 -0
  86. data/test/dummy/config/initializers/mime_types.rb +4 -0
  87. data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
  88. data/test/dummy/config/initializers/workarea.rb +5 -0
  89. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  90. data/test/dummy/config/locales/en.yml +23 -0
  91. data/test/dummy/config/puma.rb +47 -0
  92. data/test/dummy/config/routes.rb +5 -0
  93. data/test/dummy/config/secrets.yml +22 -0
  94. data/test/dummy/config/spring.rb +6 -0
  95. data/test/dummy/db/seeds.rb +2 -0
  96. data/test/dummy/log/.keep +0 -0
  97. data/test/factories/workarea/klarna.rb +146 -0
  98. data/test/integration/workarea/storefront/klarna_session_integration_test.rb +40 -0
  99. data/test/lib/workarea/klarna/gateway/capture_request_test.rb +26 -0
  100. data/test/lib/workarea/klarna/gateway/create_session_request_test.rb +26 -0
  101. data/test/lib/workarea/klarna/gateway/order_test.rb +135 -0
  102. data/test/lib/workarea/klarna/gateway/place_order_request_test.rb +34 -0
  103. data/test/lib/workarea/klarna/gateway/refund_request_test.rb +26 -0
  104. data/test/lib/workarea/klarna/gateway/request_test.rb +87 -0
  105. data/test/lib/workarea/klarna/gateway/response_test.rb +75 -0
  106. data/test/lib/workarea/klarna/gateway/update_session_request_test.rb +27 -0
  107. data/test/lib/workarea/klarna/gateway_test.rb +58 -0
  108. data/test/models/workarea/checkout/steps/klarna_payment_test.rb +79 -0
  109. data/test/models/workarea/klarna_payment_test.rb +45 -0
  110. data/test/models/workarea/payment/authorize/klarna_test.rb +34 -0
  111. data/test/models/workarea/payment/capture/klarna_test.rb +51 -0
  112. data/test/models/workarea/payment/tender/klarna_test.rb +81 -0
  113. data/test/services/workarea/setup_klarna_session_test.rb +42 -0
  114. data/test/teaspoon_env.rb +6 -0
  115. data/test/test_helper.rb +10 -0
  116. data/test/vcr_cassettes/klarna_authorize.yml +62 -0
  117. data/test/vcr_cassettes/klarna_capture.yml +60 -0
  118. data/test/vcr_cassettes/klarna_create_session.yml +61 -0
  119. data/test/vcr_cassettes/klarna_refund.yml +60 -0
  120. data/test/view_models/workarea/storefront/checkout/klarna_payment_view_model_test.rb +62 -0
  121. data/workarea-klarna.gemspec +20 -0
  122. metadata +177 -0
@@ -0,0 +1,87 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ module Klarna
5
+ class Gateway
6
+ class RequestTest < TestCase
7
+ setup :configure_klarna_data, :payment
8
+
9
+ def order
10
+ @order ||= create_order
11
+ end
12
+
13
+ def payment
14
+ @payment ||= create_payment(id: order.id)
15
+ end
16
+
17
+ def request
18
+ Request.new(order)
19
+ end
20
+
21
+ def test_validate!
22
+ assert_raises(Gateway::ContinentNotSupported) { request.validate! }
23
+
24
+ payment.set_address(unsupported_address)
25
+ assert_raises(Gateway::ContinentNotSupported) { request.validate! }
26
+
27
+ payment.set_address(supported_na_address)
28
+ assert_nothing_raised { request.validate! }
29
+
30
+ Workarea.config.klarna_na_password = nil
31
+ assert_raises(Gateway::ContinentNotSupported) { request.validate! }
32
+ end
33
+
34
+ def test_username
35
+ assert_nil(request.username)
36
+
37
+ payment.set_address(unsupported_address)
38
+ assert_nil(request.username)
39
+
40
+ payment.set_address(supported_na_address)
41
+ assert_equal(Workarea.config.klarna_na_username, request.username)
42
+
43
+ payment.set_address(supported_eur_address)
44
+ assert_equal(Workarea.config.klarna_eur_username, request.username)
45
+
46
+ @env_eur_user = ENV['WORKAREA_KLARNA_EUR_USERNAME']
47
+ ENV['WORKAREA_KLARNA_EUR_USERNAME'] = 'env_eur_user'
48
+ assert_equal('env_eur_user', request.username)
49
+ ensure
50
+ ENV['WORKAREA_KLARNA_EUR_USERNAME'] = @env_eur_user
51
+ end
52
+
53
+ def test_password
54
+ assert_nil(request.password)
55
+
56
+ payment.set_address(unsupported_address)
57
+ assert_nil(request.password)
58
+
59
+ payment.set_address(supported_na_address)
60
+ assert_equal(Workarea.config.klarna_na_password, request.password)
61
+
62
+ payment.set_address(supported_eur_address)
63
+ assert_equal(Workarea.config.klarna_eur_password, request.password)
64
+
65
+ @env_eur_pass = ENV['WORKAREA_KLARNA_EUR_PASSWORD']
66
+ ENV['WORKAREA_KLARNA_EUR_PASSWORD'] = 'env_eur_user'
67
+ assert_equal('env_eur_user', request.password)
68
+ ensure
69
+ ENV['WORKAREA_KLARNA_EUR_PASSWORD'] = @env_eur_pass
70
+ end
71
+
72
+ def test_continent_key
73
+ assert_nil(request.continent_key)
74
+
75
+ payment.set_address(unsupported_address)
76
+ assert_nil(request.continent_key)
77
+
78
+ payment.set_address(supported_na_address)
79
+ assert_equal('NA', request.continent_key)
80
+
81
+ payment.set_address(supported_eur_address)
82
+ assert_equal('EUR', request.continent_key)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,75 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ module Klarna
5
+ class Gateway
6
+ class ResponseTest < TestCase
7
+ def order
8
+ @order ||= create_order
9
+ end
10
+
11
+ def request
12
+ Request.new(order)
13
+ end
14
+
15
+ def test_body
16
+ response = Response.new(request, nil)
17
+ assert_equal({}, response.body)
18
+ assert_equal({}, response.params)
19
+
20
+ response = Response.new(
21
+ request,
22
+ OpenStruct.new(body: { foo: 'bar' }.to_json)
23
+ )
24
+ assert_equal({ 'foo' => 'bar' }, response.body)
25
+ assert_equal({ 'foo' => 'bar' }, response.params)
26
+ end
27
+
28
+ def test_success?
29
+ response = Response.new(request, nil)
30
+ refute(response.success?)
31
+
32
+ response = Response.new(request, OpenStruct.new(status: 404))
33
+ refute(response.success?)
34
+
35
+ response = Response.new(request, OpenStruct.new(status: 200))
36
+ assert(response.success?)
37
+ end
38
+
39
+ def test_message
40
+ response = Response.new(request, nil)
41
+ assert_equal(
42
+ t('workarea.klarna.gateway.response.failure', summary: ''),
43
+ response.message
44
+ )
45
+
46
+ response = Response.new(
47
+ request,
48
+ OpenStruct.new(
49
+ status: 500,
50
+ body: {
51
+ error_messages: ['address is invalid', 'tax rate missing']
52
+ }.to_json
53
+ )
54
+ )
55
+ assert_equal(
56
+ t(
57
+ 'workarea.klarna.gateway.response.failure',
58
+ summary: 'address is invalid. tax rate missing'
59
+ ),
60
+ response.message
61
+ )
62
+
63
+ response = Response.new(request, OpenStruct.new(status: 204))
64
+ assert_equal(
65
+ t(
66
+ 'workarea.klarna.gateway.response.success',
67
+ summary: t('workarea.klarna.gateway.request.base')
68
+ ),
69
+ response.message
70
+ )
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ module Klarna
5
+ class Gateway
6
+ class UpdateSessionRequestTest < TestCase
7
+ setup :create_supporting_data_for_klarna
8
+
9
+ def test_details
10
+ session = create_klarna_session(id: @order.id)
11
+ request = UpdateSessionRequest.new(@order)
12
+
13
+ assert_equal('post', request.method)
14
+ assert_equal("payments/v1/sessions/#{session.session_id}", request.path)
15
+ assert(request.summary.present?)
16
+ end
17
+
18
+ def test_body
19
+ request = UpdateSessionRequest.new(@order, '123')
20
+
21
+ assert_nil(request.body[:shipping_address])
22
+ assert_nil(request.body[:billing_address])
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ module Klarna
5
+ class GatewayTest < TestCase
6
+ setup :configure_klarna_data, :payment
7
+
8
+ def order
9
+ @order ||= create_order
10
+ end
11
+
12
+ def payment
13
+ @payment ||= create_payment(id: order.id)
14
+ end
15
+
16
+ def request
17
+ Gateway::Request.new(order)
18
+ end
19
+
20
+ def test_send_request
21
+ response = Gateway.new.send_request(request)
22
+ refute(response.success?)
23
+ assert_equal(
24
+ t('workarea.klarna.gateway.unsupported_continent', continent: nil),
25
+ response.message
26
+ )
27
+
28
+ payment.set_address(unsupported_address)
29
+ response = Gateway.new.send_request(request)
30
+ refute(response.success?)
31
+ assert_equal(
32
+ t('workarea.klarna.gateway.unsupported_continent', continent: 'South America'),
33
+ response.message
34
+ )
35
+
36
+ payment.set_address(supported_na_address)
37
+
38
+ Faraday.expects(:send)
39
+ .with('get', 'https://api-na.playground.klarna.com/')
40
+
41
+ response = Gateway.new.send_request(request)
42
+ end
43
+
44
+ def test_send_transaction_request
45
+ payment.set_address(supported_na_address)
46
+ Faraday.expects(:send).returns(
47
+ OpenStruct.new(status: 200, body: { foo: 'bar' }.to_json)
48
+ )
49
+
50
+ response = Gateway.new.send_transaction_request(request)
51
+
52
+ assert(response.is_a?(ActiveMerchant::Billing::Response))
53
+ assert(response.success?)
54
+ assert_equal({ 'foo' => 'bar' }, response.params)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,79 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ class Checkout
5
+ module Steps
6
+ class KlarnaPaymentTest < TestCase
7
+ setup :set_shipping_service, :set_product, :set_addresses
8
+
9
+ def set_shipping_service
10
+ create_shipping_service(
11
+ name: 'Test',
12
+ rates: [{ price: 5.to_m }],
13
+ tax_code: '001'
14
+ )
15
+ end
16
+
17
+ def set_product
18
+ create_product(id: 'PROD')
19
+ end
20
+
21
+ def set_addresses
22
+ address_params = {
23
+ first_name: 'Ben',
24
+ last_name: 'Crouse',
25
+ street: '22 S. 3rd St.',
26
+ city: 'Philadelphia',
27
+ region: 'PA',
28
+ postal_code: '19106',
29
+ country: 'US',
30
+ phone_number: '2159251800'
31
+ }
32
+
33
+ Addresses.new(checkout).update(
34
+ shipping_address: address_params,
35
+ billing_address: address_params
36
+ )
37
+ end
38
+
39
+ def order
40
+ @order ||= create_order(
41
+ email: 'test@workarea.com',
42
+ items: [{ product_id: 'PROD', sku: 'SKU' }]
43
+ )
44
+ end
45
+
46
+ def checkout
47
+ @checkout ||= Checkout.new(order)
48
+ end
49
+
50
+ def payment
51
+ @payment ||= checkout.payment
52
+ end
53
+
54
+ def step
55
+ @step ||= Checkout::Steps::Payment.new(checkout)
56
+ end
57
+
58
+ def test_setting_klarna_tender
59
+ assert(
60
+ step.update(
61
+ payment: 'klarna_pay_later',
62
+ klarna: { authorization_token: '123' }
63
+ )
64
+ )
65
+
66
+ assert(payment.klarna.present?)
67
+ assert(payment.klarna.amount)
68
+ assert(payment.klarna.authorization_token.present?)
69
+
70
+ step.update
71
+ assert_nil(payment.klarna)
72
+
73
+ payment.address = nil
74
+ refute(step.update)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,45 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ class KlarnaPaymentTest < TestCase
5
+ setup :configure_klarna_data
6
+
7
+ def test_set_klarna
8
+ payment = Payment.new
9
+
10
+ assert_nil(payment.klarna)
11
+
12
+ payment.set_klarna(
13
+ authorization_token: '234',
14
+ authorization_token_expires_at: 1.hour.from_now,
15
+ payment_method_category: 'pay_later',
16
+ amount: 10000000.to_m
17
+ )
18
+
19
+ assert(payment.klarna.present?)
20
+ assert_equal('234', payment.klarna.authorization_token)
21
+ assert(payment.klarna.authorization_token_expires_at.present?)
22
+ assert_equal('pay_later', payment.klarna.payment_method_category)
23
+ assert_equal(0.to_m, payment.klarna.amount)
24
+
25
+ payment.clear_klarna
26
+ assert_nil(payment.klarna)
27
+ end
28
+
29
+ def test_eligible_for_klarna?
30
+ payment = Payment.new
31
+
32
+ refute(payment.eligible_for_klarna?)
33
+
34
+ payment.build_address(unsupported_address)
35
+
36
+ assert(payment.address.valid?)
37
+ refute(payment.eligible_for_klarna?)
38
+
39
+ payment.address.attributes = supported_eur_address
40
+
41
+ assert(payment.address.valid?)
42
+ assert(payment.eligible_for_klarna?)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ class Payment
5
+ module Authorize
6
+ class KlarnaTest < TestCase
7
+ setup :create_supporting_data_for_klarna, :add_tender, :enable_klarna
8
+
9
+ def add_tender
10
+ # this auth token will need to be an active one if you want to
11
+ # regenerate the VCR cassette.
12
+ create_klarna_tender(
13
+ payment: @payment,
14
+ authorization_token: '31ae5ab6-d4d5-145f-b71b-36cd8404c5ba',
15
+ payment_method_category: 'pay_later'
16
+ )
17
+ end
18
+
19
+ def test_operation
20
+ txn = @payment.klarna.build_transaction(action: 'authorize')
21
+ operation = Authorize::Klarna.new(@payment.klarna, txn)
22
+
23
+ VCR.use_cassette('klarna_authorize') do
24
+ operation.complete!
25
+ end
26
+
27
+ assert(txn.success?)
28
+ assert(txn.response.params['order_id'].present?)
29
+ assert(txn.response.params['redirect_url'].present?)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ class Payment
5
+ class Capture
6
+ class KlarnaTest < TestCase
7
+ setup :enable_klarna
8
+
9
+ def test_operation
10
+ payment = create_payment(
11
+ address: supported_na_address,
12
+ klarna: { amount: 10.to_m }
13
+ )
14
+
15
+ # You will need a valid order_id if you want to regenerate the
16
+ # VCR cassettes for this test.
17
+ payment.klarna.stubs(:order_id).returns('1dab0505-d1d5-1041-ac57-5ffda5af139c')
18
+
19
+ txn = payment.klarna.build_transaction(amount: 5.to_m, action: 'capture')
20
+ operation = Capture::Klarna.new(payment.klarna, txn)
21
+
22
+ VCR.use_cassette('klarna_capture') do
23
+ operation.complete!
24
+ end
25
+
26
+ assert(txn.success?)
27
+ assert_equal(
28
+ t(
29
+ 'workarea.klarna.gateway.response.success',
30
+ summary: t('workarea.klarna.gateway.request.capture', amount: 5.to_m.format)
31
+ ),
32
+ txn.response.message
33
+ )
34
+
35
+ VCR.use_cassette('klarna_refund') do
36
+ operation.cancel!
37
+ end
38
+
39
+ assert(txn.cancellation.success?)
40
+ assert_equal(
41
+ t(
42
+ 'workarea.klarna.gateway.response.success',
43
+ summary: t('workarea.klarna.gateway.request.refund', amount: 5.to_m.format)
44
+ ),
45
+ txn.cancellation.message
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end