/** * Get an individual field for the history screen. * * @param string $fieldname Name of field (from the array, not the db) * @param mixed $fieldvalue Value of the field * @param array $A Array of all fields from the database * @param array $icon_arr System icon array (not used) * @param object $EntryList This entry list object * @return string HTML for field display in the table */ function PAYPAL_getPurchaseHistoryField($fieldname, $fieldvalue, $A, $icon_arr) { global $_CONF, $_PP_CONF, $LANG_PP, $_USER; static $dt = NULL; if ($dt === NULL) { $dt = new Date('now', $_USER['tzid']); } $retval = ''; switch ($fieldname) { case 'order_date': $dt->setTimestamp(strtotime($fieldvalue)); $retval = '<span title="' . $dt->format($_PP_CONF['datetime_fmt'], false) . '">' . $dt->format($_PP_CONF['datetime_fmt'], true) . '</span>'; break; case 'name': list($item_id, $item_opts) = PAYPAL_explode_opts($A['product_id']); if (is_numeric($item_id)) { // One of our catalog items, so link to it $retval = COM_createLink($fieldvalue, PAYPAL_URL . '/index.php?detail=x&id=' . $item_id); } else { // Probably came from a plugin, just show the product name $retval = htmlspecialchars($A['product_id'], ENT_QUOTES, COM_getEncodingt()); } break; case 'username': if ($A['isAdmin']) { $retval = COM_createLink($fieldvalue, PAYPAL_ADMIN_URL . '/index.php?orderhist=x&uid=' . $A['uid']); } else { $retval = COM_createLink($fieldvalue, $_CONF['site_url'] . '/users.php?mode=profile&uid=' . $A['uid']); } break; case 'quantity': $retval = '<div class="alignright">' . $fieldvalue . "</div>"; break; case 'txn_id': $base_url = $A['isAdmin'] ? PAYPAL_ADMIN_URL : PAYPAL_URL; // Admins get a link to the transaction log, regular users just // get the ID to check against their Paypal account. if ($A['isAdmin'] == 1) { $retval = COM_createLink($fieldvalue, $base_url . '/index.php?ipnlog=x&op=single&txn_id=' . $fieldvalue); } else { $retval = $fieldvalue; } break; case 'prod_type': // Return the plain-language product type description //$retval = $LANG_PP['prod_types'][$fieldvalue]; $retval = $LANG_PP['prod_types'][$A['prod_type']]; //if ($fieldvalue == PP_PROD_DOWNLOAD && $A['exptime'] > time() ) { if ($A['file'] != '' && $A['exptime'] > time()) { $retval = COM_createLink($retval, PAYPAL_URL . "/download.php?id={$A['product_id']}"); } break; case 'short_description': // If this is a plugin item, there should be a description recorded // in the purchase file. If not, just take it from the product // table. if (!empty($A['description'])) { $retval = $A['description']; } else { $retval = $fieldvalue; } break; case 'status': if ($A['isAdmin'] && is_array($LANG_PP['orderstatus'])) { $retval = ppOrderStatus::Selection($A['order_id'], 0, $fieldvalue); } elseif (isset($LANG_PP['orderstatus'][$fieldvalue])) { $retval = $LANG_PP['orderstatus'][$fieldvalue]; } else { $retval = 'Unknown'; } break; case 'order_id': $base_url = $A['isAdmin'] ? PAYPAL_ADMIN_URL : PAYPAL_URL; $retval = COM_createLink($fieldvalue, $base_url . '/index.php?order=' . $fieldvalue, array('data-uk-tooltip' => '', 'title' => 'View', 'class' => 'gl_mootip')); $retval .= ' <a href="' . PAYPAL_URL . '/index.php?printorder=' . $fieldvalue . '" target="_blank" class="uk-icon-mini uk-icon-print gl_mootip" title="Print" data-uk-tooltip>'; if (!$_PP_CONF['_is_uikit']) { $retval .= '(print)'; } $retval .= '</a>'; break; default: $retval = htmlspecialchars($fieldvalue, ENT_QUOTES, COM_getEncodingt()); break; } return $retval; }
/** * View the cart. * This function shows the shopping cart, either with the quantity fields * and option to update, or with the checkout buttons depending on the * value of $checkout. * * @uses getCheckoutButtons() * @param boolean $checkout True to indicate this is the final checkout * @return string HTML for the "view cart" form */ public function View($checkout = false) { global $_CONF, $_PP_CONF, $_USER, $LANG_PP, $_TABLES, $_SYSTEM; USES_paypal_class_product(); USES_paypal_class_currency(); $currency = new ppCurrency(); $T = new Template(PAYPAL_PI_PATH . '/templates'); $tpltype = $_SYSTEM['framework'] == 'uikit' ? '.uikit' : ''; $T->set_file('cart', $checkout ? "order{$tpltype}.thtml" : "viewcart{$tpltype}.thtml"); if (!isset($this->m_cart) || empty($this->m_cart)) { return $LANG_PP['cart_empty']; } if ($checkout) { foreach ($_PP_CONF['workflows'] as $key => $value) { $T->set_var('have_' . $value, 'true'); foreach ($this->_addr_fields as $fldname) { $T->set_var($value . '_' . $fldname, $this->m_info[$value][$fldname]); } } $T->set_var('not_final', 'true'); } $T->set_block('order', 'ItemRow', 'iRow'); // Get the workflows so we show the relevant info. if (!isset($_PP_CONF['workflows']) || !is_array($_PP_CONF['workflows'])) { USES_paypal_class_workflow(); ppWorkflow::Load(); } $T->set_block('cart', 'ItemRow', 'iRow'); $counter = 0; $subtotal = 0; $shipping = 0; foreach ($this->m_cart as $id => $item) { $counter++; $attr_desc = ''; list($item_id, $attr_keys) = PAYPAL_explode_opts($item['item_id']); if (is_numeric($item_id)) { // a catalog item, get the "right" price $P = new Product($item_id); $item_price = $P->getPrice($attr_keys, $item['quantity']); if (!empty($attr_keys)) { foreach ($attr_keys as $attr_key) { if (!isset($P->options[$attr_key])) { continue; } // invalid? //$attr_price = (float)$P->options[$attr_key]['attr_price']; $attr_name = $P->options[$attr_key]['attr_name']; $attr_value = $P->options[$attr_key]['attr_value']; $attr_desc .= "<br /> -- {$attr_name}: {$attr_value}"; /*if ($attr_price != 0) { $item_price += $attr_price; }*/ } } $text_names = explode('|', $P->custom); if (!empty($text_names) && is_array($item['extras']['custom'])) { foreach ($item['extras']['custom'] as $tid => $val) { $attr_desc .= '<br /> -- ' . htmlspecialchars($text_names[$tid]) . ': ' . htmlspecialchars($val); } } $item['descrip'] .= $attr_desc; // Get shipping amount and weight if ($P->shipping_type == 2 && $P->shipping_amt > 0) { // fixed shipping amount per item. Update actual cart $this->m_cart[$id]['shipping'] = $P->shipping_amt * $item['quantity']; $shipping += $this->m_cart[$id]['shipping']; // for display } elseif ($P->shipping_type == 1 && $P->weight > 0) { // using gateway profile, save the item's weight in the cart $this->m_cart[$id]['weight'] = $P->weight * $item['quantity']; } $this->m_cart[$id]['taxable'] = $P->taxable ? 'Y' : 'N'; $this->m_cart[$id]['type'] = $P->prod_type; } else { // A plugin item, it's not something we can look up $item_price = (double) $item['price']; if (isset($item['extras']['shipping'])) { $shipping += (double) $item['extras']['shipping']; $this->m_cart[$id]['shipping'] = $item['extras']['shipping']; } } $item_total = $item_price * $item['quantity']; $T->set_var(array('cart_item_id' => $id, 'pi_url' => PAYPAL_URL, 'cart_id' => $item['item_id'], 'pp_id' => $counter, 'item_id' => $item_id, 'item_descrip' => $item['descrip'], 'item_price' => COM_numberFormat($item_price, 2), 'item_quantity' => $item['quantity'], 'item_total' => COM_numberFormat($item_total, 2), 'item_link' => is_numeric($item_id) ? 'true' : '')); $T->parse('iRow', 'ItemRow', true); $subtotal += $item_total; } $custom_info = array('uid' => $_USER['uid'], 'transtype' => 'cart_upload', 'cart_id' => $this->cartID()); $total = $subtotal + $shipping; // A little hack to show only the total if there are no other // charges //if ($total == $subtotal) $subtotal = 0; // Format the TOC link, if any if (!empty($_PP_CONF['tc_link'])) { $tc_link = str_replace('{site_url}', $_CONF['site_url'], $_PP_CONF['tc_link']); } else { $tc_link = ''; } $T->set_var(array('paypal_url' => $_PP_CONF['paypal_url'], 'receiver_email' => $_PP_CONF['receiver_email'][0], 'custom' => serialize($custom_info), 'shipping' => $shipping > 0 ? $currency->Format($shipping) : '', 'subtotal' => $subtotal > 0 ? $currency->Format($subtotal) : '', 'total' => $currency->Format($total), 'order_instr' => htmlspecialchars($this->getInstructions()), 'tc_link' => $tc_link)); // If this is the final checkout, then show the payment buttons if ($checkout) { $T->set_var(array('gateway_vars' => $this->getCheckoutButtons(), 'checkout' => 'true')); } $T->parse('output', 'cart'); $form = $T->finish($T->get_var('output')); return $form; }
/** * 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']); } }