• Unfortunately, we have experienced significant hard drive damage that requires urgent maintenance and rebuilding. The forum will be a state of read only until we install our new drives and rebuild all the configurations needed. Please follow our Facebook page for updates, we will be back up shortly! (The forum could go offline at any given time due to the nature of the failed drives whilst awaiting the upgrades.) When you see an Incapsula error, you know we are in the process of migration.

Webengine and paypal/credits issue

Initiate Mage
Joined
Aug 26, 2021
Messages
2
Reaction score
1
Hello all,

I have an issue with Credit system on my website.
When credits are bought on website they do not appear on the history and no credits are awarded. I get money minus fee on paypal account.
Paypal history is empty, no credits altered.

I can add/subtract them manually via adminCP.

What should my troubleshooting steps be? Where should i start looking?

Regards,
Martynas
 

cMu

Elite Diviner
Joined
Jan 8, 2017
Messages
427
Reaction score
133
while paypal history is empty, means the IPN listener is probably die during the process.
check your php error log.
 
Upvote 0
Initiate Mage
Joined
Aug 26, 2021
Messages
2
Reaction score
1
Hello cMu,
Thanks for quick reply.
This is what i found:
PHP:
[13-Sep-2021 08:29:28 UTC] PHP Notice:  Undefined index: submit_changes in /public_html/admincp/modules/mconfig/paypal.php on line 48
[13-Sep-2021 08:30:06 UTC] PHP Fatal error:  Uncaught Exception: Missing POST Data in /public_html/includes/classes/paypal/PaypalIPN.php:64
Stack trace:
#0 /public_html/api/paypal.php(40): PaypalIPN->verifyIPN()
#1 {main}
  thrown in /public_html/includes/classes/paypal/PaypalIPN.php on line 64

You are probably right about IPN bit. Any thoughts on next step?
 
Upvote 0

cMu

Elite Diviner
Joined
Jan 8, 2017
Messages
427
Reaction score
133
Hello cMu,
Thanks for quick reply.
This is what i found:
PHP:
[13-Sep-2021 08:29:28 UTC] PHP Notice:  Undefined index: submit_changes in /public_html/admincp/modules/mconfig/paypal.php on line 48
[13-Sep-2021 08:30:06 UTC] PHP Fatal error:  Uncaught Exception: Missing POST Data in /public_html/includes/classes/paypal/PaypalIPN.php:64
Stack trace:
#0 /public_html/api/paypal.php(40): PaypalIPN->verifyIPN()
#1 {main}
  thrown in /public_html/includes/classes/paypal/PaypalIPN.php on line 64

You are probably right about IPN bit. Any thoughts on next step?

seems like the IPN does not get all the required POST that he needs. You can run advanced debug (such as listing all arriving POSTS into .txt file through the PHP, and start debugging.)
 
Upvote 0
Shh, quiet, you might piss somebody off
Developer
Joined
Dec 23, 2011
Messages
1,797
Reaction score
2,169
i'm not sure if this is something about the paypal API or what, but i never was able to put IPN to work properly, so i decide to use other approach like Rest API, for me works perfect and just required to set payment details, then right after user make the payment, you need to execute it in order to finish the trade, with this proccess complete you already can delivery the player reward, i'll drop here my class for paypal rest API.

pay attention that most of Settings::get() bring some data from main settings and Donate:: bring me model from database for donation.

PHP:
<?php

namespace App\Payments;

use Setting;
use App\Models\Donate;
use PayPal\Rest\ApiContext;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Api\Amount;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Api\PaymentExecution;

class PayPal implements GatewayInterface {

    use Processor;

    private $client_id = "";
    private $secret = "";
    private $api = null;
    //sandbox - live 
    private $env = "live";
    private $PAYPALstatus = [
        'created' => self::STATUS_CREATED,
        'approved' => self::STATUS_APPROVED,
        'failed' => self::STATUS_CANCEL
    ];

    public function __construct() {
        if (Setting::get('paypal_enable')) {
            $this->client_id = Setting::get('paypal_clientid');
            $this->secret = Setting::get('paypal_secret');
            $this->api = new ApiContext(
                    new OAuthTokenCredential($this->client_id, $this->secret)
            );
            $this->api->setConfig([
                //   'log.LogEnabled' => true,
                //  'log.FileName' => 'PayPal.log',
                // 'log.LogLevel' => 'DEBUG',
                'mode' => $this->env
            ]);
        }
    }

    public function createPayment(\App\Models\Donate $donate) {
        $payer = new Payer();
        $payer->setPaymentMethod("paypal");
        $item1 = new Item();
        $item1->setName(trans('strings.donation') . " - " . Setting::get('servername') . ' - ' . $donate->login . ' - ' . $donate->reward . " " . ($donate->type === self::PACKAGE_TYPE_CASH ? trans('strings.golds') : trans('strings.coins')), 1.00, doubleval($donate->price))
                ->setCurrency(Setting::get('currency'))
                ->setQuantity(1)
                ->setPrice(doubleval($donate->price));
        $itemList = new ItemList();
        $itemList->setItems(array($item1));

        $amount = new Amount();
        $amount->setCurrency(Setting::get('currency'))
                ->setTotal(doubleval($donate->price));
        $transaction = new Transaction();
        $transaction->setAmount($amount)
                ->setItemList($itemList)
                ->setDescription(trans('strings.donation') . Setting::get('servername'))
                ->setInvoiceNumber($donate->internal_code);
        $redirectUrls = new RedirectUrls();
        $redirectUrls->setReturnUrl(route('paypal::execute'))
                ->setCancelUrl(route('paypal::cancel'));
        $payment = new Payment();
        $payment->setIntent("sale")
                ->setPayer($payer)
                ->setRedirectUrls($redirectUrls)
                ->setTransactions(array($transaction));
        try {
            $payment->create($this->api);
        } catch (Exception $ex) {
            dd($ex);
        }
        $donate->transaction_code = $payment->getToken();
        $donate->save();
        $approvalUrl = $payment->getApprovalLink();
        return $approvalUrl;
    }

    public function notification() {
        $request = request();
        $paymentId = $request->paymentId;
        $payment = Payment::get($paymentId, $this->api);
        $execution = new PaymentExecution();
        $execution->setPayerId($request->PayerID);
        try {
            $result = $payment->execute($execution, $this->api);
            $transactions = $result->getTransactions();

            $donate = Donate::where('internal_code', $transactions[0]->getInvoiceNumber())->first();
            if (is_null($donate)) {
                die;
            } else {
                $this->updatePayment($donate, $result);
            }
        } catch (Exception $ex) {
            \Log::debug((array) $ex);
        }
        return $payment;
    }

    public function updatePayment($donate, $request) {
        $donate->transaction_code = $request->getId();
        $donate->status = $this->PAYPALstatus[$request->getState()];
        $donate->save();
        $this->processor($donate);
    }

    public function executeBan(\App\Models\User $user) {
        
    }

}
 
Upvote 0

cMu

Elite Diviner
Joined
Jan 8, 2017
Messages
427
Reaction score
133
i'm not sure if this is something about the paypal API or what, but i never was able to put IPN to work properly, so i decide to use other approach like Rest API, for me works perfect and just required to set payment details, then right after user make the payment, you need to execute it in order to finish the trade, with this proccess complete you already can delivery the player reward, i'll drop here my class for paypal rest API.

pay attention that most of Settings::get() bring some data from main settings and Donate:: bring me model from database for donation.

PHP:
<?php

namespace App\Payments;

use Setting;
use App\Models\Donate;
use PayPal\Rest\ApiContext;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Api\Amount;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Api\PaymentExecution;

class PayPal implements GatewayInterface {

    use Processor;

    private $client_id = "";
    private $secret = "";
    private $api = null;
    //sandbox - live 
    private $env = "live";
    private $PAYPALstatus = [
        'created' => self::STATUS_CREATED,
        'approved' => self::STATUS_APPROVED,
        'failed' => self::STATUS_CANCEL
    ];

    public function __construct() {
        if (Setting::get('paypal_enable')) {
            $this->client_id = Setting::get('paypal_clientid');
            $this->secret = Setting::get('paypal_secret');
            $this->api = new ApiContext(
                    new OAuthTokenCredential($this->client_id, $this->secret)
            );
            $this->api->setConfig([
                //   'log.LogEnabled' => true,
                //  'log.FileName' => 'PayPal.log',
                // 'log.LogLevel' => 'DEBUG',
                'mode' => $this->env
            ]);
        }
    }

    public function createPayment(\App\Models\Donate $donate) {
        $payer = new Payer();
        $payer->setPaymentMethod("paypal");
        $item1 = new Item();
        $item1->setName(trans('strings.donation') . " - " . Setting::get('servername') . ' - ' . $donate->login . ' - ' . $donate->reward . " " . ($donate->type === self::PACKAGE_TYPE_CASH ? trans('strings.golds') : trans('strings.coins')), 1.00, doubleval($donate->price))
                ->setCurrency(Setting::get('currency'))
                ->setQuantity(1)
                ->setPrice(doubleval($donate->price));
        $itemList = new ItemList();
        $itemList->setItems(array($item1));

        $amount = new Amount();
        $amount->setCurrency(Setting::get('currency'))
                ->setTotal(doubleval($donate->price));
        $transaction = new Transaction();
        $transaction->setAmount($amount)
                ->setItemList($itemList)
                ->setDescription(trans('strings.donation') . Setting::get('servername'))
                ->setInvoiceNumber($donate->internal_code);
        $redirectUrls = new RedirectUrls();
        $redirectUrls->setReturnUrl(route('paypal::execute'))
                ->setCancelUrl(route('paypal::cancel'));
        $payment = new Payment();
        $payment->setIntent("sale")
                ->setPayer($payer)
                ->setRedirectUrls($redirectUrls)
                ->setTransactions(array($transaction));
        try {
            $payment->create($this->api);
        } catch (Exception $ex) {
            dd($ex);
        }
        $donate->transaction_code = $payment->getToken();
        $donate->save();
        $approvalUrl = $payment->getApprovalLink();
        return $approvalUrl;
    }

    public function notification() {
        $request = request();
        $paymentId = $request->paymentId;
        $payment = Payment::get($paymentId, $this->api);
        $execution = new PaymentExecution();
        $execution->setPayerId($request->PayerID);
        try {
            $result = $payment->execute($execution, $this->api);
            $transactions = $result->getTransactions();

            $donate = Donate::where('internal_code', $transactions[0]->getInvoiceNumber())->first();
            if (is_null($donate)) {
                die;
            } else {
                $this->updatePayment($donate, $result);
            }
        } catch (Exception $ex) {
            \Log::debug((array) $ex);
        }
        return $payment;
    }

    public function updatePayment($donate, $request) {
        $donate->transaction_code = $request->getId();
        $donate->status = $this->PAYPALstatus[$request->getState()];
        $donate->save();
        $this->processor($donate);
    }

    public function executeBan(\App\Models\User $user) {
        
    }

}

here is the IPN listener from my CMS, and now just work with it:
PHP:
<?php    require 'autoloader.php';        date_default_timezone_set("America/Chicago");    $Database = new Database;    $Website = new Website;    $Account = new Account;    $req = 'cmd=_notify-validate';    foreach($_POST as $key => $value){        if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() == 1){            $value = stripslashes($value);        }        $value = urlencode($value);        $req .= "&$key=$value";    }    $ch = curl_init('https://ipnpb.paypal.com/cgi-bin/webscr');    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);    curl_setopt($ch, CURLOPT_POST, 1);    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);    curl_setopt($ch, CURLOPT_POSTFIELDS, $req);    curl_setopt($ch, CURLOPT_SSLVERSION, 6);    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);    curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . '/cert/cacert.pem');    curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);    curl_setopt($ch, CURLOPT_HTTPHEADER, array(        'User-Agent: PHP-IPN-Verification-Script',        'Connection: Close',    ));    $res = @curl_exec($ch);    if(!$res){        writelog('cURL error: ['.curl_errno($ch).'] '.curl_error($ch).'', 'Paypal');        die();    }    $info = curl_getinfo($ch);    if($info['http_code'] != 200){        writelog('PayPal responded with http code '.$info['http_code'].'', 'Paypal');        die();    }    curl_close($ch);
 
Upvote 0
Back
Top