#faizel_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/1311964356883251282
đ Have more to share? Add more details, code, screenshots, videos, etc. below.
hi
@silver lily
hi
this is my card submit function
async submit() {
console.log('From Submit',this.clientSecret);
if (!this.isChecked) {
this.validateTerms = true;
return;
}
this.validateTerms = false;
this.isLoading = true;
window.addEventListener('beforeunload', this.handleBeforeUnload);
window.addEventListener('popstate', this.handlePopState);
const { setupIntent, error } = await this.stripe.confirmCardSetup(
this.clientSecret,
{
payment_method: {
card: this.cardNumberElement,
},
}
);
if (!error) {
await this.createSubscription(setupIntent.payment_method);
} else {
this.message = error.message;
this.isLoading = false;
}
},
this is my create subscription frontend function afer card submit success
async createSubscription(token) {
console.log('Create Subscription',this.clientSecret);
this.message='';
await this.$inertia.post(route('subscriptions.multiplan.store'),{
plans : this.cart.length ? this.cart : [this.plan],
token,
accept_terms:this.isChecked,
tax_id:this.taxInfo().tax_id,
billing_address:this.taxInfo().billing_address
},
{
onSuccess: () => {
this.isLoading = false;
// this.isGeneratingInvoice = true;
if(this.$page.url.includes('isBack=1')){
this.startCheckingTransaction();
}
},
onError:(e) => {
if(e.requiredAction) {
this.handleRequiresAction(e);
}else {
this.message = e.message;
this.isLoading = false;
}
},
onFinish:()=>{
if(!this.isLoading){
this.isGeneratingInvoice = true;
}
}
}
);
},
this is my subscription creation and card store function from backend
public function multiPlanStore()
{
try {
$validatedData = request()->validate([
'plans' => ['required'],
'token' => ['required'],
'accept_terms' => ['required'],
'tax_id' => ['nullable'],
'billing_address' => ['nullable'],
]);
$user = auth()->user();
$user->createOrGetStripeCustomer();
$paymentMethodId = $validatedData['token'];
$user->updateDefaultPaymentMethod($paymentMethodId);
$planCollection = collect($validatedData['plans']);
foreach ($planCollection as $plan) {
try {
$subscription = auth()->user()->newSubscription(
$plan['slug'] . '_' . $plan['price']['billing_period'],
$plan['price']['stripe_price_id']
)
->create(request('token'));
$subscription->stripe_product = $plan['stripe_product_id'];
} catch (IncompletePayment $exception) {
return back()->withErrors([
'requiredAction' => true,
'clientSecret' => $exception->payment->client_secret,
'message' => $exception->getMessage(),
]);
}
}
$user->update([
'tax_id' => $validatedData['tax_id'],
'billing_address' => $validatedData['billing_address'],
]);
return to_route('auth.payment', ['isBack' => true]);
} catch (CardException $e) {
return to_route('settings.payment-methods')->with(['error' => $e->getMessage()]);
} catch (Exception $e) {
return back()->with(['error' => $e->getMessage()]);
}
}
this is my handleRequiredAction from frontend if the subscription hit to incomepletepayment exception
async handleRequiresAction(e) {
emitter.emit('open-3d-dialog', {
text: 'For your security, your card issuer or bank is requesting a second OTP verification. Please proceed with this additional step, which helps ensure your transaction is safe and secure. Thank you for your understanding.',
confirmLabel: 'Confirm',
cancelLabel: 'Cancel',
confirmBtnClass:'!bg-primary',
onConfirm:async () => {
emitter.emit('close-3d-dialog');
const {error} = await this.stripe.confirmCardPayment(e.clientSecret);
if (error) {
this.message = error.message;
this.isLoading = false;
} else {
this.startCheckingTransaction();
}
},
onCancel:()=>{
this.isGeneratingInvoice=false;
this.successCheckingTransaction=false;
this.isLoading=false;
this.message = e.message;
}
});
},
hello! can you describe your payment flow here at a high level? For example, whe your customer lands on your page, you collect the payment method from them to create a payment. At what point are you expecting 3DS to not be shown?
ok
when customer land to card information page
- we collect the payment infos and create setup intent and get 3d secure modal which is ok
- but when we create a subscription from backend (it fails even after the 3d secure modal is asked and confirmed) so as you see the code handled i provided is also handle for incomplete payment and the 3d secure modal is happen again on frontend when confirmpayment (which is in handleRequiredAction) but as i know it shouldn't be right ? because we already confirmed 3d secure on setup intent
our live users is getting issue with always getting 3d secure modal twice always.
i'm a developer and i have no idea to find solution. that's why i ask support here.
can you share why you want to create the SetupIntent first, then create a subscription? If the customer is already on session, and creating / paying for a subscription, you should use the Subscription's SetupIntent and/or PaymentIntent to collect the payment method instead so as not to have a double authentication.
This is likely the flow that you're looking for : https://docs.stripe.com/payments/accept-a-payment-deferred?platform=web&type=subscription
u mean i don't need to create setup intent ?
as my knowledge, setup intent is required for me because i implemented like this on frontend to confirm cardsetup.
const { setupIntent, error } = await this.stripe.confirmCardSetup(
this.clientSecret,
{
payment_method: {
card: this.cardNumberElement,
},
}
);
Please take a moment to review the guide I just shared. It will help you understand how everything works.
so
my current implementation which is getting setup intent first and confirmcardsetup is making double 3d secure .
so you suggest me to do with new solution which is collection payment details before creating an setup intent
am i right ?
yep, but try it out first and see if it fits your requirements
alright
let me try
is this thread automatically close ?
i need some time to try it out
can i come back here when i know update
you can start a new thread i.e. ask a new question if you come back later and the thread is closed
my colleague who is on shift when you ask a new question should be able to help you