kingmakerking
kingmakerking

Reputation: 2089

Paypal not proceeding to receive the payment

I am trying to make a donation through paypal using the this URL. When I login to PayPal and make a payment, I get the following message enter image description here

I do have the backend code and here is what it looks like.

<?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);
    }

}

I checked the logs, nothing is reported. API calls seems to be fine as well.

Any suggestion to make this work would be helpful.

Upvotes: 4

Views: 179

Answers (1)

Cameron Hurd
Cameron Hurd

Reputation: 5031

There's a possibility that the var_dump() statements you have are violating the "no content output before header" rule and therefore, the user's payment flow stops with your code, before the header('Location: ' . $redirectUrl); can redirect to PayPal to finish the job.

Try removing those var_dumps, and doing error_log(printf($val, true)) instead, as not to interrupt the call to header().

Edit - From 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;
?>

Upvotes: 3

Related Questions