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

Next.js 14集成PayPal授权后捕获订单失败求助

解决PayPal先授权后付款的捕获接口错误问题

你遇到的RESOURCE_NOT_FOUND错误核心原因是调用捕获接口时用错了ID:PayPal的/v2/payments/authorizations/{authorizationId}/capture接口需要的是授权ID,而不是你当前传递的订单ID(orderId)。

下面是具体的修复步骤:

1. 前端修改:保存授权ID而非仅订单ID

在onApprove回调中,从授权返回的详情里提取真正的授权ID并保存,替换原来只存orderId的逻辑:

export const PPButton: FC<PaypalButtonProps> = ({ amount }) => {
  const [orderId, setOrderId] = useState<string>()
  // 新增状态保存授权ID
  const [authorizationId, setAuthorizationId] = useState<string>()

  const createOrder = (data: Record<string, unknown>, actions: any) => {
    return actions.order
      .create({
        intent: 'AUTHORIZE',
        purchase_units: [
          {
            amount: {
              value: amount,
            },
          }
        ]
      })
      .then((orderID: string) => {
        setOrderId(orderID)
        return orderID;
      })
      .catch((error: any) => {
        console.error('Error creating order:', error);
        toast.error('Error creating order');
      });
  }

  const onApprove = (data: any, actions: any) => {
    console.log('data', data);
    return actions.order.authorize().then((details: any) => {
      console.log('Authorization details:', details);
      // 从详情中提取授权ID并保存
      const authId = details.purchase_units[0].payments.authorizations[0].id;
      setAuthorizationId(authId);
      toast.success('Payment authorized');
    }).catch((error: any) => {
      console.error('Error authorizing order:', error);
      toast.error('Error authorizing order');
    });
  }

  async function onCapture () {
    // 先判断是否有授权ID
    if (!authorizationId) {
      toast.error('未找到已授权的付款记录');
      return;
    }
    return fetch(`${process.env.NEXT_PUBLIC_HOST}/api/paypal/captureOrder`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        authorizationId // 传递授权ID而非订单ID
      }),
    })
      .then((response) => response.json())
      .then((orderData) => {
        toast.success('Order paid successfully')
      })
  }

  return (
    <div>
      <PayPalScriptProvider options={{ intent: 'authorize', clientId: process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID!}}>
        <PayPalButtons
          createOrder={createOrder}
          onApprove={onApprove}
        />
      </PayPalScriptProvider>
      <button onClick={onCapture}>Capture</button>
    </div>
  );
};

2. 后端修改:接收授权ID并调用正确接口

更新你的捕获接口逻辑,接收前端传递的authorizationId,并使用它调用PayPal的捕获接口:

// 捕获订单的路由处理函数
async function captureOrder(req: NextApiRequest, res: NextApiResponse) {
  try {
    // 接收authorizationId而非orderId
    const { authorizationId } = req.body;
    const accessToken = await generateAccessToken();
    // 确保环境和前端一致(沙箱/生产)
    const base = process.env.PAYPAL_ENV === 'sandbox' 
      ? 'https://api-m.sandbox.paypal.com' 
      : 'https://api-m.paypal.com';
    // 使用authorizationId拼接接口路径
    const url = `${base}/v2/payments/authorizations/${authorizationId}/capture`;
    const response = await fetch(url, {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${accessToken}`,
      },
      body: JSON.stringify({
        payment_instruction: {
          disbursement_mode: "INSTANT",
          platform_fees: [
            {
              amount: {
                currency_code: "EUR",
                value: "1000"
              }
            }
          ]
        }
      })
    });

    const result = await handleResponse(response);
    res.status(200).json(result);
  } catch (error) {
    console.error('Error in capturing the Paypal order', error);
    res.status(500).json({ error: 'Capture failed' });
  }
}

额外检查项

  • 环境一致性:确保前端使用的PayPal客户端ID和后端生成accessToken用的密钥属于同一环境(沙箱/生产),跨环境调用会导致资源找不到。
  • 授权状态验证:在PayPal沙箱后台查看对应订单,确认授权状态为COMPLETED后再尝试捕获。
  • 参数传递验证:在前端onCapture和后端接口中打印传递的authorizationId,确认ID没有被截断或修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 17:02:35