You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自定义PayPal订阅审批流程(无需使用默认批准链接)

问题描述

我已通过以下NodeJS代码成功创建PayPal订阅:

const createSubscription = async () => {
  const accessToken = await getAccessToken();

  const response = await axios.post(
    `${PAYPAL_API}/v1/billing/subscriptions`,
    {
      plan_id: subscriptionPlanId,
      application_context: {
        brand_name: "test",
        locale: "en-US",
        user_action: "SUBSCRIBE_NOW",
        return_url: "https://test.test/",
        cancel_url: "https://test.test/",
        shipping_preference: "NO_SHIPPING",
      },
    },
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${accessToken}`,
      },
    }
  );

  return response.data;
};

返回结果如下:

{
  status: 'APPROVAL_PENDING',
  id: 'I-YUSWK0P891TV',
  create_time: '2024-02-03T15:03:29Z',
  links: [
    {
      href: 'https://www.sandbox.paypal.com/webapps/billing/subscriptions?ba_token=BA-97806019K4147340Y',
      rel: 'approve',
      method: 'GET'
    },
    {
      href: 'https://api.sandbox.paypal.com/v1/billing/subscriptions/I-YUSWK0P891TV',
      rel: 'edit',
      method: 'PATCH'
    },
    {
      href: 'https://api.sandbox.paypal.com/v1/billing/subscriptions/I-YUSWK0P891TV',
      rel: 'self',
      method: 'GET'
    }
  ]
}

我希望不使用生成的approve链接,自定义整个订阅审批流程,请问PayPal是否支持该需求?若支持,能否提供相关实现指引?

我曾尝试使用@paypal/react-paypal-js SDK,但发现其主要适用于一次性支付场景。


回答

PayPal支持自定义订阅审批流程,你之前对@paypal/react-paypal-js SDK的认知有误——它完全支持订阅场景,是实现自定义审批流程的首选方案。以下是具体实现指引:

一、使用PayPal JS SDK的订阅组件实现自定义流程

1. 配置并加载PayPal JS SDK

在React项目中,通过PayPalScriptProvider加载SDK时,指定components为buttons,subscription,确保订阅功能可用:

import { PayPalScriptProvider } from "@paypal/react-paypal-js";

function App() {
  return (
    <PayPalScriptProvider
      options={{
        "client-id": "你的PayPal客户端ID",
        components: "buttons,subscription",
        currency: "USD"
      }}
    >
      {/* 你的订阅组件 */}
      <CustomSubscriptionButton />
    </PayPalScriptProvider>
  );
}

2. 渲染自定义订阅按钮并处理审批逻辑

使用usePayPalScriptReducer获取SDK加载状态,渲染自定义按钮(或自定义UI),并通过PayPal的订阅API触发审批流程,而非依赖创建订阅后返回的approve链接:

import { usePayPalScriptReducer } from "@paypal/react-paypal-js";
import { useEffect, useRef } from "react";

function CustomSubscriptionButton() {
  const [{ isPending }] = usePayPalScriptReducer();
  const paypalRef = useRef(null);

  useEffect(() => {
    if (!isPending && window.paypal) {
      // 初始化订阅按钮(可自定义样式)
      window.paypal.Buttons({
        createSubscription: async (data, actions) => {
          // 调用你的后端接口创建订阅(即你已有的createSubscription函数)
          const subscription = await fetch("/api/create-subscription", {
            method: "POST",
            headers: { "Content-Type": "application/json" }
          }).then(res => res.json());
          
          return subscription.id; // 返回订阅ID给PayPal SDK
        },
        onApprove: async (data, actions) => {
          // 订阅审批成功后的逻辑:验证订阅状态、更新数据库等
          const subscriptionDetails = await fetch(`/api/subscription/${data.subscriptionID}`, {
            method: "GET",
            headers: { Authorization: `Bearer ${你的AccessToken}` }
          }).then(res => res.json());
          
          if (subscriptionDetails.status === "ACTIVE") {
            // 处理订阅激活后的业务逻辑
            console.log("订阅已激活");
          }
        },
        onCancel: () => {
          // 用户取消订阅的逻辑
          console.log("用户取消订阅");
        },
        onError: (err) => {
          // 错误处理
          console.error("订阅出错", err);
        }
      }).render(paypalRef.current);
    }
  }, [isPending]);

  return <div ref={paypalRef} />;
}

3. 后端验证订阅状态

在onApprove回调中,必须调用PayPal的REST API验证订阅状态,避免前端篡改数据:

// 后端验证订阅状态的示例代码
const verifySubscription = async (subscriptionId) => {
  const accessToken = await getAccessToken();
  const response = await axios.get(
    `${PAYPAL_API}/v1/billing/subscriptions/${subscriptionId}`,
    {
      headers: {
        Authorization: `Bearer ${accessToken}`
      }
    }
  );
  return response.data;
};

二、完全自定义UI(不使用PayPal按钮)的实现方式

如果需要完全脱离PayPal的默认按钮样式,可通过以下步骤实现:

  • 前端收集用户支付信息(注意:PayPal不允许直接收集信用卡信息,必须使用PayPal的Hosted Fields或Vault API)
  • 调用PayPal的vault/credit-cards API存储支付方式(需获得用户授权)
  • 创建订阅时,在请求体中指定payment_source为存储的支付方式ID:
{
  plan_id: subscriptionPlanId,
  payment_source: {
    card: {
      id: "存储的信用卡ID"
    }
  },
  application_context: { /* 你的上下文配置 */ }
}
  • 订阅创建后,状态会直接变为ACTIVE(无需用户跳转审批),但需确保用户已授权使用该支付方式。

⚠️ 注意:这种方式需要严格遵守PayPal的PCI合规要求,建议优先使用第一种SDK方案,降低合规风险。


内容的提问来源于stack exchange,提问作者Kariey Zah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 13:38:20