#toxikboy_code

1 messages · Page 1 of 1 (latest)

eternal wigeonBOT
#

👋 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/1433803499170168902

📝 Have more to share? Add more details, code, screenshots, videos, etc. below.

past condor
#

const intent = await retrievePaymentIntent(intentFromBackEnd.client_secret)

// {
//   "amount": 1400,
//   "amountDetails": { "tip": { "amount": null } },
//   "amountTip": 0,
//   "captureMethod": "manual",
//   "charges": [],
//   "created": "1761914508000",
//   "currency": "eur",
//   "id": "pi_3SOHeKFq******",
//   "metadata": {  },
//   "offlineDetails": null,
//   "paymentMethod": null,
//   "paymentMethodId": null,
//   "paymentMethodOptions": {
//     "cardPresent": {
//       "requestExtendedAuthorization": false,
//       "requestIncrementalAuthorizationSupport": false,
//       "requestPartialAuthorization": "",
//       "surcharge": null
//     }
//   },
//   "sdkUuid": "xxx-xxxx-xxxx-xxxx-xxxx",
//   "statementDescriptor": null,
//   "statementDescriptorSuffix": null,
//   "status": "requiresPaymentMethod"
// }

const { paymentIntent: collectedPaymentIntent, error: collectPaymentError } = await collectPaymentMethod({
    paymentIntent: currentTapToPayIntent,
    enableCustomerCancellation: false,
    updatePaymentIntent: true,
  })

// collectPaymentError {"code": "SCPErrorInvalidRequiredParameter", "message": "A required parameter was invalid or missing."}
#

"@stripe/stripe-terminal-react-native": "^0.0.1-beta.25"

old path
#

Hi there! Do you have a request ID related to this error?

past condor
#

request ID is something from Discord help ? or something I can find on stripe developper dashboard ?

forest summit
#

stripe developer dash under logs

past condor
#

req_t5szNtGWyRU5ga this one is the retrievePaymentIntent i suppose

#

I have no request in the dashboard for collectPaymentMethod

old path
past condor
#

seems to be an old one, when i was trying some ChatGPT "non-working" solutions 😉

old path
#

Got it. That is the only recent request I found in your sandbox account with a "Received unknown parameter" error. Do you know the approximate time you saw the error you initially reported? Was it in your sandbox or live account?

past condor
#

It's in a sandbox mode "environmen name is 'local'"

#

i performed the collectPaymentMethod a few second after the retrievePaymentIntent
and retrievePaymentIntent request ID is req_t5szNtGWyRU5ga (Heure 31 oct. 2025, 13:41:49)

old path
past condor
#

so it seems the error is not something from the API but from @stripe/stripe-terminal-react-native

old path
#

Right, looking into it now

limpid totem
#

Hi there 👋 I'm helping look into this. I'll be up front that I'm not the most familiar with react native, but want to see if I can help us get our bearings here.

Is this a new integration that you're building? Or was this working previously and has now broken?

past condor
#

Hello, I manage to create and collect a payment with TapToPay, then I had to change the workflow for Connected account.
I now create the payment intent from the backend like this


$params   = [
            'amount' => $amount,
            'currency' => 'eur',
            'application_fee_amount' => $feeInCents,
            'description' => 'hello',
            'metadata' => [
                ///
            ],
        ];

$params['payment_method_types'] = ['card_present'];
$params['capture_method']       = 'manual';

$intent = PaymentIntent::create($params, ['stripe_account' => $myCustomerStripeAccount]);
#

In the front-end I retrieve the payement intent and got an error when i try ton colkect it

#
const intent = await retrievePaymentIntent(intentFromBackEnd.client_secret)

// {
//   "amount": 1400,
//   "amountDetails": { "tip": { "amount": null } },
//   "amountTip": 0,
//   "captureMethod": "manual",
//   "charges": [],
//   "created": "1761914508000",
//   "currency": "eur",
//   "id": "pi_3SOHeKFq******",
//   "metadata": {  },
//   "offlineDetails": null,
//   "paymentMethod": null,
//   "paymentMethodId": null,
//   "paymentMethodOptions": {
//     "cardPresent": {
//       "requestExtendedAuthorization": false,
//       "requestIncrementalAuthorizationSupport": false,
//       "requestPartialAuthorization": "",
//       "surcharge": null
//     }
//   },
//   "sdkUuid": "xxx-xxxx-xxxx-xxxx-xxxx",
//   "statementDescriptor": null,
//   "statementDescriptorSuffix": null,
//   "status": "requiresPaymentMethod"
// }

const { paymentIntent: collectedPaymentIntent, error: collectPaymentError } = await collectPaymentMethod({
    paymentIntent: currentTapToPayIntent,
    enableCustomerCancellation: false,
    updatePaymentIntent: true,
  })

// collectPaymentError {"code": "SCPErrorInvalidRequiredParameter", "message": "A required parameter was invalid or missing."}
limpid totem
#

Ah, I think you need to also adjust your frontend to handle that you're now creating the Payment Intents on a different Stripe account, but let me double check that.

past condor
#

Also it's now Direct payment

limpid totem
past condor
#

yes location and terminal are created with stripe_account

$location = $client->terminal->locations->create(
            [
                'display_name' => 'Application DMASP',
                'address' => [
                    'line1' => $customer->getAddress(),
                    'city' => $customer->getCity(),
                    'country' => 'FR',
                    'postal_code' => $customer->getPostalCode(),
                ],
            ],
            ['stripe_account' => $customer->getStripeAccount()]
        );


$client->terminal->connectionTokens->create(
            ['location' => $customer->getStripeLocationId()],
            ['stripe_account' => $customer->getStripeAccount()]
        );
limpid totem
#

What is the ID of one of the Connected Accounts you're testing with?

past condor
#

acct_1QwpaPFqrjzgHWas

#

in test mode

eternal wigeonBOT
limpid totem
#

I'm chatting about this with another teammate, apologies for the delays.

Just to confirm were you ever using this integration to process Destination Charge style Connect payments?

past condor
#

I did manage to create and collect a payment intent, all from frontend, but it was Indrect payment :

const { error, paymentIntent } = await createPaymentIntent({
amount,
currency: 'eur',
onBehalfOf: authUser.customer.stripeAccount,
transferDataDestination: authUser.customer.stripeAccount,
applicationFeeAmount: ***,
metadata: {
'Visite ID': currentVisit.id,
},
})

Now I change the workflow on back-end to use Direct payment. It's working with card payment ("@stripe/stripe-react-native": "0.38.6") , but not with TapToPay ( "@stripe/stripe-terminal-react-native": "^0.0.1-beta.25")

limpid totem
#

I'm not sure I'm grasping what you mean with that last part, those are two different libraries that need to be implemented differently.

Yes, what you shared in that Payment Intent creation request is what we call Destination Charges. Can you share the code you're using to call connectReader?

past condor
#

Yes, sorry it was not clear. I reworked the workflow to use Direct payment. It's ok on the back-end and the front-end with @stripe/stripe-react-native. So I supposed the back-end part is OK.
Then I got the error during collectPaymentMethod with @stripe/stripe-terminal-react-native

#
const { reader, error } = await connectReader(
          {
            reader: readers[0],
            locationId: stripeLocationId,
            onBehalfOf: authUser?.customer.stripeAccount,
          },
          'tapToPay',
        )
limpid totem
#

You need to remove onBehalfOf

#

That's only for Destination Charges

past condor
#

Ok, then same error

#
{"amount": 1400, "amountDetails": {"tip": {"amount": null}}, "amountTip": 0, "captureMethod": "manual", "charges": [], "created": "1761921595000", "currency": "eur", "id": "pi_3SOJUdFqrjzgHWas10gK3onq", "metadata": {}, "offlineDetails": null, "paymentMethod": null, "paymentMethodId": null, "paymentMethodOptions": {"cardPresent": {"requestExtendedAuthorization": false, "requestIncrementalAuthorizationSupport": false, "requestPartialAuthorization": "", "surcharge": null}}, "sdkUuid": "FC654A73-2BEE-4A3F-9352-15C9E93B5EA4", "statementDescriptor": null, "statementDescriptorSuffix": null, "status": "requiresPaymentMethod"}
wise parcel
#

Hello
Taking over to help out here

#

Can you share the exact code you're using from Stripe's Terminal SDK in your app?
There's clearly something left over in your code which is causing this behavior

past condor
#
const {
    initialize,
    collectPaymentMethod,
    confirmPaymentIntent,
    discoverReaders,
    connectReader,
    getConnectedReader,
    retrievePaymentIntent,
  } = useStripeTerminal({
    onDidChangeConnectionStatus(status) {
      if (status === 'connected') {
        setConnectionLoading(null)
        setIsLoading(false)
        // onPress()
      } else {
        if (['connecting', 'discovering', 'notConnected'].includes(status)) {
          return
        }
      }
    },
    onDidReportReaderSoftwareUpdateProgress: (progress) => {
      setIsLoading(true)
      setConnectionLoading(parseFloat(progress))
    },
    onUpdateDiscoveredReaders: async (readers) => {
      console.log('onUpdateDiscoveredReaders', readers)
      try {
        const { reader, error } = await connectReader(
          {
            reader: readers[0],
            locationId: 'tml_GPmfGwT51ezhO2',
            // onBehalfOf: authUser?.customer.stripeAccount,
          },
          'tapToPay',
        )
        if (error) {
          if (error.code === 'AlreadyConnectedToReader') {
            tryReconnectReader()
            if (tryPaymentAfterReconnect) {
              tryPaymentAfterReconnect = false
              onPress()
            }
            return
          }
          captureException(`Error connecting reader: ${error.message}`)
        }
        if (reader) {
          console.log('reader', reader)
          connectedReader.current = reader
          setIsLoading(false)
          if (tryPaymentAfterReconnect) {
            tryPaymentAfterReconnect = false
            onPress()
          }
        }
      } catch (error) {
        console.error('Error connecting reader:', error)
      }
    },
  })
#
async function onPress() {
    if (!authUser) {
      return
    }

    if (!connectedReader.current) {
      const { error } = await discoverReaders({
        discoveryMethod: 'tapToPay',
        simulated: __DEV__,
      })
      if (error) {
        if (error.code === 'INTEGRATION_ERROR.TAP_TO_PAY_UNSUPPORTED_DEVICE') {
          setIsLoading(false)
          Alert.alert("Cet appareil n'est pas compatible avec le paiement Tap-to-pay")
          return
        }
        setIsLoading(false)
        Alert.alert('Erreur lors de la découverte du lecteur', error.message)
        captureException(`Error discovering readers: ${error.message}`)
      }
      return
    }

    console.log('currentTapToPayIntent', currentTapToPayIntent)
    if (!currentTapToPayIntent) {
      dispatch(stripeCreateTapToPayIntentStart(retrievePaymentIntent))
      return
    }

    const { paymentIntent: collectedPaymentIntent, error: collectPaymentError } = await collectPaymentMethod({
      paymentIntent: currentTapToPayIntent,
      enableCustomerCancellation: false,
      updatePaymentIntent: true,
    })
    if (collectPaymentError) {
      console.log('collectPaymentError', collectPaymentError)
      setIsProcessingLocally(false)
      if (collectPaymentError.code === 'Canceled') {
        return
      }
      Alert.alert('Erreur lors de la collecte du paiement', collectPaymentError.message)
      captureException(`StripeTerminal collectPaymentMethod failed ${collectPaymentError.message}`)
      return
    }
#
    console.log('collectedPaymentIntent', collectedPaymentIntent)

    const { paymentIntent: confirmedPaymentIntent, error: confirmPaymentError } = await confirmPaymentIntent({
      paymentIntent: collectedPaymentIntent,
    })
    if (confirmPaymentError) {
      Alert.alert('Erreur lors de la confirmation du paiement', confirmPaymentError.message)
      captureException(`StripeTerminal confirmPaymentIntent failed ${confirmPaymentError.message}`)
      setIsProcessingLocally(false)
      return
    }
...
}
wise parcel
#

Is it possible that collectPaymentMethod is getting called before stripeCreateTapToPayIntentStart gets it's value from the retrieve function?

past condor
#

I've got the retrieved Payment intent :

{"amount": 1400, "amountDetails": {"tip": {"amount": null}}, "amountTip": 0, "captureMethod": "manual", "charges": [], "created": "1761921595000", "currency": "eur", "id": "pi_3SOJUdFqrjzgHWas10gK3onq", "metadata": {}, "offlineDetails": null, "paymentMethod": null, "paymentMethodId": null, "paymentMethodOptions": {"cardPresent": {"requestExtendedAuthorization": false, "requestIncrementalAuthorizationSupport": false, "requestPartialAuthorization": "", "surcharge": null}}, "sdkUuid": "FC654A73-2BEE-4A3F-9352-15C9E93B5EA4", "statementDescriptor": null, "statementDescriptorSuffix": null, "status": "requiresPaymentMethod"}

and pass it to collectedPaymentIntent

wise parcel
#

Can you try removing other params from collectPaymentMethod and just ekeep the PaymentIntent?

past condor
#

what params should I keep ?

wise parcel
#

paymentIntent

past condor
#

Perfect it worked

wise parcel
#

Nice, now try adding back the removed params one at a time

#

that would help isolate the exact param causing the issue

past condor
#

ok seems enableCustomerCancellation is not working (on iOS at least)

#

I'll test on android later

#

Thanks for your help, I will perform tests on the whole process.

wise parcel
#

NP! 🙂 Happy to help
Sorry for the delay and some confusion
Good luck