Stripe immediate payment on each quantity update - stripe-payments

We are using Stripe as the payment gateway, and we have a yearly plan i.e .billing cycle of the plan is 1 year.
Within the billing cycle, the user can update opt for more seats which will result in increasing the quantity for the subscribed plan.
Subscription subscription = Subscription.retrieve(paymentDetails.getSubscriptionId());
int currentQuentity = subscription.getQuantity();
Map<String, Object> updateParams = new HashMap<String, Object>();
updateParams.put("quantity", (currentQuentity + changeInQuantity));
subscription.update(updateParams);
So for any update stripe refunds(if quantity reduces) and charges(if quantity increases) at the end of billing cycle prorated.
In our business logic, we need immediate payment (charges or refunds) on each quantity update rather then on end of billing cycle. Is there any way in the stripe to achieve so.

I spent a lot of time trying to figure this one out, I hope I can save someone else some time. To take payment for a change of quantity or subscription plan, you need to do the following:
Update subscription with the new changes.
Create an invoice.
The thing that confused me by this is that Stripe magically knows to only invoice for the updated subscription items, and not for upcoming billing cycle items.
Retrieve the newly created invoice
Finalise the invoice
Take payment for the invoice This assumes that your customer has a payment method stored.
Only when all of the steps have been completed, you've successfully charged for the subscription change (and charged for the change only). You can do it all of it in one go. The customer should get an invoice email from Stripe at the end of it.
What makes matters complicated for me, is that reading from the documentation, I got the impression that Stripe will automatically do all of this for me as long as the subscription is set to "billing": "charge_automatically". This is not the case, and in Stripe's defence, they mention it at the bottom of the documentation page related to upgrading and downgrading plans:
If you want the customer to immediately pay the price difference when switching to a more expensive plan on the same billing cycle, you need to generate an invoice after making the switch.

To charge immediately after subscription update, you need to create an invoice just after the subscription update. This will result in an immediate charge
To create invoice you can simply call:
Stripe.apiKey = "sk_test_BQokikJOvBiI2HlWgH4UWQfQ2";
Map<String, Object> invoiceParams = new HashMap<String, Object>();
invoiceParams.put("customer", "cus_D2XUIsncG7YUX");
Invoice.create(invoiceParams);
Ref (https://stripe.com/docs/api#update_subscription):

The accepted answer is the solution if you want to maintain the same billing dates for the subscription.
A simpler solution if you need to push the billing cycle forward to that of the date of the change is to simply set the 'billing_cycle_anchor' to 'now' when updating the subscription. Stripe will immediately charge the user and apply and prorations.
example in python
stripe.Subscription.modify(
subscription_id,
billing_cycle_anchor = 'now',
......
)

You can also set proration_behavior to always_invoice and Stripe will apply both a proration and immediately invoice your customer (source).
Here's an example in curl:
curl https://api.stripe.com/v1/subscriptions/sub_HE... \
-u "sk_test_MI...:" \
-d "items[0][id]=si_Il3Z..." \
-d "items[0][quantity]"=2 \
-d "proration_behavior=always_invoice"

Related

How to get default payment method from Stripe invoice?

I am listening to Stripe's invoice.payment_failed webhook with my web app and I would like to get the default_payment_method from each invoice but for some reason it always returns nothing but an empty array!
When I query for a Stripe invoice on the command line and expand on the default_payment_method like this...
Stripe::Invoice.retrieve('in_3K6dIY2KgYRkshw2LAzya63P', :expand => "default_payment_method")
...I also get empty arrays. This surprises me because all my Stripe customers do have a default payment method associated with them.
What am I missing here?
Thanks for any help.
There are three independent places a default payment method can be set. From more specific to less specific they go :
invoice.default_payment_method (which you are looking at)
subscription.default_payment_method
customer.invoice_settings.default_payment_method
Stripe charges the most specific one if it's set. When reading from the API, those values don't inherit from the level above, they can all be set individually, if they are not set explicitly then they are null. So that's why you see it as null on the Invoice level.
Instead you likely want to look at the Subscription object or the Customer object(and can leverage the expand feature for that), depending on how you built your integration and which one it sets.
Overall though, you probably actually want the PaymentMethod used in the invoice payment though? That would be from the last_payment_error.
inv = Stripe::Invoice.retrieve({
id: 'in_1K8iiKJoUivz182DMzSkuBgp',
expand: ["customer.invoice_settings.default_payment_method",
"subscription.default_payment_method",
"payment_intent"]
}
)
print("invoice : #{inv.default_payment_method} \n")
print("subscription : #{inv.subscription.default_payment_method} \n")
print("customer : #{inv.customer.invoice_settings.default_payment_method} \n")
print("failed charge : #{inv.payment_intent.last_payment_error.payment_method} \n")

Stripe latest subscription Invoice

I want to store every invoice that a customer pays on a subscription. I wrote a database query to be executed when "invoice.payment_succeeded" event is fired. But what I did by mistake is that I took the latest invoice and stored its status in the Database:
$subscription_id = $response->data->object->subscription;
$subscription_obj = \Stripe\Subscription::retrieve($subscription_id);
$invoice_obj = \Stripe\Invoice::retrieve($subscription_obj->latest_invoice);
$latest_invoice_status = $invoice_obj->status;
Instead of doing :
$invoice_obj = \Stripe\Invoice::retrieve($response->data->object->id);
Is there a problem in what I did or the latets invoice is just identical to the invoice captured in the event ?
In my opinion, this may not give some issue, unless you are allowing users some grace period post invoice not paid. And if this duration is long enough to generate a new invoice, you can get some issue tracking here.
This can be resolved if you keep the track of invoice and payments so late in any case if required you can analyse payments for the invoice.

stripe first time the user pays for a subscription

If this is the first time this specific customer pays for this specific subscription.
I must set the cancel_at field of the subscription based on the chosen plan ID. (I don't want to set it upon the creation of the subscription). To tackle this first time , I have captured the invoice.payment_succeeded event and I did the following:
$invoices = \Stripe\Invoice::all([
"limit" => 3, //no need to get all of the invoices just checking if their number is = 1.
"status" => 'paid',
"customer" => $customer_id,
"subscription" => $subscription_id,
"expand" => ["data.charge"],
]);
if ( count($invoices->data) == 1 ) {
//First time this user pays for this specific subscription;
Can You just tell me if it is right or if I missed anything as I am new to php as well as stripe. should I be doing count($invoices) instead of what i did ?
Your code looks fine, but the only way to tell if it'll work or not is for you to run it and see if it does what you expect it to do. You can use your test mode API keys and the Stripe CLI to test the flow:
stripe trigger customer.subscription.created
This will create a test customer, a plan and a subscription. The latter will immediately create and pay an invoice, so you should get a invoice.payment_succeeded webhook event to test with.

Get Default Payment Source (default card) for Stripe Customer?

I created a POC with a customer/credit card in Stripe and I logged into my dashboard within Stripe and was able to see this customer has a default source (the test credit card I added) associated correctly. It shows this card is the default source.
When I run this .Net code:
var customerService = new CustomerService();
var stripeCustomer = await customerService.GetAsync(customerId);
To get that customer, it returns everything correctly except his source. All of the fields I had hoped I can find it from are empty! I want to know his default payment source so I can show it on the front end with a little icon to indicate it's default.
DefaultSource, DefaultSourceId, and Sources properties are all blank/null.
Is there a way to have Stripe return it, or do I need to do something else? I tried the 'expand' property for the GetAsync method but that threw an error saying the above properties are not expandable (i.e. I can't ask Stripe to expand/return Source).
Any ideas what I can do?
FYI I also tried this:
var paymentMethodService = new PaymentMethodService();
var cards = await paymentMethodService.ListAsync(new PaymentMethodListOptions { Customer = customerId, Type = "card"});
and there doesn't seem to be a property anywhere that says the card is default (although it does correctly return all cards). I believe Stripe documentation states the Customer is the holder of the default source, not the card object. What gives?
Thanks in advance!
It looks like you're using Payment Methods, since your payment method list call has the results you expect, which means the customer likely doesn't have any sources. You can try that again with the properly pluralized expand[]=sources if you do know your Customer has Sources attached.
For Payment Methods, there is no general default for the Customer. For one-time Payment Intents, you must always specify the payment_method from among those attached to the Customer for future payments.
For paying invoices (related to recurring subscriptions, eg), you can set the invoice_settings.default_payment_method for Customer. This only applies to invoices.

Why is stripe charging an account before invoice created returns

On signing up a user to a subscription, I would like to charge a different rate if the user has credit in my system. However, when the user signs up for the subscription, Stripe is charging them right away instead of waiting for me to mutate the invoice object on the invoice created webhook.
My understanding based on the docs is that charging the user will wait until after invoice create returns with a 200. However, my invoice created webhook is returning 500's so I know this isn't true.
My current code looks like this:
stripe.Subscription.create(
customer=user.stripe_customer_id,
plan=subscription_plan.stripe_product_id,
trial_period_days=trial_period,
idempotency_key=key)
My webhook looks like:
def invoice_created(request, *args, **kwargs):
user = request.user
invoice = request.data['data']['object']
stripe_customer = stripe.Customer.retrieve(user.stripe_customer_id)
if request.user.credit:
stripe_customer.add_invoice_item(
amount=-user.credit,
currency='usd',
description='Applied ${:.2f} of credit for subscription.'.format(user.credit),
invoice=invoice['id'],
)
return Response(status=200)
When I try to update the invoice, it says the invoice can't be modified. The error I'm getting is:
stripe.error.InvalidRequestError: Request "": Invalid invoice: This invoice is no longer editable
What am I supposed to do here?
My understanding based on the docs is that charging the user will wait until after invoice create returns with a 200.
This is not true for the first Invoice of a Subscription, which is always charged immediately.
If you want to add items to that first one, you'll want to create the Invoice Items on the Customer first, before you create the Subscription.

Resources