Stripe-dotnet: Creating Subscription Paying With Specific Card

Created on 23 May 2017  ·  10Comments  ·  Source: stripe/stripe-dotnet

Ok, I've exhausted myself trying to get through your documentation as well as Stripe's, and I just can't seem to sort out the following:

It appears that when I use the StripeSubscriptionService to create a subscription, that the subscription gets created, invoiced, and paid with the default credit card for the customer. Never mind that that seems to be a bit much, but I'd like to be able to supply a credit card token so that particular card is used to pay.

I've tried everything I can think of to make this happen, so I must be missing something simple. Can you help?

Thank you Jayme, and can I donate to your cause somewhere? This utility is saving me a LOT of time and energy... much appreciated.


PS: I would love to see documentation to have more granular control over subscriptions/invoices/payments... Why is it that you don't create a subscription; then create a line item for that subscription; then create an invoice; then add that line to the invoice; then pay the invoice with a credit card? Anyway, thanks in advance for your help.

Most helpful comment

I found a workaround: to make the selected card the default before creating the subscription, but this still seems "wrong" to me... I'd still love to hear from you.

All 10 comments

I found a workaround: to make the selected card the default before creating the subscription, but this still seems "wrong" to me... I'd still love to hear from you.

@zorpiedoman yes, this is the only way that works as of now. I tried doing it as well but it won't work unless you set the selected card as the default.

Also, have you faced an issue where you get an error saying "no such token : " ? It doesn't happen all the time but sometimes it does

I think I faced this issue since I updated from 8.4 to 9.0, I didn't have any such error before the update.

I'm just getting started on this so I have still only done a small amount of testing. What call are you making when you get that error? Also, if you don't mind, what are the most common processing errors you have to deal with.. that would be good to know now so I can be ready for them.. THANKS!

I haven't had much errors but this is one I'd love it was to be addressed.
The error I mentioned above is when trying to update a subscription's plan supplying it with a card id as Source

At the moment, Stripe always charges the default source on a customer for a subscription. This means that if you have a customer with two subscriptions and 3 cards, both subscriptions will create invoices on each new billing cycle and those invoices will always be paid by the default source and completely ignore the other available cards. This is a known limitation of the product that we'd love to fix in the future though.

If a customer wants to start paying with a new card, you need to put this card as the default source on it first. There are multiple approaches here:

1. The card is already saved on the customer

If the card already exists on the customer, you need to call the Update Customer API and set the existing card id card_XXXXX as the default source. The code looks like this:

var myCustomer = new StripeCustomerUpdateOptions();
myCustomer.DefaultSource = "card_XXXXXX";
var customerService = new StripeCustomerService();
StripeCustomer stripeCustomer = customerService.Update("cus_AAAAA", myCustomer);

2. The card is not saved on the customer and you want to replace the default

In that case, you would simply update the customer and put the new card token tok_XXXX as the source. This will automatically delete the current default source and then put the new card as the default. The code looks like this:

var myCustomer = new StripeCustomerUpdateOptions();
myCustomer.SourceToken = "tok_XXXXXX";
var customerService = new StripeCustomerService();
StripeCustomer stripeCustomer = customerService.Update("cus_AAAAA", myCustomer);

3. The card is not saved and you want to keep the current default card

In that case, you first need to use the Create Card API to add the card to the customer. Then you put the new card as the default as explained above. The code would look like this:

// Add the card to the customer
var myCard = new StripeCardCreateOptions();
myCard.SourceToken = "tok_XXXXXX";
var cardService = new StripeCardService();
StripeCard stripeCard = cardService.Create("cus_AAAAA", myCard);

// Put the new card as the default
var myCustomer = new StripeCustomerUpdateOptions();
myCustomer.DefaultSource = stripeCard.Id;
var customerService = new StripeCustomerService();
StripeCustomer stripeCustomer = customerService.Update("cus_AAAAA", myCustomer);

4. Put the new card as the default, delete the old one, while updating the subscription

There's an extra solution similar to the second one that can be done when updating a subscription. The Update Subscription API on Stripe's end will also take a source parameter. This allows you to update (or create) a subscription and at the same time replace the default source on the associated customer. This parameter expects a token id tok_XXXX. The code would look like this:

var subscriptionService = new StripeSubscriptionService();
subscriptionService.Source = "tok_XXXXX";
StripeSubscription stripeSubscription = subscriptionService.Update(*subscriptionId*);

@remi-stripe How would I go around in the following case :

  • Customers have multiple cards
  • When updating their subscription or creating a new one, present them the list of cards(StripeCard) to choose from
    *Perform subscription update with the selected card

What I'm doing right now is this :

  • Update the customer with the selected card to make it default
  • in StripeSubscriptionUpdateOptions/CreateOptions, Source = SelectedCard.Id

This used to work in the past with no errors but I'm getting the no such token error. Am I missing something or doing something wrong?

On further study, this seems to be happening with some cards only, and occasionally. I had three different cards, I tried with all three but it only failed with "no such token" for one specific card.

@n1schal This is likely not an issue with the library and more a problem with your code or the identifiers you pass as a parameter. I'd recommend talking to our support team directly instead so that they can look at your logs and help you debug this. You can reach them here.

The No such token: XXXX error happens when your code tries to pass an id that our system doesn't expect. If you put a specific card as the default source, the API except the new card id card_XXXXX and it must exist on the customer. If you want to pass Source on Subscription update or creation, we do not expect a card id, instead we expect a brand new token id tok_XXXXX.

Based on what you're trying to do, you should never set the Source parameter on Subscription update or creation as that card is already saved on the customer.

@remi-stripe The card is registered to the customer, otherwise how would it return the card with the specific id that I'm getting for the "No such token : card_xxxxx" error? And if it works for other cards and it fails for some, how could it be that there's a problem with my code?

I'll definitely try and contact the support team. But anyways, what's the correct way if we wanted to let subscribers choose a card for their subscription update or creation? Or should I just skip letting customers choose a card?

@n1schal When you pass source we only support a card token tok_XXXX. This means you tokenized a card client-side and are adding that card as a new card on the customer and put it as the default while deleting the old default source.

This will never work if you pass a card id card_XXXX from a card already saved on the customer. It's only for new cards. If you have a card already saved you need to first update the customer and put that card as the default and then create the subscription without passing source.

closing - thanks @remi-stripe!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Jagadeesh-Govindaraj picture Jagadeesh-Govindaraj  ·  11Comments

UweKeim picture UweKeim  ·  10Comments

MatteoMichelotti picture MatteoMichelotti  ·  14Comments

Seichis picture Seichis  ·  4Comments

metanoic picture metanoic  ·  4Comments