Skip to content

Commit

Permalink
Use jquery.payment for frontend + backend checkout form
Browse files Browse the repository at this point in the history
  • Loading branch information
radar committed Sep 3, 2013
1 parent 9c4d7c2 commit 5c400ac
Show file tree
Hide file tree
Showing 10 changed files with 565 additions and 88 deletions.
6 changes: 5 additions & 1 deletion backend/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,8 @@

* Fixed issue where selecting an existing user in the customer details step would not associate them with an order.

*Ryan Bigg and dan-ding"
*Ryan Bigg and dan-ding*

* We now use [jQuery.payment](https://stripe.com/blog/jquery-payment) (from Stripe) to provide slightly better formatting on credit card number, expiry and CVV fields.

*Ryan Bigg*
12 changes: 12 additions & 0 deletions backend/app/assets/javascripts/admin/checkouts/edit.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
//= require_self
//= require jquery.payment
$(document).ready(function() {
if ($('#customer_autocomplete_template').length > 0) {
window.customerTemplate = Handlebars.compile($('#customer_autocomplete_template').text());
}

if ($("#card_number").is("*")) {
$("#card_number").payment('formatCardNumber')
$("#card_expiry").payment('formatCardExpiry')
$("#card_code").payment('formatCardCVC')

$("#card_number").change(function() {
$("#cc_type").val($.payment.cardType(this.value))
})
}

formatCustomerResult = function(customer) {
return customerTemplate({
customer: customer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@
</div>
<div class="three columns">
<div data-hook="card_expiration" class="field">
<%= label_tag 'card_month', raw(Spree.t(:expiration) + content_tag(:span, ' *', :class => 'required')) %><br>
<%= select_month(Date.today, { :prefix => param_prefix, :field_name => 'month', :use_month_numbers => true }, :class => 'required select2', :id => 'card_month') %>
<%= select_year(Date.today, { :prefix => param_prefix, :field_name => 'year', :start_year => Date.today.year, :end_year => Date.today.year + 15 }, :class => 'required select2', :id => 'card_year') %>
<%= label_tag 'card_month', raw(t(:expiration) + content_tag(:span, ' *', :class => 'required')) %><br>
<%= text_field_tag "#{param_prefix}[expiry]", '', :id => 'card_expiry', :class => "required", :placeholder => "MM / YY" %>
</div>
</div>
<div class="omega two columns">
Expand Down
48 changes: 18 additions & 30 deletions core/app/models/spree/credit_card.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ class CreditCard < ActiveRecord::Base
has_many :payments, as: :source

before_save :set_last_digits
after_validation :set_card_type

attr_accessor :number, :verification_value

Expand All @@ -14,36 +13,19 @@ class CreditCard < ActiveRecord::Base

scope :with_payment_profile, -> { where('gateway_customer_profile_id IS NOT NULL') }

def set_last_digits
number.to_s.gsub!(/\s/,'')
verification_value.to_s.gsub!(/\s/,'')
self.last_digits ||= number.to_s.length <= 4 ? number : number.to_s.slice(-4..-1)
def expiry=(expiry)
self[:month], self[:year] = expiry.split(" / ")
self[:year] = "20" + self[:year]
end

# cheap hack to get to the type? method from deep within ActiveMerchant
# without stomping on potentially existing methods in CreditCard
class CardDetector
class << self
include ActiveMerchant::Billing::CreditCardMethods::ClassMethods
end
def number=(num)
@number = num.gsub(/[^0-9]/, '') rescue nil
end

# Some payment gateways, such as USA EPay, only support an ActiveMerchant::Billing::CreditCard
# object, rather than an object *like* that. So we need to convert it.
def to_active_merchant
ActiveMerchant::Billing::CreditCard.new(
:number => number,
:month => month,
:year => year,
:verification_value => verification_value,
:first_name => first_name,
:last_name => last_name
)
end

# sets self.cc_type while we still have the card number
def set_card_type
self.cc_type ||= CardDetector.brand?(number)
def set_last_digits
number.to_s.gsub!(/\s/,'')
verification_value.to_s.gsub!(/\s/,'')
self.last_digits ||= number.to_s.length <= 4 ? number : number.to_s.slice(-4..-1)
end

def name?
Expand Down Expand Up @@ -94,9 +76,15 @@ def has_payment_profile?
gateway_customer_profile_id.present?
end

def spree_cc_type
return 'visa' if Rails.env.development?
cc_type
def to_active_merchant
ActiveMerchant::Billing::CreditCard.new(
:number => number,
:month => month,
:year => year,
:verification_value => verification_value,
:first_name => first_name,
:last_name => last_name
)
end

private
Expand Down
52 changes: 10 additions & 42 deletions core/spec/models/spree/credit_card_spec.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
require 'spec_helper'

describe Spree::CreditCard do

let(:valid_credit_card_attributes) { { number: '4111111111111111', verification_value: '123', month: 12, year: 2014 } }
let(:valid_credit_card_attributes) { {:number => '4111111111111111', :verification_value => '123', :expiry => "12 / 14"} }

def self.payment_states
Spree::Payment.state_machine.states.keys
Expand Down Expand Up @@ -136,49 +135,18 @@ def stub_rails_env(environment)
end
end

context "#spree_cc_type" do
before { credit_card.attributes = valid_credit_card_attributes }

context "in development mode" do
before do
stub_rails_env("production")
end

it "should return visa" do
credit_card.save
credit_card.spree_cc_type.should == 'visa'
end
end

context "in production mode" do
before { stub_rails_env("production") }

it "should return the actual cc_type for a valid number" do
credit_card.number = '378282246310005'
credit_card.save
credit_card.spree_cc_type.should == 'american_express'
end
end
end

context "#set_card_type" do
before :each do
stub_rails_env("production")
credit_card.attributes = valid_credit_card_attributes
end
context "#number=" do
it "should strip non-numeric characters from card input" do
credit_card.number = "6011000990139424"
credit_card.number.should == "6011000990139424"

it "stores the credit card type after validation" do
credit_card.number = '6011000990139424'
credit_card.save
credit_card.spree_cc_type.should == 'discover'
credit_card.number = " 6011-0009-9013-9424 "
credit_card.number.should == "6011000990139424"
end

it "does not overwrite the credit card type when loaded and saved" do
credit_card.number = '5105105105105100'
credit_card.save
credit_card.number = 'XXXXXXXXXXXX5100'
credit_card.save
credit_card.spree_cc_type.should == 'master'
it "should not raise an exception on non-string input" do
credit_card.number = Hash.new
credit_card.number.should be_nil
end
end

Expand Down
12 changes: 3 additions & 9 deletions core/spec/models/spree/payment_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,7 @@
it "should build the payment's source" do
params = { :amount => 100, :payment_method => gateway,
:source_attributes => {
:year => 1.month.from_now.year,
:month =>1.month.from_now.month,
:expiry =>"1 / 99",
:number => '1234567890123',
:verification_value => '123'
}
Expand All @@ -570,13 +569,8 @@
end

it "errors when payment source not valid" do
params = {
:amount => 100,
:payment_method => gateway,
:source_attributes => {
:year => "2012", :month =>"1"
}
}
params = { :amount => 100, :payment_method => gateway,
:source_attributes => {:expiry => "1 / 12" }}

payment = Spree::Payment.new(params)
payment.should_not be_valid
Expand Down
Loading

0 comments on commit 5c400ac

Please sign in to comment.