我有一个使用 cURL 与 Paypal API 集成的 SSL 网站。
这是我的 PHP 类(class)包含文件:
class paypalApi {
public $username;
public $password;
public $signature;
function post($method, $params, $mode) {
// Method: Required
// Parameters: An array containing the requested parameters
// The request URL
$url = "https://api-3t".$mode.".paypal.com/nvp";
// Version of the API
$version = '116.0';
// Construct the query params
// Set the API method, version, and API credentials.
$credentials = array('METHOD' => $method, 'VERSION' => $version, 'USER' => $this->username, 'PWD' => $this->password, 'SIGNATURE' => $this->signature);
$params = array_merge($credentials, $params);
// Set the curl parameters.
if(function_exists('curl_exec')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
// Turn off the server and peer verification (TrustManager Concept).
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
$response = curl_exec($ch);
}
if(empty($response)) {
$opts = array('http' =>
array(
'protocol_version' => '1.1',
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => http_build_query($params)
)
);
$context = stream_context_create($opts);
$response = file_get_contents($url, false, $context);
}
// Parse the response
parse_str($response, $responseArr);
// If the request fails
if(empty($responseArr) || !array_key_exists('ACK', $responseArr)) {
global $LNG;
// Mimic a fake response
return array('L_SHORTMESSAGE0' => $LNG['error'], 'L_LONGMESSAGE0' => $LNG['payment_error_0'], 'ACK' => 'REQUEST_FAILED');
}
return $responseArr;
}
}
由于某种原因,它不起作用,点击支付按钮将用户带到 Paypal,但在完成该过程后,它将用户带回网站,url 似乎是正确的(例如 https://example.com/pro&type=successful?token=EC-8BB04791XJ708490K&PayerID=QL54Q696KZCLA
) 但没有付款。
我也尝试了沙箱,但我在 Apache 日志文件中看不到任何错误,所以我需要调试 $response
,因此我尝试添加 echo var_dump($response );
在解析响应之前。
但是我没有太多的调试经验,在 Chrome 上我不知道去哪里查看响应。(在 JS 控制台上我看不到)
我如何调试此 API 响应以检查为什么 paypal 不允许为我的网站付款? (该网站已经过验证)
更新
作为身份验证,我使用 API 签名 NVP 格式和 SetExpressCheckout
方法。
这是我的回复代码:
// Execute SetExpressCheckOut method to create the payment token and PayerID
$paypalResponse = $paypal->post('SetExpressCheckout', $params, $PayPalMode);
//Respond according to message we receive from Paypal
if(strtoupper($paypalResponse["ACK"]) == "SUCCESS") {
// Generat the PayPal payment url with the response Token
$paypalurl = 'https://www'.$PayPalMode.'.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='.$paypalResponse["TOKEN"].'';
// Redirect to PayPal payment page
header('Location: '.$paypalurl);
// Execute DoExpressCheckoutPayment to receive the payment from the user
$paypalResponse = $paypal->post('DoExpressCheckoutPayment', $params, $PayPalMode);
// Check if the payment was successful
if(strtoupper($paypalResponse["ACK"]) == "SUCCESS") {
// Verify if the payment is Completed
if($paypalResponse["PAYMENTINFO_0_PAYMENTSTATUS"] == 'Completed') {
// Execute GetExpressCheckoutDetails to retrieve the transaction details
$params = array('TOKEN' => $token);
$paypalResponse = $paypal->post('GetExpressCheckoutDetails', $params, $PayPalMode);
// If the GetExpressCheckoutDetails was successful
if(strtoupper($paypalResponse["ACK"]) == "SUCCESS") {
$date = date("Y-m-d H:m:s", strtotime(($_SESSION['SelectedPlan'] == 1 ? "+1 year" : "+1 month")));
$stmt = $db->prepare(sprintf("INSERT INTO `payments`
(`by`, `payer_id`, `payer_first_name`, `payer_last_name`, `payer_email`, `payer_country`, `txn_id`, `amount`, `currency`, `type`, `status`, `valid`, `time`) VALUES
('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s','%s', '%s', '%s', '%s')",
$db->real_escape_string($feed->id), $db->real_escape_string($paypalResponse['PAYERID']), $db->real_escape_string($paypalResponse['FIRSTNAME']), $db->real_escape_string($paypalResponse['LASTNAME']), $db->real_escape_string($paypalResponse['EMAIL']), $db->real_escape_string($paypalResponse['SHIPTOCOUNTRYNAME']), $db->real_escape_string($paypalResponse['PAYMENTREQUEST_0_TRANSACTIONID']), $db->real_escape_string($paypalResponse['AMT']), $settings['currency'], $_SESSION['SelectedPlan'], 1, $date, date("Y-m-d H:m:s")));
// Execute the statement
$stmt->execute();
// Check the affected rows
$affected = $stmt->affected_rows;
// Close the statement
$stmt->close();
// If the pro status has been added
if($affected) {
// Set the pro account to valid
$proAccount = 2;
}
} else {
$TMPL['error'] = notificationBox('error', '<strong>'.urldecode($paypalResponse['L_SHORTMESSAGE0'].'</strong>: '.$paypalResponse['L_LONGMESSAGE0']));
}
} else {
$TMPL['error'] = notificationBox('error', '<strong>'.urldecode($paypalResponse['L_SHORTMESSAGE0'].'</strong>: '.$paypalResponse['L_LONGMESSAGE0']));
}
} else {
$TMPL['error'] = notificationBox('error', '<strong>'.urldecode($paypalResponse['L_SHORTMESSAGE0'].'</strong>: '.$paypalResponse['L_LONGMESSAGE0']));
}
}
编辑
这是我的 error.log 文件:
* Hostname was NOT found in DNS cache
* Trying 173.0.82.83...
* Connected to api-3t.sandbox.paypal.com (173.0.82.83) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSL connection using ***********************
* Server certificate:
* subject: C=US; ST=California; L=San Jose; O=PayPal, Inc.; OU=PayPal Production; CN=api-3t.sandbox.paypal.com
* start date: 2015-09-16 00:00:00 GMT
* expire date: 2016-10-31 23:59:59 GMT
* issuer: C=US; O=VeriSign, Inc.; OU=VeriSign Trust Network; OU=Terms of use at https://www.verisign.com/rpa (c)10; CN=VeriSign Class 3 Secure Server CA - G3
* SSL certificate verify ok.
> POST /nvp HTTP/1.1
Host: api-3t.sandbox.paypal.com
Accept: */*
Content-Length: 862
Content-Type: application/x-www-form-urlencoded
* upload completely sent off: 862 out of 862 bytes
< HTTP/1.1 200 OK
< Date: Wed, 30 Dec 2015 09:49:59 GMT
* Server Apache is not blacklisted
< Server: Apache
< X-PAYPAL-OPERATION-NAME: SetExpressCheckout
< X-PAYPAL-API-RC:
< Connection: close
< Content-Length: 138
< Paypal-Debug-Id: 7d9949c818525
< Set-Cookie: X-PP-SILOVER=name%3DSANDBOX3.API.1%26silo_version%3D880%26app%3Dappdispatcher_apit%26TIME%3D3349709654; domain=.paypal.com; path=/; Secure; HttpOnly
< Set-Cookie: X-PP-SILOVER=; Expires=Thu, 01 Jan 1970 00:00:01 GMT
< Content-Type: text/plain; charset=utf-8
* Closing connection 0
第二次编辑
最后我能够调试响应(存在重定向问题)
TOKEN=EC-9F8624569H0752611
BILLINGAGREEMENTACCEPTEDSTATUS=0
CHECKOUTSTATUS=PaymentActionCompleted
TIMESTAMP=2015-12-30T15:41:54Z
CORRELATIONID=19204729b140
ACK=Success
VERSION=116.0
BUILD=18308778
EMAIL=info-buyer@example.org
PAYERID=QL54Q696KZCLA
PAYERSTATUS=verified
FIRSTNAME=test
LASTNAME=buyer
COUNTRYCODE=IT
SHIPTONAME=test buyer
SHIPTOSTREET=Via Unit? d\'Italia, 5783296
SHIPTOCITY=Napoli
SHIPTOSTATE=NAPOLI
SHIPTOZIP=80127
SHIPTOCOUNTRYCODE=IT
SHIPTOCOUNTRYNAME=Italy
ADDRESSSTATUS=Unconfirmed
CURRENCYCODE=EUR
AMT=4.00
ITEMAMT=4.00
SHIPPINGAMT=0.00
HANDLINGAMT=0.00
TAXAMT=0.00
INSURANCEAMT=0.00
SHIPDISCAMT=0.00
L_NAME0=Monthly Pro Plan - example subdirectory
L_NUMBER0=cfcd208495d565ef66e7dff9f98764da
L_QTY0=1
L_TAXAMT0=0.00
L_AMT0=4.00
L_DESC0=Monthly Pro Plan - example subdirectory
L_ITEMWEIGHTVALUE0= 0.00000
L_ITEMLENGTHVALUE0= 0.00000
L_ITEMWIDTHVALUE0= 0.00000
L_ITEMHEIGHTVALUE0= 0.00000
PAYMENTREQUEST_0_CURRENCYCODE=EUR
PAYMENTREQUEST_0_AMT=4.00
PAYMENTREQUEST_0_ITEMAMT=4.00
PAYMENTREQUEST_0_SHIPPINGAMT=0.00
PAYMENTREQUEST_0_HANDLINGAMT=0.00
PAYMENTREQUEST_0_TAXAMT=0.00
PAYMENTREQUEST_0_INSURANCEAMT=0.00
PAYMENTREQUEST_0_SHIPDISCAMT=0.00
PAYMENTREQUEST_0_TRANSACTIONID=61M42051UB346361T
PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false
PAYMENTREQUEST_0_SHIPTONAME=test buyer
PAYMENTREQUEST_0_SHIPTOSTREET=Via Unit? d\'Italia, 5783296
PAYMENTREQUEST_0_SHIPTOCITY=Napoli
PAYMENTREQUEST_0_SHIPTOSTATE=NAPOLI
PAYMENTREQUEST_0_SHIPTOZIP=80127
PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=IT
PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=Italy
PAYMENTREQUEST_0_ADDRESSSTATUS=Unconfirmed
PAYMENTREQUEST_0_ADDRESSNORMALIZATIONSTATUS=None
L_PAYMENTREQUEST_0_NAME0=Monthly Pro Plan - example subdirectory
L_PAYMENTREQUEST_0_NUMBER0=cfcd208495d565ef66e7dff9f98764da
L_PAYMENTREQUEST_0_QTY0=1
L_PAYMENTREQUEST_0_TAXAMT0=0.00
L_PAYMENTREQUEST_0_AMT0=4.00
L_PAYMENTREQUEST_0_DESC0=Monthly Pro Plan - example subdirectory
L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE0= 0.00000
L_PAYMENTREQUEST_0_ITEMLENGTHVALUE0= 0.00000
L_PAYMENTREQUEST_0_ITEMWIDTHVALUE0= 0.00000
L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE0= 0.00000
PAYMENTREQUESTINFO_0_TRANSACTIONID=61M42051UB346361T
PAYMENTREQUESTINFO_0_ERRORCODE=0
因此,从我的角度来看,现在一切正常,但我在沙盒 Paypal 上看不到任何交易。怎么了?
最佳答案
您的过程似乎非常复杂。让我们分解一下
// Execute SetExpressCheckOut method to create the payment token and PayerID
$paypalResponse = $paypal->post('SetExpressCheckout', $params, $PayPalMode);
//Respond according to message we receive from Paypal
if(strtoupper($paypalResponse["ACK"]) == "SUCCESS") {
// Generat the PayPal payment url with the response Token
$paypalurl = 'https://www'.$PayPalMode.'.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='.$paypalResponse["TOKEN"].'';
// Redirect to PayPal payment page
header('Location: '.$paypalurl);
到目前为止一切顺利。您调用 SEC 电话,获取您的 token 并将用户传递给 PayPal。但是接下来的部分令人困惑
// Execute DoExpressCheckoutPayment to receive the payment from the user
$paypalResponse = $paypal->post('DoExpressCheckoutPayment', $params, $PayPalMode);
// Check if the payment was successful
if(strtoupper($paypalResponse["ACK"]) == "SUCCESS") {
这没有任何意义。您刚刚使用 header
将用户退回到 PayPal,我们调用它时使用的数据似乎与我们传递给 SEC 调用的数据相同。 DoExpressCheckoutPayment
要求您传回 token 并且用户刚刚离开站点以对其进行授权。我希望看到您的代码查找 $_GET['TOKEN']
(表示用户从 PayPal 返回),然后为此构建一个新请求。现在,当您编写代码时,它只是将所有 3 个调用链接到一个巨大的链中。
流程应该是这样的
SetExpressCheckout
- 将用户跳转到 PayPal。停止处理GetExpressCheckoutDetails
- 用户已从 PayPal 返回,因为我们在查询字符串中有一个 token 。现在运行此调用让我们确保 token 有效DoExpressCheckoutPayment
- 如果 token 有效,让我们完成销售。
最后但同样重要的是,您不能只寻找成功。 Read the docs on ACK .您还可以获得SuccessWithWarning。将您的成功条件更改为
if(stripos($paypalResponse["ACK"], "SUCCESS") !== false) {
关于php - 无法在 SSL 网站上使用 Paypal API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34452327/