workarea-authorize_cim 2.1.1

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