我正在将PayPal的订阅API实现到我的项目中,但是,我收到以下卷曲错误:
array:2 [▼
"error" => "error_in_reading_cert"
"error_description" => "Unable to read x509 certificate"
]
请注意,我正在使用拉拉维尔。这是我的卷发课:
<?php
namespace AppLogicCurl;
class Curl {
/**
* Perform new POST request and return decoded JSON response
*
* @param $url
* @param $data
* @return array
*/
public function newRequest($url, $data)
{
$connection = curl_init($url);
$clientId = env('services.paypal.client-id');
$secret = env('services.paypal.secret');
curl_setopt($connection, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"Authorization: Basic $clientId:$secret",
]
);
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // don't return headers
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
CURLOPT_ENCODING => "", // handle compressed
CURLOPT_USERAGENT => "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36", // name of client
CURLOPT_AUTOREFERER => true, // set referrer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // time-out on connect
CURLOPT_TIMEOUT => 120, // time-out on response
);
curl_setopt_array($connection, $options);
curl_setopt($connection, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($connection);
if(curl_error($connection)) {
return curl_error($connection);
}
curl_close($connection);
return $this->decodeResponse($response);
}
/**
* JSON decode the response
*
* @param $response
* @return mixed
*/
public function decodeResponse($response)
{
return json_decode($response, true);
}
}
这是我PayPal课:
<?php
namespace AppLogicPaypal;
use AppLogicCurlCurl;
use Exception;
class Paypal {
public function createProduct()
{
$productDetails = [
"name" => "Feedback Form",
"description" => "Feedback form as a service.",
"type" => "SERVICE",
"category" => "SOFTWARE",
"home_url" => "https://www.feedback.com/"
];
$url = $this->getApiUrl('createProduct');
$curl = new Curl();
return $curl->newRequest($url, $productDetails);
}
public function getApiUrl($endpointName) {
$mode = config('services.paypal.mode');
$urls = [
'createProduct' => [
'live' => 'https://api.paypal.com/v1/catalogs/products',
'sandbox' => 'https://api.sandbox.paypal.com/v1/catalogs/products'
]
];
return $urls[$endpointName][$mode];
}
}
这是我接收请求的PayPal控制器:
<?php
namespace AppHttpControllers;
use AppLogicPaypalPaypal;
use AppSetting;
class PaypalController extends Controller
{
public function bootstrap()
{
$setting = Setting::where('name', '=', 'active_plan_id')->first();
if ($setting) {
return 'plan already activated';
}
$paypal = new Paypal();
$product = $paypal->createProduct();
dd($product);
}
}
上面的代码只是尝试根据PayPal的订阅文档创建产品。
在网上寻找解决方案时,我遇到了关于StackOverflow的各种问题 - 其中最有希望的是这个问题。首先,我尝试了投票最多的解决方案,但它对我不起作用,尽管这有点奇怪。我遵循它并进入我的/etc/php/7.2/apache2/php.ini 并取消注释curl.cainfo
并用下载证书的绝对路径填充它并重新启动 apache,这没有帮助。然后,我创建了一个 php info 文件并查看了选项,即使加载的配置文件正是我编辑的配置文件,我也找不到curl.cainfo
- 根据这个 curl.cainfo 不会显示在 phpinfo 中,因为 PHP7.2 直截了当地解决了这个问题。
从同一个 StackOverflow 问题中,我也尝试了:
sudo apt-get install ca-certificates
和:
sudo update-ca-certificates
但这并没有帮助。
任何帮助非常感谢。
编辑 1:刚刚注意到在 PayPal 的文档中,curl 是使用选项-k
调用的,它甚至允许不安全的连接,我想知道为什么会这样,PayPal是否在其沙盒 API 上使用自签名证书?
编辑2:我尝试从这里下载证书并指向curl.cainfo
它,但它也没有很好地工作。
编辑3:我尝试通过添加以下行$options[CURLOPT_SSL_VERIFYPEER] = false;
禁用对等证书验证,但仍然收到相同的错误
编辑4:我也尝试添加curl_setopt($connection, CURLOPT_CAINFO, '/path/to/cacert.pem');
但没有帮助
编辑5:我也尝试从命令行运行相同的请求,但出现相同的错误,这是输出:
Note: Unnecessary use of -X or --request, POST is already inferred.
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0* Trying 173.0.82.78...
* TCP_NODELAY set
0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:-- 0* Connected to api.sandbox.paypal.com (173.0.82.78) port 443 (#0)
0 0 0 0 0 0 0 0 --:--:-- 0:00:03 --:--:-- 0* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ca-certificates
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [85 bytes data]
0 0 0 0 0 0 0 0 --:--:-- 0:00:04 --:--:-- 0* TLSv1.2 (IN), TLS handshake, Certificate (11):
{ [4162 bytes data]
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
{ [944 bytes data]
* TLSv1.2 (IN), TLS handshake, Server finished (14):
{ [4 bytes data]
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
} [7 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
} [262 bytes data]
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
} [1 bytes data]
* TLSv1.2 (OUT), TLS handshake, Finished (20):
} [16 bytes data]
* TLSv1.2 (IN), TLS handshake, Finished (20):
{ [16 bytes data]
* SSL connection using TLSv1.2 / AES256-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=US; ST=California; L=San Jose; O=PayPal, Inc.; OU=PayPal Production; CN=api.sandbox.paypal.com
* start date: Aug 21 00:00:00 2018 GMT
* expire date: Aug 20 12:00:00 2020 GMT
* subjectAltName: host "api.sandbox.paypal.com" matched cert's "api.sandbox.paypal.com"
* issuer: C=US; O=DigiCert Inc; CN=DigiCert Global CA G2
* SSL certificate verify ok.
0 0 0 0 0 0 0 0 --:--:-- 0:00:05 --:--:-- 0} [5 bytes data]
> POST /v1/catalogs/products HTTP/1.1
> Host: api.sandbox.paypal.com
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Type: application/json
> Authorization: Basic client-id:secret
> Content-Length: 205
>
} [205 bytes data]
* upload completely sent off: 205 out of 205 bytes
{ [5 bytes data]
< HTTP/1.1 401 Unauthorized
< Cache-Control: max-age=0, no-cache, no-store, must-revalidate
< Content-Length: 87
< Content-Type: application/json
< Date: Wed, 25 Mar 2020 09:45:30 GMT
< Paypal-Debug-Id: f3411e0e1c2ab
<
{ [87 bytes data]
100 292 100 87 100 205 12 30 0:00:07 0:00:06 0:00:01 55
100 292 100 87 100 205 12 30 0:00:07 0:00:06 0:00:01 68
* Connection #0 to host api.sandbox.paypal.com left intact
{"error":"error_in_reading_cert","error_description":"Unable to read x509 certificate"}
编辑6:这是我尝试的完整curl命令和输出:
curl -v -k POST https://api.sandbox.paypal.com/v1/catalogs/products -H "Content-Type: application/json" -H "Authorization: Basic AW09uZVO_1NUVZXEzlYp1xgiVjweOwnIBl0rMltEK7X1zMhe9fxcPPr_IgwGplL0xSPHQo4lO3cdP27p:EB351ARk-HkEd5OmkV7NGXrUT5V2AU_zN8ZRJ55cWowGUKr845Do0MM5zrqfpCxJECqL59rwcXueQUW2" -d '{"name": "Video Streaming Service","description": "Video streaming service","type": "SERVICE","category": "SOFTWARE","image_url": "https://example.com/streaming.jpg","home_url": "https://example.com/home"}' --cacert /opt/ssl/curl.pem 2>&1 | tee curl.txt
输出:
* Rebuilt URL to: POST/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:03 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:04 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:05 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:06 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:07 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:08 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:09 --:--:-- 0* Could not resolve host: POST
* Closing connection 0
curl: (6) Could not resolve host: POST
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:-- 0* Trying 173.0.82.78...
* TCP_NODELAY set
0 0 0 0 0 0 0 0 --:--:-- 0:00:03 --:--:-- 0* Connected to api.sandbox.paypal.com (173.0.82.78) port 443 (#1)
0 0 0 0 0 0 0 0 --:--:-- 0:00:03 --:--:-- 0* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /opt/ssl/curl.pem
CApath: /etc/ssl/certs
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [85 bytes data]
* TLSv1.2 (IN), TLS handshake, Certificate (11):
{ [4162 bytes data]
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
{ [944 bytes data]
* TLSv1.2 (IN), TLS handshake, Server finished (14):
{ [4 bytes data]
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
} [7 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
} [262 bytes data]
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
} [1 bytes data]
* TLSv1.2 (OUT), TLS handshake, Finished (20):
} [16 bytes data]
* TLSv1.2 (IN), TLS handshake, Finished (20):
{ [16 bytes data]
* SSL connection using TLSv1.2 / AES256-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=US; ST=California; L=San Jose; O=PayPal, Inc.; OU=PayPal Production; CN=api.sandbox.paypal.com
* start date: Aug 21 00:00:00 2018 GMT
* expire date: Aug 20 12:00:00 2020 GMT
* issuer: C=US; O=DigiCert Inc; CN=DigiCert Global CA G2
* SSL certificate verify ok.
0 0 0 0 0 0 0 0 --:--:-- 0:00:04 --:--:-- 0} [5 bytes data]
> POST /v1/catalogs/products HTTP/1.1
> Host: api.sandbox.paypal.com
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Type: application/json
> Authorization: Basic AW09uZVO_1NUVZXEzlYp1xgiVjweOwnIBl0rMltEK7X1zMhe9fxcPPr_IgwGplL0xSPHQo4lO3cdP27p:EB351ARk-HkEd5OmkV7NGXrUT5V2AU_zN8ZRJ55cWowGUKr845Do0MM5zrqfpCxJECqL59rwcXueQUW2
> Content-Length: 205
>
} [205 bytes data]
* upload completely sent off: 205 out of 205 bytes
{ [5 bytes data]
< HTTP/1.1 401 Unauthorized
< Cache-Control: max-age=0, no-cache, no-store, must-revalidate
< Content-Length: 87
< Content-Type: application/json
< Date: Wed, 25 Mar 2020 15:54:35 GMT
< Paypal-Debug-Id: ae0a3de96fdf5
<
{ [87 bytes data]
100 292 100 87 100 205 16 39 0:00:05 0:00:05 --:--:-- 79
* Connection #1 to host api.sandbox.paypal.com left intact
{"error":"error_in_reading_cert","error_description":"Unable to read x509 certificate"}
编辑7:我运行相同的curl命令,但使用来自不同企业帐户的不同凭据,这是命令和输出:
curl -v -k POST https://api.sandbox.paypal.com/v1/catalogs/products -H "Content-Type: application/json" -H "Authorization: Basic AVx9AFnHHdAvjsRA_t5AXJEdu_XIqC4RgxOvJ_a49r3QZj9eNlSy1gRGRmLIBS52wh1LWi27adQgvwSc:EPCcwShbEMG4O9uoPvoMtbwFc02RT2vo8FayHqU3StskKR3bxx7sxXACEG7Sf-Mwx_taRFhRfp0s79Ox" -d '{"name": "Video Streaming Service","description": "Video streaming service","type": "SERVICE","category": "SOFTWARE","image_url": "https://example.com/streaming.jpg","home_url": "https://example.com/home"}' --cacert /opt/ssl/curl.pem 2>&1 | tee curl.txt
输出:
* Rebuilt URL to: POST/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:03 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:04 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:05 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:06 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:07 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:08 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:09 --:--:-- 0* Could not resolve host: POST
* Closing connection 0
curl: (6) Could not resolve host: POST
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:-- 0* Trying 173.0.82.78...
* TCP_NODELAY set
0 0 0 0 0 0 0 0 --:--:-- 0:00:03 --:--:-- 0* Connected to api.sandbox.paypal.com (173.0.82.78) port 443 (#1)
0 0 0 0 0 0 0 0 --:--:-- 0:00:03 --:--:-- 0* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /opt/ssl/curl.pem
CApath: /etc/ssl/certs
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [85 bytes data]
* TLSv1.2 (IN), TLS handshake, Certificate (11):
{ [4162 bytes data]
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
{ [944 bytes data]
* TLSv1.2 (IN), TLS handshake, Server finished (14):
{ [4 bytes data]
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
} [7 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
} [262 bytes data]
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
} [1 bytes data]
* TLSv1.2 (OUT), TLS handshake, Finished (20):
} [16 bytes data]
* TLSv1.2 (IN), TLS handshake, Finished (20):
{ [16 bytes data]
* SSL connection using TLSv1.2 / AES256-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=US; ST=California; L=San Jose; O=PayPal, Inc.; OU=PayPal Production; CN=api.sandbox.paypal.com
* start date: Aug 21 00:00:00 2018 GMT
* expire date: Aug 20 12:00:00 2020 GMT
* issuer: C=US; O=DigiCert Inc; CN=DigiCert Global CA G2
* SSL certificate verify ok.
0 0 0 0 0 0 0 0 --:--:-- 0:00:04 --:--:-- 0} [5 bytes data]
> POST /v1/catalogs/products HTTP/1.1
> Host: api.sandbox.paypal.com
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Type: application/json
> Authorization: Basic AW09uZVO_1NUVZXEzlYp1xgiVjweOwnIBl0rMltEK7X1zMhe9fxcPPr_IgwGplL0xSPHQo4lO3cdP27p:EB351ARk-HkEd5OmkV7NGXrUT5V2AU_zN8ZRJ55cWowGUKr845Do0MM5zrqfpCxJECqL59rwcXueQUW2
> Content-Length: 205
>
} [205 bytes data]
* upload completely sent off: 205 out of 205 bytes
{ [5 bytes data]
< HTTP/1.1 401 Unauthorized
< Cache-Control: max-age=0, no-cache, no-store, must-revalidate
< Content-Length: 87
< Content-Type: application/json
< Date: Wed, 25 Mar 2020 15:54:35 GMT
< Paypal-Debug-Id: ae0a3de96fdf5
<
{ [87 bytes data]
100 292 100 87 100 205 16 39 0:00:05 0:00:05 --:--:-- 79
* Connection #1 to host api.sandbox.paypal.com left intact
{"error":"error_in_reading_cert","error_description":"Unable to read x509 certificate"}
在 client:secret 上使用 base64。
如果您有:
clientId: "clientId"
secret: "mySecret"
比做base64("clientId:mySecret")
所以正确的标题是
Authorization: Basic Y2xpZW50SWQ6bXlTZWNyZXQ=
问题与使用错误的授权标头有关,如下所示:
Authorization: Basic <client-id>:<secret>
即使由于某种原因这在文档中它不起作用,也请使用以下内容:
Authorization: Bearer <access-token>
感谢Preston PHX
帮助我弄清楚。
就我而言,我使用的是 Axios,我正在标头中传递授权,就像文档所说的那样。 但这行不通, 对我有用的是:
const PAYPAL_API = 'https://api-m.sandbox.paypal.com';
const order = {
purchase_units: [
{
amount: {
currency_code: 'USD',
value: '100.00',
},
},
],
intent: 'AUTHORIZE',
};
const config = {
headers: {
'Content-Type': 'application/json',
},
auth: { username: <Your_CLIENT_ID>, password: <Your_SECRET_ID> },
};
await axios
.post(`${this.PAYPAL_API}/v2/checkout/orders`, order, config)
您可以从 https://curl.haxx.se/docs/caextract.html 下载更新的证书颁发机构捆绑包
在其他可能的配置位置中,可以通过将其添加到curl选项来传递该.pem文件:
curl_setopt($connection, CURLOPT_CAINFO, '/path/to/cacert.pem');
或者因为您有一系列选项:
CURLOPT_CAINFO => '/path/to/cacert.pem',
PayPal 不在沙盒中使用自签名证书,但由于某些环境未配置适当的证书颁发机构,因此在命令行示例中使用curl -k
(不安全/无验证对等方),因为在开发过程中无需验证对等证书。
是的,clientid 和 secret 必须采用 base64 编码。
技巧:curl 在使用 "-u" 标志时为您执行此操作。因此,您可以curl ... -u "clientid:secret"
而不是curl ... -H "Authorization: Basic ${base64_encoded_creds}"
.