workarea-authorize_cim 2.1.1

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 (118) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +20 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  4. data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/.gitignore +13 -0
  7. data/.rails-rubocop.yml +130 -0
  8. data/.rubocop.yml +13 -0
  9. data/CHANGELOG.md +90 -0
  10. data/CODE_OF_CONDUCT.md +3 -0
  11. data/CONTRIBUTING.md +3 -0
  12. data/Gemfile +12 -0
  13. data/LICENSE +52 -0
  14. data/LICENSE.md +3 -0
  15. data/README.md +40 -0
  16. data/Rakefile +50 -0
  17. data/app/errors/workarea/payment/create_profile_error.rb +19 -0
  18. data/app/models/workarea/payment.decorator +14 -0
  19. data/app/models/workarea/payment/authorize/credit_card.decorator +61 -0
  20. data/app/models/workarea/payment/capture/credit_card.decorator +38 -0
  21. data/app/models/workarea/payment/profile.decorator +169 -0
  22. data/app/models/workarea/payment/purchase/credit_card.decorator +61 -0
  23. data/app/models/workarea/payment/refund.decorator +19 -0
  24. data/app/models/workarea/payment/refund/credit_card.decorator +39 -0
  25. data/app/models/workarea/payment/store_credit_card.decorator +122 -0
  26. data/app/models/workarea/payment/tender/credit_card.decorator +25 -0
  27. data/app/models/workarea/payment/transaction.decorator +16 -0
  28. data/bin/rails +17 -0
  29. data/bin/rake +17 -0
  30. data/bin/rspec +17 -0
  31. data/bin/rubocop +17 -0
  32. data/config/initializers/configuration.rb +3 -0
  33. data/lib/active_merchant/billing/bogus_authorize_net_cim_gateway.rb +99 -0
  34. data/lib/workarea/authorize_cim.rb +47 -0
  35. data/lib/workarea/authorize_cim/engine.rb +10 -0
  36. data/lib/workarea/authorize_cim/error.rb +12 -0
  37. data/lib/workarea/authorize_cim/version.rb +7 -0
  38. data/test/dummy/Rakefile +6 -0
  39. data/test/dummy/app/assets/config/manifest.js +4 -0
  40. data/test/dummy/app/assets/images/.keep +0 -0
  41. data/test/dummy/app/assets/javascripts/application.js +13 -0
  42. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  43. data/test/dummy/app/controllers/application_controller.rb +3 -0
  44. data/test/dummy/app/controllers/concerns/.keep +0 -0
  45. data/test/dummy/app/helpers/application_helper.rb +2 -0
  46. data/test/dummy/app/jobs/application_job.rb +2 -0
  47. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  48. data/test/dummy/app/models/concerns/.keep +0 -0
  49. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  50. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  51. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  52. data/test/dummy/bin/bundle +3 -0
  53. data/test/dummy/bin/rails +4 -0
  54. data/test/dummy/bin/rake +4 -0
  55. data/test/dummy/bin/setup +34 -0
  56. data/test/dummy/bin/update +29 -0
  57. data/test/dummy/config.ru +5 -0
  58. data/test/dummy/config/application.rb +20 -0
  59. data/test/dummy/config/boot.rb +5 -0
  60. data/test/dummy/config/cable.yml +9 -0
  61. data/test/dummy/config/environment.rb +5 -0
  62. data/test/dummy/config/environments/development.rb +56 -0
  63. data/test/dummy/config/environments/production.rb +86 -0
  64. data/test/dummy/config/environments/test.rb +43 -0
  65. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  66. data/test/dummy/config/initializers/assets.rb +11 -0
  67. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  68. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  69. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  70. data/test/dummy/config/initializers/inflections.rb +16 -0
  71. data/test/dummy/config/initializers/mime_types.rb +4 -0
  72. data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
  73. data/test/dummy/config/initializers/session_store.rb +3 -0
  74. data/test/dummy/config/initializers/workarea.rb +5 -0
  75. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  76. data/test/dummy/config/locales/en.yml +23 -0
  77. data/test/dummy/config/puma.rb +47 -0
  78. data/test/dummy/config/routes.rb +5 -0
  79. data/test/dummy/config/secrets.yml +22 -0
  80. data/test/dummy/config/spring.rb +6 -0
  81. data/test/dummy/db/seeds.rb +3 -0
  82. data/test/dummy/lib/assets/.keep +0 -0
  83. data/test/dummy/log/.keep +0 -0
  84. data/test/dummy/public/404.html +67 -0
  85. data/test/dummy/public/422.html +67 -0
  86. data/test/dummy/public/500.html +66 -0
  87. data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
  88. data/test/dummy/public/apple-touch-icon.png +0 -0
  89. data/test/dummy/public/favicon.ico +0 -0
  90. data/test/factories/workarea/factories/authorize_cim_factory.rb +14 -0
  91. data/test/models/workarea/payment/authorize/credit_card_test.decorator +17 -0
  92. data/test/models/workarea/payment/authorize_cim_integration_test.rb +137 -0
  93. data/test/models/workarea/payment/capture/credit_card_test.decorator +80 -0
  94. data/test/models/workarea/payment/credit_card_integration_test.decorator +30 -0
  95. data/test/models/workarea/payment/profile_test.rb +60 -0
  96. data/test/models/workarea/payment/purchase/credit_card_test.decorator +17 -0
  97. data/test/models/workarea/payment/refund/credit_card_test.decorator +95 -0
  98. data/test/models/workarea/payment/refund_test.decorator +14 -0
  99. data/test/models/workarea/payment/store_credit_card_test.decorator +7 -0
  100. data/test/services/workarea/cancel_order_test.decorator +55 -0
  101. data/test/support/workarea/authorize_cim_gateway_duplicate_window_patch.rb +14 -0
  102. data/test/support/workarea/authorize_cim_gateway_vcr_config.rb +22 -0
  103. data/test/support/workarea/workarea_3_2_backports.rb +57 -0
  104. data/test/system/workarea/storefront/orders_system_test.decorator +28 -0
  105. data/test/test_helper.rb +17 -0
  106. data/test/vcr_cassettes/authorize_net_cim/auth_capture.yml +435 -0
  107. data/test/vcr_cassettes/authorize_net_cim/auth_void.yml +436 -0
  108. data/test/vcr_cassettes/authorize_net_cim/purchase_void.yml +436 -0
  109. data/test/vcr_cassettes/authorize_net_cim/store_auth.yml +371 -0
  110. data/test/vcr_cassettes/authorize_net_cim/store_purchase.yml +371 -0
  111. data/test/vcr_cassettes/credit_card/auth_capture.yml +438 -0
  112. data/test/vcr_cassettes/credit_card/auth_void.yml +439 -0
  113. data/test/vcr_cassettes/credit_card/purchase_void.yml +439 -0
  114. data/test/vcr_cassettes/credit_card/store_auth.yml +374 -0
  115. data/test/vcr_cassettes/credit_card/store_purchase.yml +374 -0
  116. data/test/workers/workarea/send_refund_email_test.decorator +70 -0
  117. data/workarea-authorize_cim.gemspec +27 -0
  118. metadata +187 -0
@@ -0,0 +1,80 @@
1
+ module Workarea
2
+ decorate Payment::Capture::CreditCardTest, with: :cim do
3
+ def test_complete_captures_on_the_credit_card_gateway
4
+ # no capture defined on this gateway
5
+ end
6
+
7
+ private
8
+
9
+ def reference
10
+ @reference ||= Payment::Transaction.new(
11
+ amount: 5.to_m,
12
+ response: ActiveMerchant::Billing::Response.new(
13
+ true,
14
+ 'Message',
15
+ reference_params,
16
+ { authorization: authorization }
17
+ )
18
+ )
19
+ end
20
+
21
+ def reference_params
22
+ {
23
+ 'messages' => {
24
+ 'result_code' => 'Ok',
25
+ 'message' => {
26
+ 'code' => 'I00001',
27
+ 'text' => 'Successful.'
28
+ }
29
+ },
30
+ 'direct_response' => {
31
+ 'raw' => '1,1,1,(TESTMODE) This transaction has been approved.,000000,P,0,,,77.49,CC,auth_only,,,,,,,,,,,,bcrouse@workarea.com,,,,,,,,,,,,,,F6000E62F2517691DED641D62E1B0FD8,,,,,,,,,,,,,XXXX5100,MasterCard,,,,,,,,,,,,,,,,',
32
+ 'response_code' => '1',
33
+ 'response_subcode' => '1',
34
+ 'response_reason_code' => '1',
35
+ 'message' => '(TESTMODE) This transaction has been approved.',
36
+ 'approval_code' => '000000',
37
+ 'avs_response' => 'P',
38
+ 'transaction_id' => '0',
39
+ 'invoice_number' => '',
40
+ 'order_description' => '',
41
+ 'amount' => '77.49',
42
+ 'method' => 'CC',
43
+ 'transaction_type' => 'auth_only',
44
+ 'customer_id' => '',
45
+ 'first_name' => '',
46
+ 'last_name' => '',
47
+ 'company' => '',
48
+ 'address' => '',
49
+ 'city' => '',
50
+ 'state' => '',
51
+ 'zip_code' => '',
52
+ 'country' => '',
53
+ 'phone' => '',
54
+ 'fax' => '',
55
+ 'email_address' => 'bcrouse@workarea.com',
56
+ 'ship_to_first_name' => '',
57
+ 'ship_to_last_name' => '',
58
+ 'ship_to_company' => '',
59
+ 'ship_to_address' => '',
60
+ 'ship_to_city' => '',
61
+ 'ship_to_state' => '',
62
+ 'ship_to_zip_code' => '',
63
+ 'ship_to_country' => '',
64
+ 'tax' => '',
65
+ 'duty' => '',
66
+ 'tax_exempt' => '',
67
+ 'purchase_order_number' => '',
68
+ 'md5_hash' => 'F6000E62F2517691DED641D62E1B0FD8',
69
+ 'card_code' => '',
70
+ 'cardholder_authentication_verification_response' => '',
71
+ 'account_number' => 'XXXX5100',
72
+ 'card_type' => 'MasterCard',
73
+ 'split_tender_id' => '',
74
+ 'requested_amount' => '',
75
+ 'balance_on_card' => ''
76
+ }
77
+ }
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,30 @@
1
+ module Workarea
2
+ if Workarea::VERSION::MAJOR == 3 && Workarea::VERSION::MINOR >= 3
3
+ decorate Payment::CreditCardIntegrationTest, with: :cim do
4
+ decorated { include AuthorizeCimGatewayVCRConfig }
5
+
6
+ private
7
+
8
+ def payment
9
+
10
+ @payment ||=
11
+ begin
12
+ profile = create_payment_profile
13
+ create_payment(
14
+ id: SecureRandom.hex(5).upcase,
15
+ profile_id: profile.id,
16
+ address: {
17
+ first_name: 'Ben',
18
+ last_name: 'Crouse',
19
+ street: '22 s. 3rd st.',
20
+ city: 'Philadelphia',
21
+ region: 'PA',
22
+ postal_code: '19106',
23
+ country: Country['US']
24
+ }
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module Workarea
6
+ class Payment
7
+ class ProfileTest < TestCase
8
+ def setup
9
+ @user = create_user
10
+ @reference = PaymentReference.new @user
11
+ @profile = Profile.lookup @reference
12
+ end
13
+
14
+ def test_default_credit_card
15
+ default = create_saved_credit_card(profile: @profile, default: true)
16
+ create_saved_credit_card(profile: @profile, default: false)
17
+
18
+ assert_equal(default, @profile.default_credit_card)
19
+ end
20
+
21
+ def test_default_credit_card_one_hour_ago
22
+ default = create_saved_credit_card profile: @profile
23
+ create_saved_credit_card(profile: @profile, created_at: Time.now - 1.hour)
24
+
25
+ assert_equal default, @profile.default_credit_card
26
+ end
27
+
28
+ def test_purchase_on_store_credit
29
+ @profile.update_attributes(store_credit: 10.to_m)
30
+ @profile.purchase_on_store_credit(500)
31
+ @profile.reload
32
+
33
+ assert_equal 5.to_m, @profile.store_credit
34
+
35
+ assert_raises InsufficientFunds do
36
+ @profile.purchase_on_store_credit(5000)
37
+ end
38
+ end
39
+
40
+ def test_reload_store_credit
41
+ @profile.update_attributes(store_credit: 0.to_m)
42
+ @profile.reload_store_credit(500)
43
+ @profile.reload
44
+
45
+ assert_equal 5.to_m, @profile.store_credit
46
+ end
47
+
48
+ def test_duplicate_profile
49
+ remote_profile_id = @profile.send :remote_profile_id
50
+
51
+ assert remote_profile_id.present?
52
+ assert_kind_of String, remote_profile_id
53
+ end
54
+
55
+ def test_find_duplicate_payment_profile_id
56
+ assert_match(/\A\d{5}/, @profile.send(:remote_profile_id))
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,17 @@
1
+ module Workarea
2
+ decorate Payment::Purchase::CreditCardTest, with: :cim do
3
+ def test_complete_purchase_on_the_credit_card_gateway
4
+ # no purchase on this gateway
5
+ end
6
+
7
+ def test_cancel_voids_with_the_authorization_from_the_transaction
8
+ # no void on this gateway
9
+ end
10
+
11
+ private
12
+
13
+ def payment
14
+ @payment ||= create_payment(profile: create_payment_profile)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,95 @@
1
+ module Workarea
2
+ decorate Payment::Refund::CreditCardTest, with: :cim do
3
+ def test_complete_refunds_on_the_credit_card_gateway
4
+ # no refund on this gateway
5
+ end
6
+
7
+ private
8
+
9
+ def payment
10
+ @payment ||=
11
+ begin
12
+ result = create_payment(profile: create_payment_profile)
13
+ result.set_credit_card(
14
+ number: 1,
15
+ month: 1,
16
+ year: Time.current.year + 1,
17
+ cvv: 999
18
+ )
19
+
20
+ result
21
+ end
22
+ end
23
+
24
+ def reference
25
+ @reference ||= Payment::Transaction.new(
26
+ amount: 5.to_m,
27
+ response: ActiveMerchant::Billing::Response.new(
28
+ true,
29
+ 'Message',
30
+ reference_params,
31
+ { authorization: authorization }
32
+ )
33
+ )
34
+ end
35
+
36
+ def reference_params
37
+ {
38
+ 'messages' => {
39
+ 'result_code' => 'Ok',
40
+ 'message' => {
41
+ 'code' => 'I00001',
42
+ 'text' => 'Successful.'
43
+ }
44
+ },
45
+ 'direct_response' => {
46
+ 'raw' => '1,1,1,(TESTMODE) This transaction has been approved.,000000,P,0,,,77.49,CC,auth_only,,,,,,,,,,,,bcrouse@workarea.com,,,,,,,,,,,,,,F6000E62F2517691DED641D62E1B0FD8,,,,,,,,,,,,,XXXX5100,MasterCard,,,,,,,,,,,,,,,,',
47
+ 'response_code' => '1',
48
+ 'response_subcode' => '1',
49
+ 'response_reason_code' => '1',
50
+ 'message' => '(TESTMODE) This transaction has been approved.',
51
+ 'approval_code' => '000000',
52
+ 'avs_response' => 'P',
53
+ 'transaction_id' => '0',
54
+ 'invoice_number' => '',
55
+ 'order_description' => '',
56
+ 'amount' => '77.49',
57
+ 'method' => 'CC',
58
+ 'transaction_type' => 'auth_only',
59
+ 'customer_id' => '',
60
+ 'first_name' => '',
61
+ 'last_name' => '',
62
+ 'company' => '',
63
+ 'address' => '',
64
+ 'city' => '',
65
+ 'state' => '',
66
+ 'zip_code' => '',
67
+ 'country' => '',
68
+ 'phone' => '',
69
+ 'fax' => '',
70
+ 'email_address' => 'bcrouse@workarea.com',
71
+ 'ship_to_first_name' => '',
72
+ 'ship_to_last_name' => '',
73
+ 'ship_to_company' => '',
74
+ 'ship_to_address' => '',
75
+ 'ship_to_city' => '',
76
+ 'ship_to_state' => '',
77
+ 'ship_to_zip_code' => '',
78
+ 'ship_to_country' => '',
79
+ 'tax' => '',
80
+ 'duty' => '',
81
+ 'tax_exempt' => '',
82
+ 'purchase_order_number' => '',
83
+ 'md5_hash' => 'F6000E62F2517691DED641D62E1B0FD8',
84
+ 'card_code' => '',
85
+ 'cardholder_authentication_verification_response' => '',
86
+ 'account_number' => 'XXXX5100',
87
+ 'card_type' => 'MasterCard',
88
+ 'split_tender_id' => '',
89
+ 'requested_amount' => '',
90
+ 'balance_on_card' => ''
91
+ }
92
+ }
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,14 @@
1
+ module Workarea
2
+ decorate Payment::RefundTest, with: :cim do
3
+ def test_valid_is_false_if_there_are_no_refundable_transactions
4
+ payment.store_credit = nil
5
+ profile.update_attributes!(store_credit: 0)
6
+ payment.purchase!
7
+ refund = Payment::Refund.new(payment: payment)
8
+ refund.allocate_amounts!(total: 5.to_m)
9
+
10
+ refute(refund.valid?)
11
+ assert(refund.errors[:credit_card].present?)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ module Workarea
2
+ decorate Payment::StoreCreditCardTest, with: :cim do
3
+ def test_perform_stores_on_the_gateway
4
+ # no store on this gateway
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,55 @@
1
+ module Workarea
2
+ decorate CancelOrderTest, with: :cim do
3
+ def test_refunding_payment
4
+ @order.update_attributes!(email: 'test@workarea.com')
5
+
6
+ profile = create_payment_profile(store_credit: 6.to_m)
7
+ payment = create_payment(id: @order.id, profile: profile)
8
+
9
+ travel_to 2.days.ago do
10
+ payment.set_address(
11
+ first_name: 'Ben',
12
+ last_name: 'Crouse',
13
+ street: '22 S. 3rd St.',
14
+ city: 'Philadelphia',
15
+ region: 'PA',
16
+ postal_code: '19106',
17
+ country: 'US',
18
+ phone_number: '2159251800'
19
+ )
20
+
21
+ payment.set_store_credit
22
+ payment.set_credit_card(
23
+ number: '1',
24
+ month: 1,
25
+ year: Time.current.year + 1,
26
+ cvv: '999',
27
+ amount: 5.to_m
28
+ )
29
+
30
+ payment.adjust_tender_amounts(11.to_m)
31
+ payment.purchase!
32
+ end
33
+
34
+ Payment::Refund.new(
35
+ payment: payment,
36
+ amounts: { payment.store_credit.id => 3.to_m }
37
+ ).complete!
38
+
39
+ cancel = CancelOrder.new(@order)
40
+ result = cancel.refund
41
+
42
+ assert_equal(2, Payment::Refund.count)
43
+
44
+ assert_equal(
45
+ Money.mongoize(3.to_m),
46
+ result.amounts[payment.store_credit.id.to_s]
47
+ )
48
+
49
+ assert_equal(
50
+ Money.mongoize(5.to_m),
51
+ result.amounts[payment.credit_card.id.to_s]
52
+ )
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,14 @@
1
+ decorate ActiveMerchant::Billing::AuthorizeNetCimGateway, with: :workarea do
2
+ def build_create_customer_profile_transaction_request(xml, options)
3
+ options[:extra_options] ||= {}
4
+ options[:extra_options].merge!('x_delim_char' => @options[:delimiter]) if @options[:delimiter]
5
+ options[:extra_options].merge!('x_duplicate_window' => 0)
6
+
7
+ add_transaction(xml, options[:transaction])
8
+ xml.tag!('extraOptions') do
9
+ xml.cdata!(format_extra_options(options[:extra_options]))
10
+ end unless options[:extra_options].blank?
11
+
12
+ xml.target!
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ module Workarea
2
+ module AuthorizeCimGatewayVCRConfig
3
+ def self.included(test)
4
+ super
5
+ test.setup :setup_gateway
6
+ test.teardown :reset_gateway
7
+ end
8
+
9
+ def setup_gateway
10
+ @_old_gateway = Workarea.config.gateways.credit_card
11
+ Workarea.config.gateways.credit_card = ActiveMerchant::Billing::AuthorizeNetCimGateway.new(
12
+ login: 'a',
13
+ password: 'b',
14
+ test: true
15
+ )
16
+ end
17
+
18
+ def reset_gateway
19
+ Workarea.config.gateways.credit_card = @_old_gateway
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,57 @@
1
+ # This file contains changes coming in Workarea 3.2 which are used in the payment
2
+ # integration tests
3
+
4
+ module Workarea
5
+ if Workarea::VERSION::MAJOR == 3 && Workarea::VERSION::MINOR < 2
6
+ decorate Payment::Refund, with: :workarea_backports do
7
+ # Set amounts for tenders automatically (as opposed to custom amounts)
8
+ # This will reset the current amount!
9
+ def allocate_amounts!(total:)
10
+ self.amounts = {}
11
+ allocated_amount = 0.to_m
12
+
13
+ payment.tenders.reverse.each do |tender|
14
+ amount_for_this_tender = total - allocated_amount
15
+
16
+ if amount_for_this_tender > tender.refundable_amount
17
+ amount_for_this_tender = tender.refundable_amount
18
+ end
19
+
20
+ allocated_amount += amount_for_this_tender
21
+ amounts[tender.id] = amount_for_this_tender
22
+ end
23
+ end
24
+ end
25
+
26
+ decorate Payment::Capture, with: :workarea_backports do
27
+ # Set amounts for tenders automatically (as opposed to custom amounts)
28
+ # This will reset the current amounts!
29
+ def allocate_amounts!(total:)
30
+ self.amounts = {}
31
+ allocated_amount = 0.to_m
32
+
33
+ payment.tenders.each do |tender|
34
+ amount_for_this_tender = total - allocated_amount
35
+
36
+ if amount_for_this_tender > tender.capturable_amount
37
+ amount_for_this_tender = tender.capturable_amount
38
+ end
39
+
40
+ allocated_amount += amount_for_this_tender
41
+ amounts[tender.id] = amount_for_this_tender
42
+ end
43
+ end
44
+ end
45
+
46
+ decorate Payment::Capture, Payment::Refund, with: :workarea_processing_backports do
47
+ # Deal with inconsistent Mongoid serializing of Money within a Hash field
48
+ def parse_amount(amount)
49
+ if Money === amount || String === amount || Integer === amount || Float === amount
50
+ amount.to_m
51
+ else
52
+ Money.demongoize(amount)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end