<?php
    /**
     * ipn
     *
     * @package Wojo Framework
     * @author wojoscripts.com
     * @copyright 2023
     * @version 5.00: ipn.php, v1.00 7/18/2023 6:36 PM Gewa Exp $
     *
     */
    const _WOJO = true;
    
    ini_set('log_errors', true);
    ini_set('error_log', dirname(__file__) . '/ipn_errors.log');
    
    require_once '../../../init.php';
    
    if (isset($_POST['payment_status'])) {
        require_once(BASEPATH . '/gateways/payfast/pf.inc.php');
        $pf = Database::Go()->select(Core::gTable, array('live', 'extra3'))->where('name', 'payfast', '=')->first()->run();
        
        $pfHost = ($pf->live) ? 'https://www.payfast.co.za' : 'https://sandbox.payfast.co.za';
        $error = false;
        
        pflog('ITN received from payfast.co.za');
        if (!pfValidIP($_SERVER['REMOTE_ADDR'])) {
            pflog('REMOTE_IP mismatch: ');
            $error = true;
            return false;
        }
        
        $result = pfGetData();
        
        pflog('POST received from payfast.co.za: ' . print_r($result, true));
        
        if ($result === false) {
            pflog('POST is empty: ' . print_r($result, true));
            $error = true;
            return false;
        }
        
        if (!pfValidSignature($result, $pf->extra3)) {
            pflog('Signature mismatch on POST');
            $error = true;
            return false;
        }
        
        pflog('Signature OK');
        
        $itnPostData = array();
        $itnPostDataValuePairs = array();
        
        foreach ($_POST as $key => $value) {
            if ($key == 'signature') {
                continue;
            }
            
            $value = urlencode(stripslashes($value));
            $value = preg_replace('/(.*[^%^0^D])(%0A)(.*)/i', '${1}%0D%0A${3}', $value);
            $itnPostDataValuePairs[] = "$key=$value";
        }
        
        $itnVerifyRequest = implode('&', $itnPostDataValuePairs);
        if (!pfValidData($pfHost, $itnVerifyRequest, "$pfHost/eng/query/validate")) {
            pflog("ITN mismatch for $itnVerifyRequest\n");
            pflog('ITN not OK');
            $error = true;
            return false;
        }
        
        pflog('ITN OK');
        pflog("ITN verified for $itnVerifyRequest\n");
        
        if (!$error and $_POST['payment_status'] == 'COMPLETE') {
            $custom = Utility::decode($_POST['custom_int1']);
            list($user_id, $sesid) = explode('_', $custom);
            $mc_gross = $_POST['amount_gross'];
            $membership_id = $_POST['m_payment_id'];
            $txn_id = Validator::sanitize($_POST['pf_payment_id']);
            
            $user = Database::Go()->select(User::mTable)->where('id', $user_id, '=')->first()->run();
            $cart = Product::getCartContentIpn($sesid);
            $totals = Product::getCartTotal($sesid);
            $tax = Content::calculateTax();
            
            $amount = Utility::numberParse($totals->grand);
            $items = array();
            $cdkey = array();
            
            if ($cart) {
                foreach ($cart as $k => $item) {
                    $key = Database::Go()->select(Product::cdTable, array('cdkey'))->where('product_id', $item->id, '=')->one()->run();
                    $data = array(
                        'user_id' => App::Auth()->uid,
                        'product_id' => $item->id,
                        'txn_id' => $txn_id,
                        'tax' => Utility::numberParse($item->totaltax),
                        'amount' => Validator::sanitize($item->total, 'float'),
                        'total' => Validator::sanitize($item->totaltax + $item->total, 'float'),
                        'coupon' => $item->coupon,
                        'cdkey' => ($key) ? : '',
                        'pp' => 'PayFast',
                        'ip' => Url::getIP(),
                        'file_date' => time(),
                        'currency' => 'ZAR',
                        'status' => 1,
                    );
                    
                    $items[$k]['title'] = $item->title;
                    $items[$k]['qty'] = 1;
                    $items[$k]['price'] = $item->total;
                    $items[$k]['cdkey'] = $data['cdkey'];
                    $cdkey[] = $data['cdkey'];
                    
                    Database::Go()->insert(Product::xTable, $data)->run();
                    if ($key) {
                        Database::Go()->delete(Product::cdTable)->where('cdkey', $data['cdkey'], '=')->run();
                    }
                }
                
                // invoice table
                $xdata = array(
                    'invoice_id' => substr(time(), 5),
                    'transaction_id' => $txn_id,
                    'user_id' => App::Auth()->uid,
                    'items' => json_encode($items),
                    'coupon' => $totals->discount,
                    'tax' => $totals->tax,
                    'subtotal' => $totals->subtotal,
                    'grand' => $amount,
                    'currency' => 'EUR',
                );
                Database::Go()->insert(Product::ivTable, $xdata)->run();
                
                $json['type'] = 'success';
                $json['title'] = Language::$word->SUCCESS;
                $json['message'] = Language::$word->STR_POK;
                
                /* == Notify Administrator == */
                $mailer = Mailer::sendMail();
                $tpl = Database::Go()->select(Content::eTable, array('body', 'subject'))->where('typeid', 'payComplete', '=')->first()->run();
                $core = App::Core();
                $body = str_replace(array(
                    '[LOGO]',
                    '[CEMAIL]',
                    '[COMPANY]',
                    '[SITE_NAME]',
                    '[DATE]',
                    '[SITEURL]',
                    '[NAME]',
                    '[TYPE]',
                    '[ITEMNAME]',
                    '[CDKEY]',
                    '[PRICE]',
                    '[STATUS]',
                    '[PP]',
                    '[IP]',
                    '[FB]',
                    '[TW]'
                ), array(
                    $core->plogo,
                    $core->site_email,
                    $core->company,
                    $core->site_name,
                    date('Y'),
                    SITEURL,
                    App::Auth()->name,
                    Language::$word->PRD_PRODUCT,
                    implode(', ', array_column($cart, 'title')),
                    implode(', ', array_column($items, 'cdkey')),
                    $amount,
                    'Completed',
                    'Payfast',
                    Url::getIP(),
                    $core->social->facebook,
                    $core->social->twitter
                ), $tpl->body);
                
                $mailer->Subject = $tpl->subject;
                $mailer->Body = $body;
                
                try {
                    $mailer->setFrom($core->site_email, $core->company);
                    $mailer->addAddress($core->site_email, $core->company);
                    $mailer->isHTML();
                    $mailer->send();
                } catch (\PHPMailer\PHPMailer\Exception) {
                }
                // empty cart
                Database::Go()->delete(Product::cxTable)->where('user_id', $sesid, '=')->run();
                
                pflog('Email Notification [Admin] sent successfuly');
            }
        }
    }