I’m encountering an error while integrating Stripe payment into my React Native app with an Express.js backend. When attempting to process payments, I’m receiving the following error message: "As per Indian regulations, only registered Indian businesses can accept international payments." This error is preventing the payment from being processed.
I am using
"stripe": "^14.18.0", at back end.
And Front end.
"@stripe/stripe-react-native": "~0.35.1",
Backend: Express.js
const stripe = require("stripe")(process.env.STRIPEKEY, {
apiVersion: "2023-10-16",
});
const createIntent = asyncHandler(async (req, res) => {
try {
const paymentIntent = await stripe.paymentIntents.create({
amount: req.body.amount * 100,
currency: "inr",
description: "Software development services",
payment_method_types: ["card"],
});
res.status(200).json({ clientSecret: paymentIntent.client_secret });
} catch (e) {
console.error("Error creating PaymentIntent:", error);
res.status(500).json({ error: "Failed to create PaymentIntent" });
}
});
Frontend: React Native
import {
Text,
FlatList,
View,
StyleSheet,
Pressable,
ActivityIndicator,
Alert,
} from "react-native";
import { useDispatch, useSelector } from "react-redux";
import React, { useState, useEffect } from "react";
import { useStripe } from "@stripe/stripe-react-native";
import Constants from "expo-constants";
import axios from "axios"; // Import Axios
const PaymentScreen = () => {
const FreshSabzi_API_URL = Constants?.expoConfig?.extra?.FreshSabzi_API_URL;
const { initPaymentSheet, presentPaymentSheet } = useStripe();
const [clientSecret, setClientSecret] = useState("");
useEffect(() => {
fetchPaymentIntentClientSecret();
}, []);
const fetchPaymentIntentClientSecret = async () => {
try {
const response = await axios.post(`${FreshSabzi_API_URL}payment/intent`, {
amount: 55,
});
setClientSecret(response.data.clientSecret);
} catch (error) {
console.error("Error fetching PaymentIntent client secret:", error);
// Handle the error (e.g., display an error message)
}
};
const onCheckout = async () => {
// 1. Create a payment intent
// const response = await createPaymentIntent({
// amount: Math.floor(10 * 100),
// });
// if (response.error) {
// Alert.alert("Something went wrong");
// return;
// }
console.log("clientSecret: " + clientSecret);
// 2. Initialize the Payment sheet
const initResponse = await initPaymentSheet({
merchantDisplayName: "notJust.dev",
paymentIntentClientSecret: clientSecret,
defaultBillingDetails: {
name: "Jane Doe",
},
});
if (initResponse.error) {
console.log(initResponse.error);
Alert.alert("Something went wrong");
return;
}
console.log("presentPaymentSheet started: ");
// 3. Present the Payment Sheet from Stripe
const paymentResponse = await presentPaymentSheet();
console.log("paymentResponse :" + JSON.stringify(paymentResponse));
if (paymentResponse.error) {
Alert.alert(
`Error code: ${paymentResponse.error.code}`,
paymentResponse.error.message
);
return;
}
// 4. If payment ok -> create the order
onCreateOrder();
};
const onCreateOrder = async () => {
Alert.alert("Order has been submitted");
};
return (
<>
<Pressable onPress={onCheckout} style={styles.button}>
<Text style={styles.buttonText}>Checkout</Text>
</Pressable>
</>
);
};
const styles = StyleSheet.create({
totalsContainer: {
margin: 20,
paddingTop: 10,
borderColor: "gainsboro",
borderTopWidth: 1,
},
row: {
flexDirection: "row",
justifyContent: "space-between",
marginVertical: 2,
},
text: {
fontSize: 16,
color: "gray",
},
textBold: {
fontSize: 16,
fontWeight: "500",
},
button: {
position: "absolute",
backgroundColor: "black",
bottom: 30,
width: "90%",
alignSelf: "center",
padding: 20,
borderRadius: 100,
alignItems: "center",
},
buttonText: {
color: "white",
fontWeight: "500",
fontSize: 16,
},
});
export default PaymentScreen;
Error message on Stripe in "last_payment_error":
"message": "As per Indian regulations, only registered Indian
businesses (i.e. sole proprietorships, limited liability partnerships
and companies, but not individuals) can accept international payments.
More info here: https://stripe.com/docs/india-exports
In timeline getting below message:
3D Secure attempt acknowledged 3D Secure was completed, but the
customer hasn’t been verified because the bank does not support 3D
Secure, has not set up 3D Secure for the card, or is experiencing an
outage. The card network has provided proof of the attempt.
Please help me to know where I am missing something. I am trying with Stripe Developer account in test mode.
Note: I want to understand what exactly I need to do next to remove this error. Can anyone suggest what should be the next step?
2
Answers
Solution Found: Using Indian Test Card
After further investigation, I realized that there was no issue with the code provided in the question. The main problem was with the card used for testing purposes.
I was using a US test card for transactions in INR, which led to the error mentioned in the question. The correct approach is to use an Indian test card specifically designed for transactions in INR.
For testing purposes in INR, it's recommended to use the following Indian Test Visa Card:
I had similar problem and am using django. USE credit card number=4000 0035 6000 0008. (DO NOT USE credit card number= 4242 4242 4242 4242). I did not use any webhook.
The view.py: