首页 > 解决方案 > Paypal 从 php-curl 获取访问令牌错误请求,但从终端正常工作

问题描述

我正在尝试向 Paypal 沙箱发出 curl 请求以获取访问令牌,但每次我向此 url 发出请求时

https://api.sandbox.paypal.com/v1

它发回 400 作为响应。我也尝试将 curl 请求发送到任何测试 url,我得到 200 响应。此外,如果我通过终端发送请求,则响应为 200 问题仅发生在 php-curl 中。另一个值得注意问题是这个请求在本地主机上运行良好,它只在实时服务器上获得 400。

这就是我提出 curl 请求的方式

        $username = $params['paypal_client_id'];
        $password = $params['paypal_secret'];
        $headers = array(
            "Accept-Language: en_US",
            "Accept: application/json"
            );      
        $ch = curl_init(); 
        curl_setopt($ch, CURLOPT_URL,$url); 
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 
        curl_setopt($ch, CURLOPT_USERPWD, trim($username) . ':' . trim($password));
        curl_setopt($ch, CURLOPT_POST, 1); 
        $data = curl_exec($ch); 

这就是我通过终端提出请求的方式

curl https://api.sandbox.paypal.com/v1/oauth2/token -H "Accept: application/json" -H "Accept-Language: en_US" -u "{Client_id}:{Client_secret}" -d "grant_type=client_credentials" 

我得到的回应是

Verbose info :* About to connect() to api.sandbox.paypal.com port 443 (#1)
*   Trying 173.0.82.78...
* Connected to api.sandbox.paypal.com (173.0.82.78) port 443 (#1)
* warning: ignoring value of ssl.verifyhost
* skipping SSL peer certificate verification
* NSS: client certificate not found (nickname not specified)
* SSL connection using TLS_RSA_WITH_AES_256_CBC_SHA256
* Server certificate:
*   subject: CN=api.sandbox.paypal.com,OU=PayPal Production,O="PayPal, Inc.",L=San Jose,ST=California,C=US
*   start date: Aug 21 00:00:00 2018 GMT
*   expire date: Aug 20 12:00:00 2020 GMT
*   common name: api.sandbox.paypal.com
*   issuer: CN=DigiCert Global CA G2,O=DigiCert Inc,C=US
* Server auth using Basic with user 'client_id'
> POST /v1/oauth2/token?grant_type=client_credentials HTTP/1.1
Authorization: Basic 'client_id'
Host: api.sandbox.paypal.com
Accept-Language: en_US
Accept: application/json
Content-Length: -1
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue

< HTTP/1.1 400 Bad Request
< Date: Wed, 23 Jan 2019 12:23:30 GMT
< Server: Apache
< Content-Length: 338
< Connection: close
< Content-Type: text/html; charset=iso-8859-1
< 
* Closing connection 1

非常感谢有关此问题的任何帮助谢谢。

标签: phpcurlpaypal

解决方案


正如评论已经指出的那样,很难远程调试它。我缺乏添加评论的声誉,所以会建议这个答案。这是一个复杂的问题,所以恐怕这个答案充其量只会为您指明正确的方向,而不是为您提供具体的演练。

首先,您最好使用 paypal PHP SDK,在撰写本文时可以在此页面上找到它:

https://github.com/paypal/PayPal-PHP-SDK/

如果该链接损坏,我相信 Google 会提供帮助。这几乎肯定会解决您的问题。

但是,要回答您的问题(或其他任何人的问题,由于某种原因,不能使用规范库) - 从上面的链接可以看出,Paypal 对其安全性非常严格。我强烈怀疑您的命令行 curl 使用的 SSL 连接协议与您的 php-curl 不同。如果此页面没有回答解决您的问题,我会感到惊讶:

https://github.com/paypal/tls-update#php

我在这里复制了它以防链接损坏:

PHP 要求

PHP 使用系统提供的 cURL 库,它需要 OpenSSL 1.0.1c 或更高版本。您可能需要更新 SSL/TLS 库。

指导方针

在以下位置找到 OpenSSL:

OpenSSL 安装在您的操作系统的 openssl 版本中。

安装在您的 PHP 中的 OpenSSL 扩展。在您的 php.ini 中找到它。

PHP_CURL 使用的 OpenSSL - curl_version()。

这些 OpenSSL 扩展可以是不同的,您可以单独更新每一个。

PayPal 和其他 PHP SDK 使用 PHP_CURL 用于建立 HTTP 连接的相同 OpenSSL 扩展。PHP_CURL OpenSSL 扩展必须支持 TLSv1.2。

php_curl 库使用自己版本的 OpenSSL 库,与 PHP 使用的版本不一样,即 php.ini 中的 openssl.so 文件。

验证您的 PHP 和 TLS 版本

要查找 cURL 的 openssl_version 信息,请运行:

php -r 'echo json_encode(curl_version(), JSON_PRETTY_PRINT);'

返回的 php_curl 版本可能与 openssl 版本不同,因为它们是不同的组件。

更新 OpenSSL 库时,必须更新 php_curl OpenSSL 版本,而不是 OS OpenSSL 版本。

下载 cacert.pem 和 TlsCheck.php。

在生产系统的 shell 中,运行:

php -f TlsCheck.php

成功时:

PayPal_Connection_OK

失败时:

curl_error 信息

笔记:

确保您的命令行测试使用与您的 Web 服务器使用的相同版本的 PHP 和 SSL/TLS 库。如果您使用 MAMP 或 XAMPP 作为您的开发设置,则与它们一起打包的 PHP 使用的是较早版本的 OpenSSL,您无法轻松对其进行更新。有关此问题和临时解决方法的更多信息,请参阅未知 SSL 协议错误。

最后一件事 - 如果这是您的错误的原因,我将假设您的实时服务器至少有几年的历史。这完全无关,也不关我的事,但如果它已经过时,你可能还有一大堆其他漏洞。我强烈建议更新甚至启动新服务器(说起来容易做起来难......)


推荐阅读