条带支付元素的集成.警告不支持的属性更改:options.clientCret不是可变属性



我有PaymentMethodPage,它看起来像这样:

import React, { FC, useState } from 'react';
import { Elements } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';
import {
getClientSecret,
} from '../../api/PaymentCalls/PaymentCalls';
import PaymentMethodSetupForm from './PaymentMethodSetupForm/PaymentMethodSetupForm';
import AddPaymentMethodContainer from './AddPaymentMethodContainer/AddPaymentMethodContainer';
import {
ClientSecretResponse,
} from '../../interfaces/paymentMethod.interface';

const stripePromise = loadStripe(
process.env.REACT_APP_STRIPE_PUBLIC_KEY as string
);
const PaymentMethodPage: FC = () => {
const [enableAddPaymentMethod, setEnableAddPaymentMethod] =
useState<boolean>(false);
const {
data: clientSecretKeyData,
}: UseQueryResult<ClientSecretResponse, ExtendedError> = useQuery<
ClientSecretResponse,
ExtendedError
>('getClientSecret', getClientSecret, {
retry: false,
refetchOnWindowFocus: false,
enabled: enableAddPaymentMethod,
onError: (error: ExtendedError) => {
if (error) {
console.log(error)
}
},
});
const options = {
clientSecret: clientSecretKeyData?.client_secret,
};
const addPaymentMethodHandler = (): void => {
setEnableAddPaymentMethod(!enableAddPaymentMethod);
};

return (
<AppDrawer onLogOut={logoutHandler}>
{paymentMethodData.default_payment_method !== null ? (
<Box>
<Typography>
Payment Method
</Typography>
</Box>
) : (
<Box>
<AddPaymentMethodContainer
addButtonHandler={addPaymentMethodHandler}
/>
</Box>
{clientSecretKeyData && (
<Elements stripe={stripePromise} options={options}>
<PaymentMethodSetupForm
isOpenPaymentDialog={enableAddPaymentMethod}
handleClose={addPaymentMethodHandler}
setPaymentDialogOpen={addPaymentMethodHandler}
/>
</Elements>
)}
</AppDrawer>
);
};
export default PaymentMethodPage;

如果没有付款方式,我将呈现AddPaymentMethodContainer。看起来像这样:

import React, { FC } from 'react';
import { Box, Typography, Button } from '@mui/material';
interface AddPaymentMethodContainerProps {
addButtonHandler: () => void;
}
const AddPaymentMethodContainer: FC<AddPaymentMethodContainerProps> = ({
addButtonHandler,
}) => {
return (
<Box >
<Box >
<img
src={someImage}
alt="no-payment-method"
/>
</Box>
<Typography>
No payment method found. Click the button below to provide one.
</Typography>
<Box sx={styles.addButtonContainer}>
<Button
sx={styles.addButton}
variant="contained"
onClick={addButtonHandler}
>
Add Payment
</Button>
</Box>
</Box>
);
};
export default AddPaymentMethodContainer;

单击添加按钮后,我将呈现包含Stipe PaymentElement的付款表单。。。组件如下所示:

import React, { FC, useState } from 'react';
import {
PaymentElement,
useStripe,
useElements,
} from '@stripe/react-stripe-js';
import { useMutation, UseMutationResult, useQueryClient } from 'react-query';
import { Dialog, DialogTitle, DialogContent } from '@mui/material';
interface PaymentMethodSetupFormProps {
isOpenPaymentDialog: boolean;
handleClose: () => void;
setPaymentDialogOpen: (e: boolean) => void;
}
const PaymentMethodSetupForm: FC<PaymentMethodSetupFormProps> = ({
isOpenPaymentDialog,
setPaymentDialogOpen,
handleClose,
}) => {
const stripe = useStripe();
const elements = useElements();
const [isLoading, setIsLoading] = useState<boolean>(false);

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const handleSubmit = async (event: React.SyntheticEvent) => {
event.preventDefault();
if (!stripe || !elements) {
// eslint-disable-next-line no-useless-return
return;
}
setIsLoading(true);
const result = await stripe.confirmSetup({
elements,
confirmParams: {
return_url: 'http://localhost:3000/payment-status/',
},
redirect: 'if_required',
});
if (result.error) {
console.log(`${result.error.message}`)
} else {
console.log('All okay!')
setPaymentDialogOpen(false);
}
setIsLoading(false);
};
return (
<Dialog
open={isOpenPaymentDialog}
onClose={handleClose}
>
<DialogTitle>
Payment Methods:
</DialogTitle>
<DialogContent>
<form onSubmit={handleSubmit}>
<PaymentElement />
<CustomSubmitButton
cypressId="credit-card-submit-button"
isLoading={isLoading}
text="Save"
style={{ margin: '2rem auto', fontWeight: 'bolder' }}
disabled={isLoading}
/>
</form>
</DialogContent>
</Dialog>
);
};
export default PaymentMethodSetupForm;

这里我禁用了handleSubmit的函数返回类型,因为我不知道应该是什么类型。。。这是一个承诺<gt;,所以,如果有人有任何想法(请帮忙(。总的来说,一切都很好,我不喜欢的是当我点击";ADD";按钮打开表格,然后我关闭它,第二次尝试按下按钮时,控制台中会出现警告:

Unsupported prop change: options.clientSecret is not a mutable property.

还有一个关于PaymentElement内图像的警告(针对卡号(:

Each dictionary in the list "icons" should contain a non-empty UTF8 string field "type".

还有最后一件事,这很烦人。根据他们的文档,我可以禁用以下形式的提交/保存/支付按钮:

return (
<form onSubmit={handleSubmit}>
<PaymentElement />
<button disabled={!stripe}>Submit</button>
{/* Show error message to your customers */}
{errorMessage && <div>{errorMessage}</div>}
</form>
)

但看起来这个物体总是真实的。我试着把它做成这样:

return (
<form onSubmit={handleSubmit}>
{!stripe && (
<PaymentElement />
<button>Submit</button>
{/* Show error message to your customers */}
{errorMessage && <div>{errorMessage}</div>}
)}
</form>
)

因为我为什么要禁用它,而我可以在条纹可用时渲染它。但看起来并不是这样的。提交按钮总是在那里,突然付款单出现了。。。这不太好。作为一名用户,我得到了一个按钮,在某个时候表单就会显示出来。好吧,这不需要那么多时间,但在我看来,这并不酷。

key={clientSecret}添加到<Elements>组件
还可以使用更新付款意向或确认付款意向


以下是Stripe团队对此的看法:

我们目前不支持更新clientSecret道具,任何尝试的更新都将被忽略。这是在尝试clientSecret更新时记录到控制台的警告:

Unsupported prop change: options.clientSecret is not a mutable property. 

我们确实有一些正在进行的工作来解决您的确切用例(在创建后更新PaymentIntent上的金额(。同时,一个可能的解决方案是,当客户端机密发生变化时,通过更新提供程序的密钥来重新安装提供程序并完全对应:

-<Elements options={options} stripe={stripePromise}>
+<Elements options={options} stripe={stripePromise} key={clientSecret}>

https://githubhot.com/repo/stripe/react-stripe-js/issues/246

我不熟悉useQuery,但看起来clientSecretKeyData是一个不断变化的值,因此options.client_secret也在变化。正如错误所说:

options.clientCret不是可变属性

您需要推迟安装<Elements />组件,直到client_secret可用。

最新更新