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

Next.js集成@paypal/react-paypal-js遇授权及合规错误问题

解决Next.js中@paypal/react-paypal-js组件的两个核心问题

问题1:PAYPAL_CLIENT_SECRET的配置位置

  • 绝对禁止在前端配置:CLIENT_SECRET是敏感密钥,一旦暴露在前端代码(包括Next.js客户端组件)中,会被恶意盗用,造成资金风险。
  • 正确配置方式:
    • 把密钥放在Next.js后端API路由中,通过环境变量管理:
      1. 在项目根目录创建.env.local文件,添加PAYPAL_CLIENT_SECRET=你的密钥内容
      2. 在pages/api/或app/api/目录的后端文件中,通过process.env.PAYPAL_CLIENT_SECRET读取密钥
    • 必须后端调用的原因:所有需要身份验证的PayPal API操作(比如订单捕获、订单状态查询)都要在后端发起,用CLIENT_SECRET生成合法的访问令牌后请求PayPal REST API。

问题2:"Can not pay order for unauthorized order"及COMPLIANCE_VIOLATION错误

错误根源

你当前在前端直接调用actions.order.capture()完成订单捕获,属于客户端侧交易操作,违反了PayPal的合规政策——敏感交易动作必须在后端完成,因此触发了COMPLIANCE_VIOLATION错误。

修复方案

1. 修改前端代码,将订单ID发送到后端处理

const initialOptions = {
    clientId: settings.env.paypalClientId,
    currency: "USD",
    intent: "capture",
}

return (
    <PayPalScriptProvider options={initialOptions}>
        <PayPalButtons
            createOrder={(data, actions) => {
                return actions.order.create({
                    purchase_units: [
                        {
                            amount: {
                                value: totalAmount,
                            },
                        },
                    ],
                    application_context: {
                        shipping_preference: 'NO_SHIPPING',
                    },
                })
            }}

            onApprove={async (data) => {
                // 将订单ID传给后端API完成捕获
                try {
                    const response = await fetch('/api/paypal/capture-order', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                        },
                        body: JSON.stringify({ orderId: data.orderID }),
                    });
                    const details = await response.json();
                    if (details.status === 'COMPLETED') {
                        toast.success(`交易完成,感谢 ${details.payer.name.given_name}`);
                    } else {
                        toast.error('交易失败,请重试');
                    }
                } catch (error) {
                    toast.error('订单捕获失败:' + error.message);
                }
            }}

            onCancel={() => {
                toast.error('已取消付款');
            }}
            onError={(error) => {
                console.log({ error })
                toast.error('付款出错:--' + error);
            }}
        />
    </PayPalScriptProvider>
)

2. 创建后端API路由处理订单捕获

以app/api/paypal/capture-order/route.js为例:

export async function POST(request) {
    const { orderId } = await request.json();
    const clientId = process.env.PAYPAL_CLIENT_ID;
    const clientSecret = process.env.PAYPAL_CLIENT_SECRET;

    // 第一步:获取PayPal访问令牌
    const authResponse = await fetch('https://api-m.sandbox.paypal.com/v1/oauth2/token', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            Authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,
        },
        body: 'grant_type=client_credentials',
    });
    const authData = await authResponse.json();
    const accessToken = authData.access_token;

    // 第二步:捕获订单
    const captureResponse = await fetch(`https://api-m.sandbox.paypal.com/v2/checkout/orders/${orderId}/capture`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${accessToken}`,
        },
    });
    const captureData = await captureResponse.json();

    return new Response(JSON.stringify(captureData), {
        headers: { 'Content-Type': 'application/json' },
    });
}

3. 额外注意事项

  • 生产环境需把API地址从sandbox替换为live
  • 确保.env.local中的PAYPAL_CLIENT_ID和PAYPAL_CLIENT_SECRET配置正确,且文件已加入.gitignore避免泄露
  • 后端需补充异常处理逻辑,比如订单过期、金额不匹配等情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:42:45