TLDR; I want to allow customers to place orders using the previously used/saved card of their choice in my app. This requires the ability to specify to Stripe "which" card (previously associated to a customer) to charge. This should be possible in theory according to the docs, but I'm having no luck in practice.
Alright... talk is cheap, here are the codes:
// pseudo code of a customer placing an order for the first time
var stripe = require("stripe")(".....");
(async function(userId, cardToken) {
// Create a Customer AND save the payment method
const customer = await stripe.customers.create({
source: cardToken.id, // e.g. 'tok_mastercard' (retrieved from stripe.js)
email: '[email protected]',
});
// Charge the Customer instead of the card:
const charge = await stripe.charges.create({
amount: 1000,
currency: 'usd',
customer: customer.id
});
// save customer id to DB
await setCustomerIdToDatabase(userId, customer.id);
// save Card ID (not the card token ID) to DB
await addCustomerCardToDatabase(userId, cardToken.card.id); // <= note cardToken".card".id e.g. card_kldlkns...
})(userId, cardToken /* <= provided by app*/);
So far so good. Stripe saved the card from the specified token as the default payment method for the newly created customer then charges it successfully. But then my pain begins...
// pseudo code of a customer placing subsequent orders (WITH NEW CARDS)
var stripe = require("stripe")(".....");
(async function(userId, cardToken) {
const customerId = await getCustomerIdFromDatabase(userId);
// Create a Customer AND save the payment method
await stripe.customers.createSource(
customerId,
{
source: cardToken.id, // e.g. 'tok_mastercard' (retrieved from stripe.js)
}
);
// Attempt to charge the newly added card instead the Customer:
const charge = await stripe.charges.create({
amount: 1000,
currency: 'usd',
customer: customerId,
source: cardToken.card.id // <= note cardToken".card".id e.g. card_kldlkns...
});
/////////ERROR TRHOWN: No such token: card_kldlkns...
///////// what? I just saved it with .customers.createSource and you said it was OK???
/// unreachable code
// save Card ID (not the card token ID) to DB
await addCustomerCardToDatabase(userId, cardToken.card.id); // <= note cardToken".card".id e.g. card_kldlkns...
})(userId, cardToken /* <= provided by app*/);
Fails miserably... and so does this
// pseudo code of a customer placing subsequent orders (WITH SAVED CARDS)
var stripe = require("stripe")(".....");
(async function(userId, savedCardId) {
const customerId = await getCustomerIdFromDatabase(userId);
// Attempt to charge the newly added card instead the Customer:
const charge = await stripe.charges.create({
amount: 1000,
currency: 'usd',
customer: customerId,
source: savedCardId // e.g card_kldlkns...
});
/////////ERROR TRHOWN: No such token: card_kldlkns...
///////// what??????
})(userId, savedCardId /* <= provided by app*/);
What am I not getting here? The docs clearly says Stripe wants the card.id and the customer.id back if I want to charge a specific card.
Any help is appreciated
stripe.charges.create
with both thecustomer
and thesource
equal to a card id should charge a specific card on a given customer. If you're gettingno such token
errors, try listing the sources on a given customer first to ensure a card with the specific idcard_dddyyyxxx
is really there, stripe.com/docs/api/cards/list - duckstripe.customers.createSource
call, then charged immediately after the promise resolved successfully (no error thrown). In this case, checking whether the card is really there before charging help wouldn't help much because the situation is not remediable. All I could do is throw an error to the client myself instead of let stripe throw it. Maybe that's not the way to do this at all, hence this post - rookienumberonestripe.charges.create
- duck