【问题标题】:PayPal rejects credentials on Sample Code from Website TutorialPayPal 拒绝网站教程中示例代码的凭据
【发布时间】:2015-09-10 23:20:47
【问题描述】:

我一直试图通过this interactive tutorial page 的示例找出 PHP SDK。我稍微修改了代码以适应我自己的应用程序的目的,并包含我自己的 clientId 和 clientSecret,但还不足以构成重大违规。您将在下面的注释代码中看到我所做的更改。

我的问题是 payment->create() 方法不接受我的凭据。它抛出 400 代码异常,并显示消息“无效的凭据”。我做错了什么?

代码:(输出如下)

<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <?php
        //I wrote the PayPalAutoloader and stored it in the PayPal folder.
        //the autoloader uses the namespace data to parse the folder structure
        //and loads the corresponding object or throws an Exception if the file
        //is not found.
        require_once 'PayPal-PHP-SDK/PayPalAutoloader.php';

        //added my own INI file, where I can store API related values.
        $ini = \parse_ini_file('libsec.ini', true);
        $clientId = $ini['PayPal']['clientId'];
        $clientSecret = $ini['PayPal']['clientSecret'];

        //Step 1 of 5 from website
        $sdkConfig = [ "mode" => "sandbox"];
        $oauthCredential = new \PayPal\Auth\OAuthTokenCredential($clientId, $clientSecret, $sdkConfig);
        $apiContext = new \PayPal\Rest\ApiContext($oauthCredential);
        //end Step 1 of 5


        //observation, apiContext is never actually used in Step 1 and is redefined in Step 2

        //I found that to send the request I had to call getAccessToken (not mentioned in interactive tutorial)
        $accessToken = $oauthCredential->getAccessToken($sdkConfig);

        //peaking at the accessToken value
        var_dump( $accessToken );

        //Begin Step 2 of 5 from website
        //reuse sdkConfig from Step 1, it is unchanged
        $credentials = "Bearer {$accessToken}";
        $apiContext = new \PayPal\Rest\ApiContext($credentials, 'Request' . time() );
        $apiContext->setConfig($sdkConfig);

        $payer = new \PayPal\Api\Payer();
        $payer->setPaymentMethod("paypal");

        $amount = new \PayPal\Api\Amount();
        $amount->setCurrency("USD");
        $amount->setTotal("483.00");

        $transaction = new \PayPal\Api\Transaction();
        $transaction->setDescription("Annual Dues");
        $transaction->setAmount($amount);

        //removed as $baseURL is not actually used by any of the code that follows.
        //the results of the code are the same after commenting out the baseURL variable.
        //$baseUrl = getBaseUrl();
        $rootURL = $ini['General']['rootURL'];
        $successfulTransactionURL = $rootURL . $ini['PayPal']['success_bill_pay'];
        $cancelledTransactionURL = $rootURL . $ini['PayPal']['cancel_bill_pay'];
        $redirectUrls = new \PayPal\Api\RedirectUrls();
        $redirectUrls->setReturnUrl($successfulTransactionURL);
        $redirectUrls->setCancelUrl($cancelledTransactionURL);

        $payment = new \PayPal\Api\Payment();
        $payment->setIntent("sale");
        $payment->setPayer($payer);
        $payment->setRedirectUrls($redirectUrls);
        $payment->setTransactions($transaction);

        //a var_dump is added in the create method to look at the payment formatted as JSON prior to the
        //REST API call.
        $result = $payment->create($apiContext);

        //peaking at result
        var_dump( $result );

        ?>
    </body>
</html>

输出:

上述输出是来自同一程序运行的 3 个单独的输出实例。第一个字符串是 $accessToken 的 var_dump() ,用于验证是否正在检索令牌。每次运行都会成功检索到此令牌,并且值会更改。

第二个输出是在 Payment::create() 方法中形成的 $json 对象的 var_dump。此 json 对象通过 POST 方法传递给 API 系统,以对“/v1/payments/payment”的硬编码地址进行 REST 调用。

输出的第三部分是异常,它已经传播到屏幕并阻止了 Payment::create() 方法的完成。

【问题讨论】:

    标签: php paypal


    【解决方案1】:

    经过进一步调查,问题出现在指示行的 RestHandler 中。代码如下:

        if ($credential == null || !($credential instanceof OAuthTokenCredential)) {
            throw new PayPalInvalidCredentialException("Invalid credentials passed");
        }
    

    但是,当我转储 $credential 变量时,我有:

    string 'Bearer A015kCDeXpDfAvtTj7dbRg7ldRk-OdKboQhPaY4EmYu-bRA' (length=54)
    

    SDK 必须从编写教程时开始更新。不幸的是,仍然有从 PayPal 的 API 文档到此交互式教程的链接,该教程已过时。

    事实证明,当我在 OAuthTokenCredential 对象上调用“getAccessToken”时,它会为将来再次使用做好准备。我无需存储结果并创建“承载”。 $token 字符串。我只是再次使用相同的 OAuthTokenCredential,一切正常。

    在寻找解决方案的过程中,我删除了我的代码并从网站上复制了代码,演示修复的工作代码如下:

    <!DOCTYPE html>
    <!--
    To change this license header, choose License Headers in Project Properties.
    To change this template file, choose Tools | Templates
    and open the template in the editor.
    -->
    <html>
        <head>
            <meta charset="UTF-8">
            <title></title>
        </head>
        <body>
            <?php
            //I wrote the PayPalAutoloader and stored it in the PayPal folder.
            //the autoloader uses the namespace data to parse the folder structure
            //and loads the corresponding object or throws an Exception if the file
            //is not found.
            require_once 'PayPal-PHP-SDK/PayPalAutoloader.php';
            echo "<h2>Success</h2>";
            //added my own INI file, where I can store API related values.
            $sdkConfig = array(
                "mode" => "sandbox"
            );
    
            $cred = new \PayPal\Auth\OAuthTokenCredential("AQkquBDf1zctJOWGKWUEtKXm6qVhueUEMvXO_-MCI4DQQ4-LWvkDLIN2fGsd", "EL1tVxAjhT7cJimnz5-Nsx9k2reTKSVfErNQF-CmrwJgxRtylkGTKlU4RvrX", $sdkConfig);
    
            //storing the result is not needed, because the result automatically updates the same credential object.
            //we will use the variable $cred as is and forget about the accessToken. We also will not set a "Bearer" string for the header"
            $accessToken = $cred->getAccessToken($sdkConfig);
    
    
            //peaking at the credential object to verify that the accessToken is listed.
            var_dump( $cred );
    
            //peaking at the accessToken value
            var_dump($accessToken);
    
            //Begin Step 2 of 5 from website
            $sdkConfig = array(
                "mode" => "sandbox"
            );
    
            //we comment out the redefinition of cred in Step2.... We will use the OAuthtokenCredential from Step 1,
            //which is also stored in $cred at this point.
            //$cred = "Bearer {$accessToken}";
            $apiContext = new \PayPal\Rest\ApiContext($cred, 'Request' . time());
            $apiContext->setConfig($sdkConfig);
    
            $payer = new \PayPal\Api\Payer();
            $payer->setPaymentMethod("paypal");
    
            $amount = new \PayPal\Api\Amount();
            $amount->setCurrency("USD");
            $amount->setTotal("12");
    
            $transaction = new \PayPal\Api\Transaction();
            $transaction->setDescription("creating a payment");
            $transaction->setAmount($amount);
    
            $redirectUrls = new \PayPal\Api\RedirectUrls();
            $redirectUrls->setReturnUrl("https://devtools-paypal.com/guide/pay_paypal/php?success=true");
            $redirectUrls->setCancelUrl("https://devtools-paypal.com/guide/pay_paypal/php?cancel=true");
    
            $payment = new \PayPal\Api\Payment();
            $payment->setIntent("sale");
            $payment->setPayer($payer);
            $payment->setRedirectUrls($redirectUrls);
            $payment->setTransactions(array($transaction));
    
            var_dump( $payment->create($apiContext) );
    
            //the payment object is successfully updated with the payment id.
            ?>
        </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 2012-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-02
      • 1970-01-01
      • 2021-04-13
      相关资源
      最近更新 更多