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

PayPal Checkout onApprove阶段数据库写入失败问题求助

PHP购物车PayPal Checkout升级:解决custom_ID和orderID为空问题

前端PayPal按钮代码(关键:传递参数到后端)

核心是在创建订单时注入会话ID作为custom_id,并在onApprove阶段主动将orderID和custom_ID提交到后端接口:

<script src="https://www.paypal.com/sdk/js?client-id=你的客户端ID&currency=USD"></script>
<div id="paypal-button-container"></div>

<script>
paypal.Buttons({
    createOrder: function(data, actions) {
        // 从PHP获取会话ID
        const customId = '<?php echo $seid; ?>';
        return actions.order.create({
            purchase_units: [{
                amount: {
                    value: '<?php echo $orderAmount; ?>'
                },
                custom_id: customId // 注入会话ID到PayPal订单
            }]
        });
    },
    onApprove: function(data, actions) {
        const orderId = data.orderID;
        const customId = '<?php echo $seid; ?>';

        // 提交参数到completed.php
        return fetch('completed.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                orderID: orderId,
                custom_ID: customId
            })
        }).then(res => res.json())
          .then(result => {
              result.success ? window.location.href = 'success.php' : alert(result.message);
          }).catch(err => {
              console.error(err);
              alert('支付验证失败');
          });
    },
    onError: err => console.error('PayPal按钮错误:', err)
}).render('#paypal-button-container');
</script>

后端completed.php代码(关键:接收+验证+更新)

接收前端参数后,必须先通过PayPal API验证订单合法性,再执行数据库更新:

<?php
// PayPal配置
$clientId = '你的客户端ID';
$clientSecret = '你的客户端密钥';
$paypalApiUrl = 'https://api-m.sandbox.paypal.com'; // 生产环境改为https://api-m.paypal.com

// 接收前端JSON数据
$input = file_get_contents('php://input');
$data = json_decode($input, true);

// 检查必填参数
if (empty($data['orderID']) || empty($data['custom_ID'])) {
    echo json_encode(['success' => false, 'message' => '缺少orderID或custom_ID']);
    exit;
}
$orderId = $data['orderID'];
$customId = $data['custom_ID'];

// 获取PayPal访问令牌
function getAccessToken($cid, $csec, $url) {
    $ch = curl_init($url.'/v1/oauth2/token');
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, 'grant_type=client_credentials');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERPWD, "$cid:$csec");
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode($res, true)['access_token'] ?? false;
}

// 查询PayPal订单详情
function getOrderDetails($oid, $token, $url) {
    $ch = curl_init($url."/v2/checkout/orders/$oid");
    curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer $token"]);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode($res, true);
}

// 验证订单合法性
$token = getAccessToken($clientId, $clientSecret, $paypalApiUrl);
if (!$token) {
    echo json_encode(['success' => false, 'message' => '无法获取PayPal令牌']);
    exit;
}
$orderDetails = getOrderDetails($orderId, $token, $paypalApiUrl);
if ($orderDetails['status'] !== 'COMPLETED' || $orderDetails['purchase_units'][0]['custom_id'] !== $customId) {
    echo json_encode(['success' => false, 'message' => '订单无效或未完成']);
    exit;
}

// 更新数据库(示例,根据你的表结构调整)
$conn = mysqli_connect('主机', '用户名', '密码', '数据库名');
if (!$conn) {
    echo json_encode(['success' => false, 'message' => '数据库连接失败']);
    exit;
}
$sql = "UPDATE orders SET status = 'completed', paypal_order_id = ? WHERE session_id = ?";
$stmt = mysqli_prepare($conn, $sql);
mysqli_stmt_bind_param($stmt, 'ss', $orderId, $customId);

if (mysqli_stmt_execute($stmt)) {
    echo json_encode(['success' => true, 'message' => '订单更新成功']);
} else {
    echo json_encode(['success' => false, 'message' => '数据库更新失败:'.mysqli_error($conn)]);
}

mysqli_stmt_close($stmt);
mysqli_close($conn);
?>

关键注意点

  • 前端必须显式传递custom_ID,不能仅依赖PayPal返回的custom_id,防止前端篡改
  • 后端必须验证PayPal订单的状态、custom_id、金额,确保数据真实可信
  • 数据库操作使用预处理语句,避免SQL注入

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 13:42:22