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

PayPal API 间歇性失效,部分请求返回400错误排查求助

Troubleshooting PayPal IPN 400 Bad Request & Unverified Responses

Let's break down your intermittent PayPal IPN issue step by step—here are the key areas to fix and investigate based on your code and error logs:

1. Fix HTTP Header Syntax Errors (Critical!)

Your manual HTTP headers have two issues that directly trigger 400 Bad Requests:

  • Missing colon in Connection header: You wrote Connection close instead of Connection: close. HTTP headers require a colon separating the header name and value, so this invalidates the entire request.
  • Redundant port in Host header: The Host: www.paypal.com:443 header doesn't need the :443 suffix—since you're already connecting via SSL on port 443, the Host header should just be Host: www.paypal.com (or better yet, use PayPal's dedicated IPN endpoint).

Update your header block to follow strict HTTP/1.1 syntax:

$header .= "POST /cgi-bin/webscr HTTP/1.1\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Host: ipnpb.paypal.com\r\n"; // Use dedicated IPN endpoint
$header .= "Connection: close\r\n";
$header .= "Content-Length: " . mb_strlen($req, '8bit') . "\r\n\r\n";

Note: Use \r\n instead of just \n for line breaks—HTTP requires CRLF line endings for headers.

2. Switch to PayPal's Dedicated IPN Endpoint

You're currently using www.paypal.com but have commented out the recommended ipnpb.paypal.com endpoint. PayPal phased out support for the old www.paypal.com IPN endpoint for some use cases after 2018, which explains why your issues started appearing around then.

Replace your fsockopen line with:

$fp = fsockopen('ssl://ipnpb.paypal.com', 443, $errno, $errstr, 30);

For sandbox testing, use ssl://ipnpb.sandbox.paypal.com.

3. Fix Response Parsing Logic

Your current code checks each line of the response with strcmp(trim($res), "VERIFIED"), but PayPal's response might not always return VERIFIED as a standalone line. Sometimes, the response could include extra whitespace or the status might be embedded after other response data.

Instead, read the entire response first, then check for the status:

$full_response = '';
while (!feof($fp)) {
    $full_response .= fgets($fp, 1024);
}

if (strpos(trim($full_response), "VERIFIED") !== false) {
    // Process verified payment
} elseif (strpos(trim($full_response), "INVALID") !== false) {
    error_log("Invalid Error 102");
} else {
    error_log("not verified Error 101: " . $full_response);
}

This avoids missing the status if the response format varies slightly.

4. Verify Content-Length Calculation

Using strlen($req) can give incorrect byte counts if $req contains UTF-8 characters (since strlen counts characters, not bytes). Use mb_strlen($req, '8bit') instead to get the correct byte length for the Content-Length header—mismatched lengths can cause PayPal to reject the request with a 400 error.

5. Replace fsockopen with cURL (More Reliable)

Manual fsockopen handling is error-prone and doesn't handle modern HTTP features well. Switching to cURL will automatically handle headers, line endings, and connection issues, reducing intermittent failures:

$ch = curl_init('https://ipnpb.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);

$full_response = curl_exec($ch);
if (curl_errno($ch)) {
    error_log("cURL Error: " . curl_error($ch));
} else {
    if (strpos(trim($full_response), "VERIFIED") !== false) {
        // Process verified payment
    } elseif (strpos(trim($full_response), "INVALID") !== false) {
        error_log("Invalid Error 102");
    } else {
        error_log("not verified Error 101: " . $full_response);
    }
}
curl_close($ch);

cURL is more robust against network fluctuations and adheres strictly to HTTP standards.

6. Check Server Time Synchronization

Intermittent failures can also happen if your server's clock is out of sync with PayPal's. PayPal validates timestamps in IPN requests, and a significant time drift (more than a few minutes) can cause verification failures. Ensure your server uses NTP to keep its time accurate.

7. Log Full Request/Response for Debugging

To diagnose remaining intermittent issues, log the full $req payload and $full_response from PayPal. This will let you see exactly what's being sent and received when failures occur, helping you spot edge cases (like unexpected POST parameters or malformed data).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 10:52:28