#vm1172-reactnative

1 messages · Page 1 of 1 (latest)

sonic crowBOT
north pecan
#

Hey there

swift adder
#

hey how you doing

north pecan
#

Good thanks

#

Really you can do either here, you just don't want to do both.

swift adder
#

so my preference is to do it inside the pay function since I do not want to create a paymentIntent every time on component mount

but when I do it inside the pay function the first time it doesn't register, and then it creates to paymentIntents

which is not ideal

#

sharing my pay function below

const pay = async () => {
    await fetchPaymentIntentClientSecret()
    if (!clientSecret) return
    const { paymentIntent, error } = await confirmPlatformPayPayment(clientSecret, {
      applePay: {
        cartItems: cart,
        merchantCountryCode: ALLOWED_COUNTRY,
        currencyCode: CURRENCY.toUpperCase(),
        requiredShippingAddressFields: [
          PlatformPay.ContactField.Name,
          PlatformPay.ContactField.PostalAddress
        ],
        requiredBillingContactFields: [PlatformPay.ContactField.PostalAddress],
        merchantCapabilities: [
          ApplePayMerchantCapability.Supports3DS,
          ApplePayMerchantCapability.SupportsCredit,
          ApplePayMerchantCapability.SupportsDebit
        ]
      }
    })
    if (error) {
      console.error('Stripe Apple Pay Error', error)
    } else {
      console.log(JSON.stringify(paymentIntent, null, 2))
      setClientSecret(null)
      router.push({ pathname: '/summary', params: { paymentIntentId } })
    }
  }
north pecan
#

That looks fine. Can you show me your fetchPaymentIntentClientSecret() code?

swift adder
#
  const fetchPaymentIntentClientSecret = async () => {
    const token = await getItem('token')
    const { paymentIntentId, clientSecret } = await CheckoutSessionAPI.createPaymentIntent(
      productId,
      token
    )
    setPaymentIntentId(paymentIntentId)
    setClientSecret(clientSecret)
  }
#

could it be that the local state isn't getting updated and i should instead return the values like so -

  const fetchPaymentIntentClientSecret = async (): Promise<{
    paymentIntentId: string
    clientSecret: string
  }> => {
    const token = await getItem(')
    const { paymentIntentId, clientSecret } = await CheckoutSessionAPI.createPaymentIntent(
      productId,
      token
    )
    setPaymentIntentId(paymentIntentId)
    setClientSecret(clientSecret)
    return { paymentIntentId, clientSecret }
  }

when I try returning the paymentIntentId it does not error out the first time

but then when I try to authorize a charge it fails and returns this error

{
    "code": "Failed",
    "declineCode": null,
    "localizedMessage": "The data couldn’t be read because it isn’t in the correct format.",
    "message": "The data couldn’t be read because it isn’t in the correct format.",
    "stripeErrorCode": null,
    "type": null
}
north pecan
#

Yep so what is happening is that you are using state which is asnyc

#

Wait actually no that should be fine.

#

You just click the "pay" button once here, right?

#

You don't have to click it twice?

swift adder
#

Once when I changed it to returning the paymentIntentId and clientSecret from the function

#

twice when I was not returning it

north pecan
#

Ah okay yeah

#

So that is because of the state update being async

#

So yes, the proper way to handle this would be to return the client secret from the function

#

Not set state here

swift adder
#

okay, hold on will try that out

north pecan
#

Can you show me your updated code for your pay function?

swift adder
#
const pay = async () => {
    const { paymentIntentId, clientSecret } = await fetchPaymentIntentClientSecret()
    if (!clientSecret) return
    const { paymentIntent, error } = await confirmPlatformPayPayment(clientSecret, {
      applePay: {
        cartItems: cart,
        merchantCountryCode: ALLOWED_COUNTRY,
        currencyCode: CURRENCY.toUpperCase(),
        requiredShippingAddressFields: [
          PlatformPay.ContactField.Name,
          PlatformPay.ContactField.PostalAddress
        ],
        requiredBillingContactFields: [PlatformPay.ContactField.PostalAddress],
        merchantCapabilities: [
          ApplePayMerchantCapability.Supports3DS,
          ApplePayMerchantCapability.SupportsCredit,
          ApplePayMerchantCapability.SupportsDebit
        ]
      }
    })
    if (error) {
      if (IS_DEV_ENV) console.error('Stripe Apple Pay Error', error)
    } else {
      console.log(JSON.stringify(paymentIntent, null, 2))
      router.push({ pathname: '/summary', params: { paymentIntentId } })
    }
  }
#

I should also mention I have a onShippingContactSelected function which calculates the tax. idk if that changes anything --

  const onShippingContactSelected = async (shippingContact: ShippingContact) => {
    const postalCode = shippingContact.postalAddress.postalCode
    const { amount, normalizedTax } = await getTax(postalCode)
    const newCart: PlatformPay.CartSummaryItem[] = [
      {
        label: 'Subtotal',
        amount: amount.toString(),
        paymentType: PlatformPay.PaymentType.Immediate
      },
      {
        label: 'Tax',
        amount: normalizedTax.toString(),
        isPending: false,
        paymentType: PlatformPay.PaymentType.Immediate
      },
      {
        label: 'Shipping',
        amount: '0.00',
        isPending: false,
        paymentType: PlatformPay.PaymentType.Immediate
      },
      {
        label: 'Total',
        amount: (amount + normalizedTax).toString(),
        isPending: false,
        paymentType: PlatformPay.PaymentType.Immediate
      }
    ]
    setCart(newCart)
    const { error } = await updatePlatformPaySheet({
      applePay: {
        cartItems: newCart,
        shippingMethods,
        errors: []
      }
    })
    if (error !== undefined) console.error('onShippingContactSelected', error)
    const order = {
      subtotal: amount,
      tax: normalizedTax,
      total: amount + normalizedTax
    }
    const token = await getItem('token')
    await CheckoutSessionAPI.updatePaymentIntent(paymentIntentId, shippingContact, order, token)
  }
north pecan
#

Okay so yeah I'd recommend logging out clientSecret in your pay function

#

Let's see what that looks like

swift adder
#

getTax:

  const getTax = async (postalCode: string): Promise<{ amount: number; normalizedTax: number }> => {
    const token = await getItem('token')
    const amount = props.singlePageInfo.price
    const tax = await CheckoutSessionAPI.calculateTax(amount, gentlyId, postalCode, token)
    const normalizedTax = tax / 100
    return { amount, normalizedTax }
  }
swift adder
north pecan
#

Weird... that looks fine.

#

Can you try hardcoding that in your confirmPlatformPayPayment() and see if you hit the same error?

swift adder
#

sure, one second

#

same error, with payment failed

Stripe Apple Pay Error {"code": "Failed", "declineCode": null, "localizedMessage": "The data couldn’t be read because it isn’t in the correct format.", "message": "The data couldn’t be read because it isn’t in the correct format.", "stripeErrorCode": null, "type": null}
#
    const { paymentIntent, error } = await confirmPlatformPayPayment(
      'pi_3NxYR4Ca1hzW9vNX0d3mEAS6_secret_sVdORmexTP4xQEQMcZrDYsrdD',
      {
        applePay: {
          cartItems: cart,
          merchantCountryCode: ALLOWED_COUNTRY,
          currencyCode: CURRENCY.toUpperCase(),
          // shippingMethods,
          requiredShippingAddressFields: [
            PlatformPay.ContactField.Name,
            // PlatformPay.ContactField.PhoneNumber,
            PlatformPay.ContactField.PostalAddress
          ],
          requiredBillingContactFields: [PlatformPay.ContactField.PostalAddress],
          merchantCapabilities: [
            ApplePayMerchantCapability.Supports3DS,
            ApplePayMerchantCapability.SupportsCredit,
            ApplePayMerchantCapability.SupportsDebit
          ]
        }
      }
north pecan
#

Oh whoops, pretty sure you should be passing the parameter key here

#

clientSecret: 'pi_3NxYR4Ca1hzW9vNX0d3mEAS6_secret_sVdORmexTP4xQEQMcZrDYsrdD'

#

Try that

swift adder
#

it’s expecting a string not an object

swift adder
#

i’m sure i’m doing something wrong. should i share the entire file with you?

north pecan
#

I mean it just doesn't like something you are passing to confirmPlatformPayPayment()

#

What countryCode are you using?

swift adder
#

so i had this conversation prior. before it was due to an issue with shippingMethods not being a proper value inside confirmPlatformPayPayment

in this thread - #1159119746298560573 message

swift adder
north pecan
#

Alright yeah it seems like that very well could be the case. I think running a quick test where you don't mess with Shipping at all would be good to confirm that

swift adder
#

right, so i’m not messing with shipping at all. we only have one shipping method which is free shipping.

are you intimating i should remove shipping entirely from the entire payment lifecycle and try again?

north pecan
#

Yep

#

I would basically just start cutting out everything not required from confirmPlatformPayPayment()

#

And see if we can narrow down which piece of data it doesn't like

short bluff
#

vm1172-reactnative

swift adder
#

got it. let me try that

#

shippingMethod wasn't the issue, payment still failing, will try cutting down

short bluff
#

👋 bismarck had to head out, so I'm hopping in

#

Let me know iif you're having trouble pinning down which params it doesn't like

swift adder
#

appreciate it, i need to step out for a second, is there any way to keep this thread alive?

short bluff
#

I'll keep it up for a bit, but after a long period of inactivity we typically close threads out

#

If you come back after the thread is closed you can always ask again in the main channel and someone will be around to help

sonic crowBOT