开发WP插件集成PayPal按钮:无法获取服务器生成的Order ID
问题
我正在开发一款WordPress插件,用来在页面中添加PayPal按钮,采用PayPal官方示例的JS代码。在createOrder()方法中,我通过fetch调用后端的create-paypal-order.php接口获取订单ID,相关JS代码如下:
paypal.Buttons({ createOrder() { return fetch( dir + '/includes/api/create-paypal-order.php', { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ cart: [ { sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT", quantity: "YOUR_PRODUCT_QUANTITY", }, ], }), referrerPolicy: "origin-when-cross-origin" }) .then((response) => response.json()) .then((order) => order.id) .then((order) => {console.log(order); return order;} ); }, // Finalize the transaction on the server after payer approval onApprove(order) { ... }, }).render('#paypal-button-container');
对应的PHP文件(create-paypal-order.php)代码如下:
function authenticate() { $ch = false; $client_id = "Aeh...bbX"; $client_secret = "EPRl...yZFw"; $http_header = array("Content-Type: application/json"); $post_fields = 'grant_type=client_credentials'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://api.sandbox.paypal.com/v1/oauth2/token"); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSLVERSION , 6); //NEW ADDITION curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_USERPWD, $client_id.":".$client_secret); curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields); $result = curl_exec($ch); $json = json_decode($result); $access_token = $json->access_token; curl_close($ch); return $access_token; } function create_order($access_token) { $ch = false; $http_header = array ( "Content-Type: application/json", "Authorization: Bearer " . $access_token, "PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a", ); $post_fields = '{}'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://api-m.sandbox.paypal.com/v2/checkout/orders"); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_POST, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields); $result = curl_exec($ch); $json = json_encode($result); curl_close($ch); return $json; } $access_token = authenticate(); create_order($access_token);
10天前代码能正常获取order.id,现在出现错误:Unexpected end of JSON input\n at h…IwSW2JlwdPGZBlSA_Moyiy5KHbbX¤cy=USD:3:91171,请问如何修复该错误并成功获取order.id?PHP文件是否存在问题?return的使用是否正确?
修复方案
1. 核心PHP问题修复(直接导致JSON解析错误)
你的PHP代码有3个致命问题:
- 没有输出接口结果:调用
create_order($access_token)后,没有用echo输出返回内容,前端fetch接收不到任何响应,触发“Unexpected end of JSON input”错误。 - 错误的请求方法:PayPal创建订单API要求用POST请求,但你设置了
CURLOPT_POST: false,这会导致请求失败。 - 多余的JSON编码:
$result是PayPal返回的原生JSON字符串,你用json_encode($result)会把它转成双重编码的JSON,前端解析必然出错。
修改后的create_order函数及执行代码:
function create_order($access_token) { $ch = false; $http_header = array ( "Content-Type: application/json", "Authorization: Bearer " . $access_token, "PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a", ); // 空的{}不符合PayPal订单要求,必须补充金额等核心信息 $post_fields = json_encode([ "intent" => "CAPTURE", "purchase_units" => [ [ "amount" => [ "currency_code" => "USD", "value" => "10.00" ] ] ] ]); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://api-m.sandbox.paypal.com/v2/checkout/orders"); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // 建议开启SSL验证,避免安全风险 curl_setopt($ch, CURLOPT_POST, true); // 强制POST请求 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields); $result = curl_exec($ch); // 添加curl错误排查 if(curl_errno($ch)){ $error = curl_error($ch); curl_close($ch); http_response_code(500); echo json_encode(["error" => $error]); exit; } curl_close($ch); return $result; } $access_token = authenticate(); // 输出接口结果,让前端能拿到响应 echo create_order($access_token);
2. 修复access_token获取的请求头问题
PayPal获取access_token的接口要求Content-Type为application/x-www-form-urlencoded,之前用application/json不符合规范,容易触发兼容性问题:
function authenticate() { $ch = false; $client_id = "Aeh...bbX"; $client_secret = "EPRl...yZFw"; // 修改为正确的请求头类型 $http_header = array("Content-Type: application/x-www-form-urlencoded"); $post_fields = 'grant_type=client_credentials'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://api.sandbox.paypal.com/v1/oauth2/token"); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_USERPWD, $client_id.":".$client_secret); curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields); $result = curl_exec($ch); // 添加错误排查 if(curl_errno($ch)){ $error = curl_error($ch); curl_close($ch); http_response_code(500); echo json_encode(["error" => $error]); exit; } $json = json_decode($result); // 检查是否成功获取access_token if(!isset($json->access_token)){ http_response_code(500); echo json_encode(["error" => "获取access_token失败", "details" => $json]); exit; } $access_token = $json->access_token; curl_close($ch); return $access_token; }
3. JS代码错误处理优化
给fetch添加错误捕获,避免后端返回非200状态码时的解析崩溃:
paypal.Buttons({ createOrder() { return fetch( dir + '/includes/api/create-paypal-order.php', { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ cart: [ { sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT", quantity: "YOUR_PRODUCT_QUANTITY", }, ], }), referrerPolicy: "origin-when-cross-origin" }) .then((response) => { if (!response.ok) { throw new Error('接口请求失败'); } return response.json(); }) .then((order) => { console.log(order); return order.id; }) .catch(error => { console.error('创建订单失败:', error); // 可在此添加用户可见的错误提示 }); }, onApprove(order) { ... }, }).render('#paypal-button-container');
关键问题总结
- PHP接口未
echo返回结果,导致前端无数据可解析。 - 创建订单时用了GET请求(
CURLOPT_POST: false),不符合PayPal API要求。 - 对PayPal返回的JSON字符串重复编码,导致解析失败。
- 获取access_token的请求头类型错误,存在兼容性风险。
内容的提问来源于stack exchange,提问作者dig
相关产品推荐
相关产品推荐

