使用PayPal Checkout PHP SDK如何获取买家完整收货地址
PayPal Checkout 免注册买家完整收货地址获取方案
问题现象
对接PayPal Checkout PHP SDK,采用authorize授权支付模式,需要在订单完成后获取Guest免注册买家的完整收货地址入库,但调用接口查询订单详情时,$orderResponse->result->payer->address 节点仅返回country_code国家编码,即使用户在Guest银行卡支付流程中填写了完整收货信息,也无法获取其余地址字段。
相关问题代码
后端支付处理逻辑
$environment = new \PayPalCheckoutSdk\Core\SandboxEnvironment(PAYPAL_ID, PAYPAL_SECRET); $client = new \PayPalCheckoutSdk\Core\PayPalHttpClient($environment); $authorizationId = $_POST['authorizationId']; $request = new \PayPalCheckoutSdk\Payments\AuthorizationsGetRequest($authorizationId); $authorizationResponse = $client->execute($request); $orderId = $authorizationResponse->result->supplementary_data->related_ids->order_id; $request = new OrdersGetRequest($orderId); $orderResponse = $client->execute($request); var_dump($orderResponse->result->payer->address);
代码执行输出仅包含国家码:
public 'address' => object(stdClass)[74] public 'country_code' => string 'FR' (length=2)
后端创建订单逻辑
$order = json_encode([ 'purchase_units' => [ [ 'description' => 'some desc...', 'items' => array_map(function ($product) { return [ 'name' => $product['name'] . " (n°" . $product['num'] . " | " . strtoupper($product['language']) . ")", 'quantity' => $_SESSION['cart'][$product['id']], 'unit_amount' => [ 'value' => number_format((float)$product['price'], 2, '.', ''), 'currency_code' => 'USD', ] ]; }, $products), 'amount' => [ 'currency_code' => 'USD', 'value' => $total > 200 ? $total : $total + 8, 'breakdown' => [ 'item_total' => [ 'currency_code' => 'USD', 'value' => $total ], 'shipping' => [ 'currency_code' => 'USD', 'value' => $total > 200 ? '0.00' : '8.00', ] ] ] ] ] ]);
前端JS SDK对接逻辑
paypal.Buttons({ createOrder: (data, actions) => { return actions.order.create(<?= $order; ?>); }, onApprove: async (data, actions) => { const authorization = await actions.order.authorize() const authorizationId = authorization.purchase_units[0].payments.authorizations[0].id const response = await fetch('<?= base_url('cart/process'); ?>', { method: 'post', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ authorizationId }) }) let responseText = await response.text(); $('.site-content').html(responseText); }, onCancel: function(data, actions) { alert("Order cancelled successfully!"); }, onError: function(err) { console.log(err); } }).render('#paypal-button-container');
问题原因
- 字段读取位置错误:
payer->address节点仅存储付款人账号关联的基础国家信息,完整收货地址不在这个节点下。 - 订单创建参数缺失:创建订单时没有显式声明收货地址收集规则,PayPal默认不会向商家返回Guest用户填写的完整收货明细。
- 后端参数接收逻辑有问题:前端传参使用
application/json格式,PHP原生$_POST无法直接获取JSON请求体内容,会导致参数读取异常。
修复步骤
- 第一步:调整订单创建参数,添加
application_context配置明确收货地址收集规则。
$order = json_encode([ // 新增上下文配置,声明地址收集规则 'application_context' => [ // 本站未提前收集地址选GET_FROM_FILE,由PayPal负责引导用户填写地址 // 本站已收集地址选SET_PROVIDED_ADDRESS,需在purchase_units下补充shipping节点传入已收集的地址供用户确认 // 虚拟商品无物流需求选NO_SHIPPING 'shipping_preference' => 'GET_FROM_FILE' ], 'purchase_units' => [ [ // 原有商品、金额等配置保持不变 'description' => 'some desc...', 'items' => array_map(function ($product) { return [ 'name' => $product['name'] . " (n°" . $product['num'] . " | " . strtoupper($product['language']) . ")", 'quantity' => $_SESSION['cart'][$product['id']], 'unit_amount' => [ 'value' => number_format((float)$product['price'], 2, '.', ''), 'currency_code' => 'USD', ] ]; }, $products), 'amount' => [ 'currency_code' => 'USD', 'value' => $total > 200 ? $total : $total + 8, 'breakdown' => [ 'item_total' => [ 'currency_code' => 'USD', 'value' => $total ], 'shipping' => [ 'currency_code' => 'USD', 'value' => $total > 200 ? '0.00' : '8.00', ] ] ] ] ] ]);
- 第二步:修正后端支付处理逻辑,从正确节点读取收货地址,同时修复JSON参数接收问题。
$environment = new \PayPalCheckoutSdk\Core\SandboxEnvironment(PAYPAL_ID, PAYPAL_SECRET); $client = new \PayPalCheckoutSdk\Core\PayPalHttpClient($environment); // 读取JSON格式请求体 $requestBody = json_decode(file_get_contents('php://input'), true); $authorizationId = $requestBody['authorizationId']; $request = new \PayPalCheckoutSdk\Payments\AuthorizationsGetRequest($authorizationId); $authorizationResponse = $client->execute($request); $orderId = $authorizationResponse->result->supplementary_data->related_ids->order_id; $request = new OrdersGetRequest($orderId); $orderResponse = $client->execute($request); // 从purchase_units下的shipping节点读取完整收货信息 $shipping = $orderResponse->result->purchase_units[0]->shipping; $address = $shipping->address; $addressData = [ 'recipient_name' => $shipping->name->full_name, 'address_line1' => $address->address_line_1, 'address_line2' => $address->address_line_2 ?? '', 'city' => $address->admin_area_2, 'state' => $address->admin_area_1, 'postal_code' => $address->postal_code, 'country_code' => $address->country_code ]; // 后续将$addressData存入数据库即可 var_dump($addressData);
注意:所有地址字段以服务端调用OrdersGetRequest接口返回的结果为准,不要直接使用前端传回的地址数据,避免数据篡改。
内容的提问来源于stack exchange,提问作者user18747208
相关产品推荐
相关产品推荐

