#iuri_code

1 messages Β· Page 1 of 1 (latest)

jade fableBOT
#

πŸ‘‹ 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/1407833545296056412

πŸ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

wheat arch
#

πŸ‘‹ Hi!

Do you have a request ID for the confirmation attempt? Or Payment Intent ID I can inspect

grand sparrow
#

yes

#

pi_3RyHkjQFozUHdzWV0Q1mZMMY

wheat arch
grand sparrow
#

but how I can configure this?

#

because my current flow is, someone from my internal team creates the invoice using the Stripe dashboard

#

I just use the ID to load the invoice and create a customer session from that

#

if (invoice.status === 'open') {
const customerSession = await this.stripe.customerSessions.create({
customer: (invoice.customer as Stripe.Customer)?.id,
components: {
payment_element: {
enabled: true,
features: {
payment_method_redisplay: 'enabled',
payment_method_save: 'enabled',
payment_method_save_usage: 'off_session',
payment_method_remove: 'enabled',
},
},
},
});

#

I'm using the confirmation secret from the invoice

#

const invoice = await this.stripe.invoices.retrieve(id, {
expand: ['customer', 'confirmation_secret', 'payments'],
});

  const invoiceData: PaymentTypes.GetInvoice.Invoice = {
    id: invoice.id,
    number: invoice.number,
    status: invoice.status,
    amountDue: invoice.amount_due,
    amountPaid: invoice.amount_paid,
    currency: invoice.currency,
    dueDate: invoice.due_date,
    created: invoice.created,
    customer: {
      name: (invoice.customer as Stripe.Customer)?.name || undefined,
      email: (invoice.customer as Stripe.Customer)?.email || undefined,
    },
    lines: invoice.lines.data.map((line) => ({
      description: line.description,
      amount: line.amount,
      quantity: line.quantity,
      currency: line.currency,
    })),
    confirmationSecret: invoice.confirmation_secret?.client_secret,
    hostedUrl: invoice.hosted_invoice_url || undefined,
    downloadUrl: invoice.invoice_pdf || undefined,
    paymentMethodTypes: invoice.payment_settings.payment_method_types || undefined,
  };
#

any idea?

wheat arch
#

Sorry, still looking into it

#

Sorry for the delay here.

grand sparrow
#

If I try to pay the invoice using the Stripe url I can see the Bank Transfer instruction options

wheat arch
#

I believe this is due to their not being a funding type set per the error message "The customer balance is insufficient to complete the payment. Please change the amount or provide the funding_type parameter."

#

I'm trying to identify the best way to set this given you're working with a pre-made invoice.

#

Reaching out to some of my team members to brainstorm.

grand sparrow
#

ok, thanks

#

I'm doing a test here changing the PI directly from the API to see...

await stripe.paymentIntents.update(paymentIntentId, {
  payment_method_options: {
    customer_balance: {
      funding_type: 'bank_transfer',
    },
  },
});
mighty coral
#

hi! i'm jumping in to help since mossy is handling a few other threads. getting caught up

grand sparrow
#

didn't work =/

jade fableBOT
viral zodiac
#

πŸ‘‹ Taking over this thread, catching up now

grand sparrow
#

ok

viral zodiac
#

According the documentation: "Upon confirmation, Stripe automatically opens a modal to display the bank transfer details to your customer."
Which integration guide are you following? Could you share the doc?

grand sparrow
#

I'm not sure if there is any full doc off my flow

#

it's a custom flow

#

but I can post my code here if it helps

viral zodiac
#

Could you share how you configure your code on <Elements> and <PaymentElement>, and their options config?

grand sparrow
#

sure

#

The invoice object here I retrieve from my backend using the stripe sdk:

const invoice = await this.stripe.invoices.retrieve(id, {
        expand: ['customer', 'confirmation_secret', 'payments'],
      });
{invoice && invoice.status?.toLocaleLowerCase() === 'open' && invoice.confirmationSecret && (
        <div className="mx-auto mb-2 flex min-w-[670px] max-w-2xl flex-col rounded-lg border bg-sand-200 p-6">
          <h2 className="mb-4 space-y-4 text-lg font-semibold text-gray-900">Pay Invoice</h2>
          <Elements stripe={stripe} options={paymentOptions}>
            <PaymentForm invoice={invoice} onPaymentSuccess={onPaymentSuccess} />
          </Elements>
        </div>
      )}
#

this is my PaymentElement:

      <PaymentElement onChange={() => setResult(null)} options={paymentOptions} />
#
  const paymentOptions = useMemo(() => {
    return {
      defaultValues: {
        billingDetails: {
          email: invoice?.customer.email,
          name: invoice?.customer.name,
        },
      },
    };
  }, [invoice]);
#

and on my submitting button I'm doing this:

try {
      const { error: submitError } = await elements.submit();
      if (submitError) {
        setResult({ success: false, title: 'Payment error', message: submitError.message });
        return;
      }

      const { error: stripeError, paymentIntent } = await stripe.confirmPayment({
        elements,
        clientSecret: invoice?.confirmationSecret || '',
        confirmParams: {
          return_url: window.location.href,
        },
        redirect: 'if_required',
      });

      if (stripeError) {
viral zodiac
#

Are you sharing the same paymentOptions for both <Elements> and <PaymentElement>?

grand sparrow
#

no, they are different objects

viral zodiac
#

Could you share the options used for <Elements>?

grand sparrow
#
const [paymentOptions, setPaymentOptions] = useState<any>({
    appearance: {
      theme: 'stripe',
      variables: {
        colorPrimary: '#334740',
      },
    },
  });
const loadInvoice = useCallback(
    async (invoice?: InvoiceInfo | undefined) => {
      try {
        const invoiceData = invoice ?? (await retrieveInvoiceInfo());
        setInvoice(invoiceData);
        setPaymentOptions((prev: any) => ({
          ...prev,
          clientSecret: invoiceData?.confirmationSecret,
          customerSessionClientSecret: invoiceData?.customerSessionSecret,
        }));
      } catch (err: any) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    },
    [retrieveInvoiceInfo],
  );
#

my bad, I forgot to share this part earlier

viral zodiac
#

Could you try removing clientSecret: invoice?.confirmationSecret || '', in confirmPayment()? This shouldn't be needed when clientSecret is set in <Elements> option

grand sparrow
#

same error

viral zodiac
#

Testing at my end now

grand sparrow
#

{
"type": "card_error",
"code": "",
"decline_code": "payment_intent_customer_balance_insufficient_funds",
"message": "The customer balance is insufficient to complete the payment. Please change the amount or provide the funding_type parameter.",
"payment_intent": {
"id": "pi_3RyJhyQFozUHdzWV1FHO81tG",
"object": "payment_intent",
"amount": 1000,
"amount_details": {
"tip": {}
},
"automatic_payment_methods": null,
"canceled_at": null,
"cancellation_reason": null,
"capture_method": "automatic",
"client_secret": "...",
"confirmation_method": "automatic",
"created": 1755725894,
"currency": "usd",
"description": "Payment for Invoice",
"excluded_payment_method_types": null,
"last_payment_error": {
"code": "",
"decline_code": "payment_intent_customer_balance_insufficient_funds",
"message": "The customer balance is insufficient to complete the payment. Please change the amount or provide the funding_type parameter.",
...

#

...
"payment_method": {
"id": "pm_1RyL7pQFozUHdzWVl5TqsUBW",
"object": "payment_method",
"allow_redisplay": "unspecified",
"billing_details": {
"address": {
"city": null,
"country": null,
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": "iuri@...",
"name": null,
"phone": null,
"tax_id": null
},
"created": 1755731341,
"customer": null,
"customer_balance": {},
"livemode": false,
"type": "customer_balance"
},
"type": "card_error"
},
"livemode": false,
"next_action": null,
"payment_method": null,
"payment_method_configuration_details": null,
"payment_method_options": {
"us_bank_account": {
"verification_method": "automatic"
}
},
"payment_method_types": [
"customer_balance",
"us_bank_account"
],
"processing": null,
"receipt_email": "iuri@...",
"setup_future_usage": null,
"shipping": null,
"source": null,
"status": "requires_payment_method"
},
"request_log_url": "https://dashboard.stripe.com/test/logs/req_zoT8IVGazJVavS?t=1755731341",
"shouldRetry": false
}

#

conseguiu replicar @viral zodiac ?

viral zodiac
#

I can reproduce this issue on my end

#

Checking why this is happening for bank transfer on invoice with using Payment Element

grand sparrow
#

oh ok, so is it really a problem with the library?

#

I think I've searched the github a few weeks back and didn't find any issue related to that...

viral zodiac
#

This is not really a library issue

#

I'm checking what is the best way to integrate the bank transfer on invoice using Payment Element

#

With the invoice with send_invoice, we generally expect the payment to be completed using the hosted invoice payment

grand sparrow
#

my company doesn't want to use the hosted page even embedded on an iframe...

#

actually I think I wasn't able to embed this on an iframe as well...

viral zodiac
#

When I use direct Payment Intent API directly (without Invoice), the confirmPayment() works fine. The issue seems to be just the Payment Intent created from the Invoice itself that "payment_intent_customer_balance_insufficient_funds" error will be returned

#

This will take us some time to figure out why this is not working. I'll be sending a link to you to write in to us, so that we can work with the relevant team to identify why this error is returned.

jade fableBOT
#

Hello @grand sparrow, we have sent you a direct message, please check it at https://discord.com/channels/@me/1407870730749607957

  • πŸ”—The message has instructions on how to open a direct support case with our Developer Support team, in order to help you more effectively.
grand sparrow
#

is there any workaround that I can do from my end?

#

the context from this thread is automatically attached to that?

#

I'm not sure if it worked...

viral zodiac
#

is there any workaround that I can do from my end?
I don't seem to find a workaround for this

#

the context from this thread is automatically attached to that?
Yes

grand sparrow
#

it didn't give me any link, email, id or feedback...

grand sparrow
viral zodiac
#

We've received your case. You should receive the email update once we have more information

grand sparrow
#

sorry but what email should I receive it?

#

oh I think I recevied here on my work email

#

nice!

viral zodiac
#

Great! We will provide the update once we get more information on why this doesn't work for the integration you're working on

grand sparrow
viral zodiac
jade fableBOT
grand sparrow
#

@viral zodiac in your test did you attached to an invoice or not? attaching a new PI stills not working for me here

viral zodiac
#

Did you use the new Payment Intent client secret in your Elements options?

#

The my testing, the new Payment Intent is attached to the Invoice

#

While this approach works, this is a hack / workaround. The fundamental issue is with the Bank Transfer is not being able to confirm on the Payment Intent created on Invoice, let's move our conversation over the email and we will share the updates asynchronously once we have an update why this is not working