[英]The PaymentIntent requires a payment method — React, Django Rest
I have a React app and a Django Rest API.我有一个 React 应用程序和一个 Django Rest API。
My goal is to get the PaymentRequestButtonElement working.我的目标是让 PaymentRequestButtonElement 正常工作。
In my Stripe dashboard (test mode) I get the following logs:在我的 Stripe 仪表板(测试模式)中,我得到以下日志:
200 OK
POST
/v1/payment_intents
12:22:55 PM
200 OK
POST
/v1/payment_methods
12:22:54 PM
200 OK
POST
/v1/tokens
12:22:53 PM
But in the Payments tab, I get the following:但是在“付款”选项卡中,我得到以下信息:
The PaymentIntent requires a payment method
Here is my React component:这是我的 React 组件:
import React, { useState, useEffect } from 'react';
// import { useNavigate } from 'react-router-dom';
// import { useShoppingCart } from 'use-shopping-cart';
import {
PaymentRequestButtonElement,
useStripe,
} from '@stripe/react-stripe-js';
const PaymentRequest = () => {
// const history = useNavigate();
// const { totalPrice, cartDetails, cartCount } = useShoppingCart();
const stripe = useStripe();
const [paymentRequest, setPaymentRequest] = useState(null);
const price = 350;
const handleButtonClicked = (event) => {
// if (!cartCount) {
// event.preventDefault();
// alert('Cart is empty!');
// return;
// }
paymentRequest.on('paymentmethod', handlePaymentMethodReceived);
paymentRequest.on('cancel', () => {
paymentRequest.off('paymentmethod');
});
return;
};
const handlePaymentMethodReceived = async (event) => {
// Send the cart details and payment details to our function.
const paymentDetails = {
payment_method: event.paymentMethod.id,
shipping: {
name: event.shippingAddress.recipient,
phone: event.shippingAddress.phone,
address: {
line1: event.shippingAddress.addressLine[0],
city: event.shippingAddress.city,
postal_code: event.shippingAddress.postalCode,
state: event.shippingAddress.region,
country: event.shippingAddress.country,
},
},
};
const response = await fetch('https://my-api/create-payment-intent/', {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
// cartDetails,
paymentDetails,
amount: price,
currency: 'usd',
payment_method: 'card'
// automatic_payment_methods: true,
}),
}).then((res) => {
return res.json();
});
if (response.error) {
// Report to the browser that the payment failed.
console.log(response.error);
event.complete('fail');
} else {
// Report to the browser that the confirmation was successful, prompting
// it to close the browser payment method collection interface.
event.complete('success');
// Let Stripe.js handle the rest of the payment flow, including 3D Secure if needed.
const { error, paymentIntent } = await stripe.confirmCardPayment(
response.paymentIntent.client_secret
);
if (error) {
console.log(error);
return;
}
if (paymentIntent.status === 'succeeded') {
console.log('Payment succeeded!');
} else {
console.warn(
`Unexpected status: ${paymentIntent.status} for ${paymentIntent}`
);
}
}
};
useEffect(() => {
if (stripe && paymentRequest === null) {
const pr = stripe.paymentRequest({
country: 'US',
currency: 'usd',
total: {
label: 'Demo total',
//
amount: price,
pending: true,
},
requestPayerName: true,
requestPayerEmail: true,
requestShipping: true,
shippingOptions: [
{
id: 'standard-global',
label: 'Global shipping',
detail: 'Handling and delivery fee',
amount: 350,
},
],
});
// Check the availability of the Payment Request API first.
pr.canMakePayment().then((result) => {
if (result) {
setPaymentRequest(pr);
}
});
}
}, [stripe,
paymentRequest,
// totalPrice
]);
useEffect(() => {
if (paymentRequest) {
paymentRequest.update({
total: {
label: 'Demo total',
amount: 350,
pending: false,
},
});
}
}, [
// totalPrice,
paymentRequest
]);
if (paymentRequest) {
return (
<div className="payment-request-button">
<PaymentRequestButtonElement
options={{ paymentRequest }}
onClick={handleButtonClicked}
/>
--- OR ---
</div>
);
}
return '';
};
export default PaymentRequest;
and here is my Django REST View这是我的 Django REST 查看
class PaymentIntentView(APIView):
def post(self, request, *args, **kwargs):
amount = request.data.get('amount')
currency = request.data.get('currency')
# automatic_payment_methods = request.data.get('automatic_payment_methods')
try:
intent = stripe.PaymentIntent.create(
amount=amount,
currency=currency,
# automatic_payment_methods={
# 'enabled': True,
# },
# You can also add other options like capture_method, setup_future_usage, etc.
)
return Response({'client_secret': intent.client_secret, 'id': intent.id})
except Exception as e:
return Response({'error': str(e)})
I've tried variations of passing automatic_payments as true and passing the payment_method as 'card', no joy我已经尝试过将 automatic_payments 作为 true 传递并将 payment_method 作为“卡”传递的变体,没有快乐
There's a couple of options that you can do in order to fix the problem here.您可以执行几个选项来解决此处的问题。
Option 1: Pass the PM in the backend方案一:在后台传递PM
When you call fetch on https://my-api/create-payment-intent/ you are passing the paymentDetails
that you're not using in your stripe.PaymentIntent.create
method.当您在 https://my-api/create-payment-intent/ 上调用 fetch 时,您将传递未在
paymentDetails
方法中使用的stripe.PaymentIntent.create
。 For this to work, you need to first deserialize your request to get access to this information since it's nested (eg this guide ).为此,您需要首先反序列化您的请求以访问此信息,因为它是嵌套的(例如本指南)。 Then you need to pass
payment_method
to the stripe.PaymentIntent.create
method.然后你需要将
payment_method
传递给stripe.PaymentIntent.create
方法。 In this option you don't have to change anything in your frontend code.在此选项中,您不必更改前端代码中的任何内容。
Option 2: Pass the PM in the frontend选项 2:在前端传递 PM
When you call stripe.confirmCardPayment
you can pass in the payment_method as explained here .当您调用
stripe.confirmCardPayment
时,您可以按照此处的说明传入 payment_method。 In this option you don't have to change anything in your backend code but you can remove the paymentDetails
from the request to your backend.在此选项中,您不必更改后端代码中的任何内容,但您可以从请求中删除对后端的
paymentDetails
信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.