#marka-paymentelement-migration

1 messages ยท Page 1 of 1 (latest)

jaunty agateBOT
cyan axle
#

marka-paymentelement-migration

#

๐Ÿ‘‹ @cosmic olive Can I ask for a lot more specific context with detailed code and exact request ids/object ids so that I can help you debug this?

cosmic olive
#

Well, there's not request IDs, as it's rejected at the javascript level using stripe.js at confirmPayment call if I add the setup_future_usage param. And the confirmPyament call is pretty basic with/without that param:

confirmPaymentIntent(paymentIntentKey, callback) {
let self = this;
console.log("Start confirmPmt...");
if (!self.stripe) {
self.stripe = Stripe(self.supportData.skey);
}
if (self.elements) {

    console.log("confirmPayment...");
    let elements = self.elements;
    let data = {
        payment_method_data: {
            billing_details: {
                address: {
                    line1: self.paymentData.addressLine1,
                    line2: self.paymentData.addressLine2,
                    city: self.paymentData.city,
                    state: self.paymentData.state,
                    postal_code: self.paymentData.zipCode,
                    country: self.paymentData.countryCode,
                },
                name: self.paymentData.name,
            },
        },
        //setup_future_usage: "off_session",
    };
    self.stripe.confirmPayment({ elements, clientSecret: paymentIntentKey, confirmParams: data, redirect: "if_required" })
    .then((result) => {
        if (result.error) {
cyan axle
#

sure but I'm trying to grasp what you were doing before, what's working, what's not working, etc.
You said

We have very complex payment flows with lots of options.
which means it's not a simple question and I barely understand for now what you are trying to get at, while helping other people.
If you can help me understand what you were doing before, what the context it, why you are trying to pass that parameter client-side, etc. I can then look

cosmic olive
#

Here's the primary use case, of the two I mentioned above:

Use case: I have a failed subscription invoice payment intent, and I subsequently use the Payment Element to collect new payment method data for that payment intent. On the call to Stripe.js confirmPayment, the payment intent is processed successfully with the new payment method, but the new payment method is not attached to the customer or subscription (req_1FsygjfMhEkuVc).

The documentation for Stripe.js confirmPayment says to refer to the PaymentIntent API to see all confirm params for use during the confirmPayment call (https://stripe.com/docs/js/payment_intents/confirm_payment#confirm_payment_intent-options-confirmParams). The PaymentIntent API docs clearly (and logically) show that "setup_future_usage" is one of those confirm params, and would be needed to attach the new payment method to the payment intent's customer (https://stripe.com/docs/api/payment_intents/confirm#confirm_payment_intent-setup_future_usage), which makes sense.

However, on subsequent attempts for a different payment intent (pi_3NqpreAUoPbSaQbf3u01xJCS) when setup_future_usage is added to the confirmPayment confirmParams for the confirmPayment call, it fails with: "Payment method not updated: IntegrationError: stripe.confirmPayment(): do not pass setup_future_usage at confirm time. Instead, pass setup_future_usage when the PaymentIntent is created."

This is contrary to the documentation, and logic, as the payment intent in question is a previously failed payment intent where we're trying to setup a new payment method, which is where we want the future usage setting, and for it to attach to the customer in confirmation.

#

The second use case is a simple one-off invoice for a customer (payment intent already exists), not attached to subscription. In some cases we give the customer the option of using current payment method, OR selecting a NEW payment method. For the new payment method case, we want to attach it to the customer for future use. The payment method clears the confirmPayment call, and does make the payment, but it won't attach. We don't want to go through another round of setup intents to be able to attach this new payment method for future use.

cyan axle
#

Let's take this one at a time because that's a lot of text

cosmic olive
#

Some of these customers have subscriptions and one-off invoices.

cyan axle
#

Use case: I have a failed subscription invoice payment intent, and I subsequently use the Payment Element to collect new payment method data for that payment intent. On the call to Stripe.js confirmPayment, the payment intent is processed successfully with the new payment method, but the new payment method is not attached to the customer or subscription (req_1FsygjfMhEkuVc).
and to be clear you are saying this works absolutely fine with confirmCardPayment() and you can pass setup_future_usage without any error there?

cosmic olive
#

Yes, been doing it for at least a few years now.

#

That code looked (looks like) in our prod environment:

    //confirmCardPayment(paymentIntentKey, callback) {
    //    let self = this;
    //    console.log("Start confirmPmt...");
    //    if (!self.stripe) {
    //        self.stripe = Stripe(self.supportData.skey);
    //    }
    //    if (self.elements) {
    //        let data = {
    //            payment_method: {
    //                card: self.paymentElement,
    //                billing_details: {
    //                    address: {
    //                        line1: self.paymentData.addressLine1,
    //                        line2: self.paymentData.addressLine2,
    //                        city: self.paymentData.city,
    //                        state: self.paymentData.state,
    //                        postal_code: self.paymentData.zipCode,
    //                        country: self.paymentData.countryCode,
    //                    },
    //                    name: self.paymentData.name,
    //                },
    //            },
    //        };
    //        if (!self.hasExistingCard || self.isNewDefaultCard) {
    //            data.payment_method_options = {
    //                card: {
    //                    setup_future_usage: "off_session",
    //                }
    //            }
    //        }
    //        self.stripe.confirmCardPayment(paymentIntentKey, data)
    //        .then((result) => {
cyan axle
#

Ack so that really looks like a feature request to me overall in that case, not really something we can help with here. But in the meantime you can update that PaymentIntent server-side before rendering it in PaymentElement and set setup_future_usage on it right?

cosmic olive
#

We can't. Those attempts resulted in these:

- Modify PaymentIntent to allow more payment method types:

        var options = new PaymentIntentUpdateOptions();
        if (allowBankDebits)
        {
            List<string> paymentMethods = new List<string> {
                Models.Billing.PaymentMethod.CARD,
                Models.Billing.PaymentMethod.US_BANK_ACCOUNT,
                Models.Billing.PaymentMethod.ACSS_DEBIT,
            };
            options.PaymentMethodTypes = paymentMethods; 
        }
        var paymentIntent = _paymentIntentService.Update(paymentIntentId, options);

       This failed with:

        Some of the parameters you provided (payment_method_types) cannot be used when modifying a PaymentIntent that was created by an invoice. You can try again without those parameters.


- Modify PaymentIntent to set off_session:

        var options = new PaymentIntentUpdateOptions();
        options.SetupFutureUsage = "off_session";
        var paymentIntent = _paymentIntentService.Update(paymentIntentId, options);

    This guts the existing payment intent, removing the last_payment_error section and charges section, makikng it worthless.

        - req_SpXXv9cypOu19a
        - pi_3NqotPAUoPbSaQbf28bHnu4t
        - cus_Oe75ZlUoJaGuNK
cyan axle
#

1/ You can change payment_method_types so that's expected and I never said to do this right?
2/ I don't really get what all you mean, did it work or not, what's worthless?
3/ Is this a separate discussion?

cosmic olive
#

Sorry, the payment method type change is part of this, which is a separate but related discussion. Pasted the from notes. What's worthless in the 2nd example there is that if one modifies an existing payment intent that had a last_payment_error section and a charges section, they get eliminated, basically destroying that payment intent's content.

cyan axle
#

sorry for #1 I meant you can not my bad

#

if one modifies an existing payment intent that had a last_payment_error section and a charges section, they get eliminated, basically destroying that payment intent's content.
why is that an issue though? Every new attempt destroys the previous attempt, I don't really get what the problem is. But that's the only way

cosmic olive
#

If we modify the payment intent, and the charges section is gone, there's nothing left to charge, and if the last_payment_error section is gone, and the customer decides to cancel mid-transaction, all of that history is gone for later. That payment intent doesn't know what it's for, why it failed or what charges are associated with it.

#

These are existing payment intents, created previously, and failed. That failure data is still needed, as is the charges section.

cyan axle
#

what do you call "the charges section" I really don't get it

cosmic olive
#

Charges and last_payment_error sections from an invoice with expanded payment intent:

cyan axle
#

charges was removed a year ago and replaced by latest_charge: 'ch_123'. But it was really just a sublist with the most recent Charge attempt if any. The information has not disappeared, you can still use the List Charges API https://stripe.com/docs/api/charges/list and pass payment_intent: 'pi_123' to list all Charge(s) associate with that PaymentIntent

cosmic olive
#

ok, how about last_payment_error. In my testing, that gets removed on modification of the payment intent.

cyan axle
#

sure and that's normal and that shouldn't be a problem, since you have the Charge with the failure already right?

cosmic olive
#

My thought is that if we modify the payment intent, and it removes needed info, it won't render/charge correctly when it's time to pay. Though I don't recall testing this specifically after modifcation, it just seemed like too much info was removed from it. Let me go back and look at the payment intent I referenced above in the second test.

cyan axle
#

yeah that's absolutely not a thing that would happen

#

While we talked I built 2 separate repro and clearly see that setup_future_usage can be passed to confirmCardPayment() and not confirmPayment(). This isn't a documentation issue per se, it is a feature request

cosmic olive
#

OK, yep, it does look like there's still fee data, etc., in at least that sample above. I'll explore that more to confirm.

On the docs issue, it says refer to the payment intent API to see a full list of confirm parameters, one of which is setup_future_usage. And regardless, seems like it should still be there, even if it is a feature request. It's functionality that isn't in that component which was in confirmCardPayment.

Now though it's separate, but related, how about #1 sample above where I want to add additional allowable payment methods to an existing payment intent that was originally set up with just card, so it renders the additional in the Payment Element? Any way to make that happen?

cyan axle
#

I mean we could add support for it, we just don't support it and for now we do not plan to support it. So if you want support for it it is a feature requests and you would have to reach out to our support team to flag your interest for that feature request: https://support.stripe.com/contact

#

Ah also const response = await stripe.confirmPayment({ elements: elements, confirmParams: { // does not work // setup_future_usage: 'off_session', return_url: `${window.location}`, payment_method_options: { card: { setup_future_usage: 'off_session', } } }, }); works for me, someone on my team shared it

cosmic olive
#

OK, cool. I'll try that.

On the invoice modification for payment method types, I don't think I tried that yet, will try, but what about a payment intent that is not associated with an invoice? (we carete these for one-off charges for services where a customer does not have an active subscription, and no invoice is created either).

cyan axle
#

but what about a payment intent that is not associated with an invoice?
then you can update payment_method_types already and wouldn't hit the error you mentioned

cosmic olive
#

OK, very well. Lots to try here. I appreciate the lively discussion and help. Will report back if still issues. Thanks.