WIP: Storing Stripe card details for later use

NOTE: No interface for actually selecting a stored card to use yet
This commit is contained in:
Rob Harrington
2017-02-23 17:53:33 +11:00
parent 7c831c9844
commit c97a140471
3 changed files with 102 additions and 9 deletions

View File

@@ -91,15 +91,8 @@ module Spree
options[:currency] = gateway_options[:currency]
options[:stripe_account] = stripe_account_id
if customer = creditcard.gateway_customer_profile_id
options[:customer] = customer
end
if token_or_card_id = creditcard.gateway_payment_profile_id
# The Stripe ActiveMerchant gateway supports passing the token directly as the creditcard parameter
# The Stripe ActiveMerchant gateway supports passing the customer_id and credit_card id
# https://github.com/Shopify/active_merchant/issues/770
creditcard = token_or_card_id
end
creditcard = token_from_card_profile_ids(creditcard)
return money, creditcard, options
end
@@ -128,5 +121,27 @@ module Spree
source.cc_type = CARD_TYPE_MAPPING[source.cc_type] if CARD_TYPE_MAPPING.include?(source.cc_type)
source
end
def token_from_card_profile_ids(creditcard)
if token_or_card_id = creditcard.gateway_payment_profile_id
if customer = creditcard.gateway_customer_profile_id
# Assume the gateway_payment_profile_id is a Stripe card_id
# So generate a new token, using the customer_id and card_id
return tokenize_instance_customer_card(customer, token_or_card_id)
end
# Assume the gateway_payment_profile_id is a token generated by StripeJS
return token_or_card_id
end
end
def tokenize_instance_customer_card(customer, card)
begin
token = Stripe::Token.create({card: card, customer: customer}, { stripe_account: stripe_account_id})
token.id
rescue Stripe::InvalidRequestError
# Not really sure what to do here....
end
end
end
end

View File

@@ -80,5 +80,14 @@ module Spree
refund_amount ||= credit_allowed >= order.outstanding_balance.abs ? order.outstanding_balance.abs : credit_allowed.abs
refund_amount.to_f
end
def create_payment_profile
return unless source.is_a?(CreditCard) &&
(source.number || source.gateway_payment_profile_id) &&
source.gateway_customer_profile_id.nil?
payment_method.create_profile(self)
rescue ActiveMerchant::ConnectionError => e
gateway_error e
end
end
end

View File

@@ -0,0 +1,69 @@
require 'spec_helper'
describe Spree::Gateway::StripeConnect, type: :model do
let(:provider) do
double('provider').tap do |p|
p.stub(:purchase)
p.stub(:authorize)
p.stub(:capture)
end
end
before do
Stripe.api_key = "sk_test_123456"
subject.stub(:options_for_purchase_or_auth).and_return(['money','cc','opts'])
subject.stub(:provider).and_return provider
end
describe "#token_from_card_profile_ids" do
let(:creditcard) { double(:creditcard) }
context "when the credit card provided has a gateway_payment_profile_id" do
before do
allow(creditcard).to receive(:gateway_payment_profile_id) { "token_or_card_id123" }
allow(subject).to receive(:tokenize_instance_customer_card) { "tokenized" }
end
context "when the credit card provided has a gateway_customer_profile_id" do
before { allow(creditcard).to receive(:gateway_customer_profile_id) { "customer_id123" } }
it "requests a new token via tokenize_instance_customer_card" do
result = subject.send(:token_from_card_profile_ids, creditcard)
expect(result).to eq "tokenized"
end
end
context "when the credit card provided does not have a gateway_customer_profile_id" do
before { allow(creditcard).to receive(:gateway_customer_profile_id) { nil } }
it "returns the gateway_payment_profile_id (assumed to be a token already)" do
result = subject.send(:token_from_card_profile_ids, creditcard)
expect(result).to eq "token_or_card_id123"
end
end
end
context "when the credit card provided does not have a gateway_payment_profile_id" do
before { allow(creditcard).to receive(:gateway_payment_profile_id) { nil } }
it "returns nil....?" do
result = subject.send(:token_from_card_profile_ids, creditcard)
expect(result).to be nil
end
end
end
describe "#tokenize_instance_customer_card" do
let(:customer_id) { "customer123" }
let(:card_id) { "card123" }
let(:token_mock) { { id: "test_token123" } }
before do
stub_request(:post, "https://api.stripe.com/v1/tokens")
.with(body: { "card"=>"card123", "customer"=>"customer123"})
.to_return(body: JSON.generate(token_mock))
end
it "requests a new token for the customer and card from Stripe, and returns the id of the response" do
expect(subject.send(:tokenize_instance_customer_card, customer_id, card_id)).to eq token_mock[:id]
end
end
end