我在 React 中实现了 PayPal 智能按钮:
function PayPalButtonComponent(props: PayPalButtonProps) {
const [show, set_show] = useState(false);
const [error, set_error] = useState<string>();
const create_order = (_: any, actions: any) => {
return actions.order.create({
purchase_units: [
{
amount: {
currency: props.currency || "EUR",
value: props.total
}
}
]
});
};
const handle_approve = (_: any, actions: any) => {
return actions.order.capture().then((details: any) => {
if (props.onSuccess) props.onSuccess(details);
});
};
const handle_cancel = () => {
if (props.onCancel) props.onCancel();
};
const handle_error = () => {
if (props.onError) props.onError();
};
const render_button = () => {
const Button = paypal.Buttons.driver("react", { React, ReactDOM });
return (
<Button
style={{
layout: "horizontal",
size: "responsive",
shape: "rect",
color: "gold",
tagline: false
}}
funding={{
allowed: [paypal.FUNDING.CARD, paypal.FUNDING.PAYPAL],
disallowed: [paypal.FUNDING.CREDIT]
}}
createOrder={create_order}
onApprove={handle_approve}
onError={handle_error}
onCancel={handle_cancel}
/>
);
};
useEffect(() => {
if (props.isScriptLoaded) {
if (props.isScriptLoadSucceed) set_show(true);
else set_error("Unable to load the paypalscript");
}
}, [props.isScriptLoaded, props.isScriptLoadSucceed]);
if (error) return <p>{error}</p>;
if (!show) return <FakeButton />;
return render_button();
}
我一直在努力实现这些按钮,因为没有文档,我从here找到并复制了一些代码,并试图猜测其他东西。但我不明白如何禁用按钮。
在本指南中,他们声明可以在操作对象上调用 disable() 方法,但无法弄清楚如何使用我的配置来实现这一点。
你试过类似的东西吗?您知道可以遵循的任何文档吗?
编辑
我想要完成的是在支付期间将按钮设置为禁用状态。我知道有 paypal 覆盖,但是当交易完成时,我更改了应用程序路由,因为它发生在调用 onSuccess 时,由于 actions.order.capture() 的明显异步性质,这不可能立即发生,所以有时可以再次单击贝宝按钮。如果我可以禁用按钮,我就解决了问题。
onInit 实现允许您在单击按钮之前禁用/启用该按钮,这对于结帐前的某种验证很有用(例如已检查的条款),但不适用于我的情况。我也试过在
create_order
中调用 actions.disable() 但这会破坏按钮。
这里有同样的情况,文档中的 onInit 示例并不像某些人认为的那么简单......您需要创建隐藏输入并在付款时为其分配某种变量,以便在付款后禁用按钮。可惜没有人解决这个问题。
对于 React,我会使用官方的 PayPal NPM (@paypal/react-paypal-js) 包。他们有一些关于如何使用它的很好的文档......在你的情况下,只需使用该组件,你可以设置它是否被禁用作为一个属性。
查看他们的代码示例:
import { useEffect } from "react";
import {
PayPalScriptProvider,
PayPalButtons,
usePayPalScriptReducer
} from "@paypal/react-paypal-js";
// This values are the props in the UI
const amount = "2";
const currency = "USD";
const style = {"layout":"vertical"};
// Custom component to wrap the PayPalButtons and handle currency changes
const ButtonWrapper = ({ currency, showSpinner }) => {
// usePayPalScriptReducer can be use only inside children of PayPalScriptProviders
// This is the main reason to wrap the PayPalButtons in a new component
const [{ options, isPending }, dispatch] = usePayPalScriptReducer();
useEffect(() => {
dispatch({
type: "resetOptions",
value: {
...options,
currency: currency,
},
});
}, [currency, showSpinner]);
return (<>
{ (showSpinner && isPending) && <div className="spinner" /> }
<PayPalButtons
style={style}
disabled={false}
forceReRender={[amount, currency, style]}
fundingSource={undefined}
createOrder={(data, actions) => {
return actions.order
.create({
purchase_units: [
{
amount: {
currency_code: currency,
value: amount,
},
},
],
})
.then((orderId) => {
// Your code here after create the order
return orderId;
});
}}
onApprove={function (data, actions) {
return actions.order.capture().then(function () {
// Your code here after capture the order
});
}}
/>
</>
);
}
export default function App() {
return (
<div style={{ maxWidth: "750px", minHeight: "200px" }}>
<PayPalScriptProvider
options={{
"client-id": "test",
components: "buttons",
currency: "USD"
}}
>
<ButtonWrapper
currency={currency}
showSpinner={false}
/>
</PayPalScriptProvider>
</div>
);
}