#dgsunesen-apple-pay

1 messages ยท Page 1 of 1 (latest)

shut hemlock
#

Hey there! Couple things:

payment intent has expired
What is an expired Payment Intent?
Apple Pay is not stored on the user as a payment method
They can be saved on a customer, yep

signal crystal
#

So for some of our users if they initially did a payment intent maybe more than 7 days ago it would eventually expire, and when they want to do the actual payment (capture) then for those where they successfully did the payment intent with an already saved card, we can just retry/redo the thing and then we can capture and do the payment.. See screenshot for one that is expired

#

however, when a user chose to use Apple Pay, if the initial payment intent reaches expiration (like that specific one shown in the screenshot) we cannot retry/redo the thing (behind the scenes)... It seems like it's because the Apple Pay wasn't stored on the users as a payment intent rather like a "one time payment method"

#

So our app/services is a place where people put out tasks they want done, and then people can make offers on these tasks... However, the one that created the task might already days before the tasks is actually being done and completed already find the one to do the task and accept the offer.. Then when the task is actually done THEN do the actual payment.. But that can be like n days after the initial payment intent

#

So I guess we would somehow need to save the Apple Pay as a payment method on the user when they choose to pay that way so that we have the same capabilities of retrying if the payment intent expired, right? And I'm not sure if we can already save the Apple Pay as payment method on the user when we use presentApplePay.. I see it returns a paymentMethod so maybe we can save that on the user somehow?

shut hemlock
#

Can you share an example PI where Apple Pay was attempted?

#

I'm curious to see how you're creating the PI as an Apple Pay payment method can be saved during auth/capture payment flows

signal crystal
#

this is in our test setup

#

here one went successfully through

shut hemlock
#

Well that's a PI that's using a pre-existing PM object

#

Is there an example of a PI where you don't have an existing Payment Method?

signal crystal
#

I'll see if I have one โ€” maybe in our live environment

#

would that be okay?

shut hemlock
#

Sure, ofc

signal crystal
#

this one.. I don't think there was any PM object there as the user does not have any credit card saved for future use.. The user only chose to use Apple Pay

#

and as you can see under the events and logs after it expired and the user wanted to do the payment/capture it just fails

shut hemlock
signal crystal
#

the one that failed / expired ?

shut hemlock
#

Are you passing setup_future_usage on PI creation for any Apple Pay transactions?

shut hemlock
signal crystal
#

no, I don't think we do anything with setup_future_usage

#

not even with regular credit cards โ€” there it seems to just works if we retry it again after it might have expired

shut hemlock
#

How are you setting up the cards for these off session payments?

signal crystal
#

using the CardField, useConfirmSetupIntent to save the card and then we use the setupIntents.create method to store the customerId and set usage to off_session

shut hemlock
#

Yep, that flow won't work with Apple Pay

signal crystal
#

So that's how we store and save credit cards on the user for future use and that works.. So how do we do it with Apple Pay? ๐Ÿ™‚

#

do we need to use the setup_future_usage thing ?

shut hemlock
#

Well, I'd recommend using the PaymentSheet instead of the CardField component for capturing payment details

#

(pretty sure you're using React Native, right?)

signal crystal
#

Yup

shut hemlock
#

PaymentSheet will support Apple/Google Pay out of the box

signal crystal
#

So there is no way by using the presentApplePay that we can somehow store the information for later user (after e.g. expiration)

#

as we do it now for credit cards

shut hemlock
#

Is this with a Setup Intent?

signal crystal
#

public async getSetupIntentClientSecret(customerId: string): Promise<string> {
return (
await stripe.setupIntents.create({
customer: customerId,
usage: 'off_session',
})
).client_secret;
}

shut hemlock
#

And how do you confirm the Setup Intent with an Apple Pay PM?

signal crystal
#

oh, just a sec.. I think I misunderstood you

#

when the users accepts the user to do the task and pick apple pay, we do the PI like this

#

const paymentIntent = await stripe.paymentIntents.create({ amount, currency: 'dkk', customer: customerId, payment_method: paymentMethodId, metadata, // This parameter instructs Stripe to authorize the amount but not capture it capture_method: 'manual', // Indicate that the customer is not in your checkout flow during this payment attempt. // This causes the PaymentIntent to throw an error if authentication is required off_session: true, // Causes confirmation to occur immediately when the PaymentIntent is created confirm: true, // We're fulfilling the payment on behalf of the Doer, who will receive the money when captured on_behalf_of: doerStripeConnectedAccountId, transfer_data: { destination: doerStripeConnectedAccountId, }, });

#

and then once the capture is gonna happen we do it like so

#

paymentIntent = await stripe.paymentIntents.capture( task.stripePaymentIntentId, { // Round amount value because it always ends to .00000000001 amount_to_capture: Math.round( task.price * (1 + task.shouterFeePercentage), ), // Add the Shouter fee on top of the base price application_fee_amount: task.fee, }, );

#

is this what you're asking about? ๐Ÿ™‚

shut hemlock
#

Right, but before you create the off-session payment you're creating/saving the payment method

#

How are you doing this for Apple Pay payment methods?

signal crystal
#

and that's the thing... We do not save the payment method on the user object (customer)... And that's why (I think) we are not able to retry, right?... I'm confused ๐Ÿ˜„

#

when it's for Apple Pay ๐Ÿ™‚

shut hemlock
#

Yes, exactly! For an off-session payment you need a saved/authenticated PM

signal crystal
#

and that's not possible with Apple Pay ? ๐Ÿ™‚

#

or how should I understand this?

#

unless we use the PaymentSheet?

shut hemlock
#

Yep, it's possible with Apple Pay (which is why I was asking if/how you were using Setup Intents for Apple Pay PMs)

signal crystal
#

public async createAndGetPaymentIntent(
customerId: string,
paymentMethodId: string,
amount: number,
doerStripeConnectedAccountId: string,
metadata?: { [metaKey: string]: string },
): Promise<PaymentIntentResponse> {
try {
const paymentIntent = await stripe.paymentIntents.create({
amount,
currency: 'dkk',
customer: customerId,
payment_method: paymentMethodId,
metadata,
// This parameter instructs Stripe to authorize the amount but not capture it
capture_method: 'manual',
// Indicate that the customer is not in your checkout flow during this payment attempt.
// This causes the PaymentIntent to throw an error if authentication is required
off_session: true,
// Causes confirmation to occur immediately when the PaymentIntent is created
confirm: true,
// We're fulfilling the payment on behalf of the Doer, who will receive the money when captured
on_behalf_of: doerStripeConnectedAccountId,
transfer_data: {
destination: doerStripeConnectedAccountId,
},
});

  return {
    clientSecret: paymentIntent.client_secret,
    paymentIntentId: paymentIntent.id,
    paymentIntentStatus: paymentIntent.status,
  };
} catch (error) {
  return {
    // Error code will be `authentication_required` if authentication is needed
    errorCode: error?.code,
    clientSecret: error?.raw?.payment_intent?.client_secret,
    paymentIntentId: error?.raw?.payment_intent?.id,
    paymentIntentStatus: error?.raw?.payment_intent?.status,
  };
}

}

#

Thats how we do it

#

And the same way we do it for credit cards

latent sierra
#

Hi ๐Ÿ‘‹ jumping in as my teammate needed to step away, please bear with me a moment while I catch up on the context here.

#

Wallet payment methods, such as Apple Pay, are essentially the same as card payment methods. So they can be saved for future usage, and to do so you would either leverage a Setup Intent (if saving prior to payment) or a Payment Intent with setup_future_usage (if saving during a payment).