当前位置:  开发笔记 > 编程语言 > 正文

无法在SSL网站上使用Paypal API

如何解决《无法在SSL网站上使用PaypalAPI》经验,为你挑选了1个好方法。

我有一个使用cURL与Paypal API集成的SSL网站.

这是我的PHP包括文件类:

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,但在完成该过程后,它将用户带回网站,该网址似乎是正确的(例如https://example.com/pro&type=successful?token=EC-8BB04791XJ708490K&PayerID=QL54Q696KZCLA),但没有付款.

我也尝试了沙盒,但我在Apache日志文件中看不到任何错误,所以我需要调试$response,因此我尝试echo var_dump($response);在解析响应之前添加.

但我没有太多调试经验,在Chrome上我不知道在哪里检查响应.(在JS控制台上我看不到它)

我如何调试此API响应以检查为什么paypal不允许我的网站付款?(该网站已经过验证)

UPDATE

作为身份验证我正在使用带有SetExpressCheckout方法的API签名NVP格式.

这是我的回复代码:

        // 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', ''.urldecode($paypalResponse['L_SHORTMESSAGE0'].': '.$paypalResponse['L_LONGMESSAGE0']));
                    }
                } else {
                    $TMPL['error'] = notificationBox('error', ''.urldecode($paypalResponse['L_SHORTMESSAGE0'].': '.$paypalResponse['L_LONGMESSAGE0']));
                }
            } else {
                $TMPL['error'] = notificationBox('error', ''.urldecode($paypalResponse['L_SHORTMESSAGE0'].': '.$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的交易.怎么了?



1> Machavity..:

你的过程似乎非常复杂.让我们打破这个

// 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呼叫,获取令牌并将用户传递给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") {

这没有任何意义.您刚刚将用户退回到PayPal,header我们称之为与我们传递给SEC电话的数据相同.DoExpressCheckoutPayment要求您传回令牌,用户刚离开网站进行授权.我希望看到你的代码寻找$_GET['TOKEN'](意味着用户从PayPal返回),然后为此构建一个新的请求.现在,在编写代码时,它只是在一个巨链中链接所有3个调用.

这是过程应该是什么样子

SetExpressCheckout - 将用户退回到PayPal.停止处理

GetExpressCheckoutDetails - 用户已从PayPal返回,因为我们在查询字符串中有一个TOKEN.现在运行此调用可以确保TOKEN有效

DoExpressCheckoutPayment - 如果TOKEN有效,我们完成销售.

最后但并非最不重要的是,你不能只寻找成功.阅读关于ACK的文档.您还可以获得SuccessWithWarning.将您的成功条件更改为

 if(stripos($paypalResponse["ACK"], "SUCCESS") !== false) {

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有