<?php
define('PWCIPN_LOG_FILE_PATH', dirname(__FILE__) . '/log/pwcipn/');

/**
 * @filename        InstantPaymentNotifier.php
 * @description     This class is for sending instant payment notification to a given URL
 * @version         1.0
 * @package
 * @author          Mohammad Sajjad Hossain - info@sajjadhossain.com
 *
 * @link            http://sajjadhossain.com
 * @created on      September 07, 2011
 * @Dependencies
 * @license
 ***/
class InstantPaymentNotifier
{
    private $siteUrl;

    private $requestVariables = array('txn_type' => 'instant_payment');

    private $error;

    private $items = array();

    private $success = false;

    private $debug = true;

    /**
    *@desc Constructor
    */
    public function InstantPaymentNotifier(){}

    /**
    *@desc URL to which the notification will be posted.
    * @param string $url
    */
    public function setSiteUrl($url)
    {
        $this->siteUrl = $url;
    }

    /**
    *@desc Sales order number, supplied by your shopping cart software.
    * @param string $id
    */
    public function setOrderId($id)
    {
        $this->requestVariables['order_id'] = $id;
    }

    public function setOrderUniqueId($id)
    {
        $this->requestVariables['order_unique_id'] = $id;
    }

    public function setRecurringProfileId($recurringOrdersId)
    {
        $this->requestVariables['profile_id'] = 'P-' . str_pad($recurringOrdersId, 11, '0', STR_PAD_LEFT);
    }

    public function setTransactionId($id)
    {
        $this->requestVariables['txn_id'] = $id;
    }

    public function setTransactionType($type)
    {
        $this->requestVariables['txn_type'] = $type;
    }
    
    /**
    *@desc Total amount of the sale
    * @param float $amount
    */
    public function setAmount($amount)
    {
        $this->requestVariables['total_amount'] = number_format($amount, 2, '.', '');
    }

    public function setCurrencyCode($code)
    {
        $this->requestVariables['currency'] = $code;
    }

    /**
    *@desc Customer first name.
    * @param string $name
    */
    public function setCustomerFirstName($name)
    {
        $this->requestVariables['first_name'] = $name;
    }

    /**
    *@desc Customer last name.
    * @param string $name
    */
    public function setCustomerLastName($name)
    {
        $this->requestVariables['last_name'] = $name;
    }

    /**
    *@desc Customer email
    * @param string
    */
    public function setCustomerEmail($email)
    {
        $this->requestVariables['email'] = $email;
    }

    /**
    *@desc Customer address 1
    * @param string
    */
    public function setCustomerAddress1($addr)
    {
        $this->requestVariables['address_1'] = $addr;
    }

    /**
    *@desc Customer address 2
    * @param string
    */
    public function setCustomerAddress2($addr)
    {
        $this->requestVariables['address_2'] = $addr;
    }

    /**
    *@desc Customer city
    * @param string
    */
    public function setCustomerCity($city)
    {
        $this->requestVariables['city'] = $city;
    }

    /**
    *@desc Customer state
    * @param string
    */
    public function setCustomerState($state)
    {
        $this->requestVariables['state'] = $state;
    }

    /**
    *@desc Customer zip code
    * @param string
    */
    public function setCustomerZipCode($zip)
    {
        $this->requestVariables['zip_code'] = $zip;
    }

    /**
    *@desc Customer country
    * @param string
    */
    public function setCustomerCountry($country)
    {
        $this->requestVariables['country'] = $country;
    }

    /**
    *@desc Customer phone
    * @param string
    */
    public function setCustomerPhone($phone)
    {
        $this->requestVariables['phone'] = $phone;
    }

    /**
    *@desc Name of item purchased.
    * @param string $itemName
    */
    public function setItem($itemName, $quantity, $amount)
    {
        $this->items[] = array('name' => $itemName, 'quantity' => $quantity, 'amount' => $amount);
    }

    private function setItemsForPost()
    {
        if(!empty($this->items))
        {
            $itemNames = array();
            $cnt = 1;

            foreach($this->items as $item)
            {
                $this->requestVariables['item' . $cnt] = $itemNames[] = $item['name'];
                $this->requestVariables['quantity' . $cnt] = $item['quantity'];
                $this->requestVariables['amount' . $cnt] = $item['amount'];
                $cnt++;
            }

            $this->requestVariables['item_name'] = implode(', ', $itemNames);
        }
    }
    

    public function setRecurringItem($profile)
    {
        $this->requestVariables['recurring_product_row_id1'] = $profile['recurring_product_row_id'];
        $this->requestVariables['recurring_product_description1'] = $profile['recurring_product_description'];
        $this->requestVariables['recurring_profile_id1'] = $profile['recurring_profile_id'];
        $this->requestVariables['recurring_product_quantity1'] = $profile['recurring_product_quantity'];
        $this->requestVariables['recurring_price1'] = $profile['recurring_price'];
        $this->requestVariables['recurring_shipping_charge1'] = $profile['recurring_shipping_charge'];
        $this->requestVariables['recurring_sales_tax1'] = $profile['recurring_sales_tax'];
        $this->requestVariables['recurring_cycle1'] = $profile['recurring_cycle'];
        $this->requestVariables['recurring_start_duration1'] = $profile['recurring_start_duration'];
        $this->requestVariables['date_of_next_charge1'] = $profile['date_of_next_charge'];
    }

    public function setRecurringItems($profiles)
    {
        foreach($profiles as $profile)
           $this->recurringItems[] = $profile;
    }
    private function setRecurringItemForPost()
    {
        if(!empty($this->recurringItems))
        {
            $cnt = 1;
            foreach($this->recurringItems as $item)
            {
                $this->requestVariables['recurring_product_row_id' . $cnt] = $item['recurring_product_row_id'];
                $this->requestVariables['recurring_product_description' . $cnt] = $item['recurring_product_description'];
                $this->requestVariables['recurring_profile_id' . $cnt] = $item['recurring_profile_id'];
                $this->requestVariables['recurring_product_quantity' . $cnt] = $item['recurring_product_quantity'];
                $this->requestVariables['recurring_price' . $cnt] = $item['recurring_price'];
                $this->requestVariables['recurring_shipping_charge' . $cnt] = $item['recurring_shipping_charge'];
                $this->requestVariables['recurring_sales_tax' . $cnt] = $item['recurring_sales_tax'];
                $this->requestVariables['recurring_cycle' . $cnt] = $item['recurring_cycle'];
                $this->requestVariables['recurring_start_duration' . $cnt] = $item['recurring_start_duration'];
                $this->requestVariables['date_of_next_charge' . $cnt] = $item['date_of_next_charge'];
                $cnt++;
            }
        }
    }
    
    public function setParams($params)
    {
        foreach($params as $key => $value)
          $this->requestVariables[$key] = $value;
    }

    /**
    *@desc To indicate if the sales is a recurring transaction
    */
    public function setIsRecurring()
    {
        $this->requestVariables['txn_type'] = 'subscription_payment';
    }

    public function isSuccess()
    {
        $this->requestVariables['txn_status'] = 'success';  
    }

    public function isFailed()
    {
        $this->requestVariables['txn_status'] = 'failed';  
    }

    public function setPaymentProcessor($processor)
    {
        $this->requestVariables['processor'] =  $processor;
    }

    public function setModeOfPayment($mode)
    {
        $this->requestVariables['mode_of_payment'] = $mode;
    }

    public function setCustomVariable($varName, $value)
    {
        $this->requestVariables[$varName] = $value;
    }

    public function enableDebugging()
    {
        $this->debug = true;
    }

    /**
    *@desc Returns the error message
    * @return string
    */
    public function getError()
    {
        return $this->error;
    }

    public function notify($productName = null, $productQuantity = null, $productPrice = null)
    {
        if(empty($this->siteUrl))
        {
            $this->logMessage('Site URL is missing.');
            $this->error = 'Site URL has not been set';
            return;
        }
        
        //Product Specific IPN
        if($productName && $productQuantity && $productPrice)
        {
            $this->requestVariables['item1'] = $productName;
            $this->requestVariables['quantity1'] = $productQuantity;
            $this->requestVariables['amount1'] = $productPrice;
            $this->requestVariables['item_name'] = $productName;
        }
        else 
        {   //Cart Wise IPN            
            $this->setItemsForPost();
            $this->setRecurringItemForPost();
        }
        
        $this->logMessage('Preparing request...');

        $nameValuePairs = array();

        foreach($this->requestVariables as $key => $value)
        {
            $nameValuePairs[] = $key .'=' . (empty($value) ? '' : urlencode($value));
        }

        $requestString = implode('&', $nameValuePairs);

        $this->logMessage($requestString);

        $this->logMessage('Initializing cURL...');

        $ch = curl_init();

        $this->logMessage('Sending Request to : ' . $this->siteUrl);
        curl_setopt($ch, CURLOPT_URL, $this->siteUrl);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $requestString);
        curl_setopt($ch,CURLOPT_USERAGENT, 'PWCIPN');
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_VERBOSE, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

        $this->logMessage('Getting response...');
        $response = trim(curl_exec($ch));

        $this->logMessage(urldecode($response));

        if (curl_errno($ch))
        {
            $this->error = 'cURL Error # ' . curl_errno($ch) . ' : ' . curl_error($ch);

            $this->logMessage($error);
        }
        else
        {
            curl_close($ch);
        }

        $this->logMessage('Done...');
    }

    private function logMessage($message)
    {
        if($this->debug)
        {
            isset($this->debugText) OR $this->debugText = '';
            $fileName = PWCIPN_LOG_FILE_PATH . 'log_' . date('Y-m-d') . '.php';

            $text = date('H:i:s --> ') . substr($message, 0, 4000) . "\n\r---------------------\n\r";

            if(!file_exists($fileName))
            {
                $text = "<?php die('Access Denied'); ?>\n\n" . $text;
            }

            $this->debugText .= $text;

            $f = fopen($fileName, 'ab');
            flock($f, LOCK_EX);
            fwrite($f, $text);
            flock($f, LOCK_UN);
            fclose($f);
        }
    }
}

//End of file Plexum.php