Ejemplo n.º 1
0
 /**
  *   Process the transaction.
  *   Verifies that the transaction is valid, then records the purchase and
  *   notifies the buyer and administrator
  *
  *   @uses   Validate()
  *   @uses   BaseIPN::isUniqueTxnId()
  *   @uses   BaseIPN::handlePurchase()
  */
 public function Process()
 {
     if ($this->Validate() > 0) {
         return false;
     }
     if (1 != $this->pp_data['pmt_status']) {
         return false;
     } else {
         $this->pp_data['status'] = 'paid';
     }
     if (!$this->isUniqueTxnId($this->pp_data)) {
         return false;
     }
     // Log the IPN.  Verified is 'true' if we got this far.
     $LogID = $this->Log(true);
     // shopping cart
     $fees_paid = $this->pp_data['pmt_tax'] + $this->pp_data['pmt_shipping'] + $this->pp_data['pmt_handling'];
     PAYPAL_debug("Received {$item_gross} gross payment");
     if ($this->isSufficientFunds()) {
         $this->handlePurchase();
         return true;
     } else {
         return false;
     }
 }
Ejemplo n.º 2
0
 /**
  *   Process an incoming IPN transaction
  *   Do the following:
  *       1. Verify IPN
  *       2. Log IPN
  *       3. Check that transaction is complete
  *       4. Check that transaction is unique
  *       5. Check for valid receiver email address
  *       6. Process IPN
  *
  *   @uses   BaseIPN::AddItem()
  *   @uses   BaseIPN::handleFailure()
  *   @uses   BaseIPN::handlePurchase()
  *   @uses   BaseIPN::isUniqueTxnId()
  *   @uses   BaseIPN::isSufficientFunds()
  *   @uses   BaseIPN::Log()
  *   @uses   Verify()
  *   @uses   isStatusCompleted()
  *   @param  array   $in     POST variables of transaction
  *   @return boolean true if processing valid and completed, false otherwise
  */
 public function Process()
 {
     // If no data has been received, then there's nothing to do.
     if (empty($this->ipn_data)) {
         return false;
     }
     if (!$this->Verify()) {
         $logId = $this->Log(false);
         $this->handleFailure(PAYPAL_FAILURE_VERIFY, "({$logId}) Verification failed");
         return false;
     } else {
         $logId = $this->Log(true);
     }
     // Set the custom data field to the exploded value.  This has to
     // be done after Verify() or the Paypal verification will fail.
     $this->pp_data['custom'] = $this->custom;
     switch ($this->ipn_data['txn_type']) {
         case 'web_accept':
             //usually buy now
         //usually buy now
         case 'send_money':
             //usually donation/send money
             // Process Buy Now & Send Money
             $fees_paid = $this->ipn_data['tax'] + $this->pp_data['pmt_shipping'] + $this->pp_data['pmt_handling'];
             if (!empty($this->ipn_data['item_number'])) {
                 if (!isset($this->ipn_data['quantity']) || (double) $this->ipn_data['quantity'] == 0) {
                     $this->ipn_data['quantity'] = 1;
                 }
                 $payment_gross = $this->pp_data['pmt_gross'] - $fees_paid;
                 $unit_price = $payment_gross / $this->ipn_data['quantity'];
                 $this->AddItem($this->ipn_data['item_number'], $this->ipn_data['quantity'], $unit_price, $this->ipn_data['item_name'], $this->pp_data['pmt_shipping'], $this->pp_data['pmt_handling']);
                 $currency = $this->pp_data['currency'];
                 PAYPAL_debug("Net Settled: {$payment_gross} {$currency}");
                 if ($this->isSufficientFunds()) {
                     $this->handlePurchase();
                 } else {
                     $this->handleFailure(PAYPAL_FAILURE_FUNDS, "({$logId}) Insufficient funds for purchase");
                     return false;
                 }
             }
             break;
         case 'cart':
             // shopping cart
             $fees_paid = $this->pp_data['pmt_tax'] + $this->pp_data['pmt_shipping'] + $this->pp_data['pmt_handling'];
             USES_paypal_class_cart();
             if (empty($this->pp_data['custom']['cart_id'])) {
                 $this->handleFailure(NULL, 'Missing Cart ID');
                 return false;
             }
             // Create a cart and read the info from the cart table.
             // Actual items purchased and prices will come from the IPN.
             $ppCart = new ppCart($this->pp_data['custom']['cart_id']);
             $Cart = $ppCart->Cart();
             $items = array();
             for ($i = 1; $i <= $this->ipn_data['num_cart_items']; $i++) {
                 // PayPal returns the total price as mc_gross_X, so divide
                 // by the quantity to get back to a unit price.
                 if (!isset($this->ipn_data["quantity{$i}"]) || (double) $this->ipn_data["quantity{$i}"] == 0) {
                     $this->ipn_data["quantity{$i}"] = 1;
                 }
                 $item_gross = $this->ipn_data["mc_gross_{$i}"];
                 if (isset($this->ipn_data["mc_shipping{$i}"])) {
                     $item_shipping = (double) $this->ipn_data["mc_shipping{$i}"];
                     $item_gross -= $item_shipping;
                 } else {
                     $item_shipping = 0;
                 }
                 if (isset($this->ipn_data["tax{$i}"])) {
                     $item_tax = (double) $this->ipn_data["tax{$i}"];
                     $item_gross -= $item_tax;
                 } else {
                     $item_tax = 0;
                 }
                 if (isset($this->ipn_data["mc_handling{$i}"])) {
                     $item_handling = (double) $this->ipn_data["mc_handling{$i}"];
                     $item_gross -= $item_handling;
                 } else {
                     $item_handling = 0;
                 }
                 $unit_price = $item_gross / (double) $this->ipn_data["quantity{$i}"];
                 // Add the item to the array for the order creation.
                 // IPN item numbers are indexes into the cart, so get the
                 // actual product ID from the cart
                 $this->AddItem($Cart[$this->ipn_data["item_number{$i}"]]['item_id'], $this->ipn_data["quantity{$i}"], $unit_price, $this->ipn_data["item_name{$i}"], $item_shipping, $item_handling, $item_tax, $Cart[$this->ipn_data["item_number{$i}"]]['extras']);
             }
             $payment_gross = $this->ipn_data['mc_gross'] - $fees_paid;
             PAYPAL_debug("Received {$payment_gross} gross payment");
             //$currency = $this->ipn_data['mc_currency'];
             if ($this->isSufficientFunds()) {
                 $this->handlePurchase();
             } else {
                 $this->handleFailure(PAYPAL_FAILURE_FUNDS, "({$logId}) Insufficient/incorrect funds for purchase");
                 return false;
             }
             break;
             // other, unknown, unsupported
         // other, unknown, unsupported
         default:
             switch ($this->ipn_data['reason_code']) {
                 case 'refund':
                     $this->handleRefund();
                     break;
                 default:
                     $this->handleFailure(PAYPAL_FAILURE_UNKNOWN, "({$logId}) Unknown transaction type");
                     return false;
                     break;
             }
             break;
     }
     return true;
 }
Ejemplo n.º 3
0
 /**
  *   Send an email to the buyer
  *
  *   @param  string  $status     Order status (pending, paid, etc.)
  *   @param  string  $msg        Optional message to include with email
  */
 public function Notify($status = '', $gw_msg = '')
 {
     global $_CONF, $_PP_CONF, $_TABLES;
     // Check if we're supposed to send a notification
     if ($this->uid != 1 && $_PP_CONF['purch_email_user'] || $this->uid == 1 && $_PP_CONF['purch_email_anon']) {
         PAYPAL_debug("Sending email to " . $this->uid);
         // setup templates
         $message = new Template(PAYPAL_PI_PATH . '/templates');
         $message->set_file(array('subject' => 'purchase_email_subject.txt', 'msg_admin' => 'purchase_email_admin.txt', 'msg_user' => 'purchase_email_user.txt', 'msg_body' => 'purchase_email_body.txt'));
         // Add all the items to the message
         $total = (double) 0;
         // Track total purchase value
         $files = array();
         // Array of filenames, for attachments
         $num_format = "%5.2f";
         $item_total = 0;
         $have_physical = 0;
         // Assume no physical items.
         $dl_links = '';
         // Start with empty download links
         USES_paypal_class_product();
         foreach ($this->items as $id => $item) {
             if (!PAYPAL_is_plugin_item($item['product_id'])) {
                 $P = new Product($item['product_id']);
                 if ($P->prod_type & PP_PROD_PHYSICAL == PP_PROD_PHYSICAL) {
                     $have_physical = 1;
                 }
                 // Add the file to the filename array, if any. Download
                 // links are only included if the order status is 'paid'
                 $file = $P->file;
                 if (!empty($file) && $this->status == 'paid') {
                     $files[] = $file;
                     $dl_url = PAYPAL_URL . '/download.php?';
                     // There should always be a token, but fall back to the
                     // product ID if there isn't
                     if (!empty($item['token'])) {
                         $dl_url .= 'token=' . urlencode($item['token']);
                     } else {
                         $dl_url .= 'id=' . $item['item_number'];
                     }
                     $dl_links .= "<a href=\"{$dl_url}\">{$dl_url}</a><br />";
                 }
             }
             $ext = (double) $item['quantity'] * (double) $item['price'];
             $item_total += $ext;
             $item_descr = isset($item['description']) ? $item['description'] : $item['descrip'];
             //$message->set_block('message', 'ItemList', 'List');
             $opts = json_decode($item['options_text'], true);
             if ($opts) {
                 foreach ($opts as $opt_text) {
                     $options_text .= "&nbsp;&nbsp;--&nbsp;{$opt_text}<br />";
                 }
             }
             $message->set_block('msg_body', 'ItemList', 'List');
             $message->set_var(array('qty' => $item['quantity'], 'price' => sprintf($num_format, $item['price']), 'ext' => sprintf($num_format, $ext), 'name' => $item_descr, 'options_text' => $options_text));
             //PAYPAL_debug("Qty: {$item['quantity']} : Amount: {$item['price']} : Name: {$item['name']}", 'debug_ipn');
             $message->parse('List', 'ItemList', true);
         }
         // Determine if files will be attached to this message based on
         // global config and whether there are actually any files to
         // attach. Affects the 'files' flag in the email template and
         // which email function is used.
         if ((is_numeric($this->uid) && $this->uid != 1 && $_PP_CONF['purch_email_user_attach'] || (!is_numeric($this->uid) || $this->uid == 1) && $_PP_CONF['purch_email_anon_attach']) && count($files) > 0) {
             $do_send_attachments = true;
         } else {
             $do_send_attachments = false;
         }
         $total_amount = $item_total + $this->tax + $this->shipping + $this->handling;
         $user_name = COM_getDisplayName($this->uid);
         if ($this->billto_name == '') {
             $this->billto_name = $user_name;
         }
         $message->set_var(array('payment_gross' => sprintf($num_format, $total_amount), 'payment_items' => sprintf($num_format, $item_total), 'tax' => sprintf($num_format, $this->tax), 'shipping' => sprintf($num_format, $this->shipping), 'handling' => sprintf($num_format, $this->handling), 'payment_date' => $_PP_CONF['now']->toMySQL(true), 'payer_email' => $this->buyer_email, 'payer_name' => $this->billto_name, 'site_name' => $_CONF['site_name'], 'txn_id' => $this->pmt_txn_id, 'pi_url' => PAYPAL_URL, 'pi_admin_url' => PAYPAL_ADMIN_URL, 'dl_links' => $dl_links, 'files' => $do_send_attachments ? 'true' : '', 'buyer_uid' => $this->uid, 'user_name' => $user_name, 'gateway_name' => $this->pmt_method, 'pending' => $this->status == 'pending' ? 'true' : '', 'gw_msg' => $gw_msg, 'status' => $this->status, 'order_instr' => $this->instructions));
         // parse templates for subject/text
         $subject = trim($message->parse('output', 'subject'));
         $message->set_var('purchase_details', $message->parse('detail', 'msg_body'));
         $user_text = $message->parse('user_out', 'msg_user');
         $admin_text = $message->parse('admin_out', 'msg_admin');
         if ($this->buyer_email != '') {
             // if specified to mail attachment, do so, otherwise skip
             // attachment
             if ($do_send_attachments) {
                 // Make sure plugin functions are available
                 USES_paypal_functions();
                 PAYPAL_mailAttachment($this->buyer_email, $subject, $user_text, $_CONF['site_email'], true, 0, '', '', $files);
             } else {
                 // Otherwise send a standard notification
                 COM_emailNotification(array('to' => array($this->buyer_email), 'from' => $_CONF['site_mail'], 'htmlmessage' => $user_text, 'subject' => $subject));
             }
         }
         // Send a notification to the administrator, new purchases only
         if ($status == '') {
             if ($_PP_CONF['purch_email_admin'] == 2 || $have_physical && $_PP_CONF['purch_email_admin'] == 1) {
                 PAYPAL_debug('Sending email to Admin');
                 $email_addr = empty($_PP_CONF['admin_email_addr']) ? $_CONF['site_mail'] : $_PP_CONF['admin_email_addr'];
                 COM_emailNotification(array('to' => array($email_addr), 'from' => $_CONF['noreply_mail'], 'htmlmessage' => $admin_text, 'subject' => $subject));
             }
         }
     }
 }
Ejemplo n.º 4
0
 /**
  *   Determines if the current record is valid.
  *   Checks various items that can't be empty or combinations that
  *   don't make sense.
  *   Accumulates all error messages in the Errors array.
  *   As of version 0.5.0, the category is allowed to be empty.
  *
  *   @deprecated
  *   @return boolean     True if ok, False when first test fails.
  */
 private function isValidRecord()
 {
     global $LANG_PP;
     // Check that basic required fields are filled in
     if ($this->name == '') {
         $this->Errors[] = $LANG_PP['err_missing_name'];
     }
     if ($this->short_description == '') {
         $this->Errors[] = $LANG_PP['err_missing_desc'];
     }
     if ($this->prod_type == PP_PROD_DOWNLOAD) {
         if ($this->file == '') {
             // Must have a file for a downloadable product
             $this->Errors[] = $LANG_PP['err_missing_file'];
         }
         if ($this->expiration < 1) {
             // Must have an expiration period for downloads
             $this->Errors[] = $LANG_PP['err_missing_exp'];
         }
     } elseif ($this->prod_type == PP_PROD_PHYSICAL && $this->price < 0.01) {
         // Paypal won't accept a zero amount, so non-downloadable items
         // must have a positive price.  Use "Other Virtual" for free items.
         $this->Errors[] = $LANG_PP['err_phys_need_price'];
     }
     if (!empty($this->Errors)) {
         PAYPAL_debug('Errors encountered: ' . print_r($this->Errors, true));
         return false;
     } else {
         PAYPAL_debug('isValidRecord(): No errors');
         return true;
     }
 }
Ejemplo n.º 5
0
/**
*   Send an email with attachments.
*   This is a verbatim copy of COM_mail(), but with the $attachments
*   paramater added and 3 extra lines of code near the end.
*
*   @param  string  $to         Receiver's email address
*   @param  string  $from       Sender's email address
*   @param  string  $subject    Message Subject
*   @param  string  $message    Message Body
*   @param  boolean $html       True for HTML message, False for Text
*   @param  integer $priority   Message priority value
*   @param  string  $cc         Other recipients
*   @param  string  $altBody    Alt. body (text)
*   @param  array   $attachments    Array of attachments
*   @return boolean             True on success, False on Failure
*/
function PAYPAL_mailAttachment($to, $subject, $message, $from = '', $html = false, $priority = 0, $cc = '', $altBody = '', $attachments = array())
{
    global $_CONF;
    $subject = substr($subject, 0, strcspn($subject, "\r\n"));
    $subject = COM_emailEscape($subject);
    require_once $_CONF['path'] . 'lib/phpmailer/class.phpmailer.php';
    $mail = new PHPMailer();
    $mail->SetLanguage('en', $_CONF['path'] . 'lib/phpmailer/language/');
    $mail->CharSet = COM_getCharset();
    if ($_CONF['mail_backend'] == 'smtp') {
        $mail->IsSMTP();
        $mail->Host = $_CONF['mail_smtp_host'];
        $mail->Port = $_CONF['mail_smtp_port'];
        if ($_CONF['mail_smtp_secure'] != 'none') {
            $mail->SMTPSecure = $_CONF['mail_smtp_secure'];
        }
        if ($_CONF['mail_smtp_auth']) {
            $mail->SMTPAuth = true;
            $mail->Username = $_CONF['mail_smtp_username'];
            $mail->Password = $_CONF['mail_smtp_password'];
        }
        $mail->Mailer = "smtp";
    } elseif ($_CONF['mail_backend'] == 'sendmail') {
        $mail->Mailer = "sendmail";
        $mail->Sendmail = $_CONF['mail_sendmail_path'];
    } else {
        $mail->Mailer = "mail";
    }
    $mail->WordWrap = 76;
    $mail->IsHTML($html);
    $mail->Body = $message;
    if ($altBody != '') {
        $mail->AltBody = $altBody;
    }
    $mail->Subject = $subject;
    if (is_array($from) && isset($from[0]) && $from[0] != '') {
        if ($_CONF['use_from_site_mail'] == 1) {
            $mail->From = $_CONF['site_mail'];
            $mail->AddReplyTo($from[0]);
        } else {
            $mail->From = $from[0];
        }
    } else {
        $mail->From = $_CONF['site_mail'];
    }
    if (is_array($from) && isset($from[1]) && $from[1] != '') {
        $mail->FromName = $from[1];
    } else {
        $mail->FromName = $_CONF['site_name'];
    }
    if (is_array($to) && isset($to[0]) && $to[0] != '') {
        if (isset($to[1]) && $to[1] != '') {
            $mail->AddAddress($to[0], $to[1]);
        } else {
            $mail->AddAddress($to[0]);
        }
    } else {
        // assume old style....
        $mail->AddAddress($to);
    }
    if (isset($cc[0]) && $cc[0] != '') {
        if (isset($cc[1]) && $cc[1] != '') {
            $mail->AddCC($cc[0], $cc[1]);
        } else {
            $mail->AddCC($cc[0]);
        }
    } else {
        // assume old style....
        if (isset($cc) && $cc != '') {
            $mail->AddCC($cc);
        }
    }
    if ($priority) {
        $mail->Priority = 1;
    }
    PAYPAL_debug('Attachments: ' . print_r($attachments, true));
    // Add attachments
    foreach ($attachments as $key => $value) {
        $mail->AddAttachment($value);
    }
    if (!$mail->Send()) {
        COM_errorLog("Email Error: " . $mail->ErrorInfo);
        return false;
    }
    return true;
}
Ejemplo n.º 6
0
 /**
  *   Process an incoming IPN transaction
  *   Do the following:
  *       1. Verify IPN
  *       2. Log IPN
  *       3. Check that transaction is complete
  *       4. Check that transaction is unique
  *       5. Check for valid receiver email address
  *       6. Process IPN
  *
  *   @uses   BaseIPN::AddItem()
  *   @uses   BaseIPN::handleFailure()
  *   @uses   BaseIPN::handlePurchase()
  *   @uses   BaseIPN::isUniqueTxnId()
  *   @uses   BaseIPN::isSufficientFunds()
  *   @uses   BaseIPN::Log()
  *   @uses   Verify()
  *   @uses   isStatusCompleted()
  *   @param  array   $in     POST variables of transaction
  *   @return boolean true if processing valid and completed, false otherwise
  */
 public function Process()
 {
     // If no data has been received, then there's nothing to do.
     if (empty($this->ipn_data)) {
         return false;
     }
     if (!$this->Verify()) {
         $logId = $this->Log(false);
         $this->handleFailure(PAYPAL_FAILURE_VERIFY, "({$logId}) Verification failed");
         return false;
     } else {
         $logId = $this->Log(true);
     }
     // Set the custom data field to the exploded value.  This has to
     // be done after Verify() or the Paypal verification will fail.
     $this->pp_data['custom'] = $this->custom;
     //if (!$this->isStatusCompleted($this->pp_data['pmt_status'])) {
     // Not logged since this probably isn't an error
     // $this->handleFailure(PAYPAL_FAILURE_COMPLETED,
     //                  "($logId) Status not complete");
     //    return false;
     //}
     /*if (!$this->isUniqueTxnId($this->pp_data)) {
           $this->handleFailure(PAYPAL_FAILURE_UNIQUE, 
                           "($logId) Non-unique transaction id");
           return false;
       }*/
     switch ($this->ipn_data['txn_type']) {
         case 'web_accept':
             //usually buy now
         //usually buy now
         case 'send_money':
             //usually donation/send money
             // Process Buy Now & Send Money
             $fees_paid = $this->ipn_data['tax'] + $this->pp_data['pmt_shipping'] + $this->pp_data['pmt_handling'];
             if (!empty($this->ipn_data['item_number'])) {
                 if (!isset($this->ipn_data['quantity']) || (double) $this->ipn_data['quantity'] == 0) {
                     $this->ipn_data['quantity'] = 1;
                 }
                 $payment_gross = $this->pp_data['pmt_gross'] - $fees_paid;
                 $unit_price = $payment_gross / $this->ipn_data['quantity'];
                 $this->AddItem($this->ipn_data['item_number'], $this->ipn_data['quantity'], $unit_price, $this->ipn_data['item_name'], $this->pp_data['pmt_shipping'], $this->pp_data['pmt_handling']);
                 $currency = $this->pp_data['currency'];
                 PAYPAL_debug("Net Settled: {$payment_gross} {$currency}");
                 if ($this->isSufficientFunds()) {
                     $this->handlePurchase();
                 } else {
                     $this->handleFailure(PAYPAL_FAILURE_FUNDS, "({$logId}) Insufficient funds for purchase");
                     return false;
                 }
             }
             break;
         case 'cart':
             // shopping cart
             $fees_paid = $this->pp_data['pmt_tax'] + $this->pp_data['pmt_shipping'] + $this->pp_data['pmt_handling'];
             $items = array();
             for ($i = 1; $i <= $this->ipn_data['num_cart_items']; $i++) {
                 // PayPal returns the total price as mc_gross_X, so divide
                 // by the quantity to get back to a unit price.
                 if (!isset($this->ipn_data["quantity{$i}"]) || (double) $this->ipn_data["quantity{$i}"] == 0) {
                     $this->ipn_data["quantity{$i}"] = 1;
                 }
                 $item_gross = $this->ipn_data["mc_gross_{$i}"];
                 if (isset($this->ipn_data["mc_shipping{$i}"])) {
                     $item_shipping = (double) $this->ipn_data["mc_shipping{$i}"];
                     $item_gross -= $item_shipping;
                 } else {
                     $item_shipping = 0;
                 }
                 if (isset($this->ipn_data["tax{$i}"])) {
                     $item_tax = (double) $this->ipn_data["tax{$i}"];
                     $item_gross -= $item_tax;
                 } else {
                     $item_tax = 0;
                 }
                 if (isset($this->ipn_data["mc_handling{$i}"])) {
                     $item_handling = (double) $this->ipn_data["mc_handling{$i}"];
                     $item_gross -= $item_handling;
                 } else {
                     $item_handling = 0;
                 }
                 $unit_price = $item_gross / (double) $this->ipn_data["quantity{$i}"];
                 $this->AddItem($this->ipn_data["item_number{$i}"], $this->ipn_data["quantity{$i}"], $unit_price, $this->ipn_data["item_name{$i}"], $item_shipping, $item_handling, $item_tax);
             }
             $payment_gross = $this->ipn_data['mc_gross'] - $fees_paid;
             PAYPAL_debug("Received {$payment_gross} gross payment");
             //$currency = $this->ipn_data['mc_currency'];
             if ($this->isSufficientFunds()) {
                 $this->handlePurchase();
             } else {
                 $this->handleFailure(PAYPAL_FAILURE_FUNDS, "({$logId}) Insufficient/incorrect funds for purchase");
                 return false;
             }
             break;
             // other, unknown, unsupported
         // other, unknown, unsupported
         default:
             switch ($this->ipn_data['reason_code']) {
                 case 'refund':
                     $this->handleRefund();
                     break;
                 default:
                     $this->handleFailure(PAYPAL_FAILURE_UNKNOWN, "({$logId}) Unknown transaction type");
                     return false;
                     break;
             }
             break;
     }
     return true;
 }
Ejemplo n.º 7
0
 /**
  *   Processes the purchase, for purchases made without an IPN message.
  *
  *   @param  array   $vals   Submitted values, e.g. $_POST
  */
 public function handlePurchase($vals = array())
 {
     global $_TABLES, $_CONF, $_PP_CONF;
     USES_paypal_functions();
     USES_paypal_class_cart();
     USES_paypal_class_order();
     USES_paypal_class_product();
     if (!empty($vals['cart_id'])) {
         $cart = new ppCart($vals['cart_id']);
         if (!$cart->hasItems()) {
             return;
         }
         // shouldn't be empty
         $items = $cart->Cart();
     } else {
         $cart = new ppCart();
     }
     // Create an order record to get the order ID
     $Order = $this->CreateOrder($vals, $cart);
     $db_order_id = DB_escapeString($Order->order_id);
     $prod_types = 0;
     // For each item purchased, record purchase in purchase table
     foreach ($items as $id => $item) {
         //COM_errorLog("Processing item: $id");
         list($item_number, $item_opts) = PAYPAL_explode_opts($id, true);
         // If the item number is numeric, assume it's an
         // inventory item.  Otherwise, it should be a plugin-supplied
         // item with the item number like pi_name:item_number:options
         if (PAYPAL_is_plugin_item($item_number)) {
             PAYPAL_debug("handlePurchase for Plugin item " . $item_number);
             // Initialize item info array to be used later
             $A = array();
             // Split the item number into component parts.  It could
             // be just a single string, depending on the plugin's needs.
             $pi_info = explode(':', $item['item_number']);
             PAYPAL_debug('Paymentgw::handlePurchase() pi_info: ' . print_r($pi_info, true));
             $status = LGLIB_invokeService($pi_info[0], 'productinfo', array($item_number, $item_opts), $product_info, $svc_msg);
             if ($status != PLG_RET_OK) {
                 $product_info = array();
             }
             if (!empty($product_info)) {
                 $items[$id]['name'] = $product_info['name'];
             }
             PAYPAL_debug("Paymentgw::handlePurchase() Got name " . $items[$id]['name']);
             $vars = array('item' => $item, 'ipn_data' => array());
             $status = LGLIB_invokeService($pi_info[0], 'handlePurchase', $vars, $A, $svc_msg);
             if ($status != PLG_RET_OK) {
                 $A = array();
             }
             // Mark what type of product this is
             $prod_types |= PP_PROD_VIRTUAL;
         } else {
             PAYPAL_debug("Paypal item " . $item_number);
             $P = new Product($item_number);
             $A = array('name' => $P->name, 'short_description' => $P->short_description, 'expiration' => $P->expiration, 'prod_type' => $P->prod_type, 'file' => $P->file, 'price' => $item['price']);
             if (!empty($item_opts)) {
                 $opts = explode(',', $itemopts);
                 $opt_str = $P->getOptionDesc($opts);
                 if (!empty($opt_str)) {
                     $A['short_description'] .= " ({$opt_str})";
                 }
                 $item_number .= '|' . $item_opts;
             }
             // Mark what type of product this is
             $prod_types |= $P->prod_type;
         }
         // An invalid item number, or nothing returned for a plugin
         if (empty($A)) {
             //$this->Error("Item {$item['item_number']} not found");
             continue;
         }
         // If it's a downloadable item, then get the full path to the file.
         // TODO: pp_data isn't available here, should be from $vals?
         if (!empty($A['file'])) {
             $this->items[$id]['file'] = $_PP_CONF['download_path'] . $A['file'];
             $token_base = $this->pp_data['txn_id'] . time() . rand(0, 99);
             $token = md5($token_base);
             $this->items[$id]['token'] = $token;
         } else {
             $token = '';
         }
         $items[$id]['prod_type'] = $A['prod_type'];
         // If a custom name was supplied by the gateway's IPN processor,
         // then use that.  Otherwise, plug in the name from inventory or
         // the plugin, for the notification email.
         if (empty($item['name'])) {
             $items[$id]['name'] = $A['short_description'];
         }
         // Add the purchase to the paypal purchase table
         $uid = isset($vals['uid']) ? (int) $vals['uid'] : $_USER['uid'];
         $sql = "INSERT INTO {$_TABLES['paypal.purchases']} SET \n                        order_id = '{$db_order_id}',\n                        product_id = '{$item_number}',\n                        description = '{$items[$id]['name']}',\n                        quantity = '{$item['quantity']}', \n                        user_id = '{$uid}', \n                        txn_type = '{$this->gw_id}',\n                        txn_id = '', \n                        purchase_date = '{$_PP_CONF['now']->toMySQL()}', \n                        status = 'complete',\n                        token = '{$token}',\n                        price = " . (double) $item['price'] . ",\n                        options = '" . DB_escapeString($item_opts) . "'";
         // add an expiration date if appropriate
         if (is_numeric($A['expiration']) && $A['expiration'] > 0) {
             $sql .= ", expiration = DATE_ADD('{$_PP_CONF['now']->toMySQL()}', INTERVAL {$A['expiration']} DAY)";
         }
         //echo $sql;die;
         PAYPAL_debug($sql);
         DB_query($sql);
     }
     // foreach item
     // If this was a user's cart, then clear that also
     if (isset($vals['cart_id']) && !empty($vals['cart_id'])) {
         DB_delete($_TABLES['paypal.cart'], 'cart_id', $vals['cart_id']);
     }
 }
Ejemplo n.º 8
0
 /**
  *   Create and populate an Order record for this purchase.
  *   Gets the billto and shipto addresses from the cart, if any.
  *   Items are saved in the purchases table by handlePurchase().
  *
  *   This function is called only by our own handlePurchase() function,
  *   but is made "protected" so a derived class can use it if necessary.
  *
  *   @return string  Order ID, to link to the purchases table
  */
 protected function CreateOrder()
 {
     global $_TABLES, $_PP_CONF;
     // See if an order already exists for this transaction.
     // If so, load it and update the status. If not, continue on
     // and create a new order
     $order_id = DB_getItem($_TABLES['paypal.orders'], 'order_id', "pmt_txn_id='" . DB_escapeString($this->pp_data['txn_id']) . "'");
     if (!empty($order_id)) {
         $this->Order = new ppOrder($order_id);
         if ($this->Order->order_id != '') {
             $this->Order->log_user = $this->gw->Description();
             $this->Order->UpdateStatus($this->pp_data['status']);
         }
         return 2;
     }
     $this->Order = new ppOrder();
     USES_paypal_class_cart();
     if (isset($this->pp_data['custom']['cart_id'])) {
         $cart = new ppCart($this->pp_data['custom']['cart_id']);
         if (!$_PP_CONF['sys_test_ipn'] && !$cart->hasItems()) {
             return 1;
             // shouldn't normally be empty except during testing
         }
     } else {
         $cart = NULL;
     }
     $uid = (int) $this->pp_data['custom']['uid'];
     $this->Order->uid = $uid;
     $this->Order->status = !empty($this->pp_data['status']) ? $this->pp_data['status'] : 'pending';
     if ($uid > 1) {
         USES_paypal_class_userinfo();
         $U = new ppUserInfo($uid);
     }
     // Get the billing and shipping addresses from the cart record,
     // if any.  There may not be a cart in the database if it was
     // removed by a previous IPN, e.g. this is the 'completed' message
     // and we already processed a 'pending' message
     if ($cart) {
         $BillTo = $cart->getAddress('billto');
     }
     if (empty($BillTo) && $uid > 1) {
         $BillTo = $U->getDefaultAddress('billto');
     }
     if (is_array($BillTo)) {
         $this->Order->setBilling($BillTo);
     }
     $ShipTo = $this->pp_data['shipto'];
     if (empty($ShipTo)) {
         if ($cart) {
             $ShipTo = $cart->getAddress('shipto');
         }
         if (empty($ShipTo) && $uid > 1) {
             $ShipTo = $U->getDefaultAddress('shipto');
         }
     }
     if (is_array($ShipTo)) {
         $this->Order->setShipping($ShipTo);
     }
     if (isset($this->pp_data['shipto']['phone'])) {
         $this->Order->phone = $this->pp_data['shipto']['phone'];
     }
     $this->Order->pmt_method = $this->gw_id;
     $this->Order->pmt_txn_id = $this->pp_data['txn_id'];
     $this->Order->tax = $this->pp_data['pmt_tax'];
     $this->Order->shipping = $this->pp_data['pmt_shipping'];
     $this->Order->handling = $this->pp_data['pmt_handling'];
     $this->Order->buyer_email = $this->pp_data['payer_email'];
     $this->Order->log_user = $this->gw->Description();
     $order_id = $this->Order->Save();
     $db_order_id = DB_escapeString($order_id);
     $this->Order->items = array();
     foreach ($this->items as $id => $item) {
         $options = DB_escapeString($item['options']);
         list($item_number, $options) = explode('|', $item['item_number']);
         //if (is_numeric($item['item_number'])) {
         if (is_numeric($item_number)) {
             // For Paypal catalog options, check for options and append
             // to the description.  Update quantity on hand if tracking
             // is enabled.  These actions don't apply to items from
             // other plugins.
             if (!empty($options)) {
                 // options is expected as CSV
                 $sql = "SELECT attr_value\n                            FROM {$_TABLES['paypal.prod_attr']}\n                            WHERE attr_id IN ({$options})";
                 $optres = DB_query($sql);
                 $opt_str = '';
                 while ($O = DB_fetchArray($optres, false)) {
                     $opt_str .= ', ' . $O['attr_value'];
                 }
                 $item['name'] .= $opt_str;
             }
             /*$sql = "UPDATE {$_TABLES['paypal.products']} SET
               onhand = GREATEST(0, onhand - " . 
                   (int)$item['quantity'] . ") 
               WHERE id = '" . (int)$item['item_number'] .
               "' AND track_onhand > 0";*/
             //COM_errorLog($sql);
             DB_query($sql, 1);
         }
         $sql = "INSERT INTO {$_TABLES['paypal.purchases']} SET \n                    order_id = '{$db_order_id}',\n                    product_id = '{$item['item_number']}',\n                    description = '" . DB_escapeString($item['name']) . "',\n                    quantity = '{$item['quantity']}', \n                    user_id = '{$this->pp_data['custom']['uid']}', \n                    txn_type = '{$this->pp_data['custom']['transtype']}',\n                    txn_id = '{$this->pp_data['txn_id']}', \n                    purchase_date = '{$this->sql_date}', \n                    status = 'pending',\n                    token = '" . md5(time()) . "',\n                    price = " . (double) $item['price'] . ",\n                    options = '{$options}'";
         // add an expiration date if appropriate
         if (is_numeric($item['expiration']) && $item['expiration'] > 0) {
             $sql .= ", expiration = DATE_ADD('{$_PP_CONF['now']}', INTERVAL {$item['expiration']} DAY)";
         }
         PAYPAL_debug($sql);
         DB_query($sql);
     }
     // foreach item
     // Reload the order to get the items
     $this->Order->Load();
     // If this was a user's cart, then clear that also
     if (isset($this->pp_data['custom']['cart_id']) && !empty($this->pp_data['custom']['cart_id'])) {
         if (!$_PP_CONF['sys_test_ipn']) {
             DB_delete($_TABLES['paypal.cart'], 'cart_id', $this->pp_data['custom']['cart_id']);
             PAYPAL_debug('Cart ' . $this->pp_data['custom']['cart_id'] . ' deleted');
         }
     } else {
         PAYPAL_debug('no cart to delete');
     }
     return 0;
 }