I am implementing a payment system with Stripe extension for firebase in a react native. However, i do not know how to behave in the following situation:
- I write initial information for the checkout_session when the user wants to proceed to checkout:
const initializeCheckout = () => {
//write initial payment data
const writePaymentDetails = async () => {
await setDoc(doc(getFirestore(), 'customers', getAuth().currentUser.uid, 'checkout_sessions', getAuth().currentUser.uid),{
client: 'mobile',
mode: 'payment',
amount: subTotal,
currency: 'chf',
});
}
writePaymentDetails();
navigation.navigate('Checkout');
}
After that, a stripe extension in firebase adds all the additional information (ephemeral keys, stripe customer key etc.) to the checkout_session document.
After additional data is written, i want to navigate to the checkout page and then initialize and open paymentSheet in react native as it is indicated in the official stripe tutorial
The checkout screen i implemented:
export default function CheckoutScreen() {
const { initPaymentSheet, presentPaymentSheet } = useStripe();
const [loading, setLoading] = useState(false);
const fetchPaymentSheetParams = async () => {
console.log('still works after calling fetchPaymentSheetParams');
const checkoutSessionDoc = await getDoc(doc(getFirestore(), 'customers', getAuth().currentUser.uid, 'checkout_sessions', getAuth().currentUser.uid));
const paymentIntent = checkoutSessionDoc.data().paymentIntentClientSecret;
const ephemeralKey = checkoutSessionDoc.data().ephemeralKeySecret;
const customer = checkoutSessionDoc.data().customer;
console.log(paymentIntent, ephemeralKey, customer);
return{
paymentIntent: paymentIntent,
ephemeralKey,
customer,
};
};
const initializePaymentSheet = async () => {
const {
paymentIntent,
ephemeralKey,
customer,
} = await fetchPaymentSheetParams();
const { error } = await initPaymentSheet({
customerId: customer,
customerEphemeralKeySecret: ephemeralKey,
paymentIntentClientSecret: paymentIntent,
allowsDelayedPaymentMethods: false,
});
if (!error) {
setLoading(true);
}
};
const openPaymentSheet = async () => {
const { error } = await presentPaymentSheet();
if (error) {
Alert.alert(`Error code: ${error.code}`, error.message);
} else {
Alert.alert('Success', 'Your order is confirmed!');
}
};
useEffect(() => {
console.log('Payment sheet is being initialized');
initializePaymentSheet();
}, []);
return (
<View style={{flex: 1, justifyContent: 'center'}}>
<Button
disabled={loading}
title="Checkout"
onPress={openPaymentSheet}
/>
</View>
);
}
However, i don't know how to wait until the firebase function ends in step 2 before moving to the next step. Now, if i navigate to the checkout screen just after writing the initial data and try to read an ephemeral key, stripe customer key and payment intent, they are undefined.
So, my question is how to make the transition correctly so that the additional information is not undefined?