I looked around at other solutions but none of them seem to be use case for me. We're not using webhooks instead Cron jobs on the 1st of the month after payments are processed.
My service offers X hours per month.
When user subscriptions they get X hours.
When the user upgrades they immediately get X hours difference between the two, only on upgrade. This works great, the sum is correct.
My issue is that when the user downgrade stripe issues a refund on the next invoice, incorret.
Here is an example that is incorrect, apprentely the user has nothing to pay the next billing cycle which makes no sense; they should pay the downgraded cost.
The code looks like so:
If it's an upgrade:
subscription = await stripe.subscriptions.update(existingSub.id, {
cancel_at_period_end: false,
proration_behavior: "always_invoice",
default_tax_rates: [taxRate.id],
items: [
{
// We need to upgrade the existing item.
id: existingSub.items.data[0].id,
price: price.id,
quantity: 1,
},
],
});
If it's a new sub
await stripe.subscriptions.create({
customer: req.user.stripeCustomerId,
items: [
{
price: price.id,
},
],
billing_cycle_anchor: endOfMonth.unix(),
default_tax_rates: [taxRate.id],
metadata: {
productId,
paymentMethodId,
amount,
userUid: req.user.uid,
},
default_payment_method: paymentMethodId,
});
I'm not sure how to downgrade.
In your scenario above, the user has already paid for the subscription upfront. When you downgraded the subscription, the difference between the subscriptions was pro-rated and credited to the Customer credit balance [0] and applied to the next invoice.
If you don’t want the difference to be prorated when downgrading (maybe your company has a no refund policy), then you would want to apply proration_behavior='none' [1] when downgrading
You can read more about upgrading/downgrading subscriptions here : https://stripe.com/docs/billing/subscriptions/upgrade-downgrade
[0]https://stripe.com/docs/billing/customer/balance#examples
[1]https://stripe.com/docs/api/subscriptions/update#update_subscription-proration_behavior
Related
I have created subscription using stripe api for 1 month interval.
const subscription = await stripe.subscriptions.create(
{
customer: customer.id,
items: [
{
price: productPrice.id,
},
],
// payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent'],
application_fee_percent: fee,
},
{
stripeAccount: accountId,
}
);
Subscription created successfully based on product and price.but i can't wait for 1 month (next billing) for testing so i need to test now how will work for next payment.it will auto deduct from payment method? or customer will notify about next due and have to pay? there need more code for it?
Stripe has a feature called Test Clocks that allows to move subscriptions forward in time. So you could create a subscription with a test clock, then advance the clock by one month to see exactly what happens.
But to answer your question: if the customer (or the subscription) has a default payment method set, then yes Stripe will automatically attempt to make a payment at the end of every billing cycle.
I have a Stripe Checkout Session linked to a connected account. The connected account is subject to a 10% charge from my platform. It works well currently, however now I have added the ability for customers to use coupons in the checkout window, the application fee is being calculated from the total amount before the discount is applied.
For example, if I charge €32, the application fee is €3.20. If a discount reduces the charge to €10, the fee should be €1. But it is still charging €3.20.
I have a function which calculates the application fee amount, the problem is that this is done when the checkout session is created - this happens before the customer enters the discount.
I can't think of a way around this issue since the session is always created prior to the discount being applied. Any help/suggestions are appreciated!!
const calculateApplicationFeeAmount = (total) => total * site.stripeFee;
const session = await stripe.checkout.sessions.create(
{
payment_method_types: ["card"],
line_items: [
{
name: price.name,
amount: price.amount,
currency: site.currency,
quantity: 1,
},
],
payment_intent_data: {
application_fee_amount: calculateApplicationFeeAmount(price.amount),
description: price.name,
},
mode: "payment",
allow_promotion_codes: true,
success_url: `${config.baseUrl.url}/unlock/session/{CHECKOUT_SESSION_ID}`,
cancel_url: `${config.baseUrl.url}/unlock/${deviceID}`,
metadata: {
deviceID: deviceID,
},
},
{
stripeAccount: site.stripeAccount,
}
);
return session;
The best solution here would probably be to :
Use payment_intent_data.capture_method:manual when creating the checkout session
After receiving the checkout.session.completed event, update the application_fee_amount on the PaymentIntent
Capture the PaymentIntent
The limitation is that not all payment methods support manual capture.
Alternatively, you could also refund the application fee later : https://stripe.com/docs/api/fee_refunds/create
I'm attempting to create subscriptions through the Stripe API. I already create the products and items and now need to submit the subscription for the user, but I need to charge the customer for the full price now - no matter which day of the month it is - then charge at the beginning of each month - even if it starts tomorrow.
It looks like I could create a one-off item to charge for now then set up a subscription for the monthly billing cycle, but I'm wondering if I can do it all in one call with the subscription => create function. I do not want to prorate the first month and I cannot see a way to tell it to charge the full price now and set up recurring on the first of each month following. Is there a way to do this?
One way to go about the flow you're describing is to combine the backdate_start_date and billing_cycle_anchor properties. The idea is that when creating the subscription you would set the billing_cycle_anchor to the first of the next month, and you would set the backdate_start_date to the first of the current month. For example, say you wanted to sign up a user for a $10.00 subscription that starts today (February 5th), but you want to bill them for the full $10.00 right away (even though they missed the first 5 days). Then, you want to bill them $10.00 again on March 1st, and the first of every month thereafter. When creating the subscription you would set:
billing_cycle_anchor: 1614556800 (March 1st)
backdate_start_date: 1612137600 (February 1st)
Which would result in a $10.00 invoice today, and a $10.00 invoice again on the first of March, and subsequent $10.00 invoices on the first of every month going forward.
Here's what this would look like in Node:
(async () => {
const product = await stripe.products.create({ name: "t-shirt" });
const customer = await stripe.customers.create({
name: "Jenny Rosen",
email: "jenny.rosen#gmail.com",
payment_method: "pm_card_visa",
invoice_settings: {
default_payment_method: "pm_card_visa",
},
});
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [
{
quantity: 1,
price_data: {
unit_amount: 1000,
currency: "usd",
recurring: {
interval: "month",
},
product: product.id,
},
},
],
backdate_start_date: 1612137600,
billing_cycle_anchor: 1614556800,
expand: ["latest_invoice"],
});
console.log(subscription);
})();
I have created a subscription service using Stripe. I can subscribe a user to use recurring payments. This is the relevant code (node):
// Create the subscription
const subscription = await stripe.subscriptions.create({
customer: req.body.customerId,
items: [{ price: req.body.priceId }],
expand: ['latest_invoice.payment_intent'],
});
This works and uses the priceId as shown in the dashboard:
However, it falls over when I sell a product which isn't recurring. I get the error:
The price specified is set to `type=one_time` but this field only accepts prices with `type=recurring`
I understand the error, but I am not sure if I can set a subscription to not be recurring.
My app has 3 tiers:
once off
monthly
yearly
Ideally, I would like not to add a whole new section of code to handle what seems like a subset of what subscriptions do, but even if I do, the paymentIntent object seems to only take an amount rather than the API ID as shown in the picture. Is there any way to do this using the infrastructure I have already built?
You can't create a subscription with a non-recurring price, instead for one-off payments you'd use a PaymentIntent.
Prices are meant for use with subscriptions and the Checkout product, but you can still use the data in them for PaymentIntents. For instance:
// get the price
const price = await stripe.prices.retrieve(req.body.priceId);
// check if the price is recurring or not
if (price.recurring !== null) {
// Create the subscription
const subscription = await stripe.subscriptions.create({
customer: req.body.customerId,
items: [{ price: req.body.priceId }],
expand: ['latest_invoice.payment_intent'],
});
// do something with the subscription
} else {
const pi = await stripe.paymentIntents.create({
customer: req.body.customerId,
currency: 'usd',
amount: price.unit_amount,
});
// do something with the PaymentIntent
}
you can also attach one-time items via the subscription.create call by placing them in add_invoice_items.
see: https://stripe.com/docs/api/subscriptions/create?lang=node#create_subscription-add_invoice_items
I am using Stripe in NodeJS to create subscirptions. I want an invoice to be generated near the end of the billing period. For example, if the billing period is 1-30 Septmeber, I want the invoice to be generated on 30 September. The API docs says that billing_cycle_anchor should do this. But it has no effect when I use it, as an invoice is generated straight away and the user is charged. Code example below.
stripeSubscription = await stripe.subscriptions.create({
customer: id,
items: [{ plan: planId }],
billing_cycle_anchor: moment()
.add('30', 'days')
.unix();,
});
How can I get monthly subscription to generate and charge at the end of the billing period?
Can billing_cycle_anchor be set to the 1st of January, regardless of when the user starts the subscription?
e.g.
this.currentYear = (new Date()).getFullYear();
this.newYear = (new Date(this.currentYear + 1 + '/01/01 00:01')).getTime()/1000;
Then in the function call:
firebase.default
.firestore()
.collection('users')
.doc(user.uid)
.collection('checkout_sessions')
.add({
price: 'price_BLAHBLAH',
billing_cycle_anchor: this.newYear, //1672503000 01/01/2023 12:10 AM
...
})