#jmschp_best-practices
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/1382323242848620606
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
hi there!
so to make it work I add to set
paymentMethodTypes: ["card"]in the StripeJS element.
what happens if you don't set this?
If I don't set paymentMethodTypes: ["card"], when confirming the payment I get
{
"error": {
"message": "Payment details were collected through Stripe Elements using automatic payment methods and cannot be confirmed through the API configured with payment_method_types.",
"payment_intent": {
"id": "pi_2RYmGm2ALfsUTznj0RbErzna",
"object": "payment_intent",
"amount": 9900,
"amount_details": {
"tip": {}
},
"automatic_payment_methods": null,
"canceled_at": null,
"cancellation_reason": null,
"capture_method": "automatic",
"client_secret": "pi_2R**********************_******_*********************pxvm",
"confirmation_method": "automatic",
"created": 1749639156,
"currency": "usd",
"description": "Payment for Invoice",
"last_payment_error": null,
"livemode": false,
"next_action": null,
"payment_method": null,
"payment_method_configuration_details": null,
"payment_method_types": [
"card"
],
"processing": null,
"receipt_email": null,
"setup_future_usage": "off_session",
"shipping": null,
"source": null,
"status": "requires_payment_method"
},
"request_log_url": "https://dashboard.stripe.com/test/logs/req_AS1yBFUes9wH4v?t=1749639158",
"type": "invalid_request_error"
}
}
give me a few minutes to try to reproduce this.
๐ taking over for my colleague. Let me catch up.
you need to use mode: 'subscription' on the PaymentElement when you're handling invoices
Even if it is not for a subscription?
yes
In the cuurnt flow I am working on, the customer is able to select a subscription or a one time time payment.
I am updating the element mode and amount accordingly.
So then I should just hardcode subscription
and only update the amount.
if in both cases you're using invoices then yes
yes, I am using invoices
all our payment are doen via Invoices
thanks
I am going to try this
By the way, not the most intuitive approach ๐
and by doing so, you wouldn't need to specify the PMTs, you can rely on the PaymentElement to show the PMTs that are suitable
By the way, not the most intuitive approach ๐
I agree, we've been talking about this internally for quite some time now, we either need to rename mode'subscription'to mode'billing'or create a new mode'invoice'or something
but in all cases this would mean a breaking change and we would have to wait until the next stripe.js major version
I tried, and it did not work
Got the same error
are you still specifying the PMTs manually?
No
can you please share how you initialize the PaymentElement and the request ID that created the invoice?
Request ID for creating th Invoice
req_p8kJzgciCXqNMP
async stripeSetup() {
try {
this.stripeStartProcessing();
let amount = 0;
let mode = "subscription";
if (this.selected.id === "sale") {
amount = this.selected.cost * 100;
mode = "payment";
} else {
amount = this.selected.price_cents;
mode = "subscription";
}
if (this.stripeElements) {
this.stripeElements.update({ amount: amount, mode: mode });
} else {
this.stripeElements = this.stripe.elements({
amount: amount,
currency: "usd",
customerSessionClientSecret: await this.currentUser.getStripeCustomerSession(),
mode: "subscription",
// paymentMethodTypes: ["card"],
setupFutureUsage: "off_session",
});
}
if (!this.stripePaymentElement) {
this.stripeCreatePaymentElement();
}
} catch (e) {
this.handleError(e);
} finally {
this.stripeFinishProcessing();
}
},
stripeCreatePaymentElement() {
try {
this.stripePaymentElement = this.stripeElements.create("payment", {
layout: "accordion",
});
this.stripePaymentElement.on("ready", (_event) => {
this.stripeFinishProcessing();
});
this.stripePaymentElement.on("loaderror", (event) => {
this.handleError(event.error);
});
this.stripePaymentElement.mount("#stripe-payment-element");
} catch (e) {
this.handleError(e);
}
},
This is the 2 Vue methods that initialize the element and mont the payment element
This is confirming payment
async stripeConfirmPayment() {
try {
this.stripeStartProcessing();
if (!this.invoice) {
await this.createInvoice();
}
const { error: submitError } = await this.stripeElements.submit();
if (submitError) {
this.handleError(submitError);
return;
}
const returnPath = this.$router.resolve({
name: "account-documents-slug",
params: { slug: this.$route.params.documentId },
query: {
selected: this.selected.id === "sale" ? "sale" : "subscription",
planId: this.selected.id !== "sale" ? this.selected.id : null,
isDocumentOrder: this.isDocumentOrder,
},
});
const returnUrl = `${window.location.origin}${returnPath.href}`;
const { error } = await this.stripe.confirmPayment({
clientSecret: this.invoice.payment_intent_client_secret,
confirmParams: { return_url: returnUrl },
elements: this.stripeElements,
});
if (error) {
this.handleError(error);
}
} catch (error) {
this.handleError(error);
}
},
you're still updating the mode
this.stripeElements.update({ amount: amount, mode: mode });