Paypal未能继续接收付款。

4
我正在尝试通过URL使用Paypal进行捐赠。当我登录PayPal并进行付款时,我会收到以下消息:enter image description here 我有后端代码,它看起来像这样。
<?php
use PayPal\Rest\ApiContext;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Api\Payer;
use PayPal\Api\Details;
use PayPal\Api\Amount;
use PayPal\Api\Transaction;
use PayPal\Api\Payment;
use PayPal\Api\RedirectUrls;
use PayPal\Api\PaymentExecution;

require __DIR__ . DIRECTORY_SEPARATOR . '../vendor/autoload.php';

/**
* Edri PayPal Pyment
*/
class Edri_PayPal_Payment
{
    
    private $api;

    private $payer;

    private $details;

    private $amount;

    private $transaction;

    private $payment;

    private $redirectUrls;


    function __construct()
    {
        $this->api = $this->setup_PayPal_Api();
    }

    private function debug($val)
    {
        echo '<pre>';
        var_dump($val);
        echo '</pre>';
    }

    private function setup_PayPal_Api()
    {
        $api = new ApiContext(
            new OAuthTokenCredential(
                'MyPayPalClientID',
                'MyClientSecret'
            )
        );

        $api->setConfig(array(
            'mode' => 'live',
            'http.ConnectionTimeOut' => 30,
            'Log.LogEnabled' => false,
            'Log.FileName' => '',
            'Log.LogLevel' => 'FINE',
            'validation.level' => 'log'
        ));

        return $api;
    }

    private function setupPayer()
    {
        $this->payer = new Payer();

        $this->payer->setPayment_method('paypal');
    }

    private function setupDetails($amount)
    {
        $this->details = new Details();
        $this->details->setShipping('0.00')
            ->setTax('0.00')
            ->setsubTotal($amount);
    }

    private function setupAmount($amount)
    {

        $this->amount = new Amount();

        $this->amount->setCurrency('EUR')
            ->setTotal($amount)
            ->setDetails($this->details);
    }
    
    private function setupTransaction($amount)
    {

        $this->transaction = new Transaction();

        $this->transaction->setAmount($this->amount)
            ->setDescription('Make a donation of €' . $amount .  ' to EDRi');
    }
    
    private function setupPayment()
    {
        $this->payment = new Payment();

        $this->payment->setIntent('sale')
            ->setPayer($this->payer)
            ->setTransactions(array($this->transaction))
            ->setRedirectUrls($this->redirectUrls);
    }

    private function setupRedirectUrls()
    {
        $this->redirectUrls = new RedirectUrls();

        $this->redirectUrls->setReturnUrl('https://edri.org/payment?pppa=true')
            ->setCancelUrl('https://edri.org/payment?pppa=false');
    }

    public function prepare_payment ($paymentCredtials) {
        $amount = str_replace(',', '', number_format($paymentCredtials['edriPayment_amount'], 2));

        $this->setupPayer();
        $this->setupDetails($amount);
        $this->setupAmount($amount);
        $this->setupTransaction($amount);
        $this->setupRedirectUrls();
        $this->setupPayment();  

        try {

            $this->payment->create($this->api);

            $paymentID = $this->payment->getId();
        
        } catch (Exception $e) {
            $this->log($e);
            
            header('Location: https://edri.org/donation-oops');

            return false;
        }

        return $paymentID;

    }

    private function log($log){

        $file = __DIR__ . DIRECTORY_SEPARATOR . '../logs/paypal_log.txt';


        // Open the file to get existing content
        $current = file_get_contents($file);
        // Append a new person to the file
        $current .=  $prefix . ' ' . date('m/d/Y h:i:s a', time()) . ' //// ' . "\n";
        $current .=  self::var_dump_str($log) . "\n";
        // Write the contents back to the file
        file_put_contents($file, $current);
    }

    public function execute_payment($paymentCredentials)
    {
        $this->debug($paymentCredentials);

        $payment = Payment::get($paymentCredentials['paymentId'], $this->api);

        $execution = new PaymentExecution();

        $execution->setPayerId($paymentCredentials['PayerID']);


        try {

            echo $payment->execute($execution, $this->api);
        
        } catch (Exception $e) {
            $this->log($e);
            
            header('Location: https://edri.org/donation-oops');

            return false;
        }

        return $payment->state = 'approved' ? true : false;
        
    }

    public function kickoff_payment()
    {

        foreach ($this->payment->getLinks() as $link) {
            if ($link->getRel() == 'approval_url') {
                $redirectUrl = $link->getHref();
            }
        }

        header('Location: ' . $redirectUrl);
    }

}

我查看了日志,没有报告任何问题。API调用似乎也正常。
有什么建议可以让它正常工作会很有帮助。

请先通过此方式验证您的Paypal账户。如果您的代码正确,那么这一步可能可以解决您的问题。 - AddWeb Solution Pvt Ltd
1个回答

3
有可能您的 var_dump() 语句违反了“在标头之前无内容输出”规则,因此,用户的付款流程会在您的代码之前停止,header('Location: ' . $redirectUrl); 无法重定向到PayPal以完成工作。尝试删除这些 var_dump 并改用 error_log(printf($val, true)),以便不中断对 header () 的调用。通过 http://php.net/manual/en/function.header.php 可知。

Remember that header() must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP. It is a very common error to read code with include, or require, functions, or another file access function, and have spaces or empty lines that are output before header() is called. The same problem exists when using a single PHP/HTML file.

<html>
<?php
/* This will give an error. Note the output
 * above, which is before the header() call */
header('Location: http://www.example.com/');
exit;
?>

嗨@cameron-hurd,您的意思是我应该使用var_dump($val)替换上面的代码,并将其替换为error_log(printf($val, true))吗? - kingmakerking
没错 - error_log 不会输出任何内容,传递 true 作为第二个参数给 printf 将返回值,而不是输出该值。如果输出前的内容是问题所在,这将让您绕过它,同时仍然检查变量的值。 - Cameron Hurd
我进行了替换,现在它只打印出单词“Array”,而不是之前的消息(如图所示):( - kingmakerking
我在前端页面中调用了$current .= self::var_dump_str($log) . "\n"; 它的定义如下: 静态函数var_dump_str() { $argc = func_num_args(); $argv = func_get_args(); if ($argc > 0) { ob_start(); call_user_func_array('var_dump', $argv); $result = ob_get_contents(); ob_end_clean(); return $result; } 返回'';} - kingmakerking
暂时尝试将其注释掉 - 出于上述相同的原因。我们希望避免输出,以便查看是否由于header()调用而阻止了客户端的重定向。 - Cameron Hurd
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接