<?php

// callback might be included many times in unit tests, so avoid defining the function twice
if (!function_exists('_requestConfirmation')) {
    function _requestConfirmation($paypal_url, $request, $testing)
    {
        if ($testing) {
            return 'VERIFIED';
        } else {
            // no credit card info transmitted, so no need to use SSL
            $fp = fsockopen ($paypal_url, 80, $errno, $errstr, 30);
            if (!$fp) {
                echo "$errstr ($errno)\n";
                exit;
            }
            fputs($fp, $request);
            $res = '';
            while (!feof($fp)) {
                $res = fgets($fp, 1024);
            }
            fclose($fp);
            return $res;
        }
    }
}

define('INCLUDE_STEPS', 'pluginCallback');
require_once dirname(__FILE__) . '/../../../common/common.php';
require_once 'classes/class.gateway.plugin.php';

if (!isset($GLOBALS['testing'])) {
    $testing = false;
} else {
    $testing = $GLOBALS['testing'];
}

$GLOBALS['logger']->log(5, 'Paypal callback invoked');

////////////////////////////////////
// read post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';

foreach ($_POST as $key => $value) {
  $value = urlencode(stripslashes($value));
  $req .= "&$key=$value";
}

// post back to PayPal system to validate
if (isset($_POST['test_ipn']) && $_POST['test_ipn'] == 1) {
    $paypal_url = 'www.sandbox.paypal.com';
} else {
    $paypal_url = 'www.paypal.com';
}
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= 'Content-Length: ' . strlen($req) . "\r\n\r\n";

// Assign IPN Variables
// Different possible transaction types (txn_type) for subscriptions:
// 1. 'subsc_signup': issued just after the client has paid the inicial amount. We ignore this.
// 2. 'subscr_payment': issued just after the previous one and for every subsequent payment.
$ppTransType = $_POST['txn_type'];
$ppTransID = $_POST['txn_id']; // Transaction ID (Unique)
$ppPayStatus = $_POST['payment_status']; // Payment Status
$ppPayAmount = $_POST['mc_gross']; // Total paid for this transaction
list($tInvoiceID,$tIsRecurring,$tGenerateInvoice) = explode("_", $_POST["custom"]);
$GLOBALS['logger']->log(5, "\$ppTransType: $ppTransType; \$ppTransID: $ppTransID; \$ppPayStatus: $ppPayStatus;");
$GLOBALS['logger']->log(5, "\$ppPayAmount: $ppPayAmount; \$tInvoiceID: $tInvoiceID; \$tIsRecurring: $tIsRecurring; \$tGenerateInvoice: $tGenerateInvoice");

// Create Plugin class object to interact with CE.
$cPlugin = new Plugin($tInvoiceID);

// Check to see if this Invoice is already paid.
// Skip if this is a call for a cancellation
if($cPlugin->IsPaid()==1 && $ppTransType == 'subscr_payment') {
    $GLOBALS['logger']->log(5, 'Previous subscription invoice is already paid');
    // If it is, then check to see if the GenerateInvoice variable was passed to the script
    if($tGenerateInvoice && $tIsRecurring) {
        $GLOBALS['logger']->log(5, 'Generating new invoice');
        // If it was and is TRUE (1), Generate a New Invoice, and set internal Plugin object
        // variables to the new invoice's information.
        $newInvoice = $cPlugin->GenerateNewInvoice($ppPayAmount,'', $ppTransID);
    } else {
        // If it was FALSE (0), set $newInvoice to false
        $newInvoice = false;
    }
        
    // Exit the script if either of the two conditions above return false.
    if(!$newInvoice) {
        $GLOBALS['logger']->log(1, 'Error: exiting Paypal callback invocation');
        exit;
    }
}

$GLOBALS['logger']->log(5, "Requesting callback confirmation; sending request: $paypal_url?$req");
$res = _requestConfirmation($paypal_url, $header.$req, $testing);


//Add plugin details
$cPlugin->m_Amount = $ppPayAmount;
$cPlugin->m_TransactionID = $ppTransID;
$cPlugin->m_Action = "charge";
$cPlugin->m_Last4 = "NA";

if (strcmp ($res, "VERIFIED") == 0) {
    $GLOBALS['logger']->log(5, "Callback has been verified successfully");
    // TODO check that receiver_email is an email address in your PayPal account
    if($tIsRecurring) {
        // Uncomment to test payment failures through subscription cancellations
        // if ($ppTransType == 'subscr_cancel') $ppTransType = 'subscr_failed';
        switch($ppTransType) {
            case 'subscr_payment':
                switch($ppPayStatus) {
                    case "Completed":
                        // Payment was succesful/completed.
                        $transaction = "Paypal payment of $ppPayAmount was accepted. Original Signup Invoice: $tInvoiceID (OrderID:".$ppTransID.")";
                        $cPlugin->PaymentAccepted($ppPayAmount,$transaction,$ppTransID, $testing);
                        if ($newInvoice) {
                            $cPlugin->updateDateRecurringEntry();
                        }
                    break;
                    case "Pending":
                        $transaction = "Paypal payment of $ppPayAmount was marked 'pending' by Paypal. Original Signup Invoice: $tInvoiceID (OrderID:".$ppTransID.")";
                        $cPlugin->PaymentAccepted($ppPayAmount,$transaction,$ppTransID, $testing);
                    break;
                    case "Failed":
                        $transaction = "Paypal payment of $ppPayAmount was rejected. Original Signup Invoice: $tInvoiceID (OrderID:".$ppTransID.")";
                        $cPlugin->PaymentRejected($transaction);
                    break;
                }
                break;
            case 'subscr_cancel':
                $GLOBALS['logger']->log(5, "Subscription has been cancelled on Paypal's side.");
                $subject = 'Gateway recurring payment cancelled';
                $message = "Recurring payment for invoice $tInvoiceID, corresponding to package \"{$_POST['item_name']}\" has been cancelled by customer.";
                // If createTicket returns false it's because this transaction has already been done
                // Use subscr_id because txn_id is not sent on cancellation IPNs from Paypal
                if (!$cPlugin->createTicket($_POST['subscr_id'], $subject, $message)) exit;

                // Reset recurringfee entry so that invoice entry gets generated without the IPN call.
                // We don't use the nextbilldate in the recurringfee table cause there was a bug in this plugin's
                // early implementation that wasn't updating that field. So we calculate it from scratch every time.
        // First we need to determine the next due date.
        $cycles = array(
            'D' => 'day',
            'M' => 'month',
            'Y' => 'year',
        );
        // Warning: don't use $_POST['subscr_date'] here: when $_POST['txn_type'] is 'subscr_cancel' this contains
        // the cancellation date, not the subscription date.
        $nextDueDate = $cPlugin->m_Invoice->getDate('timestamp');
        if (isset($_POST['period1'])) {
            $period = explode(' ', $_POST['period1']);
            $nextDueDate = strtotime("+{$period[0]} {$cycles[$period[1]]}", $nextDueDate);
        }
        if ($nextDueDate < time()) {
            $period = explode(' ', $_POST['period3']);
            while ($nextDueDate < time()) {
                $nextDueDate = strtotime("+{$period[0]} {$cycles[$period[1]]}", $nextDueDate);
            }
        }
                $transaction = "Paypal subscription cancelled by customer. Original Signup Invoice: $tInvoiceID";
                $cPlugin->resetRecurring($transaction, $_POST['subscr_id'], $nextDueDate);
                break;
            case 'subscr_failed':
                // this is caused by lack of funds for example
                $subject = 'Gateway recurring payment failed';
                $reason = isset($_POST['pending_reason'])? $_POST['pending_reason'] : 'unknown';
                $message = "Recurring payment for invoice $tInvoiceID, corresponding to package \"{$_POST['item_name']}\" has failed.\n";
                $message .= "Reason: $reason.";
                // if createTicket returns false it's because this transaction has already been done
                if (!$cPlugin->createTicket($_POST['subscr_id'], $subject, $message)) exit;
                // log failed transaction
                $transaction = "Recurring subscription payment failed. Reason: $reason.";
                $cPlugin->logFailedSubscriptionPayment($transaction, $_POST['subscr_id']);
                break;
        }
    } else {
        // Add Code for Normal Payment
        switch($ppPayStatus) {
            case "Completed":
                // Payment was succesful/completed.
                $transaction = "Paypal payment of $ppPayAmount was accepted. Original Signup Invoice: $tInvoiceID (OrderID:".$ppTransID.")";
                $cPlugin->PaymentAccepted($ppPayAmount,$transaction,$ppTransID, $testing);
            break;
            case "Pending":
                $transaction = "Paypal payment of $ppPayAmount was accepted. Original Signup Invoice: $tInvoiceID (OrderID:".$ppTransID.")";
                $cPlugin->PaymentAccepted($ppPayAmount,$transaction,$ppTransID, $testing);
            break;
            case "Failed":
                $transaction = "Paypal payment of $ppPayAmount was rejected. Original Signup Invoice: $tInvoiceID (OrderID:".$ppTransID.")";
                $cPlugin->PaymentRejected($transaction);
            break;
        }
    }
} elseif (strcmp ($res, "INVALID") == 0) {
    $GLOBALS['logger']->log(5, "Callback verification returned 'INVALID'");
    $transaction = "Paypal IPN returned INVALID to Confirmation.";
    $cPlugin->PaymentRejected($transaction);
}

?>
