#samiya_api
1 messages · Page 1 of 1 (latest)
👋 Welcome to your new thread!
⏲️ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
⏱️ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
🔗 This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1422492831758549052
📝 Have more to share? Add more details, code, screenshots, videos, etc. below.
Ok, yes you can do that. Basically you just need to create a seperate paymentIntent with capture_method=manual to hold the payment, and later decide to capture or release the funds after the trial.
How can I create that?
I do not need to change the trial period, which is currently 7 days. I want it to be like that only but just add preauthorization on day1
And also, after 7 days, I want to automatically capture the payment if the subscription is still active and release if the subscption has been cancelled
👋 Hi there, taking over for my colleague. Just a moment, and I'll take a look
Just to check: are you creating the Subscription using the Stripe API, or handling recurring payments yourself?
Uisng stripe API
If you need I can share the code of how I am creating setupIntent and subscription?
Sure
creating setup intent code:
function createIntent($stripe, $customer, $data , $priceId) {
$intent = $stripe->setupIntents->create(
[
'customer' => $customer->id,
'automatic_payment_methods' => ['enabled' => true],
'usage' => 'off_session',
'metadata' => [
'priceId' => $priceId,
'from' => 'paymentElement',
'passbackconversiontrackingid' => $data['rtid'],
'vertical' => $data['vertical'],
'subvertical' => $data['subvertical'],
'ABTest' => $data['ABTest'],
'experiment' => $data['experiment'],
'alternative' => $data['alternative'],
'url' => $data['url'],
'agreedToTerms' => $data['agreedToTerms'],
'termsText' => $data['termsText'],
'brand' => isset($data['brand']) ? $data['brand'] : null,
'services_selected' => isset($data['services_selected']) ? $data['services_selected'] : null,
'sky_account_number' => isset($data['sky_account_number']) ? $data['sky_account_number'] : null,
'termination_option' => isset($data['termination_option']) ? $data['termination_option'] : null,
'termination_date' => isset($data['termination_date']) ? $data['termination_date'] : null,
]
]
);
echo json_encode(array(
'type' => 'setup',
'clientSecret' => $intent->client_secret)
);
}
Thanks. There isn't any built-in functionality for this, so you'd have to create a separate PaymentIntent with capture_method=manual as my colleague mentioned.
Though I assume you'd want to release it both cases, whether the subscription is cancelled or continued, since the Stripe Subscription will automatically take payment after the trial ends
If I create a new file e.g preauthorize.php, but how will that be triggered on day 1 to add a hold on payments?
That depends on how your backend works; you'd have to have some sort of scheduler setup
Is there a reason why you create the pre-authorisation on day 1, rather than immediately when the subscription is created? e.g. you could rely on the Stripe webhooks relating to the subscription starting
If I want to add pre-authorisation immediately when the subscription is created, then what do I need to do?
You could create that PaymentIntent with manual capture in response to one of the webhook events, e.g. customer.subscription.created
Yes that sounds good.
Thank you very much
I have one more question once I create a paymentintent in response to the webhook, there will be a hold on the payment?
And also will the payment be deducted normally on the trail end or will that be a manual process
Since you're creating the PaymentIntent, that's up to you. By specifying capture_method=manual that would place a hold on the payment
Though note that there are limitations to this. For example, you can only place a hold for around 5–7 days: https://docs.stripe.com/payments/place-a-hold-on-a-payment-method
If you want to capture the payment at the end of the trial, or any other time, you would have to do that via the Capture a PaymentIntent API
But it's not clear to me why you would want to capture the amount at the end of the trial, since the Subscription will automatically charge the customer for the first billing cycle as soon as the trial period ends
Currently yes, the subscription automatically charges the customer on the trial end. What I am asking that once we specify capture_method= manual, Will the customers still be charged after the trial ends automatically?
The manual capture PaymentIntent you're intending to create is not related to the Subscription object. When the trial period ends, the Subscription will automatically charge the customer
To clarify: you want to have a free trial period, and not bill customers for this? Then after this X-day trial, the customer should be billed for the first time, and then every subsequent billing cycle, as usual?
Currently, our subscription flow offers a 7-day free trial.
- At signup: card is collected, no charge is made (0 € setupintent).
- At day 7: the first invoice is charged (e.g., £19.9).
Problem
- Many users request an immediate refund after being charged.
- Some users even dispute the transaction (chargeback).
- This creates operational overhead and increases risk.
Hypothesis
By introducing a preauthorization during the trial period (before the first invoice is due), we can:
- Reduce surprise at the end of the trial.
- Detect risky/invalid cards earlier.
- Potentially lower refund requests and chargebacks.
Proposed Flow
- Day 0 (signup): SetupIntent at 0 € (as today, no friction).
- Day 1: Create a PaymentIntent for the full subscription amount of the first rebill (e.g., £19.9) with capture_method=manual.
- This places a hold on the card.
- Customer may see this as a “pending transaction”.
- Day 7 (trial end):
- If subscription active → capture the existing PaymentIntent.
- If cancelled during trial → cancel the PaymentIntent (funds are released).
Thanks for the info. Often the simplest solution is to remind users just before the free trial ends, so they're not surprised by the charge, and can then cancel before the charge happens.
Adding a preauthorisation to a customer's card can often cause more support queries, since users might be surprised that a hold is on their card for a free trial
But in any case, if you want to implement the flow above, you could create a Payment Intent with manual capture on day 0 (or whenever), but you should then release it at the end and never charge it. The Stripe Subscription will automatically charge them on day 7
Also note the restrictions on holds — you may not be able to hold funds for 7 days anyway, depending on the card type.
See the Merchant-initiated Transaction column here: https://docs.stripe.com/payments/place-a-hold-on-a-payment-method#card-not-present-transactions
You can also listen for the customer.subscription.trial_will_end webhook, and trigger an event (e.g. email the customer) a few days before the trial ends: https://docs.stripe.com/api/events/types#event_types-customer.subscription.trial_will_end
How do we release it at the end?
You would cancel the PaymentIntent: https://docs.stripe.com/api/payment_intents/cancel
Can you please clarify if I am correct?
So when we create a paymentIntent with manual capture (suppose on subscription creation), it will hold the funds but the subscptions flow will work automatically?
Yes. This PaymentIntent you'd be creating is completely separate from the Subscription. The Subscription will continue to work as usual: after the trial period ends, it will automatically charge the user
Since both work independently so will the funds hold from the customers account through paymentIntent will not be released once the subscrptions charges the customer?
That's correct
when we create the payment intent, can we mention there after what timeperiod we want to release this fund since subscrption will anyway charge the customer
Or can we create a new webhook to release the fund, like one webhook to create intent with manual capture on day1 and another webhook to release funds when the subscription is active on day 7. Not capture funds since it will be handled through subscription?
hi there, taking over from my colleague and getting caught up on this thread
the first point you should note is the validity windows for manual capture: https://docs.stripe.com/payments/place-a-hold-on-a-payment-method#authorization-validity-windows
any charges that are not captured manually within these timeframes will be automatically released
but with that in mind, it sounds like you want to release the hold when the subscription payment is successfully processed, when the trial ends
so effectively you want to know how to determine when the trial has ended, is that correct?
for that you can use the customer.subscription.updated event, and check for status: 'active' on the subscription object
https://docs.stripe.com/billing/subscriptions/webhooks#state-changes
I want to hold payments on day1 and then if the subscription is active after trial period, then capture the payment from the existing paymentIntent and if the subscription is cancelled during any time in these 7 days of trial, then release the payment
Hi there, I'm back again! 🙂
As Glo mentioned, you can check the customer.subscription.updated webhook, to get updates. For example, whether the subscription has been cancelled
And one more question.
Payment released means it will be deducted from the users account?
No, you're no longer "holding" onto their funds; the pre-authorisation is being released and returned to the customer
That happens when you cancel the PaymentIntent, or the hold expires after 5–7 days
To charge the pre-authorised amount to the customer's card, you would have to "capture" the funds: https://docs.stripe.com/api/payment_intents/capture
So if I create a webhook with three events: subscription.created, subscrption.active and subscription.cancelled. On first event paymentIntent with manual capture
2nd to release the hold if subscrption is cancelled
3rd to release when the subscription turns active and the amount of subsciption is charged
Yes, that's roughly correct:
- You receive
customer.subscription.createdwhen the subscription is created - You receive
customer.subscription.updatedwhen any changes happen, so you should pay attention to the various fields, especiallystatus
There is no specific event for a subscription being cancelled; it's also a.updatedevent.
When the subscription charges the customer after the trial ends. What would happen by default, pre-authorisation is being released and returned to the customer or it will still remain on hold
Since your PaymentIntent with pre-authorisation is completely separate from the Subscription, nothing will happen when the trial ends.
However, as mentioned before, it's likely that the pre-auth will expire before the seven-day trial period ends, since a hold is only valid for a limited time: https://docs.stripe.com/payments/place-a-hold-on-a-payment-method#authorization-validity-windows
Isnt it possible to have pre-authorization directly on the subscrption so that if the subscption is cancelled during the trial, authorization will be released automatically and if it is still active till trial ends then funds are released and the customer be charged to the amount mentioned in the subsciption
This isn't something that's supported by the Subscriptions API. You can capture a customer's payment details when the subscription is created, and this may perform validation on the card, and can include a 3DS check — but you can't automatically place a hold on a certain amount of funds.
As the documentation mentions, placing a hold is intended for only a short period of time
And how do we cancel the hold like if i use the webhook.event to check the status of subscription and if the subscption status is cancelled, the hold of funds should be released. Is there a specific function to release the holds?
Yeah, for that you would cancel the PaymentIntent: https://docs.stripe.com/api/payment_intents/cancel
if ($previous && isset($previous->status)) {
$prevStatus = $previous->status;
$currentStatus = $subscription->status;
if ($prevStatus !== $currentStatus) {
if ($currentStatus === 'active') {
// Trial ended and subscription activated
try {
$stripe->paymentIntents->capture($paymentIntentId);
} catch (Exception $e) {
error_log("Failed to capture PaymentIntent: " . $e->getMessage());
}
} elseif ($currentStatus === 'canceled' || $currentStatus === 'incomplete_expired') {
// Subscription cancelled or expired during trial - release hold
try {
$stripe->paymentIntents->cancel($paymentIntentId);
} catch (Exception $e) {
error_log("Failed to cancel PaymentIntent: " . $e->getMessage());
}
}
}
}
break;
Is this correct to cancel payment intent?
From what I understood, your main concern is about customers being surprised when their trial ends and they are charged. That leads to customer support effort, refunds, or even chargebacks.
To prevent those surprise charges in the first place, here are a couple of possibilities:
- Set the Subscription
collection_method=send_invoice(API doc), which would prevent the customer from being charged automatically when the trial ends. They would then have to choose to pay the invoice, or you can trigger it via the Pay an Invoice API - Alternatively, you could be to automatically send customers a reminder a while before the trial ends. This could be triggered by listening to the
customer.subscription.trial_will_endevent
Thank you for the suggestions but I want to go test the pre authorization method one.
I have one more question🙃
On Day 7 invoice should use the existing PaymentIntent instead of creating a new one
That's not possible. The PaymentIntent you'd be creating will remain separate from the Subscription and they can't be combined
Since the hold on Visa cards would likely expire before the end of the seven day trial, this wouldn't be possible anyway
So far what I understood is that. We cant directly hold funds in case of setupIntents (trial based payments). Instead we can create a paymentintent using webhooks to release and hold. But the paymentIntent and the subscprition will remain separate. We will just be updating the paymentIntent based on subscription status. Direct pre-authorisation on subscription is not posible. Hence the paymentIntenr we create will remain seperate from the subscription and cant be combined in any way
That's correct based on what we've been discussing 👍
Thank you very much for the help