/** * Get the form variables for the purchase button. * * @uses PaymentGw::_Supports() * @uses _encButton() * @uses getActionUrl() * @return string HTML for purchase button */ public function CheckoutButton($cart) { global $_PP_CONF, $_USER, $_TABLES; if (!$this->_Supports('checkout')) { return ''; } $cartItems = $cart->Cart(); $cartID = $cart->CartID(); $custom_arr = array('uid' => $_USER['uid'], 'transtype' => 'cart_upload', 'cart_id' => $cartID); $fields = array('cmd' => '_cart', 'upload' => '1', 'cancel_return' => PAYPAL_URL . '/index.php?view=cart', 'return' => PAYPAL_URL . '/index.php?thanks=paypal', 'rm' => '2', 'paymentaction' => 'sale', 'notify_url' => $this->ipn_url, 'currency_code' => $this->currency_code, 'custom' => str_replace('"', '\'', serialize($custom_arr))); $address = $cart->getAddress('shipto'); if (!empty($address)) { list($fname, $lname) = explode(' ', $address['name']); $fields['first_name'] = htmlspecialchars($fname); $fields['last_name'] = htmlspecialchars($lname); $fields['address1'] = htmlspecialchars($address['address1']); $fields['address2'] = htmlspecialchars($address['address2']); $fields['city'] = htmlspecialchars($address['city']); $fields['state'] = htmlspecialchars($address['state']); $fields['country'] = htmlspecialchars($address['country']); $fields['zip'] = htmlspecialchars($address['zip']); } $i = 1; $total_amount = 0; $shipping = 0; $weight = 0; foreach ($cartItems as $cart_item_id => $item) { //$opt_str = ''; list($db_item_id, $options) = explode('|', $item['item_id']); if (is_numeric($db_item_id)) { $P = new Product($db_item_id); $db_item_id = DB_escapeString($db_item_id); $oc = 0; if (is_array($item['options'])) { $opts = explode(',', $options); foreach ($opts as $optval) { $opt_info = $P->getOption($optval); if ($opt_info) { $opt_str .= ', ' . $opt_info['value']; $fields['on' . $oc . '_' . $i] = $opt_info['name']; $fields['os' . $oc . '_' . $i] = $opt_info['value']; $oc++; } } //$item['descrip'] .= $opt_str; } else { $opts = array(); } $fields['amount_' . $i] = $P->getPrice($opts, $item['quantity']); if ($P->taxable == 0) { $fields['tax_' . $i] = '0.00'; } } else { // Plugin item $fields['amount_' . $i] = $item['price']; } //$fields['item_number_' . $i] = htmlspecialchars($item['item_id']); $fields['item_number_' . $i] = (int) $cart_item_id; $fields['item_name_' . $i] = htmlspecialchars($item['descrip']); $total_amount += $item['price']; if (is_array($item['extras']['custom'])) { foreach ($item['extras']['custom'] as $id => $val) { $fields['on' . $oc . '_' . $i] = $P->getCustom($id); $fields['os' . $oc . '_' . $i] = $val; $oc++; } } $fields['quantity_' . $i] = $item['quantity']; if (isset($item['shipping'])) { $fields['shipping_' . $i] = $item['shipping']; $shipping += $item['shipping']; } if (isset($item['weight']) && $item['weight'] > 0) { $weight += $item['weight']; } if (isset($item['tax'])) { $fields['tax_' . $i] = $item['tax']; } elseif (isset($item['options']['tax'])) { $fields['tax_' . $i] = $item['options']['tax']; } $i++; } if ($shipping > 0) { $total_amount += $shipping; } if ($weight > 0) { $fields['weight_cart'] = $weight; $fields['weight_unit'] = $_PP_CONF['weight_unit'] == 'kgs' ? 'kgs' : 'lbs'; } // Set the business e-mail address based on the total puchase amount // There must be an address configured; if not then this gateway can't // be used for this purchase $this->setReceiver($total_amount); $fields['business'] = $this->receiver_email; if (empty($fields['business'])) { return ''; } $gatewayVars = array(); $enc_btn = ''; if ($this->config['encrypt']) { $enc_btn = self::_encButton($fields); if (!empty($enc_btn)) { $gatewayVars[] = '<input type="hidden" name="cmd" value="_s-xclick" />'; $gatewayVars[] = '<input type="hidden" name="encrypted" ' . 'value="' . $enc_btn . '" />'; } } if (empty($enc_btn)) { // If we didn't get an encrypted button, set the plaintext vars foreach ($fields as $name => $value) { $gatewayVars[] = '<input type="hidden" name="' . $name . '" value="' . $value . '" />'; } } $gateway_vars = implode("\n", $gatewayVars); $T = new Template(PAYPAL_PI_PATH . '/templates/buttons/' . $this->gw_name); $T->set_file(array('btn' => 'btn_checkout.thtml')); $T->set_var('paypal_url', $this->getActionUrl()); $T->set_var('gateway_vars', $gateway_vars); $retval = $T->parse('', 'btn'); return $retval; }
/** * 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->buyer_email = $this->pp_data['payer_email']; $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(); if ($cart) { $this->Order->instructions = $cart->getInstructions(); } $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']); $option_desc = array(); list($item_number, $options) = explode('|', $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. $P = new Product($item['item_id']); $item['short_description'] = $P->short_description; if (!empty($options)) { // options is expected as CSV $sql = "SELECT attr_name, 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']; $option_desc[] = $O['attr_name'] . ': ' . $O['attr_value']; } } // Get the product record and custom strings if (isset($item['extras']['custom']) && is_array($item['extras']['custom']) && !empty($item['extras']['custom'])) { foreach ($item['extras']['custom'] as $cust_id => $cust_val) { $option_desc[] = $P->getCustom($cust_id) . ': ' . $cust_val; } } } $sql = "INSERT INTO {$_TABLES['paypal.purchases']} SET\n order_id = '{$db_order_id}',\n product_id = '{$item['item_number']}',\n description = '" . DB_escapeString($item['short_description']) . "',\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 = 'paid',\n token = '" . md5(time()) . "',\n price = " . (double) $item['price'] . ",\n options = '{$options}',\n options_text = '" . DB_escapeString(json_encode($option_desc)) . "'"; // add an expiration date if appropriate if (is_numeric($item['expiration']) && $item['expiration'] > 0) { $sql .= ", expiration = DATE_ADD('{$this->sql_date}', 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; }