<?php #ini_set('display_errors', 1); error_reporting(E_ALL);

if (!defined('INCLUDED_AMEMBER_CONFIG')) 
    die("Direct access to this location is not allowed");
 
/*
*
*
*     Author: Alex Scott
*      Email: alex@cgi-central.net
*        Web: http://www.cgi-central.net
*    Details: PayPal Payment Plugin
*    FileName $RCSfile$
*    Release: 3.1.8PRO ($Revision: 3497 $)
*
* Please direct bug reports,suggestions or feedback to the cgi-central forums.
* http://www.cgi-central.net/forum/
*
* aMember PRO is a commercial software. Any distribution is strictly prohibited.
*/

if (!defined('PATH_SEPARATOR'))
    define('PATH_SEPARATOR', ':');
ini_set('include_path', $pp_inc_path=dirname(__FILE__).'/lib'.PATH_SEPARATOR.ini_get('include_path'));
if (($inc_path=@ini_get('include_path')) != $pp_inc_path){
    $error = "Cannot use ini_set to change include_path, but it is required for PayPal Pro plugin. Current
    include path is [$inc_path], while we have to set [$pp_inc_path]";
    if (!$_SESSION['check_paypal_pro_error']) $db->log_error ($error);
    $_SESSION['check_paypal_pro_error'] = $error;
    return $error;
}

require_once 'PayPal.php';
require_once 'PayPal/Profile/API.php';

class payment_paypal_pro extends amember_payment {
    var $title = _PLUG_PAY_PAYPALPRO_TITLE;
    var $description = _PLUG_PAY_PAYPALPRO_DESC;
    var $fixed_price=0;
    var $recurring=0;
    var $built_in_trials=0;
    var $paypal_domain = null;
    
    
    function get_payment_params($payment_id){
        // returns 
        global $db;
        $payment = $db->get_payment($payment_id);
        if ($payment['data'][0]['BASKET_PRODUCTS'])
            $product_ids = (array)$payment['data'][0]['BASKET_PRODUCTS'];
        else 
            $product_ids = array($payment['product_id']);
        $products = array();
        foreach ($product_ids as $product_id)
            $products[] = $db->get_product($product_id);
        $member  = $db->get_user($payment[member_id]);
        $title = (count($products) == 1) ? $products[0]['title'] : $config['multi_title'];
        $invoice = $payment_id;
        return array($payment['amount'], $title, $products, $member, $invoice);
    }

    function get_common_currency($products){
        $c = '';
        foreach ($products as $p){
            if ($p['paypal_currency'] == '')
                $p['paypal_currency'] = 'USD';
            if (($c != '') && ($c != $p['paypal_currency']))
                fatal_error(_PLUG_PAY_PAYPALPRO_FERROR, 0);
            $c = $p['paypal_currency'];
        }
        return $c;
    }
    
    function & get_paypal_caller(){
        global $db;
        #ini_set('include_path', $pp_inc_path=dirname(__FILE__).'/lib'.PATH_SEPARATOR.ini_get('include_path'));
        
        $profile = @new APIProfile();
        $profile->setAPIUsername($this->config['api_user']);
        $profile->setSubject($this->config['business']);
        $profile->setEnvironment($this->config['testing'] ? 'sandbox' : 'live');
        if ($this->config['api_sig']){
            $profile->setSignature($this->config['api_sig']);
            $profile->setAPIPassword($this->config['api_pass']);
        } else { // use certificate file
            $profile->setAPIPassword($this->config['cert_pass']);
            if (($this->config['cert_file'][0] != '/') && 
                     ($this->config['cert_file'][0] != "\\"))
               $this->config['cert_file'] = 
                    dirname(__FILE__) . '/' . $this->config['cert_file'];
            $profile->setCertificateFile($this->config['cert_file']);
        }
        $caller =& PayPal::getCallerServices($profile);

        if (PayPal::isError($caller)) {
            fatal_error(_PLUG_PAY_PAYPALPRO_FERROR2 . $caller->getMessage());
        }

/*
        if (preg_match("/^mysql\d+\.secureserver\.net$/i", $db->config['host'])){
            //use GoDaddy proxy
            $caller->setOpt ('curl', CURLOPT_HTTPPROXYTUNNEL, TRUE); 
            $caller->setOpt ('curl', CURLOPT_PROXYTYPE, CURLPROXY_HTTP); 
            $caller->setOpt ('curl', CURLOPT_PROXY, 'http://64.202.165.130:3128');
            $caller->setOpt ('curl', CURLOPT_SSL_VERIFYPEER, FALSE);        
        }
*/
        
        return $caller;
    }
    
    function do_bill($amount, $title, $products, $u, $invoice){
        global $config;
        $token = $this->set_express_checkout($invoice);
        if (!$token) fatal_error(_PLUG_PAY_PAYPALPRO_FERROR3);
        html_redirect("https://{$this->paypal_domain}/cgi-bin/webscr?cmd=_express-checkout&token=$token", 0,
            _PLUG_PAY_PAYPALPRO_REDIRECT, 
            _PLUG_PAY_PAYPALPRO_REDIRECT2);
    }

    function get_rand($length){
        $all_g = "ABCDEFGHIJKLMNOPQRSTWXZ";
        $pass = "";
        srand((double)microtime()*1000000);
        for($i=0;$i<$length;$i++) {
            srand((double)microtime()*1000000);
            $pass .= $all_g[ rand(0, strlen($all_g) - 1) ];
        }
        return $pass;
    }

    function set_express_checkout($payment_id){
    
        global $config;
        
        list($amount, $title, $products, $u, $invoice) =
            $x = $this->get_payment_params($payment_id);
        
        $caller = & $this->get_paypal_caller();

        $OrderTotal =& PayPal::getType('BasicAmountType');
        $curr = $this->get_common_currency($products);
        $OrderTotal->setattr('currencyID', $curr);
        $OrderTotal->setval($amount, 'iso-8859-1');

        $SetExpressCheckoutRequestDetails =& PayPal::getType('SetExpressCheckoutRequestDetailsType');
        $SetExpressCheckoutRequestDetails->setBuyerEmail($u['email'], 'iso-8859-1');
//        $SetExpressCheckoutRequestDetails->setLocaleCode('US', 'iso-8859-1');
        $SetExpressCheckoutRequestDetails->setNoShipping('1', 'iso-8859-1');
        $SetExpressCheckoutRequestDetails->setInvoiceID($invoice. '-'.$this->get_rand(3), 'iso-8859-1');
        $SetExpressCheckoutRequestDetails->setOrderDescription($title, 'iso-8859-1');
        $SetExpressCheckoutRequestDetails->setCancelURL($config['root_url']."/cancel.php?from=paypal_pro&payment_id=invoice", 'iso-8859-1');
        $SetExpressCheckoutRequestDetails->setReturnURL($config['root_url']."/plugins/payment/paypal_pro/return.php", 'iso-8859-1');
        $SetExpressCheckoutRequestDetails->setOrderTotal($OrderTotal);

        $SetExpressCheckout =& PayPal::getType('SetExpressCheckoutRequestType');
        $SetExpressCheckout->setSetExpressCheckoutRequestDetails($SetExpressCheckoutRequestDetails);
        $result = $caller->SetExpressCheckout($SetExpressCheckout);
        
        if (PayPal::isError($result)) {
            fatal_error(_PLUG_PAY_PAYPALPRO_FERROR4. $result->getMessage());
            return null;
        } elseif ($err = $result->getErrors()) {
            fatal_error(_PLUG_PAY_PAYPALPRO_FERROR4. $err->getLongMessage());
        } else {
            return $result->getToken();
        }
    }

    function do_express_checkout($payment_id, $details){
        global $config;
        
        list($amount, $title, $products, $u, $invoice) =
            $x = $this->get_payment_params($payment_id);
            

        $curr = $this->get_common_currency($products);

        $caller = & $this->get_paypal_caller();
        $OrderTotal =& PayPal::getType('BasicAmountType');
        $OrderTotal->setattr('currencyID', $curr);
        $OrderTotal->setval($amount, 'iso-8859-1');
        $PaymentDetails =& PayPal::getType('PaymentDetailsType');
        $PaymentDetails->setInvoiceID($invoice. '-'.$this->get_rand(3), 'iso-8859-1');
        $PaymentDetails->setOrderDescription($title, 'iso-8859-1');
        $PaymentDetails->setOrderTotal($OrderTotal);

        $DoExpressCheckoutPaymentRequestDetails =& PayPal::getType('DoExpressCheckoutPaymentRequestDetailsType');
        $DoExpressCheckoutPaymentRequestDetails->setPaymentDetails($PaymentDetails);
        $payer = $details->getPayerInfo();
        $DoExpressCheckoutPaymentRequestDetails->setPayerID($payer->getPayerID(), 'iso-8859-1');
        $DoExpressCheckoutPaymentRequestDetails->setToken($details->getToken(), 'iso-8859-1');
        $DoExpressCheckoutPaymentRequestDetails->setPaymentAction('Sale', 'iso-8859-1');

        $DoExpressCheckoutPayment =& PayPal::getType('DoExpressCheckoutPaymentRequestType');
        $DoExpressCheckoutPayment->setDoExpressCheckoutPaymentRequestDetails($DoExpressCheckoutPaymentRequestDetails);

        $result = $caller->DoExpressCheckoutPayment($DoExpressCheckoutPayment);
        
        if (PayPal::isError($result)) {
           fatal_error(_PLUG_PAY_PAYPALPRO_FERROR5 . $result->getMessage());
        } elseif ($err = $result->getErrors()) {
            fatal_error($err->getLongMessage());
        } else {
            $rd = $result->getDoExpressCheckoutPaymentResponseDetails();
            $pi = $rd->getPaymentInfo();
            if ($pi->getPaymentStatus() == 'Completed')
                return array($pi->getTransactionID(), $amount);
            else 
                fatal_error(_PLUG_PAY_PAYPALPRO_FERROR6);
        }
    }
    
    function get_express_checkout_details($token){
        global $config;
        $caller = & $this->get_paypal_caller();
        $GetExpressCheckoutDetails =& PayPal::getType('GetExpressCheckoutDetailsRequestType');
        $GetExpressCheckoutDetails->setToken($token, 'iso-8859-1');
        $result = $caller->GetExpressCheckoutDetails($GetExpressCheckoutDetails);

        if (PayPal::isError($result)) {
            fatal_error(_PLUG_PAY_PAYPALPRO_FERROR4. $result->getMessage());
            return null;
        } elseif ($err = $result->getErrors()) {
            if ($err->getErrorCode() == 10411)
                fatal_error($err->getLongMessage() . "<br />\n".sprintf(_PLUG_PAY_PAYPALPRO_FERROR7, "<a href='$config[root_url]/signup.php'>", "</a>"), 1);
            else
                fatal_error(_PLUG_PAY_PAYPALPRO_FERROR4 . $err->getLongMessage());
        } else {
            return $result->getGetExpressCheckoutDetailsResponseDetails();
        }
    }


    function process_postback($vars){
        global $db, $config;

        $token = $vars['token'];
        if ($token == '')         
            $this->postback_error(_PLUG_PAY_PAYPALPRO_ERROR);

        $details = $this->get_express_checkout_details($token);
        
        $invoice = intval($details->getInvoiceID());
        $payment = $db->get_payment($invoice);
        if (!$payment)
            $this->postback_error(sprintf(_PLUG_PAY_PAYPALPRO_ERROR2, $invoice));
        
        if ($vars['confirm'] <= 0){ 
            list($amount, $title, $products, $u, $invoicex) =
                $this->get_payment_params($invoice);
            $t = new_smarty();
            $t->assign('payment', $payment);
            $t->assign('member', $u);
            $t->assign('products', $products);
            $subtotal = 0;
            foreach ($products as $i => $p){
                $pr = $db->get_product($p['product_id']);
                $products[$i]['price'] = $pr['price'];
                $subtotal += $pr['price'];
            }
            $t->assign('subtotal', $subtotal);
            $t->assign('total', $payment['amount']);
            
            $t->display(dirname(__FILE__)."/confirm.html");
            exit();
        }
            
        
        list($txn_id, $amt) = $this->do_express_checkout($invoice, $details);
        
        if ($txn_id != '') {
            $err = $db->finish_waiting_payment(
                $invoice, $this->get_plugin_name(),
                $txn_id, $amt, $vars=array());
            if ($err) {
                fatal_error($err);
                return false;
            } else {
                header("Location: $config[root_url]/thanks.php?payment_id=$invoice");
                return true;
            }
        } else {
            fatal_error(_PLUG_PAY_PAYPALPRO_FERROR8);
            return false;
        }
    }
    
    function init(){
        parent::init();
        add_product_field('paypal_currency',
            'PayPal Currency',
            'select',
            'valid only for PayPal processing.<br /> You should not change it<br /> if you use
            another payment processors',
            '',
            array('options' => array(
                '' => 'USD',
                'GBP' => 'GBP',
                'EUR' => 'EUR',
                'CAD' => 'CAD',
                'AUD' => 'AUD',
                'JPY' => 'JPY'
            ))
            );
        if ($this->config['testing'])
            $this->paypal_domain = "www.sandbox.paypal.com";
        else
            $this->paypal_domain = "www.paypal.com";
    }
}

global $paypal_pro_pl;
$paypal_pro_pl = instantiate_plugin('payment', 'paypal_pro');

/* Direct Payment */
$plugins['payment'][] = 'paypal_pro_cc';
require_once($config['root_dir']."/plugins/payment/cc_core/cc_core.inc.php");

class payment_paypal_pro_cc extends payment {
    function do_payment($payment_id, $member_id, $product_id,
            $price, $begin_date, $expire_date, &$vars){
        return cc_core_do_payment('paypal_pro_cc', $payment_id, $member_id, $product_id,
            $price, $begin_date, $expire_date, $vars);
    }
    function get_cancel_link($payment_id){
        global $db;                            
        return cc_core_get_cancel_link('paypal_pro_cc', $payment_id);
    }
    function get_plugin_features(){
        return array(
            'title' => $config['payment']['paypal_pro']['title'] ? $config['payment']['paypal_pro']['title'] : _PLUG_PAY_PAYPALPRO_TITLE2,
            'description' => $config['payment']['paypal_pro']['description'] ? $config['payment']['paypal_pro']['description'] : _PLUG_PAY_PAYPALPRO_DESC2,
            'name_f' => 2,
            'type_options' => array('Visa'       => 'Visa', 
                                    'MasterCard' => 'MasterCard', 
                                    'Discover'   => 'Discover',
                                    'Amex'       => 'American Express'),
            'currency' => array(
                'USD' => 'USD',
                'GBP' => 'GBP',
                'EUR' => 'EUR',
                'CAD' => 'CAD',
                'AUD' => 'AUD',
                'JPY' => 'JPY'
            ),
            'no_recurring' => 1,
            'phone' => 1,
            'code'  => 1,
        );
    }

    function get_rand($length){
        $all_g = "ABCDEFGHIJKLMNOPQRSTWXZ";
        $pass = "";
        srand((double)microtime()*1000000);
        for($i=0;$i<$length;$i++) {
            srand((double)microtime()*1000000);
            $pass .= $all_g[ rand(0, strlen($all_g) - 1) ];
        }
        return $pass;
    }

    /*************************************************************
      cc_bill - do real cc bill
    ***************************************************************/
    function cc_bill($cc_info, $member, $amount, 
        $currency, $product_description, 
        $charge_type, $invoice, $payment){

        global $config;
        $log = array();
        //////////////////////// cc_bill /////////////////////////
        if ($charge_type == CC_CHARGE_TYPE_TEST) 
            return array(CC_RESULT_SUCCESS, "", "", array('test transaction' => 'no validation'));

        global $paypal_pro_pl;            
        $caller = & $paypal_pro_pl->get_paypal_caller();    
        
        $OrderTotal =& PayPal::getType('BasicAmountType');
        if ($currency == '') $currency = 'USD';
        $OrderTotal->setattr('currencyID', $currency);
        $OrderTotal->setval($amount, 'iso-8859-1');
        $PaymentDetails =& PayPal::getType('PaymentDetailsType');
        $PaymentDetails->setInvoiceID($invoice.'-'.$this->get_rand(3), 'iso-8859-1');
        $PaymentDetails->setOrderDescription($product_description, 'iso-8859-1');
        $PaymentDetails->setOrderTotal($OrderTotal);
        $PayerName =& PayPal::getType('PersonNameType');
        $PayerName->setLastName($cc_info['cc_name_l'], 'iso-8859-1');
        $PayerName->setFirstName($cc_info['cc_name_f'], 'iso-8859-1');
        $Address =& PayPal::getType('AddressType');
        $Address->setPostalCode($cc_info['cc_zip'], 'iso-8859-1');
        $Address->setPhone($cc_info['cc_phone'], 'iso-8859-1');
        
        if ($cc_info['cc_country'] == 'UK') $cc_info['cc_country'] = 'GB';
        $Address->setCountry($cc_info['cc_country'], 'iso-8859-1');
        $Address->setStateOrProvince($cc_info['cc_state'], 'iso-8859-1');
        $Address->setCityName($cc_info['cc_city'], 'iso-8859-1');
        $Address->setStreet1($cc_info['cc_street'], 'iso-8859-1');
        $Address->setName($cc_info['cc_name_f'] . ' ' . $cc_info['cc_name_l'], 'iso-8859-1');
        $CardOwner =& PayPal::getType('PayerInfoType');
        $CardOwner->setAddress($Address);
        if ($cc_info['cc_country'] == 'UK') $cc_info['cc_country'] = 'GB';
        $CardOwner->setPayerCountry($cc_info['cc_country'], 'iso-8859-1');
        $CardOwner->setPayerName($PayerName);
        $CardOwner->setPayer($member['email'], 'iso-8859-1');
        $CreditCard =& PayPal::getType('CreditCardDetailsType');
        if ($cc_info['cc_code'] != '')
            $CreditCard->setCVV2($cc_info['cc_code'], 'iso-8859-1');
        $CreditCard->setCardOwner($CardOwner);
        $CreditCard->setExpYear('20'.substr($cc_info['cc-expire'], 2,2), 'iso-8859-1');
        $CreditCard->setExpMonth(substr($cc_info['cc-expire'], 0, 2), 'iso-8859-1');
        $CreditCard->setCreditCardNumber($cc_info['cc_number'], 'iso-8859-1');
        $CreditCard->setCreditCardType($cc_info['cc_type'], 'iso-8859-1');
        $DoDirectPaymentRequestDetails =& PayPal::getType('DoDirectPaymentRequestDetailsType');
        $DoDirectPaymentRequestDetails->setIPAddress($_SERVER['REMOTE_ADDR'], 'iso-8859-1');
        $DoDirectPaymentRequestDetails->setCreditCard($CreditCard);
        $DoDirectPaymentRequestDetails->setPaymentDetails($PaymentDetails);
        $DoDirectPaymentRequestDetails->setPaymentAction('Sale', 'iso-8859-1');
        $DoDirectPayment =& PayPal::getType('DoDirectPaymentRequestType');
        $DoDirectPayment->setDoDirectPaymentRequestDetails($DoDirectPaymentRequestDetails);
        $result = $caller->DoDirectPayment($DoDirectPayment);        
        
        if (PayPal::isError($result)) {
            return array(CC_RESULT_INTERNAL_ERROR, $result->getMessage(), "", $log);
        } elseif ($err = $result->getErrors()) {
            $error = "";
            if(is_array($err)){
                foreach($err as $e){
                    $error .= $e->getLongMessage()."<br/>";
                }
            }else{
                $error = $err->getLongMessage();
            }

            return array(CC_RESULT_DECLINE_PERM, $error, "", $log);
        } else {
            return array(CC_RESULT_SUCCESS, "", $result->getTransactionID(), $log);
        }
    }
}

function paypal_pro_cc_get_member_links($user){
    return cc_core_get_member_links('paypal_pro_cc', $user);
}

function paypal_pro_cc_rebill(){
    return cc_core_rebill('paypal_pro_cc');
}

cc_core_init('paypal_pro_cc');
