spree_gateway 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +14 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +22 -0
  5. data/Gemfile +21 -0
  6. data/LICENSE +26 -0
  7. data/README.md +68 -0
  8. data/Rakefile +14 -0
  9. data/Versionfile +12 -0
  10. data/app/assets/javascripts/store/gateway/stripe.js.coffee +58 -0
  11. data/app/assets/javascripts/store/spree_gateway.js +2 -0
  12. data/app/assets/stylesheets/store/spree_gateway.css +8 -0
  13. data/app/controllers/spree/checkout_controller_decorator.rb +51 -0
  14. data/app/controllers/spree/skrill_status_controller.rb +39 -0
  15. data/app/models/spree/billing_integration/skrill/quick_checkout.rb +48 -0
  16. data/app/models/spree/gateway/authorize_net.rb +16 -0
  17. data/app/models/spree/gateway/authorize_net_cim.rb +132 -0
  18. data/app/models/spree/gateway/balanced_gateway.rb +65 -0
  19. data/app/models/spree/gateway/banwire.rb +15 -0
  20. data/app/models/spree/gateway/beanstream.rb +193 -0
  21. data/app/models/spree/gateway/braintree_gateway.rb +147 -0
  22. data/app/models/spree/gateway/card_save.rb +10 -0
  23. data/app/models/spree/gateway/data_cash.rb +10 -0
  24. data/app/models/spree/gateway/eway.rb +20 -0
  25. data/app/models/spree/gateway/fatzebra.rb +15 -0
  26. data/app/models/spree/gateway/linkpoint.rb +28 -0
  27. data/app/models/spree/gateway/maxipago.rb +14 -0
  28. data/app/models/spree/gateway/moneris.rb +11 -0
  29. data/app/models/spree/gateway/pay_junction.rb +16 -0
  30. data/app/models/spree/gateway/pay_pal_gateway.rb +12 -0
  31. data/app/models/spree/gateway/payflow_pro.rb +17 -0
  32. data/app/models/spree/gateway/paymill.rb +12 -0
  33. data/app/models/spree/gateway/pin_gateway.rb +15 -0
  34. data/app/models/spree/gateway/sage_pay.rb +11 -0
  35. data/app/models/spree/gateway/samurai.rb +63 -0
  36. data/app/models/spree/gateway/secure_pay_au.rb +10 -0
  37. data/app/models/spree/gateway/stripe_gateway.rb +103 -0
  38. data/app/models/spree/gateway/usa_epay.rb +9 -0
  39. data/app/models/spree/gateway/worldpay.rb +91 -0
  40. data/app/models/spree/skrill_transaction.rb +19 -0
  41. data/app/views/spree/admin/log_entries/_braintree.html.erb +31 -0
  42. data/app/views/spree/admin/log_entries/_stripe.html.erb +28 -0
  43. data/app/views/spree/admin/payments/source_forms/_quickcheckout.html.erb +8 -0
  44. data/app/views/spree/admin/payments/source_forms/_stripe.html.erb +1 -0
  45. data/app/views/spree/admin/payments/source_views/_quickcheckout.html.erb +39 -0
  46. data/app/views/spree/admin/payments/source_views/_stripe.html.erb +1 -0
  47. data/app/views/spree/checkout/payment/_quickcheckout.html.erb +26 -0
  48. data/app/views/spree/checkout/payment/_stripe.html.erb +21 -0
  49. data/config/initializers/savon.rb +3 -0
  50. data/config/locales/bg.yml +11 -0
  51. data/config/locales/de.yml +11 -0
  52. data/config/locales/en.yml +30 -0
  53. data/config/locales/sv.yml +11 -0
  54. data/config/routes.rb +20 -0
  55. data/db/migrate/20111118164631_create_skrill_transactions.rb +14 -0
  56. data/db/migrate/20121017004102_update_braintree_payment_method_type.rb +9 -0
  57. data/db/migrate/20130213222555_update_stripe_payment_method_type.rb +9 -0
  58. data/db/migrate/20130415222802_update_balanced_payment_method_type.rb +9 -0
  59. data/db/migrate/20131008221012_update_paypal_payment_method_type.rb +9 -0
  60. data/db/migrate/20131112133401_migrate_stripe_preferences.rb +8 -0
  61. data/lib/active_merchant/billing/skrill.rb +18 -0
  62. data/lib/generators/spree_gateway/install/install_generator.rb +28 -0
  63. data/lib/spree_gateway.rb +3 -0
  64. data/lib/spree_gateway/engine.rb +42 -0
  65. data/script/rails +5 -0
  66. data/spec/factories/payment_method_factory.rb +4 -0
  67. data/spec/features/stripe_checkout_spec.rb +82 -0
  68. data/spec/models/gateway/authorize_net_cim_spec.rb +17 -0
  69. data/spec/models/gateway/authorize_net_spec.rb +17 -0
  70. data/spec/models/gateway/balanced_gateway_spec.rb +9 -0
  71. data/spec/models/gateway/banwire_spec.rb +9 -0
  72. data/spec/models/gateway/braintree_gateway_spec.rb +289 -0
  73. data/spec/models/gateway/eway_spec.rb +17 -0
  74. data/spec/models/gateway/fatzebra_spec.rb +47 -0
  75. data/spec/models/gateway/linkpoint_spec.rb +60 -0
  76. data/spec/models/gateway/pay_junction_spec.rb +17 -0
  77. data/spec/models/gateway/payflow_pro_spec.rb +17 -0
  78. data/spec/models/gateway/pin_gateway_spec.rb +57 -0
  79. data/spec/models/gateway/stripe_gateway_spec.rb +122 -0
  80. data/spec/models/gateway/usa_epay_spec.rb +38 -0
  81. data/spec/models/savon_spec.rb +9 -0
  82. data/spec/spec_helper.rb +56 -0
  83. data/spree_gateway.gemspec +28 -0
  84. metadata +104 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d5d3726bd0c9b7b135b3f5dacbcfd398d31aabfd
4
- data.tar.gz: fc69e94bee6f5c693bcf4a755eabc1cb8ac3444f
3
+ metadata.gz: f751968527a2e023c5e2c4189428bf5e4a952b55
4
+ data.tar.gz: 06a553b7f41105e7c09f1c0d10821cc6f18e23e3
5
5
  SHA512:
6
- metadata.gz: 76f307329dcff7d747c82f09128f5f31a7f373a7a68cf613fcd92a09484a7dd8fc31ee39f786256e20608655183836bfe998247b6051f5bec91a61ababbc074f
7
- data.tar.gz: 4f310eade2edd90abf2aa86ca04846555256c94ed24522676195b6354d295b55791b7e160e7aee91ecc5e3bef5060916c7b2c5f0fef33d7dda703dd8ac5d58a8
6
+ metadata.gz: 354a2777107b68af1d7fccc812e206d75b0a34f44a53b4b15e45e8f64febdb6dfa6690a384cee68efa0021470cf719cfbec506503aa47edc5baedba32811eb95
7
+ data.tar.gz: 884e431a7ada47f245b29121ac09ad2b21ed5cb3f75598c2a9b471cbdef17c6bf522cdf006ce00258c7f95a04cf6823b64d6d8454ce28005e751229988215bb2
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .project
7
+ tmp
8
+ nbproject
9
+ *.swp
10
+ spec/dummy
11
+ Gemfile.lock
12
+ .rvmrc
13
+ .localeapp
14
+ .coveralls.yml
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/.travis.yml ADDED
@@ -0,0 +1,22 @@
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
data/Gemfile ADDED
@@ -0,0 +1,21 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'ffaker'
5
+ gem 'sqlite3'
6
+ gem 'pg'
7
+ gem 'mysql2'
8
+ gem 'pry'
9
+ gem 'coffee-rails', '~> 4.0.0' # necessary for stripe.js.coffee
10
+ gem 'sass-rails', '~> 4.0.0'
11
+ gem 'poltergeist', '1.4.1'
12
+ gem 'selenium-webdriver'
13
+ gem 'database_cleaner', '1.0.1'
14
+
15
+ end
16
+
17
+ gem 'braintree'
18
+
19
+ gem 'spree', github: 'spree/spree', :branch => '2-1-stable'
20
+
21
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2013 Spree Commerce
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,68 @@
1
+ # Spree Gateway
2
+
3
+ [![Build Status](https://secure.travis-ci.org/spree/spree_gateway.png?branch=master)](http://travis-ci.org/spree/spree_gateway)
4
+
5
+ Community supported Spree Payment Method Gateways.
6
+
7
+ These can be used with Spree >= 1.0.x (but see note below for necessary changes)
8
+
9
+ http://guides.spreecommerce.com/developer/payments.html
10
+
11
+ ## Installation
12
+
13
+ In your Gemfile:
14
+
15
+ **Spree edge**
16
+
17
+ ```ruby
18
+ gem 'spree'
19
+ gem 'spree_gateway', github: 'spree/spree_gateway'
20
+ ```
21
+
22
+ **Spree 1.3**
23
+
24
+ ```ruby
25
+ gem 'spree', '~> 1.3'
26
+ gem 'spree_gateway', github: 'spree/spree_gateway', branch: '1-3-stable'
27
+ ```
28
+
29
+ **Note:** *Please consult the Versionfile at the root of the repository to determine which branch to use.*
30
+
31
+ Then run from the command line:
32
+
33
+ $ bundle install
34
+ $ rails g spree_gateway:install
35
+
36
+ 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.
37
+
38
+ ## Contributing
39
+
40
+ In the spirit of [free software][1], **everyone** is encouraged to help improve this project.
41
+
42
+ Here are some ways *you* can contribute:
43
+
44
+ * by using prerelease versions
45
+ * by reporting [bugs][2]
46
+ * by suggesting new features
47
+ * by writing or editing documentation
48
+ * by writing specifications
49
+ * by writing code (*no patch is too small*: fix typos, add comments, clean up inconsistent whitespace)
50
+ * by refactoring code
51
+ * by resolving [issues][2]
52
+ * by reviewing patches
53
+
54
+ Starting point:
55
+
56
+ * Fork the repo
57
+ * Clone your repo
58
+ * Run `bundle`
59
+ * Run `bundle exec rake test_app` to create the test application in `spec/test_app`
60
+ * Make your changes
61
+ * Ensure specs pass by running `bundle exec rspec spec`
62
+ * Submit your pull request
63
+
64
+ Copyright (c) 2013 Spree Commerce, released under the [New BSD License][3]
65
+
66
+ [1]: http://www.fsf.org/licensing/essays/free-sw.html
67
+ [2]: https://github.com/spree/spree_gateway/issues
68
+ [3]: https://github.com/spree/spree_gateway/tree/master/LICENSE
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+ require 'spree/testing_support/common_rake'
4
+ require 'bundler/gem_tasks'
5
+
6
+ RSpec::Core::RakeTask.new
7
+
8
+ task :default => [:spec]
9
+
10
+ desc "Generates a dummy app for testing"
11
+ task :test_app do
12
+ ENV['LIB_NAME'] = 'spree_gateway'
13
+ Rake::Task['common:test_app'].invoke
14
+ end
data/Versionfile ADDED
@@ -0,0 +1,12 @@
1
+ # This file is used to designate compatibilty with different versions of Spree
2
+ # Please see http://spreecommerce.com/documentation/extensions.html#versionfile for details
3
+
4
+ # Examples
5
+ #
6
+ "2.1.x" => { :branch => "master" }
7
+ "2.0.x" => { :branch => "2-0-stable" }
8
+ "1.3.x" => { :branch => "1-3-stable" }
9
+ "1.2.x" => { :branch => "1-2-stable" }
10
+ "1.1.x" => { :branch => "1-1-stable" }
11
+ "1.0.x" => { :branch => "1-0-stable" }
12
+
@@ -0,0 +1,58 @@
1
+ # Inspired by https://stripe.com/docs/stripe.js
2
+
3
+ # Map cc types from stripe to spree
4
+ mapCC = (ccType) ->
5
+ if (ccType == 'MasterCard')
6
+ 'mastercard'
7
+ else if (ccType == 'Visa')
8
+ 'visa'
9
+ else if (ccType == 'American Express')
10
+ 'amex'
11
+ else if (ccType == 'Discover')
12
+ 'discover'
13
+ else if (ccType == 'Diners Club')
14
+ 'dinersclub'
15
+ else if (ccType == 'JCB')
16
+ 'jcb'
17
+
18
+
19
+ $(document).ready ->
20
+ # For errors that happen later.
21
+ Spree.stripePaymentMethod.prepend("<div id='stripeError' class='errorExplanation' style='display:none'></div>")
22
+
23
+ $('.continue').click ->
24
+ $('#stripeError').hide()
25
+ if Spree.stripePaymentMethod.is(':visible')
26
+ expiration = $('.cardExpiry:visible').payment('cardExpiryVal')
27
+ params = $.extend(
28
+ {
29
+ number: $('.cardNumber:visible').val(),
30
+ cvc: $('.cardCode:visible').val(),
31
+ exp_month: expiration.month || 0,
32
+ exp_year: expiration.year || 0,
33
+ },
34
+ Spree.stripeAdditionalInfo
35
+ )
36
+
37
+ Stripe.card.createToken(params, stripeResponseHandler);
38
+ return false
39
+
40
+ stripeResponseHandler = (status, response) ->
41
+ if response.error
42
+ $('#stripeError').html(response.error.message)
43
+ $('#stripeError').show()
44
+ else
45
+ Spree.stripePaymentMethod.find('#card_number, #card_expiry, #card_code').prop("disabled" , true)
46
+ Spree.stripePaymentMethod.find(".ccType").prop("disabled", false)
47
+ Spree.stripePaymentMethod.find(".ccType").val(mapCC(response.card.type))
48
+
49
+ # token contains id, last4, and card type
50
+ token = response['id'];
51
+ # insert the token into the form so it gets submitted to the server
52
+ paymentMethodId = Spree.stripePaymentMethod.prop('id').split("_")[2]
53
+ Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][gateway_payment_profile_id]' value='" + token + "'/>");
54
+ Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][last_digits]' value='" + response.card.last4 + "'/>");
55
+ Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][month]' value='" + response.card.exp_month + "'/>");
56
+ Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][year]' value='" + response.card.exp_year + "'/>");
57
+ # Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][cc_type]' value='" + mapCC(response.card.type) + "'/>");
58
+ Spree.stripePaymentMethod.parents("form").get(0).submit();
@@ -0,0 +1,2 @@
1
+ //= require spree
2
+ //= require store/checkout
@@ -0,0 +1,8 @@
1
+ /* needs to exist for the feature specs to be happy */
2
+
3
+ /*
4
+ * This is a manifest file that includes stylesheets for spree_frontend
5
+ *= require normalize
6
+ *= require skeleton
7
+ *= require store/screen
8
+ */
@@ -0,0 +1,51 @@
1
+ module Spree
2
+ CheckoutController.class_eval do
3
+ before_filter :confirm_skrill, :only => [:update]
4
+
5
+ def skrill_return
6
+
7
+ unless @order.payments.where(:source_type => 'Spree::SkrillTransaction').present?
8
+ payment_method = PaymentMethod.find(params[:payment_method_id])
9
+ skrill_transaction = SkrillTransaction.new
10
+
11
+ payment = @order.payments.create({:amount => @order.total,
12
+ :source => skrill_transaction,
13
+ :payment_method => payment_method},
14
+ :without_protection => true)
15
+ payment.started_processing!
16
+ payment.pend!
17
+ end
18
+
19
+ @order.update_attributes({:state => "complete", :completed_at => Time.now}, :without_protection => true)
20
+
21
+ until @order.state == "complete"
22
+ if @order.next!
23
+ @order.update!
24
+ state_callback(:after)
25
+ end
26
+ end
27
+
28
+ @order.finalize!
29
+
30
+ flash.notice = Spree.t(:order_processed_successfully)
31
+ redirect_to completion_route
32
+ end
33
+
34
+ def skrill_cancel
35
+ flash[:error] = Spree.t(:payment_has_been_cancelled)
36
+ redirect_to edit_order_path(@order)
37
+ end
38
+
39
+ private
40
+ def confirm_skrill
41
+ return unless (params[:state] == "payment") && params[:order][:payments_attributes]
42
+
43
+ payment_method = PaymentMethod.find(params[:order][:payments_attributes].first[:payment_method_id])
44
+ if payment_method.kind_of?(BillingIntegration::Skrill::QuickCheckout)
45
+ #TODO confirming payment method
46
+ redirect_to edit_order_checkout_url(@order, :state => 'payment'),
47
+ :notice => Spree.t(:complete_skrill_checkout)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,39 @@
1
+ module Spree
2
+ class SkrillStatusController < ApplicationController
3
+ def update
4
+ @order = Order.find_by_number!(params[:order_id])
5
+ payment_method = PaymentMethod.find(params[:payment_method_id])
6
+ skrill_transaction = SkrillTransaction.create_from_postback params
7
+
8
+ payment = @order.payments.where(:state => "pending",
9
+ :payment_method_id => payment_method).first
10
+
11
+ if payment
12
+ payment.source = skrill_transaction
13
+ payment.save
14
+ else
15
+ payment = @order.payments.create(:amount => @order.total,
16
+ :source => skrill_transaction,
17
+ :payment_method => payment_method)
18
+ end
19
+
20
+ payment.started_processing!
21
+
22
+ unless payment.completed?
23
+ case params[:status]
24
+ when "0"
25
+ payment.pend #may already be pending
26
+ when "2" #processed / captured
27
+ payment.complete!
28
+ when "-1", "-2"
29
+ payment.failure!
30
+ else
31
+ raise "Unexpected payment status"
32
+ end
33
+ end
34
+
35
+ render :text => ""
36
+ end
37
+
38
+ end
39
+ 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,16 @@
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
+
14
+ alias_method_chain :options, :test_preference
15
+ end
16
+ end
@@ -0,0 +1,132 @@
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
+ ActiveMerchant::Billing::Response.class_eval do
9
+ attr_writer :authorization
10
+ end
11
+
12
+ def provider_class
13
+ self.class
14
+ end
15
+
16
+ def options
17
+ # add :test key in the options hash, as that is what the ActiveMerchant::Billing::AuthorizeNetGateway expects
18
+ if self.preferred_test_mode
19
+ self.class.preference :test, :boolean, :default => true
20
+ else
21
+ self.class.remove_preference :test
22
+ end
23
+
24
+ super
25
+ end
26
+
27
+ def authorize(amount, creditcard, gateway_options)
28
+ t_options = { :order => {:invoice_number => gateway_options[:order_id] } }
29
+ create_transaction( amount, creditcard, :auth_only, t_options )
30
+ end
31
+
32
+ def purchase(amount, creditcard, gateway_options)
33
+ create_transaction(amount, creditcard, :auth_capture)
34
+ end
35
+
36
+ def capture(authorization, creditcard, gateway_options)
37
+ create_transaction((authorization.amount * 100).round, creditcard, :prior_auth_capture, :trans_id => authorization.response_code)
38
+ end
39
+
40
+ def credit(amount, creditcard, response_code, gateway_options)
41
+ create_transaction(amount, creditcard, :refund, :trans_id => response_code)
42
+ end
43
+
44
+ def void(response_code, creditcard, gateway_options)
45
+ create_transaction(nil, creditcard, :void, :trans_id => response_code)
46
+ end
47
+
48
+ def payment_profiles_supported?
49
+ true
50
+ end
51
+
52
+ # Create a new CIM customer profile ready to accept a payment
53
+ def create_profile(payment)
54
+ if payment.source.gateway_customer_profile_id.nil?
55
+ profile_hash = create_customer_profile(payment)
56
+ payment.source.update_attributes(:gateway_customer_profile_id => profile_hash[:customer_profile_id], :gateway_payment_profile_id => profile_hash[:customer_payment_profile_id])
57
+ end
58
+ end
59
+
60
+ # simpler form
61
+ def create_profile_from_card(card)
62
+ if card.gateway_customer_profile_id.nil?
63
+ profile_hash = create_customer_profile(card)
64
+ card.update_attributes(:gateway_customer_profile_id => profile_hash[:customer_profile_id], :gateway_payment_profile_id => profile_hash[:customer_payment_profile_id])
65
+ end
66
+ end
67
+
68
+ private
69
+ # Create a transaction on a creditcard
70
+ # Set up a CIM profile for the card if one doesn't exist
71
+ # Valid transaction_types are :auth_only, :capture_only and :auth_capture
72
+ def create_transaction(amount, creditcard, transaction_type, options = {})
73
+ #create_profile(creditcard, creditcard.gateway_options)
74
+ creditcard.save
75
+ if amount
76
+ amount = "%.2f" % (amount / 100.0) # This gateway requires formated decimal, not cents
77
+ end
78
+ transaction_options = {
79
+ :type => transaction_type,
80
+ :amount => amount,
81
+ :customer_profile_id => creditcard.gateway_customer_profile_id,
82
+ :customer_payment_profile_id => creditcard.gateway_payment_profile_id,
83
+ }.update(options)
84
+ t = cim_gateway.create_customer_profile_transaction(:transaction => transaction_options)
85
+ logger.debug("\nAuthorize Net CIM Transaction")
86
+ logger.debug(" transaction_options: #{transaction_options.inspect}")
87
+ logger.debug(" response: #{t.inspect}\n")
88
+ t
89
+ end
90
+
91
+ # Create a new CIM customer profile ready to accept a payment
92
+ def create_customer_profile(payment)
93
+ options = options_for_create_customer_profile(payment)
94
+ response = cim_gateway.create_customer_profile(options)
95
+ if response.success?
96
+ { :customer_profile_id => response.params['customer_profile_id'],
97
+ :customer_payment_profile_id => response.params['customer_payment_profile_id_list'].values.first }
98
+ else
99
+ payment.send(:gateway_error, response)
100
+ end
101
+ end
102
+
103
+ def options_for_create_customer_profile(payment)
104
+ if payment.is_a? CreditCard
105
+ info = { :bill_to => generate_address_hash(payment.address), :payment => { :credit_card => payment } }
106
+ else
107
+ info = { :bill_to => generate_address_hash(payment.order.bill_address),
108
+ :payment => { :credit_card => payment.source } }
109
+ end
110
+ validation_mode = preferred_validate_on_profile_create ? preferred_server.to_sym : :none
111
+
112
+ { :profile => { :merchant_customer_id => "#{Time.now.to_f}",
113
+ #:ship_to_list => generate_address_hash(creditcard.checkout.ship_address),
114
+ :email => payment.order.email,
115
+ :payment_profiles => info },
116
+ :validation_mode => validation_mode }
117
+ end
118
+
119
+ # As in PaymentGateway but with separate name fields
120
+ def generate_address_hash(address)
121
+ return {} if address.nil?
122
+ {:first_name => address.firstname, :last_name => address.lastname, :address1 => address.address1, :address2 => address.address2, :city => address.city,
123
+ :state => address.state_text, :zip => address.zipcode, :country => address.country.iso, :phone_number => address.phone}
124
+ end
125
+
126
+ def cim_gateway
127
+ ActiveMerchant::Billing::Base.gateway_mode = preferred_server.to_sym
128
+ gateway_options = options
129
+ ActiveMerchant::Billing::AuthorizeNetCimGateway.new(gateway_options)
130
+ end
131
+ end
132
+ end