#jmschp_best-practices

1 messages ยท Page 1 of 1 (latest)

violet sunBOT
#

๐Ÿ‘‹ 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.

cloud rain
#

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?

vocal breach
#

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"
  }
}
cloud rain
#

give me a few minutes to try to reproduce this.

vocal breach
#

Note I am on the lates acacia version

#

2025-02-24.acacia

violet sunBOT
sour radish
#

๐Ÿ‘‹ taking over for my colleague. Let me catch up.

#

you need to use mode: 'subscription' on the PaymentElement when you're handling invoices

vocal breach
#

Even if it is not for a subscription?

sour radish
#

yes

vocal breach
#

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.

sour radish
#

if in both cases you're using invoices then yes

vocal breach
#

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 ๐Ÿ™‚

sour radish
#

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

vocal breach
#

I tried, and it did not work
Got the same error

sour radish
#

are you still specifying the PMTs manually?

vocal breach
#

No

sour radish
#

can you please share how you initialize the PaymentElement and the request ID that created the invoice?

vocal breach
#

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);
      }
    },
sour radish
#

you're still updating the mode

this.stripeElements.update({ amount: amount, mode: mode });

vocal breach
#

oh shiT!

#

Sorry! ahahahah

#

Done
Its seem to be working

thanks