我已经构建了一个电子商务Web应用程序,我正在尝试使用Stripe集成支付网关。
我用Firebase函数做后台...
我已经使用了条纹支付元素来构建一个卡表单,所以当我点击Buy Now按钮时,
enter image description here
enter image description here
Stripe API正在更新状态为requires_payment_method
{
> id: 'pi_3O19vcSHgvSf9YWJ1IG2OQz6',
> object: 'payment_intent',
> amount: 4839800,
> amount_capturable: 0,
> amount_details: { tip: {} },
> amount_received: 0,
> application: null,
> application_fee_amount: null,
> automatic_payment_methods: null,
> canceled_at: null,
> cancellation_reason: null,
> capture_method: 'automatic',
> client_secret: 'pi_3O19vcSHgvSf9YWJ1IG2OQz6_secret_bDfh5jdZ42kEwJSAkhmKV66Hr',
> confirmation_method: 'automatic',
> created: 1697297940,
> currency: 'inr',
> customer: null,
> description: null,
> invoice: null,
> last_payment_error: null,
> latest_charge: null,
> livemode: false,
> metadata: {},
> next_action: null,
> on_behalf_of: null,
> payment_method: null,
> payment_method_configuration_details: null,
> payment_method_options: {
> card: {
> installments: null,
> mandate_options: null,
> network: null,
> request_three_d_secure: 'automatic'
> }
> },
> payment_method_types: [ 'card' ],
> processing: null,
> receipt_email: null,
> review: null,
> setup_future_usage: null,
> shipping: null,
> source: null,
> statement_descriptor: null,
> statement_descriptor_suffix: null,
> status: 'requires_payment_method',
> transfer_data: null,
> transfer_group: null
}
下面是后端index.js文件
const functions = require("firebase-functions");
const cors = require("cors");
const express = require("express");
// const stripe = require("stripe")(process.env.REACT_APP_STRIPE_S_KEY);
const stripe = require("stripe")(
"sk_test_51Lx20gSHgvSf9YWJE38GQ3cVmP0AGMzoN5DDV9HKWkmXTdNUZg3sYGc2awYKggWJ70cjpKYmXMJjjvBXn9r4nj1Z009XYH8Yiw"
);
// config
const app = express();
app.use(express.json());
app.use(cors()); //CORS == cross object references
app.get("/config", (req, res) =>
res.send({
publishablekey:
"pk_test_51Lx20gSHgvSf9YWJnU5hpwZ8HmOUodPhMjoimQNjuu1GPQumoAV0ip6OficVVnszkjpFijVv5Kl8Amt0imLnt3pD00MtJASpXe",
})
);
app.post("/payment/create", async (req, res) => {
const total = req.query.total;
console.log(total);
const paymentIntent = await stripe.paymentIntents.create({
amount: total,
currency: "INR",
payment_method_types: ["card"],
// automatic_payment_methods: { enabled: true },
});
console.log(paymentIntent);
res.status(201).send({
clientSecret: paymentIntent.client_secret,
});
});
// app.listen(5252, () =>
// console.log(`Node server listening at http://localhost:5252`)
// );
exports.api = functions.https.onRequest(app);
下面是Payments.jsx文件
import { useEffect, useState } from "react";
import { loadStripe } from "@stripe/stripe-js";
import { final_subtotal } from "./Reducer";
import React from "react";
import AxiosToFetch from "../axios";
import { useStateValue } from "./StateProvider";
import { Link } from "react-router-dom";
import CartProducts from "./CartProducts";
import CheckoutForm from "./CheckoutForm";
import { Elements } from "@stripe/react-stripe-js";
const Payments = () => {
const [{ Cart }, dispatch] = useStateValue();
const [stripepromise, setStripepromise] = useState(null);
const [clientSecret, setClientSecret] = useState("");
/* eslint-disable */
useEffect(() => {
AxiosToFetch({
method: "post",
url: `/payment/create?total=${final_subtotal(Cart) * 100}`,
}).then(async (res) => {
console.log(res);
const clintSecret = await res.data.clientSecret;
setClientSecret(clintSecret);
});
}, [Cart]);
useEffect(() => {
AxiosToFetch.get("/config").then(async (r) => {
const { publishablekey } = await r.data;
setStripepromise(loadStripe(publishablekey));
});
}, []);
const appearance = {
theme: "night",
labels: "floating,",
};
const options = {
clientSecret,
appearance,
};
return (
<div className="container-fluid">
<h2 className="text-center p-2">
Your Checkout{" "}
<Link className="text-warning" to="/cart">
{Cart.length} items
</Link>
</h2>
<hr />
{/* this above tag is used to draw a horizontal line */}
<h3 className="mt-2">Review items and dehlivery </h3>
<div className="container">
{Cart.map((item) => (
<CartProducts
id={item.id}
image={item.image}
title={item.title}
price={item.price}
ratings={0}
/>
))}
</div>
<hr/>
{
clientSecret && stripepromise &&
<Elements stripe={stripepromise} options={options}>
<CheckoutForm />
</Elements>}
</div>
);
};
export default Payments;
下面是Checkoutform.jsx文件
import { useState } from "react";
import {
useStripe,
useElements,
PaymentElement,
} from "@stripe/react-stripe-js";
import { useNavigate } from "react-router-dom";
import { final_subtotal } from "./Reducer";
import { useStateValue } from "./StateProvider";
import CurrencyFormat from "react-currency-format";
const CheckoutForm = () => {
const [{ Cart }, dispatch] = useStateValue();
let total_price = final_subtotal(Cart);
const navigate = useNavigate();
const stripe = useStripe();
const elements = useElements();
const [message, setMessage] = useState(null);
const [processing, setProcessing] = useState(false);
const handlesubmit = async (e) => {
e.preventDefault();
if (!stripe || !elements) {
alert("getting in valid response");
}
setProcessing(true);
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: navigate("/order"),
},
});
if (error) {
setMessage(error.message);
}
setProcessing("false");
};
return (
<form
className="card container bg-dark "
style={{ width: "30rem" }}
onSubmit={handlesubmit}
>
<div className="card-body">
<div className="card-title">
<PaymentElement />
</div>
<div className="card-title ">
<CurrencyFormat
renderText={(value) => (
<>
<h5>
Order Total ({Cart?.length} items) : {value}
</h5>
</>
)}
decimalScale={2}
displayType="text"
value={total_price}
thousandSeparator={true}
prefix="₹"
/>
</div>
<div className="card-title text-center pt-1">
<button
className=" btn btn-warning "
style={{ minWidth: "20rem" }}
disabled={total_price === 0 ? true : false && processing}
>
Buy Now
</button>
<div className="text-danger pt-1">{message}</div>
</div>
</div>
</form>
);
};
export default CheckoutForm;
请告诉我哪里出错了……
1条答案
按热度按时间7hiiyaii1#
您可以在Dashboard request log上进行确认,但
requires_payment_method
通常意味着确认调用失败或从未发生。您可能希望在您的“提交”函数周围添加更多的调试日志。