i am creating a website in "next.js" with the backend of "Strapi". This is a simple ecommerce type project. The payment gateway i am using is "Stripe". I included my code for checkout in both frontend and the backend and when i am using test mode in "Stripe" it is working well but when i am putting my real credentials there is showing an error.
{"error": {
"message": "You cannot accept payments using this API as it is no longer supported in India. Please refer to https://stripe.com/docs/payments for accepting payments.",
"type": "invalid_request_error"}}
I am confused why this is working fine in demo and not in real.
Below is my code:-
"use strict";
/**
* order controller
*/
const stripe = require("stripe")(
"sk_test_my_test_code_from_stripe"
);
const { createCoreController } = require("@strapi/strapi").factories;
module.exports = createCoreController("api::order.order", ({ strapi }) => ({
async create(ctx) {
const {
shippingAdress,
city,
state,
amount,
pin,
mobile_number,
name,
token,
items,
} = ctx.request.body;
await stripe.charges.create({
amount: amount * 100,
currency: "INR",
source: token,
description: `order by user ${ctx.state.user.email}`,
});
const order = await strapi.db.query("api::order.order").create({
data: {
shippingAdress,
city,
state,
amount,
pin,
mobile_number,
name,
token,
items,
user: ctx.state.user.email,
},
});
return order;
},
}));
my next.js frontend
import React,{useState} from 'react'
import { useRouter } from 'next/router'
import {loadStripe} from '@stripe/stripe-js';
import {BACKEND_URL} from '../helper/baseUrl'
import {
CardElement,
Elements,
useStripe,
useElements,
} from '@stripe/react-stripe-js';
// import { strip } from 'jest-docblock';
import { useCart } from 'react-use-cart';
// import {BACKEND_URL} from '../helpers'
const stripePromise = loadStripe('pk_test_code_from_stripe');
const CheckoutForm = () => {
const router = useRouter()
const [formData,setFormData] = useState({})
const [payProcessing,setPayProcessing] = useState(false)
const [error,setError] = useState(false)
const [done,setDone] = useState(false)
const stripe = useStripe();
const elements = useElements();
const {cartTotal,items,emptyCart} = useCart()
const [paybutton,setPayButton] = useState(true)
//amount,shippingAddress,city,state,pin,token
const handleChange = (e)=>{
setFormData({
...formData,
[e.target.name]:e.target.value
})
}
const makePaymentRequest = async (allformData)=>{
try{
const res = await fetch(`${BACKEND_URL}/api/orders`,{
method:"post",
headers:{
"Content-Type":"application/json",
"Authorization":"Bearer "+localStorage.getItem("jwt")
},
body:JSON.stringify(allformData)
})
if(res.status != 200) throw Error('Payment failed')
return await res.json()
}catch(err){
console.log(err)
setError(true)
}
}
const handleSubmit = async (event) => {
event.preventDefault();
if (elements == null) {
return;
}
const cardElement = elements.getElement(CardElement)
const payload = await stripe.createToken(cardElement)
const allFormData = {
...formData,
token:payload.token.id,
amount:cartTotal,
items:items
}
setPayProcessing(true)
await makePaymentRequest(allFormData)
setDone(true)
setPayProcessing(false)
emptyCart()
};
if(error) return <div className="text-center"> <h1 className="text-danger mt-5">Payment failed</h1></div>
if(done) return <div className="text-center"><h1 className="text-success mt-5">Payment done successfully</h1> </div>
// if(payProcessing) return <h1>Payment is processing...</h1>
if(payProcessing) return <div className="text-center"> <h1 className="text-success mt-5">Wait, Processing Your Payment</h1> </div>
return (
<form className='mt-5' onSubmit={handleSubmit}>
<div className="mb-3">
<input
type="text"
name="shippingAdress"
placeholder="Your Address"
onChange={handleChange}
className="form-control"
required
/>
</div>
<div className="mb-3">
<input
type="text"
name="city"
placeholder="City"
onChange={handleChange}
className="form-control"
required
/>
</div>
<div className="mb-3">
<input
type="text"
name="state"
placeholder="State"
onChange={handleChange}
className="form-control"
required
/>
</div>
<div className="mb-3">
<input
type="number"
name="pin"
placeholder="Pin Code"
onChange={handleChange}
className="form-control"
required
/>
</div>
<div className="mb-3">
<input
type="number"
name="mobile_number"
placeholder="Mobile Number"
onChange={handleChange}
className="form-control"
required
/>
</div>
<div className="mb-3">
<input
type="text"
name="name"
placeholder="Name"
onChange={handleChange}
className="form-control"
required
/>
</div>
<CardElement onChange={(e)=>{
if(e.complete){
setPayButton(false)
}else{
setPayButton(true)
}
}} />
<br />
<div className="text-center">
<button className="btn btn-success" style={{width:'40%'}} type="submit" disabled={(!stripe || !elements) || paybutton}>
Pay Now
</button>
</div>
</form>
)
}
const Checkout = ()=>{
return(
<Elements stripe={stripePromise}>
<CheckoutForm />
</Elements>
)
}
export default Checkout
my package.json
{
"name": "project",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@apollo/client": "^3.5.5",
"@auth0/nextjs-auth0": "^1.7.0",
"@stripe/react-stripe-js": "^1.7.0",
"@stripe/stripe-js": "^1.22.0",
"aos": "^2.3.4",
"graphql": "^16.3.0",
"next": "12.0.9",
"react": "17.0.2",
"react-carousel-slider": "^2.0.13",
"react-countup": "^6.1.1",
"react-dom": "17.0.2",
"react-image-gallery": "^1.2.7",
"react-number-easing": "^1.0.2",
"react-toastify": "^8.1.0",
"react-use-cart": "^1.13.0",
"tiny-slider": "^2.9.4"
},
"devDependencies": {
"eslint": "8.7.0",
"eslint-config-next": "12.0.9"
}
}
As per latest RBI guidelines, Stripe has switched from Charges API to Payment Intent API. Use below API as per data:
Stripe::PaymentIntent.create(
:customer => customer.id,
:amount => params[:amount],
:description => 'Rails Stripe transaction',
:currency => 'usd',
)
It worked for me. Checkout Stripe API documentation here
It might be cause you're using charges API, which does not support 3d secure transactions.
Try to use payment intents API, it supports 3d secure transactions, it'll work.
However you'll get payment acknowledgment response through webhooks
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.