Merge pull request #8557 from Matt-Yorkley/card-brand-formatting

Credit card brand formatting
This commit is contained in:
Filipe
2021-12-15 20:18:21 +00:00
committed by GitHub
5 changed files with 71 additions and 97 deletions

View File

@@ -17,7 +17,7 @@ angular.module("admin.payments").factory 'AdminStripeElements', ($rootScope, Sta
console.error(JSON.stringify(response.error))
else
secrets.token = response.token.id
secrets.cc_type = @mapTokenApiCardBrand(response.token.card.brand)
secrets.cc_type = response.token.card.brand
secrets.card = response.token.card
submit()
@@ -33,28 +33,10 @@ angular.module("admin.payments").factory 'AdminStripeElements', ($rootScope, Sta
console.error(JSON.stringify(response.error))
else
secrets.token = response.paymentMethod.id
secrets.cc_type = @mapPaymentMethodsApiCardBrand(response.paymentMethod.card.brand)
secrets.cc_type = response.paymentMethod.card.brand
secrets.card = response.paymentMethod.card
submit()
# Maps the brand returned by Stripe's tokenAPI to that required by activemerchant
mapTokenApiCardBrand: (cardBrand) ->
switch cardBrand
when 'MasterCard' then return 'master'
when 'Visa' then return 'visa'
when 'American Express' then return 'american_express'
when 'Discover' then return 'discover'
when 'JCB' then return 'jcb'
when 'Diners Club' then return 'diners_club'
# Maps the brand returned by Stripe's paymentMethodsAPI to that required by activemerchant
mapPaymentMethodsApiCardBrand: (cardBrand) ->
switch cardBrand
when 'mastercard' then return 'master'
when 'amex' then return 'american_express'
when 'diners' then return 'diners_club'
else return cardBrand # a few brands are equal, for example, visa
# It doesn't matter if any of these are nil, all are optional.
makeCardData: (secrets) ->
{'name': secrets.name,

View File

@@ -16,7 +16,7 @@ angular.module('Darkswarm').factory 'StripeElements', ($rootScope, Messages) ->
@reportError(response.error, t("error") + ": #{response.error.message}")
else
secrets.token = response.token.id
secrets.cc_type = @mapTokenApiCardBrand(response.token.card.brand)
secrets.cc_type = response.token.card.brand
secrets.card = response.token.card
submit()
.catch (response) =>
@@ -37,7 +37,7 @@ angular.module('Darkswarm').factory 'StripeElements', ($rootScope, Messages) ->
@reportError(response.error, t("error") + ": #{response.error.message}")
else
secrets.token = response.paymentMethod.id
secrets.cc_type = @mapPaymentMethodsApiCardBrand(response.paymentMethod.card.brand)
secrets.cc_type = response.paymentMethod.card.brand
secrets.card = response.paymentMethod.card
submit()
.catch (response) =>
@@ -56,24 +56,6 @@ angular.module('Darkswarm').factory 'StripeElements', ($rootScope, Messages) ->
# $evalAsync is improved way of triggering a digest without calling $apply
$rootScope.$evalAsync()
# Maps the brand returned by Stripe's tokenAPI to that required by activemerchant
mapTokenApiCardBrand: (cardBrand) ->
switch cardBrand
when 'MasterCard' then return 'master'
when 'Visa' then return 'visa'
when 'American Express' then return 'american_express'
when 'Discover' then return 'discover'
when 'JCB' then return 'jcb'
when 'Diners Club' then return 'diners_club'
# Maps the brand returned by Stripe's paymentMethodsAPI to that required by activemerchant
mapPaymentMethodsApiCardBrand: (cardBrand) ->
switch cardBrand
when 'mastercard' then return 'master'
when 'amex' then return 'american_express'
when 'diners' then return 'diners_club'
else return cardBrand # a few brands are equal, for example, visa
# It doesn't matter if any of these are nil, all are optional.
makeCardData: (secrets) ->
{'name': secrets.name,

View File

@@ -39,20 +39,8 @@ module Spree
end
end
# cc_type is set by jquery.payment, which helpfully provides different
# types from Active Merchant. Converting them is necessary.
def cc_type=(type)
real_type = case type
when 'mastercard', 'maestro'
'master'
when 'amex'
'american_express'
when 'dinersclub'
'diners_club'
else
type
end
self[:cc_type] = real_type
reformat_card_type!(type)
end
def set_last_digits
@@ -127,6 +115,27 @@ module Spree
private
def reformat_card_type!(type)
self[:cc_type] = active_merchant_card_type(type)
end
# ActiveMerchant requires certain credit card brand names to be stored in a specific format.
# See: https://github.com/activemerchant/active_merchant/blob/master/lib/active_merchant/billing/credit_card.rb#L89
def active_merchant_card_type(type)
card_type = type.to_s.downcase
case card_type
when "mastercard", "maestro", "master card"
"master"
when "amex", "american express"
"american_express"
when "dinersclub", "diners club"
"diners_club"
else
card_type
end
end
def expiry_not_in_the_past
return unless year.present? && month.present?

View File

@@ -34,7 +34,7 @@ describe 'StripeElements Service', ->
StripeElements.requestToken(secrets, submit)
$rootScope.$digest() # required for #then to by called
expect(secrets.token).toEqual "token"
expect(secrets.cc_type).toEqual "master"
expect(secrets.cc_type).toEqual "MasterCard"
expect(submit).toHaveBeenCalled()
describe "with unsatifactory data", ->
@@ -52,19 +52,3 @@ describe 'StripeElements Service', ->
expect(Loading.clear).toHaveBeenCalled()
expect(RailsFlashLoader.loadFlash).toHaveBeenCalledWith({error: "Error: There was a problem"})
expect(Bugsnag.notify).toHaveBeenCalled()
describe 'mapTokenApiCardBrand', ->
it "maps the brand returned by Stripe's tokenAPI to that required by activemerchant", ->
expect(StripeElements.mapTokenApiCardBrand('MasterCard')).toEqual "master"
expect(StripeElements.mapTokenApiCardBrand('Visa')).toEqual "visa"
expect(StripeElements.mapTokenApiCardBrand('American Express')).toEqual "american_express"
expect(StripeElements.mapTokenApiCardBrand('Discover')).toEqual "discover"
expect(StripeElements.mapTokenApiCardBrand('JCB')).toEqual "jcb"
expect(StripeElements.mapTokenApiCardBrand('Diners Club')).toEqual "diners_club"
describe 'mapPaymentMethodsApiCardBrand', ->
it "maps the brand returned by Stripe's paymentMethodsAPI to that required by activemerchant", ->
expect(StripeElements.mapPaymentMethodsApiCardBrand('mastercard')).toEqual "master"
expect(StripeElements.mapPaymentMethodsApiCardBrand('amex')).toEqual "american_express"
expect(StripeElements.mapPaymentMethodsApiCardBrand('diners')).toEqual "diners_club"
expect(StripeElements.mapPaymentMethodsApiCardBrand('visa')).toEqual "visa"

View File

@@ -4,16 +4,16 @@ require 'spec_helper'
module Spree
describe CreditCard do
describe "original specs from Spree" do
let(:valid_credit_card_attributes) {
{
number: '4111111111111111',
verification_value: '123',
month: 12,
year: Time.zone.now.year + 1
}
let(:valid_credit_card_attributes) {
{
number: '4111111111111111',
verification_value: '123',
month: 12,
year: Time.zone.now.year + 1
}
}
describe "original specs from Spree" do
def self.payment_states
Spree::Payment.state_machine.states.keys
end
@@ -151,25 +151,6 @@ module Spree
end
end
context "#cc_type=" do
it "converts between the different types" do
credit_card.cc_type = 'mastercard'
expect(credit_card.cc_type).to eq 'master'
credit_card.cc_type = 'maestro'
expect(credit_card.cc_type).to eq 'master'
credit_card.cc_type = 'amex'
expect(credit_card.cc_type).to eq 'american_express'
credit_card.cc_type = 'dinersclub'
expect(credit_card.cc_type).to eq 'diners_club'
credit_card.cc_type = 'some_outlandish_cc_type'
expect(credit_card.cc_type).to eq 'some_outlandish_cc_type'
end
end
context "#associations" do
it "should be able to access its payments" do
expect { credit_card.payments.to_a }.not_to raise_error
@@ -198,6 +179,42 @@ module Spree
end
end
describe "formatting the card type for ActiveMerchant" do
context "#cc_type=" do
let(:credit_card) { build(:credit_card) }
it "converts the card type format" do
credit_card.cc_type = 'mastercard'
expect(credit_card.cc_type).to eq 'master'
credit_card.cc_type = 'maestro'
expect(credit_card.cc_type).to eq 'master'
credit_card.cc_type = 'amex'
expect(credit_card.cc_type).to eq 'american_express'
credit_card.cc_type = 'dinersclub'
expect(credit_card.cc_type).to eq 'diners_club'
credit_card.cc_type = 'some_outlandish_cc_type'
expect(credit_card.cc_type).to eq 'some_outlandish_cc_type'
end
end
context "on save" do
it "converts the card type format" do
expect_any_instance_of(Spree::CreditCard).to receive(:reformat_card_type!).
at_least(:once).and_call_original
credit_card = Spree::CreditCard.create(
valid_credit_card_attributes.merge(cc_type: "Master Card")
)
expect(credit_card.cc_type).to eq "master"
end
end
end
describe "setting default credit card for a user" do
let(:user) { create(:user) }
let(:onetime_card_attrs) do