archetype_spree_gateway 3.9.5

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 (124) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +39 -0
  5. data/Gemfile +9 -0
  6. data/Guardfile +9 -0
  7. data/LICENSE.md +26 -0
  8. data/README.md +105 -0
  9. data/Rakefile +15 -0
  10. data/app/models/spree/billing_integration.rb +21 -0
  11. data/app/models/spree/check.rb +41 -0
  12. data/app/models/spree/gateway/authorize_net.rb +45 -0
  13. data/app/models/spree/gateway/authorize_net_cim.rb +213 -0
  14. data/app/models/spree/gateway/balanced_gateway.rb +64 -0
  15. data/app/models/spree/gateway/banwire.rb +15 -0
  16. data/app/models/spree/gateway/beanstream.rb +193 -0
  17. data/app/models/spree/gateway/braintree_gateway.rb +184 -0
  18. data/app/models/spree/gateway/card_save.rb +10 -0
  19. data/app/models/spree/gateway/cyber_source.rb +10 -0
  20. data/app/models/spree/gateway/data_cash.rb +10 -0
  21. data/app/models/spree/gateway/epay.rb +10 -0
  22. data/app/models/spree/gateway/eway.rb +18 -0
  23. data/app/models/spree/gateway/eway_rapid.rb +14 -0
  24. data/app/models/spree/gateway/maxipago.rb +14 -0
  25. data/app/models/spree/gateway/migs.rb +11 -0
  26. data/app/models/spree/gateway/moneris.rb +10 -0
  27. data/app/models/spree/gateway/pay_junction.rb +14 -0
  28. data/app/models/spree/gateway/pay_pal_gateway.rb +12 -0
  29. data/app/models/spree/gateway/payflow_pro.rb +15 -0
  30. data/app/models/spree/gateway/paymill.rb +12 -0
  31. data/app/models/spree/gateway/payu_polska_gateway.rb +24 -0
  32. data/app/models/spree/gateway/pin_gateway.rb +60 -0
  33. data/app/models/spree/gateway/quickpay.rb +9 -0
  34. data/app/models/spree/gateway/sage_pay.rb +11 -0
  35. data/app/models/spree/gateway/secure_pay_au.rb +10 -0
  36. data/app/models/spree/gateway/spreedly_core_gateway.rb +11 -0
  37. data/app/models/spree/gateway/stripe_ach_gateway.rb +60 -0
  38. data/app/models/spree/gateway/stripe_apple_pay_gateway.rb +10 -0
  39. data/app/models/spree/gateway/stripe_elements_gateway.rb +61 -0
  40. data/app/models/spree/gateway/stripe_gateway.rb +151 -0
  41. data/app/models/spree/gateway/usa_epay_transaction.rb +9 -0
  42. data/app/models/spree/gateway/worldpay.rb +91 -0
  43. data/app/models/spree/payu_polska.rb +41 -0
  44. data/app/models/spree_gateway/apple_pay_order_decorator.rb +20 -0
  45. data/app/models/spree_gateway/apple_pay_payment_decorator.rb +9 -0
  46. data/app/models/spree_gateway/credit_card_decorator.rb +10 -0
  47. data/app/models/spree_gateway/order_decorator.rb +28 -0
  48. data/app/models/spree_gateway/payment_decorator.rb +36 -0
  49. data/app/views/spree/checkout/_payment_confirm.html.erb +39 -0
  50. data/app/views/spree/checkout/_payu.html +12 -0
  51. data/config/initializers/inflections.rb +3 -0
  52. data/config/initializers/spree_permitted_attributes.rb +5 -0
  53. data/config/locales/bg.yml +4 -0
  54. data/config/locales/de.yml +4 -0
  55. data/config/locales/en.yml +47 -0
  56. data/config/locales/sv.yml +4 -0
  57. data/config/routes.rb +19 -0
  58. data/db/migrate/20200317135551_add_spree_check_payment_source.rb +22 -0
  59. data/db/migrate/20200422114908_add_intent_key_to_payment.rb +5 -0
  60. data/lib/active_merchant/billing/stripe_gateway_decorator.rb +33 -0
  61. data/lib/controllers/spree/api/v2/storefront/intents_controller.rb +45 -0
  62. data/lib/controllers/spree/apple_pay_domain_verification_controller.rb +11 -0
  63. data/lib/generators/spree_gateway/install/install_generator.rb +19 -0
  64. data/lib/spree_frontend/controllers/spree/checkout_controller_decorator.rb +19 -0
  65. data/lib/spree_gateway/engine.rb +80 -0
  66. data/lib/spree_gateway/version.rb +5 -0
  67. data/lib/spree_gateway.rb +4 -0
  68. data/lib/views/backend/spree/admin/log_entries/_braintree.html.erb +31 -0
  69. data/lib/views/backend/spree/admin/log_entries/_stripe.html.erb +28 -0
  70. data/lib/views/backend/spree/admin/payments/source_forms/_quickcheckout.html.erb +8 -0
  71. data/lib/views/backend/spree/admin/payments/source_forms/_stripe.html.erb +79 -0
  72. data/lib/views/backend/spree/admin/payments/source_forms/_stripe_ach.html.erb +86 -0
  73. data/lib/views/backend/spree/admin/payments/source_forms/_stripe_apple_pay.html.erb +0 -0
  74. data/lib/views/backend/spree/admin/payments/source_forms/_stripe_elements.html.erb +79 -0
  75. data/lib/views/backend/spree/admin/payments/source_views/_stripe.html.erb +1 -0
  76. data/lib/views/backend/spree/admin/payments/source_views/_stripe_ach.html.erb +21 -0
  77. data/lib/views/backend/spree/admin/payments/source_views/_stripe_apple_pay.html.erb +1 -0
  78. data/lib/views/backend/spree/admin/payments/source_views/_stripe_elements.html.erb +1 -0
  79. data/lib/views/frontend/spree/checkout/payment/_stripe.html.erb +86 -0
  80. data/lib/views/frontend/spree/checkout/payment/_stripe_ach.html.erb +81 -0
  81. data/lib/views/frontend/spree/checkout/payment/_stripe_ach_verify.html.erb +16 -0
  82. data/lib/views/frontend/spree/checkout/payment/_stripe_additional_info.html.erb +16 -0
  83. data/lib/views/frontend/spree/checkout/payment/_stripe_apple_pay.html.erb +109 -0
  84. data/lib/views/frontend/spree/checkout/payment/_stripe_elements.html.erb +110 -0
  85. data/script/rails +7 -0
  86. data/spec/factories/check_factory.rb +10 -0
  87. data/spec/features/admin/stripe_elements_payment_spec.rb +100 -0
  88. data/spec/features/stripe_checkout_spec.rb +130 -0
  89. data/spec/features/stripe_elements_3ds_checkout_spec.rb +225 -0
  90. data/spec/models/gateway/authorize_net_cim_spec.rb +29 -0
  91. data/spec/models/gateway/authorize_net_spec.rb +23 -0
  92. data/spec/models/gateway/balanced_gateway_spec.rb +17 -0
  93. data/spec/models/gateway/banwire_spec.rb +11 -0
  94. data/spec/models/gateway/beanstream_spec.rb +17 -0
  95. data/spec/models/gateway/braintree_gateway_spec.rb +420 -0
  96. data/spec/models/gateway/card_save_spec.rb +11 -0
  97. data/spec/models/gateway/cyber_source_spec.rb +11 -0
  98. data/spec/models/gateway/data_cash_spec.rb +11 -0
  99. data/spec/models/gateway/epay_spec.rb +11 -0
  100. data/spec/models/gateway/eway_rapid_spec.rb +23 -0
  101. data/spec/models/gateway/eway_spec.rb +29 -0
  102. data/spec/models/gateway/maxipago_spec.rb +17 -0
  103. data/spec/models/gateway/moneris_spec.rb +11 -0
  104. data/spec/models/gateway/pay_junction_spec.rb +23 -0
  105. data/spec/models/gateway/pay_pal_spec.rb +11 -0
  106. data/spec/models/gateway/payflow_pro_spec.rb +23 -0
  107. data/spec/models/gateway/paymill_spec.rb +11 -0
  108. data/spec/models/gateway/pin_gateway_spec.rb +54 -0
  109. data/spec/models/gateway/quickpay_spec.rb +11 -0
  110. data/spec/models/gateway/sage_pay_spec.rb +11 -0
  111. data/spec/models/gateway/secure_pay_au_spec.rb +11 -0
  112. data/spec/models/gateway/stripe_ach_gateway_spec.rb +186 -0
  113. data/spec/models/gateway/stripe_gateway_spec.rb +199 -0
  114. data/spec/models/gateway/usa_epay_transaction_spec.rb +49 -0
  115. data/spec/models/gateway/worldpay_spec.rb +11 -0
  116. data/spec/models/spree/order_spec.rb +79 -0
  117. data/spec/requests/apple_pay_domain_verification.rb +45 -0
  118. data/spec/requests/spree/api/v2/storefront/intents_controller_spec.rb +198 -0
  119. data/spec/spec_helper.rb +10 -0
  120. data/spec/support/order_walktrough.rb +73 -0
  121. data/spec/support/wait_for_stripe.rb +27 -0
  122. data/spec/support/within_stripe_3ds_popup.rb +10 -0
  123. data/spree_gateway.gemspec +37 -0
  124. metadata +277 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f5d09441469ac5dede82534c51cabe9f81584cb3c07909c852e1fb08101574b1
4
+ data.tar.gz: 319f475d119d8b552201331626935ce439c4dc9199e738c779df2f19d8cbd696
5
+ SHA512:
6
+ metadata.gz: 99d8aaec4ffd482c9dfc52e6873222ed604b36c5cd03c6a0ce5df80a465740ca1dba779d5337eae27b84b6b96f5cfe3d091000c769c410f475115afbe3bfb6fd
7
+ data.tar.gz: 0f32987262dc458ce2e662cd1286cf0f90dc5ed5ee354a9fd8267522da99374ea6e0389edbec07d964fc0f33eb2571c83280a41c75979ece41155b90dc388365
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .localeapp/locales
7
+ .project
8
+ coverage
9
+ default
10
+ Gemfile.lock
11
+ tmp
12
+ nbproject
13
+ pkg
14
+ *.sw?
15
+ spec/dummy
16
+ .rvmrc
17
+ .sass-cache
18
+ public/spree
19
+ .ruby-version
20
+ .ruby-gemset
21
+ gemfiles/*.gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ -r spec_helper
3
+ -f documentation
data/.travis.yml ADDED
@@ -0,0 +1,39 @@
1
+ os: linux
2
+ dist: bionic
3
+
4
+ cache: bundler
5
+
6
+ addons:
7
+ apt:
8
+ sources:
9
+ - google-chrome
10
+ packages:
11
+ - google-chrome-stable
12
+
13
+ services:
14
+ - mysql
15
+ - postgresql
16
+ - redis-server
17
+
18
+ language: ruby
19
+
20
+ rvm:
21
+ - 2.7
22
+ - 3.0
23
+
24
+ env:
25
+ - DB=mysql
26
+ - DB=postgres
27
+
28
+ before_install:
29
+ - mysql -u root -e "GRANT ALL ON *.* TO 'travis'@'%';"
30
+
31
+ before_script:
32
+ - CHROME_MAIN_VERSION=`google-chrome-stable --version | sed -E 's/(^Google Chrome |\.[0-9]+ )//g'`
33
+ - CHROMEDRIVER_VERSION=`curl -s "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_$CHROME_MAIN_VERSION"`
34
+ - curl "https://chromedriver.storage.googleapis.com/${CHROMEDRIVER_VERSION}/chromedriver_linux64.zip" -O
35
+ - unzip chromedriver_linux64.zip -d ~/bin
36
+
37
+ script:
38
+ - bundle exec rake test_app
39
+ - bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rails-controller-testing'
4
+ gem 'spree', github: 'spree/spree', branch: 'main'
5
+ gem 'spree_backend', github: 'spree/spree_backend', branch: 'main'
6
+ gem 'spree_frontend', github: 'spree/spree_legacy_frontend', branch: 'main'
7
+ gem 'activemerchant', github: 'archetype2142/active-merchant', branch: 'master'
8
+
9
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ guard "rspec", cmd: "bundle exec rspec", all_after_pass: false, all_on_start: false do
2
+ watch("spec/spec_helper.rb") { "spec" }
3
+ watch("config/routes.rb") { "spec/controllers" }
4
+ watch(%r{^spec/(.+)_spec\.rb$}) { |m| "spec/#{m[1]}_spec.rb"}
5
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
6
+ watch(%r{^app/(.*)\.erb$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
7
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
8
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb" }
9
+ end
data/LICENSE.md ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2014 Spree Commerce Inc. and other contributors.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Spree nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # Spree Gateway
2
+
3
+ [![Build Status](https://api.travis-ci.org/spree/spree_gateway.svg?branch=main)](https://travis-ci.org/spree/spree_gateway)
4
+ [![Code Climate](https://codeclimate.com/github/spree/spree_gateway.svg)](https://codeclimate.com/github/spree/spree_gateway)
5
+
6
+ Community supported Spree Payment Method Gateways. It works as a wrapper for
7
+ [active_merchant](https://github.com/activemerchant/active_merchant) gateway.
8
+
9
+ Supported payment gateways:
10
+ * Authorize.net (with CIM support)
11
+ * Apple Pay (via Stripe)
12
+ * BanWire
13
+ * Bambora (previously Beanstream)
14
+ * Braintree
15
+ * CyberSource
16
+ * ePay
17
+ * eWay
18
+ * maxipago
19
+ * MasterCard Payment Gateway Service (formerly MiGS)
20
+ * Moneris
21
+ * PayJunction
22
+ * Payflow
23
+ * Paymill
24
+ * Pin Payments
25
+ * QuickPay
26
+ * sage Pay
27
+ * SecurePay
28
+ * Spreedly
29
+ * Stripe (with Stripe Elements)
30
+ * USAePay
31
+ * Worldpay (previously Cardsave)
32
+
33
+ For`PayPal` support head over to [braintree_vzero](https://github.com/spree-contrib/spree_braintree_vzero) extension.
34
+
35
+ ## Installation
36
+
37
+ 1. Add this extension to your Gemfile with this line:
38
+
39
+ ```ruby
40
+ gem 'spree_gateway', '~> 3.7'
41
+ ```
42
+
43
+ 2. Install the gem using Bundler:
44
+ ```ruby
45
+ bundle install
46
+ ```
47
+
48
+ 3. Copy & run migrations
49
+ ```ruby
50
+ bundle exec rails g spree_gateway:install
51
+ ```
52
+
53
+ Finally, make sure to **restart your app**. Navigate to *Configuration > Payment Methods > New Payment Method* in the admin panel and you should see that a bunch of additional gateways have been added to the list.
54
+
55
+ ## Contributing
56
+
57
+ In the spirit of [free software][1], **everyone** is encouraged to help improve this project.
58
+
59
+ Here are some ways *you* can contribute:
60
+
61
+ * by using prerelease versions
62
+ * by reporting [bugs][2]
63
+ * by suggesting new features
64
+ * by writing or editing documentation
65
+ * by writing specifications
66
+ * by writing code (*no patch is too small*: fix typos, add comments, clean up inconsistent whitespace)
67
+ * by refactoring code
68
+ * by resolving [issues][2]
69
+ * by reviewing patches
70
+
71
+ Starting point:
72
+
73
+ * Fork the repo
74
+ * Clone your repo
75
+ * (You will need to `brew install mysql postgres` if you don't already have them installed)
76
+ * Run `bundle`
77
+ * (You may need to `bundle update` if bundler gets stuck)
78
+ * Run `bundle exec rake test_app` to create the test application in `spec/test_app`
79
+ * Make your changes
80
+ * Ensure specs pass by running `bundle exec rspec spec`
81
+ * (You will need to `brew install phantomjs` if you don't already have it installed)
82
+ * Submit your pull request
83
+
84
+
85
+ License
86
+ ----------------------
87
+
88
+ Spree is released under the [New BSD License][3].
89
+
90
+ About Spark Solutions
91
+ ----------------------
92
+ [![Spark Solutions](http://sparksolutions.co/wp-content/uploads/2015/01/logo-ss-tr-221x100.png)][spark]
93
+
94
+ Spree Gateway is maintained by [Spark Solutions Sp. z o.o.][spark].
95
+
96
+ We are passionate about open source software.
97
+ We are [available for hire][spark].
98
+
99
+ [spark]:http://sparksolutions.co?utm_source=github
100
+
101
+ [1]: http://www.fsf.org/licensing/essays/free-sw.html
102
+ [2]: https://github.com/spree/spree_gateway/issues
103
+ [3]: https://github.com/spree/spree_gateway/blob/main/LICENSE.md
104
+ [4]: https://github.com/spree
105
+ [5]: https://github.com/spree/spree_gateway/graphs/contributors
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/extension_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default => [:spec]
10
+
11
+ desc "Generates a dummy app for testing"
12
+ task :test_app do
13
+ ENV['LIB_NAME'] = 'spree_gateway'
14
+ Rake::Task['extension:test_app'].invoke
15
+ end
@@ -0,0 +1,21 @@
1
+ module Spree
2
+ class BillingIntegration < PaymentMethod
3
+ validates :name, presence: true
4
+
5
+ preference :server, :string, default: 'test'
6
+ preference :test_mode, :boolean, default: true
7
+
8
+ def provider
9
+ integration_options = options
10
+ ActiveMerchant::Billing::Base.integration_mode = integration_options[:server].to_sym
11
+ integration_options[:test] = true if integration_options[:test_mode]
12
+ @provider ||= provider_class.new(integration_options)
13
+ end
14
+
15
+ def options
16
+ options_hash = {}
17
+ preferences.each { |key, value| options_hash[key.to_sym] = value }
18
+ options_hash
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ module Spree
2
+ class Check < Spree::Base
3
+
4
+ attr_accessor :imported
5
+
6
+ belongs_to :payment_method
7
+ belongs_to :user, class_name: Spree.user_class.to_s, foreign_key: 'user_id',
8
+ optional: true
9
+ has_many :payments, as: :source
10
+
11
+ scope :with_payment_profile, -> { where.not(gateway_customer_profile_id: nil) }
12
+
13
+ validates :account_holder_name, presence: true
14
+ validates :account_holder_type, presence: true, inclusion: { in: %w[Individual Company] }
15
+ validates :account_number, presence: true, numericality: { only_integer: true }
16
+ validates :routing_number, presence: true, numericality: { only_integer: true }
17
+
18
+ def has_payment_profile?
19
+ gateway_customer_profile_id.present? || gateway_payment_profile_id.present?
20
+ end
21
+
22
+ def actions
23
+ %w[capture void credit]
24
+ end
25
+
26
+ def can_capture?(payment)
27
+ payment.pending? || payment.checkout?
28
+ end
29
+
30
+ # Indicates whether its possible to void the payment.
31
+ def can_void?(payment)
32
+ !payment.failed? && !payment.void?
33
+ end
34
+
35
+ # Indicates whether its possible to credit the payment. Note that most gateways require that the
36
+ # payment be settled first which generally happens within 12-24 hours of the transaction.
37
+ def can_credit?(payment)
38
+ payment.completed? && payment.credit_allowed > 0
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,45 @@
1
+ module Spree
2
+ class Gateway::AuthorizeNet < Gateway
3
+ preference :login, :string
4
+ preference :password, :string
5
+ preference :server, :string, default: "test"
6
+
7
+ def provider_class
8
+ ActiveMerchant::Billing::AuthorizeNetGateway
9
+ end
10
+
11
+ def options
12
+ if !['live','test'].include?(self.preferred_server)
13
+ raise "You must set the 'server' preference in your payment method (Gateway::AuthorizeNet) to either 'live' or 'test'"
14
+ end
15
+ super().merge(test: (self.preferred_server != "live"))
16
+ end
17
+
18
+ def cancel(response_code)
19
+ provider
20
+ # From: http://community.developer.authorize.net/t5/The-Authorize-Net-Developer-Blog/Refunds-in-Retail-A-user-friendly-approach-using-AIM/ba-p/9848
21
+ # DD: if unsettled, void needed
22
+ response = provider.void(response_code)
23
+ # DD: if settled, credit/refund needed (CAN'T DO WITHOUT CREDIT CARD ON AUTH.NET)
24
+ #response = provider.refund(response_code) unless response.success?
25
+
26
+ response
27
+ end
28
+
29
+ def credit(amount, response_code, refund, gateway_options = {})
30
+ gateway_options[:card_number] = refund[:originator].payment.source.last_digits
31
+ auth_net_gateway.refund(amount, response_code, gateway_options)
32
+ end
33
+
34
+ private
35
+
36
+ def auth_net_gateway
37
+ @_auth_net_gateway ||= begin
38
+ ActiveMerchant::Billing::Base.gateway_mode = preferred_server.to_sym
39
+ gateway_options = options
40
+ gateway_options[:test_requests] = false # DD: never ever do test requests because just returns transaction_id = 0
41
+ ActiveMerchant::Billing::AuthorizeNetGateway.new(gateway_options)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,213 @@
1
+ module Spree
2
+ class Gateway::AuthorizeNetCim < Gateway
3
+ preference :login, :string
4
+ preference :password, :string
5
+ preference :server, :string, default: "test"
6
+ preference :test_mode, :boolean, default: false
7
+ preference :validate_on_profile_create, :boolean, default: false
8
+
9
+ ActiveMerchant::Billing::Response.class_eval do
10
+ attr_writer :authorization
11
+ end
12
+
13
+ def provider_class
14
+ self.class
15
+ end
16
+
17
+ def options
18
+ if !['live','test'].include?(self.preferred_server)
19
+ raise "You must set the 'server' preference in your payment method (Gateway::AuthorizeNetCim) to either 'live' or 'test'"
20
+ end
21
+
22
+ # add :test key in the options hash, as that is what the
23
+ # ActiveMerchant::Billing::AuthorizeNetGateway expects
24
+ if self.preferred_server != "live"
25
+ self.preferences[:test] = true
26
+ else
27
+ self.preferences.delete(:test)
28
+ end
29
+
30
+ super
31
+ end
32
+
33
+ def authorize(amount, creditcard, gateway_options)
34
+ create_transaction(amount, creditcard, :auth_only, transaction_options(gateway_options))
35
+ end
36
+
37
+ def purchase(amount, creditcard, gateway_options)
38
+ create_transaction(amount, creditcard, :auth_capture, transaction_options(gateway_options))
39
+ end
40
+
41
+ # capture is only one where source is not passed in for payment profile
42
+ def capture(amount, response_code, gateway_options)
43
+ # no credit card needed
44
+ create_transaction(amount, nil, :prior_auth_capture, trans_id: response_code)
45
+ end
46
+
47
+ def credit(amount, creditcard, response_code, gateway_options = {})
48
+ create_transaction(amount, creditcard, :refund, transaction_options(gateway_options).merge(trans_id: response_code))
49
+ end
50
+
51
+ def void(response_code, creditcard, gateway_options = {})
52
+ create_transaction(nil, creditcard, :void, transaction_options(gateway_options).merge(trans_id: response_code))
53
+ end
54
+
55
+ def cancel(response_code)
56
+ # From: http://community.developer.authorize.net/t5/The-Authorize-Net-Developer-Blog/Refunds-in-Retail-A-user-friendly-approach-using-AIM/ba-p/9848
57
+ # DD: if unsettled, void needed
58
+ response = void(response_code, nil)
59
+ # DD: if settled, credit/refund needed
60
+ response = credit(nil, nil, response_code) unless response.success?
61
+
62
+ response
63
+ end
64
+
65
+ def payment_profiles_supported?
66
+ true
67
+ end
68
+
69
+ # Create a new CIM customer profile ready to accept a payment. Called by Spree::Payment on after_save.
70
+ def create_profile(payment)
71
+ if payment.source.gateway_customer_profile_id.nil?
72
+ profile_hash = create_customer_profile(payment)
73
+ payment.source.update(gateway_customer_profile_id: profile_hash[:customer_profile_id], gateway_payment_profile_id: profile_hash[:customer_payment_profile_id])
74
+ end
75
+ end
76
+
77
+ # Get the CIM payment profile; Needed for updates.
78
+ def get_profile(payment)
79
+ if payment.source.has_payment_profile?
80
+ profile = cim_gateway.get_customer_profile({
81
+ customer_profile_id: payment.source.gateway_customer_profile_id
82
+ })
83
+ if profile
84
+ profile.params['profile'].deep_symbolize_keys!
85
+ end
86
+ end
87
+ end
88
+
89
+ # Get the CIM payment profile; Needed for updates.
90
+ def get_payment_profile(payment)
91
+ if payment.source.has_payment_profile?
92
+ profile = cim_gateway.get_customer_payment_profile({
93
+ customer_profile_id: payment.source.gateway_customer_profile_id,
94
+ customer_payment_profile_id: payment.source.gateway_payment_profile_id
95
+ })
96
+ if profile
97
+ profile.params['payment_profile'].deep_symbolize_keys!
98
+ end
99
+ end
100
+ end
101
+
102
+ # Update billing address on the CIM payment profile
103
+ def update_payment_profile(payment)
104
+ if payment.source.has_payment_profile?
105
+ if hash = get_payment_profile(payment)
106
+ hash[:bill_to] = generate_address_hash(payment.order.bill_address)
107
+ if hash[:payment][:credit_card]
108
+ # activemerchant expects a credit card object with 'number', 'year', 'month', and 'verification_value?' defined
109
+ payment.source.define_singleton_method(:number) { "XXXXXXXXX#{payment.source.last_digits}" }
110
+ hash[:payment][:credit_card] = payment.source
111
+ end
112
+ cim_gateway.update_customer_payment_profile({
113
+ customer_profile_id: payment.source.gateway_customer_profile_id,
114
+ payment_profile: hash
115
+ })
116
+ end
117
+ end
118
+ end
119
+
120
+ private
121
+
122
+ def transaction_options(gateway_options = {})
123
+ { order: { invoice_number: gateway_options[:order_id] } }
124
+ end
125
+
126
+ # Create a transaction on a creditcard
127
+ # Set up a CIM profile for the card if one doesn't exist
128
+ # Valid transaction_types are :auth_only, :capture_only and :auth_capture
129
+ def create_transaction(amount, creditcard, transaction_type, options = {})
130
+ creditcard.save if creditcard
131
+
132
+ transaction_options = {
133
+ type: transaction_type
134
+ }.update(options)
135
+
136
+ if amount
137
+ amount = "%.2f" % (amount / 100.0) # This gateway requires formated decimal, not cents
138
+ transaction_options.update({
139
+ amount: amount
140
+ })
141
+ end
142
+
143
+ if creditcard
144
+ transaction_options.update({
145
+ customer_profile_id: creditcard.gateway_customer_profile_id,
146
+ customer_payment_profile_id: creditcard.gateway_payment_profile_id
147
+ })
148
+ end
149
+
150
+ logger.debug("\nAuthorize Net CIM Request")
151
+ logger.debug(" transaction_options: #{transaction_options.inspect}")
152
+ t = cim_gateway.create_customer_profile_transaction(transaction: transaction_options)
153
+ logger.debug("\nAuthorize Net CIM Response")
154
+ logger.debug(" response: #{t.inspect}\n")
155
+ t
156
+ end
157
+
158
+ # Create a new CIM customer profile ready to accept a payment
159
+ def create_customer_profile(payment)
160
+ options = options_for_create_customer_profile(payment)
161
+ response = cim_gateway.create_customer_profile(options)
162
+ if response.success?
163
+ { customer_profile_id: response.params['customer_profile_id'],
164
+ customer_payment_profile_id: response.params['customer_payment_profile_id_list'].values.first }
165
+ else
166
+ payment.send(:gateway_error, response)
167
+ end
168
+ end
169
+
170
+ def options_for_create_customer_profile(payment)
171
+ if payment.is_a? CreditCard
172
+ info = { bill_to: generate_address_hash(payment.address),
173
+ payment: { credit_card: payment } }
174
+ else
175
+ info = { bill_to: generate_address_hash(payment.order.bill_address),
176
+ payment: { credit_card: payment.source } }
177
+ end
178
+ validation_mode = preferred_validate_on_profile_create ? preferred_server.to_sym : :none
179
+
180
+ { profile: { merchant_customer_id: "#{Time.now.to_f}",
181
+ ship_to_list: generate_address_hash(payment.order.ship_address),
182
+ email: payment.order.email,
183
+ payment_profiles: info },
184
+ validation_mode: validation_mode }
185
+ end
186
+
187
+ # As in PaymentGateway but with separate name fields
188
+ def generate_address_hash(address)
189
+ return {} if address.nil?
190
+ {
191
+ first_name: address.firstname,
192
+ last_name: address.lastname,
193
+ address1: address.address1,
194
+ address2: address.address2,
195
+ city: address.city,
196
+ state: address.state_text,
197
+ zip: address.zipcode,
198
+ country: address.country.iso,
199
+ phone_number: address.phone
200
+ }
201
+ end
202
+
203
+ def cim_gateway
204
+ @_cim_gateway ||= begin
205
+ ActiveMerchant::Billing::Base.gateway_mode = preferred_server.to_sym
206
+ gateway_options = options
207
+ gateway_options[:test_requests] = false # DD: never ever do test requests because just returns transaction_id = 0
208
+ ActiveMerchant::Billing::AuthorizeNetCimGateway.new(gateway_options)
209
+ end
210
+ end
211
+
212
+ end
213
+ end
@@ -0,0 +1,64 @@
1
+ module Spree
2
+ class Gateway::BalancedGateway < Gateway
3
+ preference :login, :string
4
+ preference :on_behalf_of_uri, :string
5
+
6
+ def authorize(money, creditcard, gateway_options)
7
+ if token = creditcard.gateway_payment_profile_id
8
+ # The Balanced ActiveMerchant gateway supports passing the token directly as the creditcard parameter
9
+ creditcard = token
10
+ end
11
+ provider.authorize(money, creditcard, gateway_options)
12
+ end
13
+
14
+ def capture(authorization, creditcard, gateway_options)
15
+ gateway_options[:on_behalf_of_uri] = self.preferred_on_behalf_of_uri
16
+ provider.capture((authorization.amount * 100).round, authorization.response_code, gateway_options)
17
+ end
18
+
19
+ def create_profile(payment)
20
+ return unless payment.source.gateway_payment_profile_id.nil?
21
+
22
+ options = {}
23
+ options[:email] = payment.order.email
24
+ options[:login] = preferred_login
25
+
26
+ card_store_response = provider.store(payment.source, options)
27
+ card_uri = card_store_response.authorization.split(';').first
28
+
29
+ # A success just returns a string of the token. A failed request returns a bad request response with a message.
30
+ payment.source.update!(:gateway_payment_profile_id => card_uri)
31
+ rescue Error => ex
32
+ payment.send(:gateway_error, ex.message)
33
+ end
34
+
35
+ def options
36
+ super().merge(:test => self.preferred_test_mode)
37
+ end
38
+
39
+ def payment_profiles_supported?
40
+ true
41
+ end
42
+
43
+ def purchase(money, creditcard, gateway_options)
44
+ if token = creditcard.gateway_payment_profile_id
45
+ # The Balanced ActiveMerchant gateway supports passing the token directly as the creditcard parameter
46
+ creditcard = token
47
+ end
48
+ provider.purchase(money, creditcard, gateway_options)
49
+ end
50
+
51
+ def provider_class
52
+ ActiveMerchant::Billing::BalancedGateway
53
+ end
54
+
55
+ def credit(money, creditcard, response_code, gateway_options)
56
+ provider.refund(money, response_code, {})
57
+ end
58
+
59
+ def void(response_code, creditcard, gateway_options)
60
+ provider.void(response_code)
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,15 @@
1
+ module Spree
2
+ class Gateway::Banwire < Gateway
3
+ preference :login, :string
4
+
5
+
6
+ def provider_class
7
+ ActiveMerchant::Billing::BanwireGateway
8
+ end
9
+
10
+ def purchase(money, creditcard, gateway_options)
11
+ gateway_options[:description] = "Spree Order"
12
+ provider.purchase(money, creditcard, gateway_options)
13
+ end
14
+ end
15
+ end