Stipe, React Native, [Unhandled Promise Rejection: SyntaxError: JSON Parse Error: Unexpected Identifier "Error"]
I'm developing an app with Expo, Firebase Cloud Function and Stripe, for some reason the first time I navigate to the screen CardPayment
the code returns the error: [Unhandled promise rejection: SyntaxError: JSON Parse error: Unexpected identifier "Error"]
, but if I refresh the screen the code runs perfectly. Anyone have any idea why and how I can fix it? I've tried a bunch of stuff, even using axios, but nothing seems to be working.
Backend
exports.addCardForExistingCustomer = functions.https.onRequest(async (req, res) => {
const ephemeralKey = await stripe.ephemeralKeys.create(
{customer: `${req.query.customer}`},
{apiVersion: '2020-08-27'}
);
const setupIntent = await stripe.setupIntents.create({
customer: `${req.query.customer}`
});
const paymentMethods = await stripe.paymentMethods.list({
customer: `${req.query.customer}`,
type: 'card',
});
res.json({
setupIntent: setupIntent.client_secret,
ephemeralKey: ephemeralKey.secret,
customer: `${req.query.customer}`,
paymentMethods: paymentMethods,
})
});
Frontend
export default function CardPayment() {
const { initPaymentSheet, presentPaymentSheet } = useStripe();
const [loading, setLoading] = useState(false);
const [customerId, setCustomerId] = useState('');
const fetchPaymentSheetParams = async () => {
const response = await fetch(`https://<<path>>.cloudfunctions.net/addCardForExistingCustomer?customer=${customerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
});
const { setupIntent, ephemeralKey, customer } = await response.json();
return {
setupIntent,
ephemeralKey,
customer,
};
};
const initializePaymentSheet = async () => {
const {
setupIntent,
ephemeralKey,
customer,
} = await fetchPaymentSheetParams();
console.log(setupIntent)
const { error } = await initPaymentSheet({
customerId: customer,
customerEphemeralKeySecret: ephemeralKey,
setupIntentClientSecret: setupIntent,
});
if (!error) {
setLoading(true);
} else {
console.log(error)
}
};
const openPaymentSheet = async () => {
const { error } = await presentPaymentSheet();
if (!error) {
Alert.alert('Success', 'Your payment method is successfully set up for future payments!');
}
};
const fetchCustomer = async () => {
const fetchInformation = doc(db, 'clients', 'user', 'Information', auth.currentUser.uid)
await getDoc(fetchInformation)
.then((snapshot) => {
const stripeId = snapshot.data().stripeCustomerId
setCustomerId(stripeId)
initializePaymentSheet();
})
}
useEffect(() => {
fetchCustomer()
}, []);
if (loading == false) {
return (
<View>
<ActivityIndicator/>
</View>
)
} else {
return (
<View>
<CustomButton
buttonTxt={'Add Credit/Debit Card'}
txtColor={'white'}
backgroundColor={'black'}
onPress={openPaymentSheet}
/>
</View>
)
}
}
Answer
fetchCustomer
on the frontend isn't waiting for the getDoc
promise chain to complete. Try putting return
or await
before the call to getDoc
. If return
is used, fetchCustomer
as posted doesn't need to be an async
function.
If this resolves the error, my guess would be that some kind of response caching is allowing the then
handler of getDoc(fetchInformation)
to win a race condition set up in promise job handling (in the microtask queue) when the page is reloaded.
It is not self-evident why this handler (async (snapshot) => {...}
) has been declared as an async
function - it appears to be straight forward synchronous code.
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM