未捕获(承诺中)集成错误:stripe.confirmCardPayment意图机密的值无效



我在尝试使用stripe:结账时遇到此错误

未捕获(承诺中(集成错误:stripe.confirmCardPayment意向机密的值无效:该值应为形式为${id}secret${secret}的客户端机密。您指定了:。。。。。

我在我的网站上使用stripe,并用firebase函数实现了它。当我在本地运行我的网站和firebase功能时,我不会收到这个错误,但当我把它放在firebase主机上时,它不起作用,我会收到这个错误。在本地,我会运行以下命令:npm start启动网站,然后在函数文件夹中cd,然后运行npm run serve。我该怎么解决这个问题?以下是使用firebase函数运行的index.js文件:index.js

const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors');
const stripe = require('stripe')(secret_key)
const app = express();
app.use(cors({
origin: true
}));
app.use(express.json());
app.post('/payments/create', async (req, res) => {
try {
const { amount, shipping } = req.body;
const paymentIntent = await stripe.paymentIntents.create({
shipping,
amount,
currency: 'eur'
});
res
.status(200)
.send(paymentIntent.client_secret);
}catch(err) {
res
.status(500)
.json({
statusCode: 500,
message: err.message
});
}
})
app.get('*', (req, res) => {
res
.status(404)
.send('404, Not Found');
});
exports.api = functions.https.onRequest(app);

这是package.json

{
"name": "evelinas-art-store",
"version": "0.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "^4.11.2",
"@stripe/react-stripe-js": "^1.1.2",
"@stripe/stripe-js": "^1.11.0",
"@testing-library/jest-dom": "^5.11.6",
"@testing-library/react": "^11.2.2",
"@testing-library/user-event": "^12.6.0",
"axios": "^0.21.1",
"ckeditor4-react": "^1.3.0",
"firebase": "^8.2.1",
"moment": "^2.29.1",
"node-sass": "^4.14.1",
"react": "^17.0.1",
"react-country-region-selector": "^3.0.1",
"react-dom": "^17.0.1",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.1",
"redux": "^4.0.5",
"redux-logger": "^3.0.6",
"redux-persist": "^6.0.0",
"redux-saga": "^1.1.3",
"redux-thunk": "^2.3.0",
"reselect": "^4.0.0",
"web-vitals": "^0.2.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

具有条带支付的文件

import React, { useState, useEffect } from 'react';
import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';
import FormInput from './../forms/FormInput';
import Button from './../forms/Button';
import { CountryDropdown } from 'react-country-region-selector';
import { apiInstance } from './../../Utils';
import { selectCartTotal, selectCartItemsCount, selectCartItems } from './../../redux/Cart/cart.selectors';
import { saveOrderHistory } from './../../redux/Orders/orders.actions';
import { createStructuredSelector } from 'reselect';
import { useSelector, useDispatch } from 'react-redux';
import { useHistory } from 'react-router-dom';
import './styles.scss';
const initialAddressState = {
line1: '',
line2: '',
city: '',
state: '',
postal_code: '',
country: '',
};
const mapState = createStructuredSelector({
total: selectCartTotal,
itemCount: selectCartItemsCount,
cartItems: selectCartItems,
});
const PaymentDetails = () => {
const stripe = useStripe();
const elements = useElements();
const history = useHistory();
const { total, itemCount, cartItems } = useSelector(mapState);
const dispatch = useDispatch();
const [billingAddress, setBillingAddress] = useState({ ...initialAddressState });
const [shippingAddress, setShippingAddress] = useState({ ...initialAddressState });
const [recipientName, setRecipientName] = useState('');
const [nameOnCard, setNameOnCard] = useState('');
useEffect(() => {
if (itemCount < 1) {
history.push('/dashboard');
}
}, [itemCount]);
const handleShipping = evt => {
const { name, value } = evt.target;
setShippingAddress({
...shippingAddress,
[name]: value
});
};
const handleBilling = evt => {
const { name, value } = evt.target;
setBillingAddress({
...billingAddress,
[name]: value
});
}
const handleFormSubmit = async evt => {
evt.preventDefault();
const cardElement = elements.getElement('card');
if (
!shippingAddress.line1 || !shippingAddress.city ||
!shippingAddress.state || !shippingAddress.postal_code ||
!shippingAddress.country || !billingAddress.line1 ||
!billingAddress.city || !billingAddress.state ||
!billingAddress.postal_code || !billingAddress.country ||
!recipientName || !nameOnCard
) {
return;
}
apiInstance.post('/payments/create', {
amount: total * 100,
shipping: {
name: recipientName,
address: {
...shippingAddress
}
}
}).then(({ data: clientSecret }) => {
stripe.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: {
name: nameOnCard,
address: {
...billingAddress
}
}
}).then(({ paymentMethod }) => {
stripe.confirmCardPayment(clientSecret, {
payment_method: paymentMethod.id
})
.then(({ paymentIntent }) => {
const configOrder = {
orderTotal: total,
orderItems: cartItems.map(item => {
const { documentID, productThumbnail, productName,
productPrice, quantity } = item;
return {
documentID,
productThumbnail,
productName,
productPrice,
quantity
};
})
}
dispatch(
saveOrderHistory(configOrder)
);
});
})

});
};
const configCardElement = {
iconStyle: 'solid',
style: {
base: {
fontSize: '16px'
}
},
hidePostalCode: true
};
return (
<div className="paymentDetails">
<form onSubmit={handleFormSubmit}>
<div className="group">
<h2>
Shipping Address
</h2>
<FormInput
required
placeholder="Recipient Name"
name="recipientName"
handleChange={evt => setRecipientName(evt.target.value)}
value={recipientName}
type="text"
/>
<FormInput
required
placeholder="Line 1"
name="line1"
handleChange={evt => handleShipping(evt)}
value={shippingAddress.line1}
type="text"
/>
<FormInput
placeholder="Line 2"
name="line2"
handleChange={evt => handleShipping(evt)}
value={shippingAddress.line2}
type="text"
/>
<FormInput
required
placeholder="City"
name="city"
handleChange={evt => handleShipping(evt)}
value={shippingAddress.city}
type="text"
/>
<FormInput
required
placeholder="State"
name="state"
handleChange={evt => handleShipping(evt)}
value={shippingAddress.state}
type="text"
/>
<FormInput
required
placeholder="Postal Code"
name="postal_code"
handleChange={evt => handleShipping(evt)}
value={shippingAddress.postal_code}
type="text"
/>
<div className="formRow checkoutInput">
<CountryDropdown
required
onChange={val => handleShipping({
target: {
name: 'country',
value: val
}
})}
value={shippingAddress.country}
valueType="short"
/>
</div>
</div>
<div className="group">
<h2>
Billing Address
</h2>
<FormInput
required
placeholder="Name on Card"
name="nameOnCard"
handleChange={evt => setNameOnCard(evt.target.value)}
value={nameOnCard}
type="text"
/>
<FormInput
required
placeholder="Line 1"
name="line1"
handleChange={evt => handleBilling(evt)}
value={billingAddress.line1}
type="text"
/>
<FormInput
placeholder="Line 2"
name="line2"
handleChange={evt => handleBilling(evt)}
value={billingAddress.line2}
type="text"
/>
<FormInput
required
placeholder="City"
name="city"
handleChange={evt => handleBilling(evt)}
value={billingAddress.city}
type="text"
/>
<FormInput
required
placeholder="State"
name="state"
handleChange={evt => handleBilling(evt)}
value={billingAddress.state}
type="text"
/>
<FormInput
required
placeholder="Postal Code"
name="postal_code"
handleChange={evt => handleBilling(evt)}
value={billingAddress.postal_code}
type="text"
/>
<div className="formRow checkoutInput">
<CountryDropdown
required
onChange={val => handleBilling({
target: {
name: 'country',
value: val
}
})}
value={billingAddress.country}
valueType="short"
/>
</div>
</div>
<div className="group">
<h2>
Card Details
</h2>
<CardElement
options={configCardElement}
/>
</div>
<Button
type="submit"
>
Pay Now
</Button>
</form>
</div>
);
}
export default PaymentDetails;```

根据文档https://stripe.com/docs/api/payment_intents/create条纹。PaymentIntent.create((

你需要通过这个:

import stripe
stripe.api_key = "sk_test_51I5EU6DbwDQYqmKoHRVYU2jw4jtzB8aQa6byuVIMyfDvYl3lxHOzmIRUZ6SabMmk1TV0jNu4w9akIgPY4E3krUbj00ewcroCvC"
const PaymentIntentVar =  stripe.PaymentIntent.create(
amount=2000,
currency="usd",
payment_method_types=["card"],
)

我猜你有错别字吧?付款意向?之后请尝试:

console.log(PaymentIntentVar)

在index.js中看看你是否得到了正确的回应?你能分享一下吗!

同样在";具有条带支付的文件":

而不是:

const cardElement = elements.getElement('card');

这个:

stripe.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: {
name: nameOnCard,
address: {
...billingAddress
}
}
})

这样做:

stripe.createPaymentMethod({
type: 'card',
card: elements.getElement(CardElement),
billing_details: {
name: nameOnCard,
address: {
...billingAddress
}
}
})

还检查您是否通过前端和后端上的console.log((在前端和后端传递了正确的公钥和私钥

也可以使用Stripe,试试这个

import {loadStripe} from '@stripe/stripe-js';
const stripe = loadStripe('secret_key');

以下是可能的场景以及我如何理解配置。

  1. 通行证
  2. 需要3d安全
  3. 失败-资金不足

https://stripe.com/docs/payments/accept-a-payment?platform=web&ui=结账#额外的测试资源

因此,首先您尝试从前端付款

const { error, paymentMethod } = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: {
name: `${stateProps.userProfile.firstName} ${stateProps.userProfile.lastName}`,
email: stateProps.user.email
}
});

从该paymentMethod,您检索paymentMethod.Id并将其发送到您的服务器以进行支付-在这一点上,我们假设支付将起作用,不需要3d安全。

在我的情况下,我需要的是paymentMethod.Id,因为我已经将所有账单详细信息放在了不同的对象中。

在后端,以下是我使用C#

try
{
if (request.PaymentMethodId != null)
{
var createOptions = new PaymentIntentCreateOptions
{
PaymentMethod = request.PaymentMethodId,
Amount = request.total,
Currency = "gbp",
ConfirmationMethod = "manual",
Confirm = true,
//ReturnUrl = "",
Metadata = new Dictionary<string, string>
{
{ "OrderId", request.orderId.ToString() },
}
};
paymentIntent = paymentIntentService.Create(createOptions);
}
if (request.PaymentIntentId != null)
{
var confirmOptions = new PaymentIntentConfirmOptions { };
paymentIntent = paymentIntentService.Confirm(
request.PaymentIntentId,
confirmOptions
);
}
}
catch (StripeException e)
{
return new ViewModels.ResponseObject
{
Success = false,
Title = "An Error Occcured.",
Message = e.Message,
Data = e.Message
};
}
if (paymentIntent.Status == "requires_action" && paymentIntent.NextAction.Type == "use_stripe_sdk")
{
return new ViewModels.ResponseObject
{
Success = false,
Data = new
{
requires_action = true,
payment_intent_client_secret = paymentIntent.ClientSecret
},
Title = "Requires Action",
Message = "Requires Action"
};
}
else if (paymentIntent.Status == "succeeded")
{
return new ViewModels.ResponseObject
{
Success = true,
Title = "Payment Successful.",
Message = "Thank you. Your payment has been successful. A confirmation message has been sent to you by email.",
Data = null
};
}
else
{
return new ViewModels.ResponseObject
{
Success = false,
Title = "An Error Occcured.",
Message = "An error has occured with your payment. A representative from our store has been notified and will be in touch with you to resolve the issue.",
Data = null
};
}

因此,如果你阅读代码,你会发现它试图付款,如果失败,它会给你clientSecret,你可以将其返回给客户。

这就是你现在可以在前端用来构建支付意向的东西(我们已经知道,由于3d安全,支付意向会失败(,它会自动打开3d安全身份验证窗口。

在我看来,往返两次似乎是一种浪费,但这就是我如何设法让它屈服的原因。

如果元素选项配置不正确,就会发生这种情况。

我使用的是vue-stripe框架,在开发这个框架时也遇到了同样的错误。

vue组件设置

`<StripeElementPayment
ref="checkoutRef"
:pk="stripeConfig._apiKey"
mode="payment"
:test-mode="true"
:elements-options="elementsOptions"
:confirm-params="confirmParams"
:locale="stripeConfig._locale"
:stripe-account="stripeConfig._stripeAccount"
/>`

//元素选项,最后三个元素对于测试来说不是疯狂的

`elementsOptions: any = {
appearance: {}, // appearance options
mode: 'payment',
currency: 'aud',
amount: this.totalAmount

}`

相关内容

最新更新