solidus_gateway 0.9.0
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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.travis.yml +23 -0
- data/Gemfile +9 -0
- data/LICENSE.md +26 -0
- data/README.md +38 -0
- data/Rakefile +21 -0
- data/app/models/spree/billing_integration/skrill/quick_checkout.rb +48 -0
- data/app/models/spree/gateway/authorize_net.rb +31 -0
- data/app/models/spree/gateway/authorize_net_cim.rb +201 -0
- data/app/models/spree/gateway/balanced_gateway.rb +65 -0
- data/app/models/spree/gateway/banwire.rb +15 -0
- data/app/models/spree/gateway/beanstream.rb +193 -0
- data/app/models/spree/gateway/braintree_gateway.rb +184 -0
- data/app/models/spree/gateway/card_save.rb +10 -0
- data/app/models/spree/gateway/data_cash.rb +10 -0
- data/app/models/spree/gateway/eway.rb +20 -0
- data/app/models/spree/gateway/linkpoint.rb +28 -0
- data/app/models/spree/gateway/maxipago.rb +14 -0
- data/app/models/spree/gateway/migs.rb +11 -0
- data/app/models/spree/gateway/moneris.rb +10 -0
- data/app/models/spree/gateway/pay_junction.rb +16 -0
- data/app/models/spree/gateway/pay_pal_gateway.rb +12 -0
- data/app/models/spree/gateway/payflow_pro.rb +18 -0
- data/app/models/spree/gateway/paymill.rb +12 -0
- data/app/models/spree/gateway/pin_gateway.rb +60 -0
- data/app/models/spree/gateway/sage_pay.rb +11 -0
- data/app/models/spree/gateway/secure_pay_au.rb +10 -0
- data/app/models/spree/gateway/spreedly_core_gateway.rb +10 -0
- data/app/models/spree/gateway/stripe_gateway.rb +126 -0
- data/app/models/spree/gateway/usa_epay.rb +9 -0
- data/app/models/spree/gateway/worldpay.rb +91 -0
- data/app/models/spree/skrill_transaction.rb +19 -0
- data/bin/rails +7 -0
- data/circle.yml +6 -0
- data/config/locales/bg.yml +11 -0
- data/config/locales/de.yml +11 -0
- data/config/locales/en.yml +30 -0
- data/config/locales/sv.yml +11 -0
- data/config/routes.rb +12 -0
- data/db/migrate/20111118164631_create_skrill_transactions.rb +14 -0
- data/db/migrate/20121017004102_update_braintree_payment_method_type.rb +9 -0
- data/db/migrate/20130213222555_update_stripe_payment_method_type.rb +9 -0
- data/db/migrate/20130415222802_update_balanced_payment_method_type.rb +9 -0
- data/db/migrate/20131008221012_update_paypal_payment_method_type.rb +9 -0
- data/db/migrate/20131112133401_migrate_stripe_preferences.rb +8 -0
- data/lib/active_merchant/billing/skrill.rb +18 -0
- data/lib/assets/javascripts/spree/frontend/solidus_gateway.js +1 -0
- data/lib/assets/stylesheets/spree/frontend/solidus_gateway.css +3 -0
- data/lib/controllers/frontend/spree/checkout_controller_decorator.rb +51 -0
- data/lib/controllers/frontend/spree/skrill_status_controller.rb +39 -0
- data/lib/generators/solidus_gateway/install/install_generator.rb +28 -0
- data/lib/solidus_gateway.rb +4 -0
- data/lib/spree_gateway/engine.rb +67 -0
- data/lib/views/backend/spree/admin/log_entries/_braintree.html.erb +31 -0
- data/lib/views/backend/spree/admin/log_entries/_stripe.html.erb +28 -0
- data/lib/views/backend/spree/admin/payments/source_forms/_quickcheckout.html.erb +8 -0
- data/lib/views/backend/spree/admin/payments/source_forms/_stripe.html.erb +1 -0
- data/lib/views/backend/spree/admin/payments/source_views/_quickcheckout.html.erb +39 -0
- data/lib/views/backend/spree/admin/payments/source_views/_stripe.html.erb +1 -0
- data/lib/views/frontend/spree/checkout/payment/_quickcheckout.html.erb +26 -0
- data/lib/views/frontend/spree/checkout/payment/_stripe.html.erb +80 -0
- data/solidus_gateway.gemspec +33 -0
- data/spec/factories/skrill_factory.rb +6 -0
- data/spec/features/stripe_checkout_spec.rb +78 -0
- data/spec/lib/active_merchant/billing_skrill_spec.rb +18 -0
- data/spec/models/billing_integration/skrill_quick_checkout_spec.rb +11 -0
- data/spec/models/gateway/authorize_net_cim_spec.rb +29 -0
- data/spec/models/gateway/authorize_net_spec.rb +23 -0
- data/spec/models/gateway/balanced_gateway_spec.rb +17 -0
- data/spec/models/gateway/banwire_spec.rb +11 -0
- data/spec/models/gateway/beanstream_spec.rb +17 -0
- data/spec/models/gateway/braintree_gateway_spec.rb +437 -0
- data/spec/models/gateway/card_save_spec.rb +11 -0
- data/spec/models/gateway/data_cache_spec.rb +11 -0
- data/spec/models/gateway/eway_spec.rb +29 -0
- data/spec/models/gateway/linkpoint_spec.rb +62 -0
- data/spec/models/gateway/maxipago_spec.rb +17 -0
- data/spec/models/gateway/moneris_spec.rb +11 -0
- data/spec/models/gateway/pay_junction_spec.rb +23 -0
- data/spec/models/gateway/pay_pal_spec.rb +11 -0
- data/spec/models/gateway/payflow_pro_spec.rb +23 -0
- data/spec/models/gateway/paymill_spec.rb +11 -0
- data/spec/models/gateway/pin_gateway_spec.rb +55 -0
- data/spec/models/gateway/sage_pay_spec.rb +11 -0
- data/spec/models/gateway/secure_pay_au_spec.rb +11 -0
- data/spec/models/gateway/stripe_gateway_spec.rb +200 -0
- data/spec/models/gateway/usa_epay_spec.rb +49 -0
- data/spec/models/gateway/worldpay_spec.rb +11 -0
- data/spec/models/skrill_transaction_spec.rb +9 -0
- data/spec/spec_helper.rb +50 -0
- metadata +317 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 8ce4994806351d5327bf00d2f9bf191338bbeecb
|
|
4
|
+
data.tar.gz: c5bbc490c8db7133c29e686a9d0bb76e201863ca
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 5470ee6c4a91f27f7ad7ba187ab7978f879331f3ea6235520ed3940988432a3b3ac81b132371ea1e261e3ce0ad0bec3ae5041cd99aadd6dc794f7e98f29c6fa7
|
|
7
|
+
data.tar.gz: 158ab601aa3a283aefe1b5f21b40b8e2de54c3fccb701dc3271bc2d467a8d5849fd8f2ecfa5b1a036ec1ab3e4c1e2766b33f8d528205a3503587510f0a708b85
|
data/.gitignore
ADDED
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--colour
|
data/.travis.yml
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
language: ruby
|
|
2
|
+
before_script:
|
|
3
|
+
- sh -e /etc/init.d/xvfb start
|
|
4
|
+
- export DISPLAY=:99.0
|
|
5
|
+
- bundle exec rake test_app
|
|
6
|
+
env:
|
|
7
|
+
- DB=sqlite
|
|
8
|
+
- DB=mysql
|
|
9
|
+
- DB=postgres
|
|
10
|
+
script:
|
|
11
|
+
- bundle exec rspec spec
|
|
12
|
+
notifications:
|
|
13
|
+
email:
|
|
14
|
+
- ryan@spreecommerce.com
|
|
15
|
+
irc:
|
|
16
|
+
use_notice: true
|
|
17
|
+
skip_join: true
|
|
18
|
+
channels:
|
|
19
|
+
- "irc.freenode.org#spree"
|
|
20
|
+
rvm:
|
|
21
|
+
- 1.9.3
|
|
22
|
+
- 2.0.0
|
|
23
|
+
- 2.1.2
|
data/Gemfile
ADDED
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,38 @@
|
|
|
1
|
+
Solidus Gateway
|
|
2
|
+
===============
|
|
3
|
+
|
|
4
|
+
Community supported Solidus Payment Method Gateways. It works as a wrapper for
|
|
5
|
+
active_merchant gateway. Note that for some gateways you might still need to
|
|
6
|
+
add another gem to your Gemfile to make it work. For example active_merchant
|
|
7
|
+
require `braintree` but it doesn't include that gem on its gemspec. So you
|
|
8
|
+
need to manually add it to your rails app Gemfile.
|
|
9
|
+
|
|
10
|
+
Installation
|
|
11
|
+
------------
|
|
12
|
+
|
|
13
|
+
In your Gemfile:
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
gem "solidus_gateway"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Then run from the command line:
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
bundle install
|
|
23
|
+
rails g solidus_gateway:install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Finally, make sure to **restart your app**. Navigate to *Configuration >
|
|
27
|
+
Payment Methods > New Payment Method* in the admin panel and you should see
|
|
28
|
+
that a bunch of additional gateways have been added to the list.
|
|
29
|
+
|
|
30
|
+
Testing
|
|
31
|
+
-------
|
|
32
|
+
|
|
33
|
+
Then just run the following to automatically build a dummy app if necessary and
|
|
34
|
+
run the tests:
|
|
35
|
+
|
|
36
|
+
```shell
|
|
37
|
+
bundle exec rake
|
|
38
|
+
```
|
data/Rakefile
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'bundler'
|
|
2
|
+
Bundler::GemHelper.install_tasks
|
|
3
|
+
|
|
4
|
+
require 'rspec/core/rake_task'
|
|
5
|
+
require 'spree/testing_support/common_rake'
|
|
6
|
+
|
|
7
|
+
RSpec::Core::RakeTask.new
|
|
8
|
+
|
|
9
|
+
task :default do
|
|
10
|
+
if Dir["spec/dummy"].empty?
|
|
11
|
+
Rake::Task[:test_app].invoke
|
|
12
|
+
Dir.chdir("../../")
|
|
13
|
+
end
|
|
14
|
+
Rake::Task[:spec].invoke
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
desc "Generates a dummy app for testing"
|
|
18
|
+
task :test_app do
|
|
19
|
+
ENV['LIB_NAME'] = 'solidus_gateway'
|
|
20
|
+
Rake::Task['common:test_app'].invoke
|
|
21
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
class BillingIntegration::Skrill::QuickCheckout < BillingIntegration
|
|
3
|
+
preference :merchant_id, :string
|
|
4
|
+
preference :language, :string, :default => 'EN'
|
|
5
|
+
preference :currency, :string, :default => 'EUR'
|
|
6
|
+
preference :payment_options, :string, :default => 'ACC'
|
|
7
|
+
preference :pay_to_email, :string , :default => 'your@merchant.email_here'
|
|
8
|
+
|
|
9
|
+
def provider_class
|
|
10
|
+
ActiveMerchant::Billing::Skrill
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def redirect_url(order, opts = {})
|
|
14
|
+
opts.merge! self.preferences
|
|
15
|
+
|
|
16
|
+
set_global_options(opts)
|
|
17
|
+
|
|
18
|
+
opts[:detail1_text] = order.number
|
|
19
|
+
opts[:detail1_description] = "Order:"
|
|
20
|
+
|
|
21
|
+
opts[:pay_from_email] = order.email
|
|
22
|
+
opts[:firstname] = order.bill_address.firstname
|
|
23
|
+
opts[:lastname] = order.bill_address.lastname
|
|
24
|
+
opts[:address] = order.bill_address.address1
|
|
25
|
+
opts[:address2] = order.bill_address.address2
|
|
26
|
+
opts[:phone_number] = order.bill_address.phone.gsub(/\D/,'') if order.bill_address.phone
|
|
27
|
+
opts[:city] = order.bill_address.city
|
|
28
|
+
opts[:postal_code] = order.bill_address.zipcode
|
|
29
|
+
opts[:state] = order.bill_address.state.nil? ? order.bill_address.state_name.to_s : order.bill_address.state.abbr
|
|
30
|
+
opts[:country] = order.bill_address.country.name
|
|
31
|
+
opts[:pay_to_email] = self.preferred_pay_to_email
|
|
32
|
+
opts[:hide_login] = 1
|
|
33
|
+
opts[:merchant_fields] = 'platform,order_id,payment_method_id'
|
|
34
|
+
opts[:platform] = 'Spree'
|
|
35
|
+
opts[:order_id] = order.number
|
|
36
|
+
|
|
37
|
+
skrill = self.provider
|
|
38
|
+
skrill.payment_url(opts)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
def set_global_options(opts)
|
|
43
|
+
opts[:recipient_description] = Spree::Config[:site_name]
|
|
44
|
+
opts[:payment_methods] = self.preferred_payment_options
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
class Gateway::AuthorizeNet < Gateway
|
|
3
|
+
preference :login, :string
|
|
4
|
+
preference :password, :string
|
|
5
|
+
|
|
6
|
+
def provider_class
|
|
7
|
+
ActiveMerchant::Billing::AuthorizeNetGateway
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def options_with_test_preference
|
|
11
|
+
options_without_test_preference.merge(test: self.preferred_test_mode)
|
|
12
|
+
end
|
|
13
|
+
alias_method_chain :options, :test_preference
|
|
14
|
+
|
|
15
|
+
def credit(amount, response_code, refund, gateway_options = {})
|
|
16
|
+
gateway_options[:card_number] = refund[:originator].payment.source.last_digits
|
|
17
|
+
auth_net_gateway.refund(amount, response_code, gateway_options)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def auth_net_gateway
|
|
23
|
+
@_auth_net_gateway ||= begin
|
|
24
|
+
ActiveMerchant::Billing::Base.gateway_mode = preferred_server.to_sym
|
|
25
|
+
gateway_options = options
|
|
26
|
+
gateway_options[:test_requests] = false # DD: never ever do test requests because just returns transaction_id = 0
|
|
27
|
+
ActiveMerchant::Billing::AuthorizeNetGateway.new(gateway_options)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
class Gateway::AuthorizeNetCim < Gateway
|
|
3
|
+
preference :login, :string
|
|
4
|
+
preference :password, :string
|
|
5
|
+
preference :test_mode, :boolean, :default => false
|
|
6
|
+
preference :validate_on_profile_create, :boolean, :default => false
|
|
7
|
+
|
|
8
|
+
def provider_class
|
|
9
|
+
self.class
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def options
|
|
13
|
+
# add :test key in the options hash, as that is what the ActiveMerchant::Billing::AuthorizeNetGateway expects
|
|
14
|
+
if self.preferred_test_mode
|
|
15
|
+
self.preferences[:test] = true
|
|
16
|
+
else
|
|
17
|
+
self.preferences.delete(:test)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def authorize(amount, creditcard, gateway_options)
|
|
24
|
+
create_transaction(amount, creditcard, :auth_only, transaction_options(gateway_options))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def purchase(amount, creditcard, gateway_options)
|
|
28
|
+
create_transaction(amount, creditcard, :auth_capture, transaction_options(gateway_options))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# capture is only one where source is not passed in for payment profile
|
|
32
|
+
def capture(amount, response_code, gateway_options)
|
|
33
|
+
# no credit card needed
|
|
34
|
+
create_transaction(amount, nil, :prior_auth_capture, trans_id: response_code)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def credit(amount, creditcard, response_code, gateway_options = {})
|
|
38
|
+
create_transaction(amount, creditcard, :refund, transaction_options(gateway_options).merge(trans_id: response_code))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def void(response_code, creditcard, gateway_options = {})
|
|
42
|
+
create_transaction(nil, creditcard, :void, transaction_options(gateway_options).merge(trans_id: response_code))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def cancel(response_code)
|
|
46
|
+
# From: http://community.developer.authorize.net/t5/The-Authorize-Net-Developer-Blog/Refunds-in-Retail-A-user-friendly-approach-using-AIM/ba-p/9848
|
|
47
|
+
# DD: if unsettled, void needed
|
|
48
|
+
response = void(response_code, nil)
|
|
49
|
+
# DD: if settled, credit/refund needed
|
|
50
|
+
response = credit(nil, nil, response_code) unless response.success?
|
|
51
|
+
|
|
52
|
+
response
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def payment_profiles_supported?
|
|
56
|
+
true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Create a new CIM customer profile ready to accept a payment. Called by Spree::Payment on after_save.
|
|
60
|
+
def create_profile(payment)
|
|
61
|
+
if payment.source.gateway_customer_profile_id.nil?
|
|
62
|
+
profile_hash = create_customer_profile(payment)
|
|
63
|
+
payment.source.update_attributes(gateway_customer_profile_id: profile_hash[:customer_profile_id], gateway_payment_profile_id: profile_hash[:customer_payment_profile_id])
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Get the CIM payment profile; Needed for updates.
|
|
68
|
+
def get_profile(payment)
|
|
69
|
+
if payment.source.has_payment_profile?
|
|
70
|
+
profile = cim_gateway.get_customer_profile({
|
|
71
|
+
customer_profile_id: payment.source.gateway_customer_profile_id
|
|
72
|
+
})
|
|
73
|
+
if profile
|
|
74
|
+
profile.params['profile'].deep_symbolize_keys!
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Get the CIM payment profile; Needed for updates.
|
|
80
|
+
def get_payment_profile(payment)
|
|
81
|
+
if payment.source.has_payment_profile?
|
|
82
|
+
profile = cim_gateway.get_customer_payment_profile({
|
|
83
|
+
customer_profile_id: payment.source.gateway_customer_profile_id,
|
|
84
|
+
customer_payment_profile_id: payment.source.gateway_payment_profile_id
|
|
85
|
+
})
|
|
86
|
+
if profile
|
|
87
|
+
profile.params['payment_profile'].deep_symbolize_keys!
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Update billing address on the CIM payment profile
|
|
93
|
+
def update_payment_profile(payment)
|
|
94
|
+
if payment.source.has_payment_profile?
|
|
95
|
+
if hash = get_payment_profile(payment)
|
|
96
|
+
hash[:bill_to] = generate_address_hash(payment.order.bill_address)
|
|
97
|
+
if hash[:payment][:credit_card]
|
|
98
|
+
# activemerchant expects a credit card object with 'number', 'year', 'month', and 'verification_value?' defined
|
|
99
|
+
payment.source.define_singleton_method(:number) { "XXXXXXXXX#{payment.source.last_digits}" }
|
|
100
|
+
hash[:payment][:credit_card] = payment.source
|
|
101
|
+
end
|
|
102
|
+
cim_gateway.update_customer_payment_profile({
|
|
103
|
+
customer_profile_id: payment.source.gateway_customer_profile_id,
|
|
104
|
+
payment_profile: hash
|
|
105
|
+
})
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private
|
|
111
|
+
|
|
112
|
+
def transaction_options(gateway_options = {})
|
|
113
|
+
{ order: { invoice_number: gateway_options[:order_id] } }
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Create a transaction on a creditcard
|
|
117
|
+
# Set up a CIM profile for the card if one doesn't exist
|
|
118
|
+
# Valid transaction_types are :auth_only, :capture_only and :auth_capture
|
|
119
|
+
def create_transaction(amount, creditcard, transaction_type, options = {})
|
|
120
|
+
creditcard.save if creditcard
|
|
121
|
+
|
|
122
|
+
transaction_options = {
|
|
123
|
+
type: transaction_type
|
|
124
|
+
}.update(options)
|
|
125
|
+
|
|
126
|
+
if amount
|
|
127
|
+
amount = "%.2f" % (amount / 100.0) # This gateway requires formated decimal, not cents
|
|
128
|
+
transaction_options.update({
|
|
129
|
+
amount: amount
|
|
130
|
+
})
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
transaction_options.update({
|
|
134
|
+
customer_profile_id: creditcard.gateway_customer_profile_id,
|
|
135
|
+
customer_payment_profile_id: creditcard.gateway_payment_profile_id
|
|
136
|
+
}) if creditcard
|
|
137
|
+
|
|
138
|
+
logger.debug("\nAuthorize Net CIM Request")
|
|
139
|
+
logger.debug(" transaction_options: #{transaction_options.inspect}")
|
|
140
|
+
t = cim_gateway.create_customer_profile_transaction(:transaction => transaction_options)
|
|
141
|
+
logger.debug("\nAuthorize Net CIM Response")
|
|
142
|
+
logger.debug(" response: #{t.inspect}\n")
|
|
143
|
+
t
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Create a new CIM customer profile ready to accept a payment
|
|
147
|
+
def create_customer_profile(payment)
|
|
148
|
+
options = options_for_create_customer_profile(payment)
|
|
149
|
+
response = cim_gateway.create_customer_profile(options)
|
|
150
|
+
if response.success?
|
|
151
|
+
{ customer_profile_id: response.params['customer_profile_id'],
|
|
152
|
+
customer_payment_profile_id: response.params['customer_payment_profile_id_list'].values.first }
|
|
153
|
+
else
|
|
154
|
+
payment.send(:gateway_error, response)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def options_for_create_customer_profile(payment)
|
|
159
|
+
if payment.is_a? CreditCard
|
|
160
|
+
info = { bill_to: generate_address_hash(payment.address),
|
|
161
|
+
payment: { credit_card: payment } }
|
|
162
|
+
else
|
|
163
|
+
info = { bill_to: generate_address_hash(payment.order.bill_address),
|
|
164
|
+
payment: { credit_card: payment.source } }
|
|
165
|
+
end
|
|
166
|
+
validation_mode = preferred_validate_on_profile_create ? preferred_server.to_sym : :none
|
|
167
|
+
|
|
168
|
+
{ profile: { merchant_customer_id: "#{Time.now.to_f}",
|
|
169
|
+
ship_to_list: generate_address_hash(payment.order.ship_address),
|
|
170
|
+
email: payment.order.email,
|
|
171
|
+
payment_profiles: info },
|
|
172
|
+
validation_mode: validation_mode }
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# As in PaymentGateway but with separate name fields
|
|
176
|
+
def generate_address_hash(address)
|
|
177
|
+
return {} if address.nil?
|
|
178
|
+
{
|
|
179
|
+
first_name: address.firstname,
|
|
180
|
+
last_name: address.lastname,
|
|
181
|
+
address1: address.address1,
|
|
182
|
+
address2: address.address2,
|
|
183
|
+
city: address.city,
|
|
184
|
+
state: address.state_text,
|
|
185
|
+
zip: address.zipcode,
|
|
186
|
+
country: address.country.iso,
|
|
187
|
+
phone_number: address.phone
|
|
188
|
+
}
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def cim_gateway
|
|
192
|
+
@_cim_gateway ||= begin
|
|
193
|
+
ActiveMerchant::Billing::Base.gateway_mode = preferred_server.to_sym
|
|
194
|
+
gateway_options = options
|
|
195
|
+
gateway_options[:test_requests] = false # DD: never ever do test requests because just returns transaction_id = 0
|
|
196
|
+
ActiveMerchant::Billing::AuthorizeNetCimGateway.new(gateway_options)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
end
|
|
201
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
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_attributes!(:gateway_payment_profile_id => card_uri)
|
|
31
|
+
rescue Error => ex
|
|
32
|
+
payment.send(:gateway_error, ex.message)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def options_with_test_preference
|
|
36
|
+
options_without_test_preference.merge(:test => self.preferred_test_mode)
|
|
37
|
+
end
|
|
38
|
+
alias_method_chain :options, :test_preference
|
|
39
|
+
|
|
40
|
+
def payment_profiles_supported?
|
|
41
|
+
true
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def purchase(money, creditcard, gateway_options)
|
|
45
|
+
if token = creditcard.gateway_payment_profile_id
|
|
46
|
+
# The Balanced ActiveMerchant gateway supports passing the token directly as the creditcard parameter
|
|
47
|
+
creditcard = token
|
|
48
|
+
end
|
|
49
|
+
provider.purchase(money, creditcard, gateway_options)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def provider_class
|
|
53
|
+
ActiveMerchant::Billing::BalancedGateway
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def credit(money, creditcard, response_code, gateway_options)
|
|
57
|
+
provider.refund(money, response_code, {})
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def void(response_code, creditcard, gateway_options)
|
|
61
|
+
provider.void(response_code)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|