solidus_gateway_checkout_v2 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b4553466121a1142278574daa84f17c3b9e2b35c
4
+ data.tar.gz: d843f8152afe2d8fe4de2a5fbd7c95ccb91ad122
5
+ SHA512:
6
+ metadata.gz: 4322ff8f704df7d0d735331aa68c511013d97875f5e8be9778630bbf7ff40e3b4d7990900dd0eaea929ecf684550840066722099f18a81b1398b0c60316a8be2
7
+ data.tar.gz: d738d9ce3b724bfcb71dc3403661e82ffdf2a70b4cf967c588fd86eab5b5cffe8fe1f2d7ff7dbb16215bce098d214d59b3d81d7ebeebf3f1807e690d9f5d9488
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ tmp
6
+ spec/dummy
7
+ Gemfile.lock
8
+ .rvmrc
9
+ coverage
10
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,82 @@
1
+ # Contributing
2
+
3
+ *(Originally copied from [Spree Static Content's Contribution guidelines](https://github.com/spree-contrib/spree_static_content/blob/master/CONTRIBUTING.md)*
4
+
5
+ Solidus Gateway Checkout V2 is an open source project and we encourage contributions.
6
+
7
+ In the spirit of [free software][1], **everyone** is encouraged to help improve this project.
8
+
9
+ Here are some ways *you* can contribute:
10
+
11
+ * by using prerelease versions
12
+ * by reporting [bugs][2]
13
+ * by suggesting new features
14
+ * by writing [translations][3]
15
+ * by writing or editing documentation
16
+ * by writing specifications
17
+ * by writing code (*no patch is too small*: fix typos, add comments, clean up inconsistent whitespace)
18
+ * by refactoring code
19
+ * by resolving [issues][2]
20
+ * by reviewing patches
21
+
22
+ ---
23
+
24
+ ## Filing an issue
25
+
26
+ When filing an issue on this extension, please first do these things:
27
+
28
+ * Verify you can reproduce this issue in a brand new application.
29
+ * Run through the steps to reproduce the issue again.
30
+
31
+ In the issue itself please provide:
32
+
33
+ * A comprehensive list of steps to reproduce the issue.
34
+ * What you're *expecting* to happen compared with what's *actually* happening.
35
+ * The version of Spree *and* the version of Rails.
36
+ * A list of all extensions.
37
+ * Any relevant stack traces ("Full trace" preferred)
38
+ * Your `Gemfile`
39
+
40
+ In 99% of cases, this information is enough to determine the cause and solution to the problem that is being described.
41
+
42
+ ---
43
+
44
+ ## Pull requests
45
+
46
+ We gladly accept pull requests to fix bugs and, in some circumstances, add new features to this extension.
47
+
48
+ Here's a quick guide:
49
+
50
+ 1. Fork the repo.
51
+
52
+ 2. Run the tests. We only take pull requests with passing tests, and it's great to know that you have a clean slate.
53
+
54
+ 3. Create new branch then make changes and add tests for your changes. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, we need tests!
55
+
56
+ 4. Push to your fork and submit a pull request. If the changes will apply cleanly to the latest stable branches and master branch, you will only need to submit one pull request.
57
+
58
+ At this point you're waiting on us. We may suggest some changes or improvements or alternatives.
59
+
60
+ Some things that will increase the chance that your pull request is accepted, taken straight from the Ruby on Rails guide:
61
+
62
+ * Use Rails idioms and helpers.
63
+ * Include tests that fail without your code, and pass with it.
64
+ * Update the documentation, the surrounding one, examples elsewhere, guides, whatever is affected by your contribution.
65
+
66
+ ---
67
+
68
+ ## TL;DR
69
+
70
+ * Fork the repo
71
+ * Clone your repo
72
+ * Run `bundle install`
73
+ * Run `bundle exec rake test_app` to create the test application in `spec/dummy`
74
+ * Make your changes
75
+ * Ensure specs pass by running `bundle exec rspec spec`
76
+ * Submit your pull request
77
+
78
+ And in case we didn't emphasize it enough: **we love tests!**
79
+
80
+ [1]: http://www.fsf.org/licensing/essays/free-sw.html
81
+ [2]: https://github.com/whelton/solidus_gateway_checkout_v2/issues
82
+ [3]: https://github.com/whelton/solidus_gateway_checkout_v2/tree/master/config/locales
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "solidus", github: "solidusio/solidus", branch: "master"
4
+
5
+ group :development, :test do
6
+ gem "pry-rails"
7
+ end
8
+
9
+ gemspec
data/LICENSE.md ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2016 James Whelton and 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 Solidus 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,35 @@
1
+ # Solidus Gateway Checkout V2
2
+
3
+ Adds [Checkout.com V2](checkout.com) Gateway to Soldius, supporting both server and card tokenisation payments (via the JS library.)
4
+
5
+ ---
6
+ ## Basic Installation
7
+
8
+ Add to your `Gemfile`:
9
+
10
+ ```ruby
11
+ gem 'solidus_gateway_checkout_v2'
12
+ ```
13
+
14
+ Make sure to **restart your app**. Navigate to *Configuration >
15
+ Payment Methods > New Payment Method* in the admin panel and you should see
16
+ that Checkout V2 has been added to the list.
17
+
18
+
19
+ That's all!
20
+
21
+ ---
22
+
23
+ ## Contributing
24
+
25
+ See corresponding [guidelines][1] and check out the [issues][2].
26
+
27
+ ---
28
+
29
+ Copyright (c) 2015 [James Whelton][3] and [contributors][4], released under the [New BSD License][5]
30
+
31
+ [1]: https://github.com/whelton/solidus_gateway_checkout_v2/blob/master/CONTRIBUTING.md
32
+ [2]: https://github.com/whelton/solidus_gateway_checkout_v2/issues
33
+ [3]: https://github.com/whelton
34
+ [4]: https://github.com/whelton/solidus_gateway_checkout_v2/graphs/contributors
35
+ [5]: https://github.com/whelton/solidus_gateway_checkout_v2/blob/master/LICENSE.md
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_checkout_v2'
20
+ Rake::Task['common:test_app'].invoke
21
+ end
@@ -0,0 +1,33 @@
1
+
2
+ class Spree::Gateway::CheckoutV2Gateway < Spree::Gateway
3
+
4
+ preference :secret_key, :string
5
+ preference :publishable_key, :string
6
+ preference :use_card_tokenisation, :boolean, default: true
7
+ preference :test, :boolean, default: true
8
+
9
+ def method_type
10
+ 'checkout_v2'
11
+ end
12
+
13
+ def provider_class
14
+ ActiveMerchant::Billing::CheckoutV2
15
+ end
16
+
17
+ def authorize(money, creditcard, gateway_options)
18
+ if creditcard.number.blank? && creditcard.gateway_payment_profile_id.present?
19
+ provider.authorize(money, creditcard.gateway_payment_profile_id, gateway_options)
20
+ else
21
+ provider.authorize(money, creditcard, gateway_options)
22
+ end
23
+ end
24
+
25
+ def purchase(money, creditcard, gateway_options)
26
+ if creditcard.number.blank? && creditcard.gateway_payment_profile_id.present?
27
+ provider.purchase(money, creditcard.gateway_payment_profile_id, gateway_options)
28
+ else
29
+ provider.purchase(money, creditcard, gateway_options)
30
+ end
31
+ end
32
+
33
+ end
data/bin/rails ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
4
+ ENGINE_PATH = File.expand_path('../../lib/spree_gateway/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,4 @@
1
+ ---
2
+ en:
3
+ spree:
4
+ payment_has_been_cancelled: The payment has been cancelled.
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Spree::Core::Engine.add_routes do
2
+
3
+ end
@@ -0,0 +1,218 @@
1
+ # From https://github.com/activemerchant/active_merchant/blob/8f8c46e65969896c869dfb7dbef3a3b47921e1c4/lib/active_merchant/billing/gateways/checkout_v2.rb
2
+ #
3
+ # Solidus currently (version '1.1.1' at time of writing) uses Active Merchant at '~> 1.48.0'
4
+ # CheckoutV2 Gateway was added in Active Merchant at '1.51.0'
5
+ # so Solidus does not currently have access to it
6
+ #
7
+ # This has been modified to authorize with card token if provided as payment method
8
+
9
+ module ActiveMerchant #:nodoc:
10
+ module Billing #:nodoc:
11
+ class CheckoutV2 < Gateway
12
+ self.display_name = "Checkout.com V2 Gateway"
13
+ self.homepage_url = "https://www.checkout.com/"
14
+ self.live_url = "https://api2.checkout.com/v2"
15
+ self.test_url = "http://sandbox.checkout.com/api2/v2"
16
+
17
+ self.supported_countries = ['AD', 'AT', 'BE', 'BG', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FO', 'FI', 'FR', 'GB', 'GI', 'GL', 'GR', 'HR', 'HU', 'IE', 'IS', 'IL', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SI', 'SM', 'SK', 'SJ', 'TR', 'VA']
18
+ self.default_currency = "USD"
19
+ self.money_format = :cents
20
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
21
+
22
+ def initialize(options={})
23
+ requires!(options, :secret_key)
24
+ super
25
+ end
26
+
27
+ def purchase(amount, payment_method, options={})
28
+ MultiResponse.run do |r|
29
+ r.process { authorize(amount, payment_method, options) }
30
+ r.process { capture(amount, r.authorization, options) }
31
+ end
32
+ end
33
+
34
+ def authorize(amount, payment_method, options={})
35
+ post = {}
36
+ post[:autoCapture] = "n"
37
+ add_invoice(post, amount, options)
38
+
39
+ if payment_method.is_a?(String) && payment_method.include?('card_tok_')
40
+ post[:cardToken] = payment_method
41
+ post[:email] = options[:email]
42
+
43
+ commit(:authorize_token, post)
44
+ else
45
+ add_payment_method(post, payment_method)
46
+ add_customer_data(post, options)
47
+
48
+ commit(:authorize, post)
49
+ end
50
+ end
51
+
52
+ def capture(amount, authorization, options={})
53
+ post = {}
54
+ add_invoice(post, amount, options)
55
+ add_customer_data(post, options)
56
+
57
+ commit(:capture, post, authorization)
58
+ end
59
+
60
+ def void(authorization, options={})
61
+ post = {}
62
+ commit(:void, post, authorization)
63
+ end
64
+
65
+ def refund(amount, authorization, options={})
66
+ post = {}
67
+ add_invoice(post, amount, options)
68
+ add_customer_data(post, options)
69
+
70
+ commit(:refund, post, authorization)
71
+ end
72
+
73
+ def verify(credit_card, options={})
74
+ MultiResponse.run(:use_first_response) do |r|
75
+ r.process { authorize(100, credit_card, options) }
76
+ r.process(:ignore_result) { void(r.authorization, options) }
77
+ end
78
+ end
79
+
80
+ def supports_scrubbing?
81
+ true
82
+ end
83
+
84
+ def scrub(transcript)
85
+ transcript.
86
+ gsub(%r((Authorization: )[^\\]*)i, '\1[FILTERED]').
87
+ gsub(%r(("number\\":\\")\d+), '\1[FILTERED]').
88
+ gsub(%r(("cvv\\":\\")\d+), '\1[FILTERED]')
89
+ end
90
+
91
+ private
92
+
93
+ def add_invoice(post, money, options)
94
+ post[:value] = amount(money)
95
+ post[:trackId] = options[:order_id]
96
+ post[:currency] = options[:currency] || currency(money)
97
+ end
98
+
99
+ def add_payment_method(post, payment_method)
100
+ post[:card] = {}
101
+ post[:card][:name] = payment_method.name
102
+ post[:card][:number] = payment_method.number
103
+ post[:card][:cvv] = payment_method.verification_value
104
+ post[:card][:expiryYear] = format(payment_method.year, :four_digits)
105
+ post[:card][:expiryMonth] = format(payment_method.month, :two_digits)
106
+ end
107
+
108
+ def add_customer_data(post, options)
109
+ post[:email] = options[:email] || "unspecified@example.com"
110
+ address = options[:billing_address]
111
+ if(address && post[:card])
112
+ post[:card][:billingDetails] = {}
113
+ post[:card][:billingDetails][:address1] = address[:address1]
114
+ post[:card][:billingDetails][:address2] = address[:address2]
115
+ post[:card][:billingDetails][:city] = address[:city]
116
+ post[:card][:billingDetails][:state] = address[:state]
117
+ post[:card][:billingDetails][:country] = address[:country]
118
+ post[:card][:billingDetails][:postcode] = address[:zip]
119
+ post[:card][:billingDetails][:phone] = { number: address[:phone] } unless address[:phone].blank?
120
+ end
121
+ end
122
+
123
+ def commit(action, post, authorization = nil)
124
+ begin
125
+ raw_response = ssl_post(url(post, action, authorization), post.to_json, headers)
126
+ response = parse(raw_response)
127
+ rescue ResponseError => e
128
+ raise unless(e.response.code.to_s =~ /4\d\d/)
129
+ response = parse(e.response.body)
130
+ end
131
+
132
+ succeeded = success_from(response)
133
+ Response.new(
134
+ succeeded,
135
+ message_from(succeeded, response),
136
+ response,
137
+ authorization: authorization_from(response),
138
+ error_code: error_code_from(succeeded, response),
139
+ test: test?,
140
+ avs_result: avs_result(action, response),
141
+ cvv_result: cvv_result(action, response))
142
+ end
143
+
144
+ def headers
145
+ {
146
+ "Authorization" => @options[:secret_key],
147
+ "Content-Type" => "application/json;charset=UTF-8"
148
+ }
149
+ end
150
+
151
+ def url(post, action, authorization)
152
+ if action == :authorize
153
+ "#{base_url}/charges/card"
154
+ elsif action == :authorize_token
155
+ "#{base_url}/charges/token"
156
+ else
157
+ "#{base_url}/charges/#{authorization}/#{action}"
158
+ end
159
+ end
160
+
161
+ def base_url
162
+ test? ? test_url : live_url
163
+ end
164
+
165
+ def avs_result(action, response)
166
+ action == :purchase ? AVSResult.new(code: response["card"]["avsCheck"]) : nil
167
+ end
168
+
169
+ def cvv_result(action, response)
170
+ action == :purchase ? CVVResult.new(response["card"]["cvvCheck"]) : nil
171
+ end
172
+
173
+ def parse(body)
174
+ JSON.parse(body)
175
+ rescue JSON::ParserError
176
+ {
177
+ "message" => "Invalid JSON response received from CheckoutV2Gateway. Please contact CheckoutV2Gateway if you continue to receive this message.",
178
+ "raw_response" => scrub(body)
179
+ }
180
+ end
181
+
182
+ def success_from(response)
183
+ response["responseCode"] == ("10000" || "10100")
184
+ end
185
+
186
+ def message_from(succeeded, response)
187
+ if succeeded
188
+ "Succeeded"
189
+ elsif response["errors"]
190
+ response["message"] + ": " + response["errors"].first
191
+ else
192
+ response["responseMessage"] || response["message"] || "Unable to read error message"
193
+ end
194
+ end
195
+
196
+ STANDARD_ERROR_CODE_MAPPING = {
197
+ "20014" => STANDARD_ERROR_CODE[:invalid_number],
198
+ "20100" => STANDARD_ERROR_CODE[:invalid_expiry_date],
199
+ "20054" => STANDARD_ERROR_CODE[:expired_card],
200
+ "40104" => STANDARD_ERROR_CODE[:incorrect_cvc],
201
+ "40108" => STANDARD_ERROR_CODE[:incorrect_zip],
202
+ "40111" => STANDARD_ERROR_CODE[:incorrect_address],
203
+ "20005" => STANDARD_ERROR_CODE[:card_declined],
204
+ "20088" => STANDARD_ERROR_CODE[:processing_error],
205
+ "20001" => STANDARD_ERROR_CODE[:call_issuer],
206
+ "30004" => STANDARD_ERROR_CODE[:pickup_card]
207
+ }
208
+
209
+ def authorization_from(raw)
210
+ raw["id"]
211
+ end
212
+
213
+ def error_code_from(succeeded, response)
214
+ succeeded ? nil : STANDARD_ERROR_CODE_MAPPING[response["responseCode"]]
215
+ end
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,4 @@
1
+ require "spree_core"
2
+ require "spree_gateway_checkout_v2/engine"
3
+ require "sass/rails"
4
+ require "coffee_script"
@@ -0,0 +1,30 @@
1
+ module SpreeGatewayCheckoutV2
2
+ class Engine < Rails::Engine
3
+ engine_name 'solidus_gateway_checkout_v2'
4
+
5
+ config.autoload_paths += %W(#{config.root}/lib)
6
+
7
+ initializer "spree.gateway.payment_methods", :after => "spree.register.payment_methods" do |app|
8
+ app.config.spree.payment_methods << Spree::Gateway::CheckoutV2Gateway
9
+ end
10
+
11
+ def self.activate
12
+ if SpreeGatewayCheckoutV2::Engine.frontend_available?
13
+ Dir.glob(File.join(File.dirname(__FILE__), "../../controllers/frontend/*/*_decorator*.rb")) do |c|
14
+ Rails.configuration.cache_classes ? require(c) : load(c)
15
+ end
16
+ end
17
+ end
18
+
19
+
20
+ def self.frontend_available?
21
+ @@frontend_available ||= ::Rails::Engine.subclasses.map(&:instance).map{ |e| e.class.to_s }.include?('Spree::Frontend::Engine')
22
+ end
23
+
24
+ if self.frontend_available?
25
+ paths["app/views"] << "lib/views/frontend"
26
+ end
27
+
28
+ config.to_prepare &method(:activate).to_proc
29
+ end
30
+ end
@@ -0,0 +1,83 @@
1
+ <%= render "spree/checkout/payment/gateway", payment_method: payment_method %>
2
+
3
+ <% if payment_method.preferences[:use_card_tokenisation] %>
4
+ <!-- Using Card Tokenisation For Checkout V2 Gateway -->
5
+ <script type="text/javascript" src="https://<%= payment_method.preferences[:test_mode] ? 'sandbox.checkout.com/js/v1/checkoutkit.js' : 'cdn.checkout.com/js/checkoutkit.js' %>"></script>
6
+ <script type="text/javascript">
7
+ // Payment Method Element & Id
8
+ Spree.checkoutV2PaymentMethod = $('#payment_method_' + <%= payment_method.id %>);
9
+ Spree.checkoutV2PaymentMethodId = Spree.checkoutV2PaymentMethod.prop('id').split("_")[2];
10
+ // CheckoutKit Credentials
11
+ CheckoutKit.setPublicKey('<%= payment_method.preferred_publishable_key %>');
12
+ CheckoutKit.setCustomerEmail('<%= current_order.email %>');
13
+ // CheckoutKit API Error Event Handler
14
+ CheckoutKit.addEventHandler(CheckoutKit.Events.API_ERROR, function(response){
15
+ // Create Error Messages
16
+ var messages = '<b>'+response.data.message+'</b>';
17
+ messages += '<ul>';
18
+ $.each(response.data.errors, function(index, value){
19
+ messages += '<li>'+value+'</li>';
20
+ });
21
+ messages += '</ul>';
22
+ // Show Errors
23
+ $('#checkoutV2Error').html(messages);
24
+ $('#checkoutV2Error').show();
25
+ // Enable Inputs
26
+ Spree.checkoutV2PaymentMethod.find('#name_on_card_'+Spree.checkoutV2PaymentMethodId+', #card_number, #card_expiry, #card_code').prop("disabled", false);
27
+ $('#checkout_form_payment input[type="submit"]').removeClass('disabled').prop('disabled', false);
28
+ });
29
+ // Response Handler
30
+ var checkoutV2ResponseHandler = function(response){
31
+ // Disable Inputs (Meaning they won't be submitted with form)
32
+ Spree.checkoutV2PaymentMethod.find('#card_number, #card_expiry, #card_code').prop("disabled", true);
33
+ // Enable Name Input
34
+ Spree.checkoutV2PaymentMethod.find('#name_on_card_'+Spree.checkoutV2PaymentMethodId).prop("disabled", false);
35
+ // Create Hidden Inputs With Data From API
36
+ Spree.checkoutV2PaymentMethod.append("<input type='hidden' id='checkout_v2_token' name='payment_source[" + Spree.checkoutV2PaymentMethodId + "][gateway_payment_profile_id]' value='" + response.id + "'/>");
37
+ Spree.checkoutV2PaymentMethod.append("<input type='hidden' name='payment_source[" + Spree.checkoutV2PaymentMethodId + "][paymentMethod]' value='" + response.card.paymentMethod + "'/>");
38
+ Spree.checkoutV2PaymentMethod.append("<input type='hidden' name='payment_source[" + Spree.checkoutV2PaymentMethodId + "][last_digits]' value='" + response.card.last4 + "'/>");
39
+ Spree.checkoutV2PaymentMethod.append("<input type='hidden' name='payment_source[" + Spree.checkoutV2PaymentMethodId + "][month]' value='" + response.card.expiryMonth + "'/>");
40
+ Spree.checkoutV2PaymentMethod.append("<input type='hidden' name='payment_source[" + Spree.checkoutV2PaymentMethodId + "][year]' value='" + response.card.expiryYear + "'/>");
41
+ // Submit
42
+ return Spree.checkoutV2PaymentMethod.parents("form").trigger('submit');
43
+ };
44
+ // On Page Ready
45
+ $(document).ready(function() {
46
+ // Prepend div to Payment Method Element to display any errors
47
+ Spree.checkoutV2PaymentMethod.prepend("<div id='checkoutV2Error' class='errorExplanation' style='display:none'></div>");
48
+ // Form Submission Handler
49
+ $('#checkout_form_payment').submit(function(e) {
50
+ var expiration, card;
51
+ // Hide any existing errors
52
+ $('#checkoutV2Error').hide();
53
+ // Check if the token input exists
54
+ // Meaning we already gotten a token and can do a normal submission
55
+ if ( $( "#checkout_v2_token" ).length ){
56
+ return true;
57
+ }
58
+ // If CheckoutV2 Payment Method Element is visible, stop form submission and create card token
59
+ if (Spree.checkoutV2PaymentMethod.is(':visible')) {
60
+ e.preventDefault(); // Stop form submission
61
+ // Disable Inputs
62
+ Spree.checkoutV2PaymentMethod.find('#name_on_card_'+Spree.checkoutV2PaymentMethodId+', #card_number, #card_expiry, #card_code').prop("disabled", true);
63
+ // Create Card Token
64
+ expiration = $('.cardExpiry:visible').payment('cardExpiryVal');
65
+ card = {
66
+ number: $('.cardNumber:visible').val(),
67
+ name: $('#name_on_card_'+Spree.checkoutV2PaymentMethodId+':visible').val(),
68
+ expiryMonth: expiration.month || 0,
69
+ expiryYear: expiration.year || 0,
70
+ cvv: $('.cardCode:visible').val()
71
+ };
72
+ CheckoutKit.createCardToken(card, function(response){
73
+ // If response has a card and id and not of type error, call the response handler.
74
+ // If it is an error, the added error handler above will pick it up
75
+ if (('id' in response) && ('card' in response) && !(response.type == 'error')) {
76
+ checkoutV2ResponseHandler(response);
77
+ }
78
+ });
79
+ }
80
+ });
81
+ });
82
+ </script>
83
+ <% end %>
@@ -0,0 +1,32 @@
1
+ # encoding: UTF-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.platform = Gem::Platform::RUBY
5
+ s.name = "solidus_gateway_checkout_v2"
6
+ s.version = "1.0.1"
7
+ s.summary = "Checkout V2 Payment Gateway for Solidus"
8
+ s.description = s.summary
9
+ s.required_ruby_version = ">= 2.1"
10
+
11
+ s.author = "James Whelton"
12
+ s.email = "james@whelton.io"
13
+ s.homepage = "https://github.com/whelton/solidus_gateway_checkout_v2"
14
+ s.license = %q{BSD-3}
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- spec/*`.split("\n")
18
+ s.require_path = "lib"
19
+ s.requirements << "none"
20
+
21
+ s.add_dependency "solidus_core", "~> 1.1"
22
+
23
+ s.add_development_dependency "rspec-rails", "~> 3.2"
24
+ s.add_development_dependency "simplecov"
25
+ s.add_development_dependency "sqlite3"
26
+ s.add_development_dependency "sass-rails"
27
+ s.add_development_dependency "coffee-rails"
28
+ s.add_development_dependency "factory_girl", "~> 4.4"
29
+ s.add_development_dependency "capybara"
30
+ s.add_development_dependency "poltergeist", "~> 1.5.0"
31
+ s.add_development_dependency "database_cleaner", "1.2.0"
32
+ end
@@ -0,0 +1,47 @@
1
+ require "simplecov"
2
+ SimpleCov.start "rails"
3
+
4
+ ENV["RAILS_ENV"] ||= "test"
5
+
6
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
7
+
8
+ require "rspec/rails"
9
+
10
+ require "capybara/rspec"
11
+ require 'capybara/poltergeist'
12
+
13
+ require "database_cleaner"
14
+ require "braintree"
15
+ require "ffaker"
16
+
17
+ require "spree/testing_support/factories"
18
+ require "spree/testing_support/order_walkthrough"
19
+
20
+ Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each { |f| require f }
21
+
22
+ RSpec.configure do |config|
23
+ config.infer_spec_type_from_file_location!
24
+ config.mock_with :rspec
25
+
26
+ config.filter_run focus: true
27
+ config.run_all_when_everything_filtered = true
28
+ config.use_transactional_fixtures = false
29
+
30
+ config.include FactoryGirl::Syntax::Methods
31
+
32
+ config.before :suite do
33
+ DatabaseCleaner.clean_with :truncation
34
+ end
35
+
36
+ config.before do
37
+ DatabaseCleaner.strategy = RSpec.current_example.metadata[:js] ? :truncation : :transaction
38
+ DatabaseCleaner.start
39
+ end
40
+
41
+ config.after do
42
+ DatabaseCleaner.clean
43
+ end
44
+
45
+ Capybara.javascript_driver = :poltergeist
46
+ FactoryGirl.find_definitions
47
+ end
metadata ADDED
@@ -0,0 +1,202 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: solidus_gateway_checkout_v2
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - James Whelton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: solidus_core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sass-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: coffee-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: factory_girl
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '4.4'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '4.4'
111
+ - !ruby/object:Gem::Dependency
112
+ name: capybara
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: poltergeist
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 1.5.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 1.5.0
139
+ - !ruby/object:Gem::Dependency
140
+ name: database_cleaner
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '='
144
+ - !ruby/object:Gem::Version
145
+ version: 1.2.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '='
151
+ - !ruby/object:Gem::Version
152
+ version: 1.2.0
153
+ description: Checkout V2 Payment Gateway for Solidus
154
+ email: james@whelton.io
155
+ executables: []
156
+ extensions: []
157
+ extra_rdoc_files: []
158
+ files:
159
+ - ".gitignore"
160
+ - ".rspec"
161
+ - CONTRIBUTING.md
162
+ - Gemfile
163
+ - LICENSE.md
164
+ - README.md
165
+ - Rakefile
166
+ - app/models/spree/gateway/checkout_v2_gateway.rb
167
+ - bin/rails
168
+ - config/locales/en.yml
169
+ - config/routes.rb
170
+ - lib/active_merchant/billing/checkout_v2.rb
171
+ - lib/solidus_gateway_checkout_v2.rb
172
+ - lib/spree_gateway_checkout_v2/engine.rb
173
+ - lib/views/frontend/spree/checkout/payment/_checkout_v2.html.erb
174
+ - solidus_gateway_checkout_v2.gemspec
175
+ - spec/spec_helper.rb
176
+ homepage: https://github.com/whelton/solidus_gateway_checkout_v2
177
+ licenses:
178
+ - BSD-3
179
+ metadata: {}
180
+ post_install_message:
181
+ rdoc_options: []
182
+ require_paths:
183
+ - lib
184
+ required_ruby_version: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '2.1'
189
+ required_rubygems_version: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ requirements:
195
+ - none
196
+ rubyforge_project:
197
+ rubygems_version: 2.4.5
198
+ signing_key:
199
+ specification_version: 4
200
+ summary: Checkout V2 Payment Gateway for Solidus
201
+ test_files:
202
+ - spec/spec_helper.rb