#yeet_api

1 messages · Page 1 of 1 (latest)

tardy atlasBOT
#

đź‘‹ 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/1389820334836027434

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

Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.

night forge
fair flicker
#

Hi! Looking into this.

night forge
#

Cool

fair flicker
night forge
#

Yes i bought the m2 reader and I'm trying to connect it to my react native app for payments

#

i think the tap to pay in that article is about the native tap to pay in the phone itself. i want to tap to pay with the reader i bought to use in my ipad

fair flicker
#

Understood! Do you have a screenshot of where you are seeing the "this feature is currently not avaialble for the selected reader" error?

night forge
#

one second

#

the reader is connecting to my app. but when i press tap to pay to make a payment, its giving that error

#

this is the handler reader payment function which gets called when i press tap card
const handleReaderPayment = async () => {
if (!reader) return Alert.alert('Error', 'No reader connected');

const currentSecret = await fetchPaymentIntent('reader');
if (!currentSecret) {
return Alert.alert('Error', 'Still fetching payment-intent');
}

setLoading(true);

const { paymentIntent: retrievedIntent, error: retrieveError } =
await retrievePaymentIntent(clientSecret);

if (retrieveError || !retrievedIntent) {
setLoading(false);
return Alert.alert('Error', 'Failed to retrieve PaymentIntent');
}

const { paymentIntent: collectedIntent, error: collectError } =
await collectPaymentMethod({
paymentIntent: retrievedIntent,
updatePaymentIntent: true,
enableCustomerCancellation: true,
});

if (collectError || !collectedIntent) {
setLoading(false);
return finalizePayment(collectError || new Error('Collection failed'), null);
}

const { paymentIntent: processedIntent, error: processError } =
await processPayment(collectedIntent.id);

await finalizePayment(processError, processedIntent?.id);
};

#

and this is fetch payment intent which i think works properly now

const fetchPaymentIntent = useCallback(async selectedMode => {
if (totalAmount <= 0) return null;
try {
const res = await fetch(${API}/create-payment-intent, {
method : 'POST',
headers: { 'Content-Type': 'application/json' },
body : JSON.stringify({
amount : totalAmount,
in_person : selectedMode === 'reader',
}),
});
const data = await res.json();
if (res.ok && data?.data?.clientSecret) {
console.log('[clientSecret]', data.data.clientSecret);
setClientSecret(data.data.clientSecret);
return data.data.clientSecret;
} else {
Alert.alert('Error', data.message || 'Unable to create PI');
return null;
}
} catch {
Alert.alert('Error', 'Network error');
return null;
}
}, [totalAmount]);

#

func (app *application) CreatePaymentIntent(w http.ResponseWriter, r *http.Request) {
log.Println("[Stripe] Incoming request: CreatePaymentIntent")

var payload struct {
    Amount    float64 `json:"amount"`    
    InPerson  bool    `json:"in_person"` 
                                            
}

if err := app.readJSON(w, r, &payload); err != nil {
    app.errorJSON(w, err, http.StatusBadRequest)
    return
}
log.Printf("[Stripe] Amount: $%.2f | InPerson: %v\n", payload.Amount, payload.InPerson)


amountCents := int64(payload.Amount * 100)


var params *stripe.PaymentIntentParams

if payload.InPerson {
    
    params = &stripe.PaymentIntentParams{
        Amount:   stripe.Int64(amountCents),
        Currency: stripe.String(string(stripe.CurrencyUSD)),
        PaymentMethodTypes: []*string{
            stripe.String("card_present"),
        },
        
    }
    log.Println("[Stripe] Creating IN-PERSON (card_present) PaymentIntent…")
} else {
    
    params = &stripe.PaymentIntentParams{
        Amount:   stripe.Int64(amountCents),
        Currency: stripe.String(string(stripe.CurrencyUSD)),
        AutomaticPaymentMethods: &stripe.PaymentIntentAutomaticPaymentMethodsParams{
            Enabled: stripe.Bool(true),
        },
        
    }
    log.Println("[Stripe] Creating ONLINE (card) PaymentIntent…")
}


pi, err := paymentintent.New(params)
if err != nil {
    log.Printf("[Stripe] Failed to create PaymentIntent: %v\n", err)
    app.errorJSON(w, err, http.StatusInternalServerError)
    return
}


resp := JSONResponse{
    Error: false,
    Data:  map[string]string{"clientSecret": pi.ClientSecret},
}
app.writeJSON(w, http.StatusOK, resp)

}
this is my payment backend handler in go.

young wyvern
#

Hi @night forge I'm also an engineer from Stripe. Can you add some logs to your code to print out where this error is thrown from (e.g., is it from collectPaymentMethod or confirmPayment?)

night forge
#

okay one second

#

Server response: {"data": {"clientSecret": "pi_3RgIsoBo2H3RxTBK3VNraJZf_secret_6N0Nj2yPHJQU14nGhg4C1tDXE"}, "error": false, "message": ""}
(NOBRIDGE) LOG [Stripe] âś… Received clientSecret: pi_3RgIsoBo2H3RxTBK3VNraJZf_secret_6N0Nj2yPHJQU14nGhg4C1tDXE
(NOBRIDGE) LOG [Stripe] Retrieving PaymentIntent from Stripe
(NOBRIDGE) LOG [Stripe] Collecting payment method from reader…
(NOBRIDGE) LOG [Stripe] ❌ collectPaymentMethod failed: This feature is currently not available for the selected reader.
(NOBRIDGE) LOG [Stripe] Finalizing payment…
(NOBRIDGE) LOG [Stripe] ❌ Stripe payment error: This feature is currently not available for the selected reader.

young wyvern
#

Got it, so the problem occred at payment method collection

night forge
#

yup

#

const handleReaderPayment = async () => {
console.log('[Stripe] Starting handleReaderPayment');

if (!reader) {
console.log('[Stripe] ❌ No reader connected');
return Alert.alert('Error', 'No reader connected');
}

console.log('[Stripe] Fetching new PaymentIntent…');
const currentSecret = await fetchPaymentIntent('reader');
if (!currentSecret) {
console.log('[Stripe] ❌ Failed to fetch PaymentIntent');
return Alert.alert('Error', 'Still fetching payment-intent');
}

setLoading(true);

console.log('[Stripe] Retrieving PaymentIntent from Stripe');
const { paymentIntent: retrievedIntent, error: retrieveError } =
await retrievePaymentIntent(clientSecret);

if (retrieveError || !retrievedIntent) {
console.log('[Stripe] ❌ Failed to retrieve PaymentIntent:', retrieveError?.message);
setLoading(false);
return Alert.alert('Error', 'Failed to retrieve PaymentIntent');
}

console.log('[Stripe] Collecting payment method from reader…');
const { paymentIntent: collectedIntent, error: collectError } =
await collectPaymentMethod({
paymentIntent: retrievedIntent,
updatePaymentIntent: true,
enableCustomerCancellation: true,
});

if (collectError || !collectedIntent) {
console.log('[Stripe] ❌ collectPaymentMethod failed:', collectError?.message);
setLoading(false);
return finalizePayment(collectError || new Error('Collection failed'), null);
}

console.log('[Stripe] Processing payment…');
const { paymentIntent: processedIntent, error: processError } =
await processPayment(collectedIntent.id);

if (processError) {
console.log('[Stripe] ❌ processPayment failed:', processError.message);
} else {
console.log('[Stripe] âś… Payment processed successfully:', processedIntent?.id);
}

await finalizePayment(processError, processedIntent?.id);
};

#

my tap to pay not activating so it wont reach my finalize properly

young wyvern
#

Can you set updatePaymentIntent to false?

night forge
#

same issue

#

(NOBRIDGE) LOG [Stripe] Retrieving PaymentIntent from Stripe
(NOBRIDGE) LOG [Stripe] Collecting payment method from reader…
(NOBRIDGE) LOG [Stripe] ❌ collectPaymentMethod failed: This feature is currently not available for the selected reader.
(NOBRIDGE) LOG [Stripe] Finalizing payment…
(NOBRIDGE) LOG [Stripe] ❌ Stripe payment error: This feature is currently not available for the selected reader.

young wyvern
#

set enableCustomerCancellation to false as well

night forge
#

okay one sec

#

i have to restart app each time haha

#

okay it says reader connected now

#

its processing im testing

young wyvern
#

No problem, M2 reader doesn't have a display so it doesn't provide an option for customer to cancel on the device

night forge
#

[Stripe terminal]: didRequestReaderDisplayMessage tryAnotherReadMethod
(NOBRIDGE) LOG [Stripe terminal]: didRequestReaderInput ["swipeCard", "insertCard", "tapCard"]
(NOBRIDGE) LOG [Stripe terminal]: didRequestReaderDisplayMessage removeCard
(NOBRIDGE) LOG [Stripe terminal]: didChangePaymentStatus ready
(NOBRIDGE) LOG [Stripe] Processing payment…

its just been stuck at this

young wyvern
#

OK, so it doesn't raise error for collectPaymentMethod now

night forge
#

no the tap had activated

young wyvern
#

I'm not following

night forge
#

let me see if it processed in my dashboard

#

so the tap to pay activated and i tapped my card.

#

now its just stuck at processing payment

young wyvern
#

Ok, what's the paymentIntent ID?

night forge
#

pi_3RgIybBo2H3RxTBK0ENxcQXT_secret_mAvh6cXwaXe85Ia5FRrMLDngM

young wyvern
#

I don't see any payment intent confirmation request, and also this is in livemode.

#

I'd suggest use sandbox during development

night forge
#

i dont see it in my dashboard either

young wyvern
#

Can you also share with me the reader ID?

night forge
#

[Stripe terminal]: didUpdateDiscoveredReaders [{"availableUpdate": null, "batteryLevel": 1, "batteryStatus": "nominal", "deviceSoftwareVersion": "2.01.00.35-SZZZ_Prod_US_v12-481001", "deviceType": "stripeM2", "id": null, "ipAddress": null, "isCharging": false, "label": null, "location": {"address": [Object], "displayName": "home", "id": "tml_GGBqowM4DFED9J", "livemode": true}, "locationId": "tml_GGBqowM4DFED9J", "locationStatus": "set", "serialNumber": "STRM26214022988", "simulated": false, "status": "offline"}]
this is the discovered reader

#

"serialNumber": "STRM26214022988"

#

thats the serial number

young wyvern
#

Ok, let me take a look

#

hmm, I don't see any requests from your reader to confirm the payment Does processPayment return?

    await processPayment(collectedIntent.id);```
#

Did you use a valid card to tap the reader?

night forge
#

ya i used a vallid card

#

and no process payment doesnt return

#

its just stuck at processing payment indefinitely

young wyvern
#

Hmm, can you try another card?

night forge
#

i dont have another one on me right now.

#

what could the issue with the payment id be for it not showing up in my dashboard?

young wyvern
#

You should try again with another card. And I'd also highly recommend you getting a test Terminal card and work on your development on sandbox mode

night forge
#

okay how do i get a test terminal card

young wyvern
night forge
#

could it be that im not asking for the pin or something in my app?

#

thats why its getting stuck at processing payment indefinitely?

young wyvern
#

I don't think that's related. Currently I don't have sufficient info to determine the cause of the problem