stripe/paypal

stripe

stripe

前端(不用写代码,拿url地址即可)---获取对应的plan_id,传给后端,后端返回url地址,跳出去进行支付,后端返回回调定位回前端地址,根据返回参数判断是否支付成功即可

沙盒--支付卡号

paypal

react-paypal-js

相关文档
PayPal

需要切换PayPalScriptProvider -option配置

需要再PayPalButtons 在延迟展示(等PayPalScriptProvider 更新完成)

否则会导致按钮无法展示

查看更新验证

ts 复制代码
// nextjs 简单示例
import { PayPalScriptProvider, PayPalButtons } from "@paypal/react-paypal-js";
const Plans: React.FC = () => {
// 控制支付按钮刷新--显示
const [showpaypalbutton, setShowpaypalbutton] = useState(true); 
 const [initOptions, setInitOptions] = useState({
    clientId: process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID as string,
    vault: true, // false
    intent: "subscription", // capture - subscription
  })
  return (
<PayPalScriptProvider
                key={`paypal-provider-${paypalInfo.plan_type}`}
                options={initOptions}
              >
                {showpaypalbutton && mode === "subscription" && (<div>
                  <PayPalButtons
                    style={{
                      layout: "vertical",
                    }}
                    onCancel={async (data) => {
                      const result = await client_request("/subscription_cancel", "POST", {
                        ...data,
                      })
                      messageApi.warning("Payment Cancelled. Thank you for trying!");
                      console.log("onCancel", result);
                    }}
                    createSubscription={async () => {
                      const result = await client_request("/create_subscribe", "POST", { plan: 1 })
                      const _res = result.data as {
                        subscription_id: string
                        approve_url: string
                      }
                      console.log("create_order_createSubscription", _res.subscription_id);
                      subscriptionId.current = _res.subscription_id
                      return _res.subscription_id
                    }}

                    onApprove={async (data, actions) => {
                      console.log("onApprove", data);
                      const result = await client_request("/subscription_confirm", "POST", {
                        ...data,
                        status: "success"
                      })
                      if (result.code === 0) {
                        getPlans()
                      }
                      messageApi.success(
                        "Payment Successful! All videos are now unlocked. Enjoy!"
                      );

                      return Promise.resolve();
                    }}
                    onError={async (err) => {
                      console.log("onError", err);
                      messageApi.error(
                        "Payment Failed. Something went wrong. Please try again."
                      );
                    }}
                  />
                </div>)}

                {showpaypalbutton && mode === "one-time" && (<div>
                  <PayPalButtons
                    style={{
                      layout: "vertical",
                    }}
                    onCancel={async (data) => {
                      console.log("onCancel", data);
                      const result = await client_request("/subscription_cancel", "POST", {
                        ...data,
                        status: "cancel"
                      })
                      messageApi.warning("Payment Cancelled. Thank you for trying!");
                      console.log("onCancel", result);
                    }}
                    createOrder={async (data, actions) => {
                      const result = await client_request("/create_order", "POST", { ...data })
                      const _res = result.data as {
                        order_id: string
                        approve_url: string
                      }
                      subscriptionId.current = _res.order_id
                      // if (_res.approve_url) {
                      //   window.open(_res.approve_url, '_blank');
                      // }
                      return _res.order_id
                    }}
                    onApprove={async (data, actions) => {
                      console.log("create_order_onApprove=====", data);
                      const result = await client_request("/order_return", "POST", {
                        ...data,
                        status: "success"
                      })
                      if (result.code === 0) {
                        getPlans()
                      }
                      console.log("create_order", result);
                      messageApi.success(
                        "Payment Successful! All videos are now unlocked. Enjoy!"
                      );

                      return Promise.resolve();
                    }}
                    onError={async (err) => {
                      console.log("onError", err);
                      messageApi.error(
                        "Payment Failed. Something went wrong. Please try again."
                      );
                    }}
                  />
                </div>)}
              </PayPalScriptProvider>
)
};

export default Plans;
相关推荐
FungLeo1 天前
成为全栈·Next.js 网站前台篇·数据获取与缓存:60 秒再验证背后到底发生了什么
react·isr·next.js·成为全栈·react cache·opennext
liangshanbo12157 天前
React 性能瓶颈定位面试题——原理深挖版
react·performance·profiler
liangshanbo12157 天前
React 性能优化实战
性能优化·react
FungLeo7 天前
成为全栈·React 管理后台篇·按钮级权限:能力映射、菜单过滤与自锁保护
react·rbac·路由守卫·权限控制·前端权限·成为全栈
FungLeo7 天前
成为全栈·React 管理后台篇·评论审核工作流:把状态下拉改成可理解的动作
react·内容安全·状态机·交互设计·成为全栈·评论审核
liangshanbo12158 天前
React 状态持久化面试题——原理深挖版
react·状态持久化
liangshanbo12158 天前
Redux 的中间件(Middleware)的工作机制
中间件·react·redux
FungLeo8 天前
成为全栈·React 管理后台篇·Markdown 编辑器:预览、暗色主题与连续图片粘贴
图片上传·react·响应式设计·markdown编辑器·异步编程·成为全栈
FungLeo9 天前
成为全栈·React 管理后台篇·表单页范式:校验、数据回填与未保存保护
react·表单设计·zod·react hook form·成为全栈·数据回填
名字还没想好☜9 天前
React 文件上传实战:预览 URL 回收、多文件逐个进度与拖拽放置区踩坑
前端·react·next.js