/** * Generate the paypal button link * * @param int $order_id * @return string */ public function generate_paypal_form($order_id) { $order = new jigoshop_order($order_id); if ($this->testmode == 'yes') { $url = $this->testurl . '?test_ipn=1&'; } else { $url = $this->liveurl . '?'; } if (in_array($order->billing_country, array('US', 'CA'))) { $order->billing_phone = str_replace(array('(', '-', ' ', ')'), '', $order->billing_phone); $phone_args = array('night_phone_a' => substr($order->billing_phone, 0, 3), 'night_phone_b' => substr($order->billing_phone, 3, 3), 'night_phone_c' => substr($order->billing_phone, 6, 4), 'day_phone_a' => substr($order->billing_phone, 0, 3), 'day_phone_b' => substr($order->billing_phone, 3, 3), 'day_phone_c' => substr($order->billing_phone, 6, 4)); } else { $phone_args = array('night_phone_b' => $order->billing_phone, 'day_phone_b' => $order->billing_phone); } // filter redirect page $checkout_redirect = apply_filters('jigoshop_get_checkout_redirect_page_id', jigoshop_get_page_id('thanks')); $paypal_args = array_merge(array('cmd' => '_cart', 'business' => $this->testmode == 'yes' ? $this->testemail : $this->email, 'no_note' => 1, 'currency_code' => Jigoshop_Base::get_options()->get('jigoshop_currency'), 'charset' => 'UTF-8', 'rm' => 2, 'upload' => 1, 'return' => add_query_arg('key', $order->order_key, add_query_arg('order', $order_id, get_permalink($checkout_redirect))), 'cancel_return' => $order->get_cancel_order_url(), 'custom' => $order_id, 'notify_url' => $this->notify_url, 'first_name' => $order->billing_first_name, 'last_name' => $order->billing_last_name, 'company' => $order->billing_company, 'address1' => $order->billing_address_1, 'address2' => $order->billing_address_2, 'city' => $order->billing_city, 'state' => $order->billing_state, 'zip' => $order->billing_postcode, 'country' => $order->billing_country, 'email' => $order->billing_email, 'invoice' => $order->get_order_number(), 'amount' => number_format((double) $order->order_total, $this->decimals), 'bn' => 'Jigoshop_SP'), $phone_args); if ($this->send_shipping == 'yes') { $paypal_args['no_shipping'] = 1; $paypal_args['address_override'] = 1; $paypal_args['first_name'] = $order->shipping_first_name; $paypal_args['last_name'] = $order->shipping_last_name; $paypal_args['address1'] = $order->shipping_address_1; $paypal_args['address2'] = $order->shipping_address_2; $paypal_args['city'] = $order->shipping_city; $paypal_args['state'] = $order->shipping_state; $paypal_args['zip'] = $order->shipping_postcode; $paypal_args['country'] = $order->shipping_country; // PayPal counts Puerto Rico as a US Territory, won't allow payment without it if ($paypal_args['country'] == 'PR') { $paypal_args['country'] = 'US'; $paypal_args['state'] = 'PR'; } } else { $paypal_args['no_shipping'] = 1; $paypal_args['address_override'] = 0; } // If prices include tax, send the whole order as a single item if (Jigoshop_Base::get_options()->get('jigoshop_prices_include_tax') == 'yes') { // Discount $paypal_args['discount_amount_cart'] = number_format((double) $order->order_discount, $this->decimals); // Don't pass items - PayPal breaks tax due to catalog prices include tax. // PayPal has no option for tax inclusive pricing. // Pass 1 item for the order items overall $item_names = array(); foreach ($order->items as $item) { $_product = $order->get_product_from_item($item); $title = $_product->get_title(); //if variation, insert variation details into product title if ($_product instanceof jigoshop_product_variation) { $title .= ' (' . jigoshop_get_formatted_variation($_product, $item['variation'], true) . ')'; } $item_names[] = $title . ' x ' . $item['qty']; } $paypal_args['item_name_1'] = sprintf(__('Order %s', 'jigoshop'), $order->get_order_number()) . ' - ' . implode(', ', $item_names); $paypal_args['quantity_1'] = 1; $paypal_args['amount_1'] = number_format($order->order_total - $order->order_shipping - $order->order_shipping_tax + $order->order_discount, $this->decimals, '.', ''); if ($order->order_shipping + $order->order_shipping_tax > 0) { $paypal_args['item_name_2'] = __('Shipping cost', 'jigoshop'); $paypal_args['quantity_2'] = '1'; $paypal_args['amount_2'] = number_format($order->order_shipping + $order->order_shipping_tax, $this->decimals, '.', ''); } } else { // Cart Contents $item_loop = 0; foreach ($order->items as $item) { $_product = $order->get_product_from_item($item); if ($_product->exists() && $item['qty']) { $item_loop++; $title = $_product->get_title(); //if variation, insert variation details into product title if ($_product instanceof jigoshop_product_variation) { $title .= ' (' . jigoshop_get_formatted_variation($_product, $item['variation'], true) . ')'; } $paypal_args['item_name_' . $item_loop] = $title; $paypal_args['quantity_' . $item_loop] = $item['qty']; $paypal_args['amount_' . $item_loop] = number_format(apply_filters('jigoshop_paypal_adjust_item_price', $item['cost'], $item, 10, 2), $this->decimals); //Apparently, Paypal did not like "28.4525" as the amount. Changing that to "28.45" fixed the issue. } } // Shipping Cost if (jigoshop_shipping::is_enabled() && $order->order_shipping > 0) { $item_loop++; $paypal_args['item_name_' . $item_loop] = __('Shipping cost', 'jigoshop'); $paypal_args['quantity_' . $item_loop] = '1'; $paypal_args['amount_' . $item_loop] = number_format((double) $order->order_shipping, $this->decimals); } $paypal_args['tax'] = $order->get_total_tax(false, false); // no currency sign or pricing options for separators $paypal_args['tax_cart'] = $order->get_total_tax(false, false); // no currency sign or pricing options for separators $paypal_args['discount_amount_cart'] = $order->order_discount; if ($this->force_payment == 'yes') { $sum = 0; for ($i = 1; $i < $item_loop; $i++) { $sum += $paypal_args['amount_' . $i]; } $item_loop++; if ($sum == 0 || $order->order_discount && $sum - $order->order_discount == 0) { $paypal_args['item_name_' . $item_loop] = __('Force payment on free', 'jigoshop'); $paypal_args['quantity_' . $item_loop] = '1'; $paypal_args['amount_' . $item_loop] = 0.01; // force payment } } } $paypal_args = apply_filters('jigoshop_paypal_args', $paypal_args); return jigoshop_render_result('gateways/paypal', array('url' => $url, 'fields' => $paypal_args)); }
/** * Generates WorldPay form and redirects to WordPay with Order information */ public function display_worldpay_redirect_form($order_id) { $order = new jigoshop_order($order_id); if ($this->testmode == 'yes') { $worldpay_url = "https://secure-test.worldpay.com/wcc/purchase"; $testmode = (int) 100; } else { $worldpay_url = "https://secure.worldpay.com/wcc/purchase"; $testmode = (int) 0; } $order_total = number_format($order->order_total, 2, '.', ''); $worldpay_args = array('instId' => $this->installation_id, 'cartId' => $order_id, 'amount' => $order_total, 'currency' => $this->currency, 'testMode' => $testmode, 'email' => $order->billing_email, 'MC_invoice' => $order->order_key); // Send 'canned' name if testmode or full name if not testmode. if ($this->testmode == 'yes') { $worldpay_args['name'] = 'AUTHORISED'; } else { $worldpay_args['name'] = $order->billing_first_name . ' ' . $order->billing_last_name; } // Address info $worldpay_args['address1'] = $order->billing_address_1; $worldpay_args['address2'] = $order->billing_address_2; $worldpay_args['town'] = $order->billing_city; $worldpay_args['region'] = $order->billing_state; $worldpay_args['postcode'] = $order->billing_postcode; $worldpay_args['country'] = $order->billing_country; $worldpay_args['fixContact'] = ''; /* no address editing */ // Setup the Dymanic URL properties using Jigoshop Request API $worldpay_args['MC_callback'] = $this->notify_url; $worldpay_args['MC_cancel_return'] = $order->get_cancel_order_url(); // Cart Contents - Generate cart description $desc = ''; if (sizeof($order->items) > 0) { foreach ($order->items as $item) { $_product = $order->get_product_from_item($item); if ($_product->exists() && $item['qty']) { $title = $_product->get_title(); // if variation, insert variation details into product title if ($_product instanceof jigoshop_product_variation) { $title .= ' (' . jigoshop_get_formatted_variation($_product, $item['variation'], true) . ')'; } $desc .= $item['qty'] . ' x ' . $title . '<br/>'; } } // Add the description $worldpay_args['desc'] = $desc; } if ($this->fixed_currency == 'yes') { $worldpay_args['hideCurrency'] = ''; } // MD5 hash the main parameters we are sending to WorldPay if ($this->md5_encrypt == 'yes' && !empty($this->secret_word)) { // Add the fields you are hashing $hash_fields = 'instId:cartId:amount:currency'; $worldpay_args['signatureFields'] = $hash_fields; // Add the hash signature $hash_message = $this->secret_word . ':' . $this->installation_id . ':' . $order_id . ':' . $order_total . ':' . $this->currency; $worldpay_args['signature'] = md5($hash_message); } $worldpay_form_array = array(); foreach ($worldpay_args as $key => $value) { if ($key == 'hideCurrency') { $worldpay_form_array[] = '<input type="hidden" name="' . $key . '" />'; continue; } if ($key == 'fixContact') { $worldpay_form_array[] = '<input type="hidden" name="' . $key . '" />'; continue; } $worldpay_form_array[] = '<input type="hidden" name="' . $key . '" value="' . $value . '" />'; } return jigoshop_render_result('gateways/worldpay', array('url' => $worldpay_url, 'fields' => $worldpay_args)); }
function jigoshop_process_shop_order_meta($post_id) { $jigoshop_options = Jigoshop_Base::get_options(); $jigoshop_errors = array(); $order = new jigoshop_order($post_id); // Get old data + attributes $data = (array) maybe_unserialize(get_post_meta($post_id, 'order_data', true)); //Get old order items $old_order_items = (array) maybe_unserialize(get_post_meta($post_id, 'order_items', true)); // Add/Replace data to array $customerDetails = array('billing_first_name', 'billing_last_name', 'billing_company', 'billing_euvatno', 'billing_address_1', 'billing_address_2', 'billing_city', 'billing_postcode', 'billing_country', 'billing_state', 'billing_email', 'billing_phone', 'shipping_first_name', 'shipping_last_name', 'shipping_company', 'shipping_address_1', 'shipping_address_2', 'shipping_city', 'shipping_postcode', 'shipping_country', 'shipping_state'); $order_fields = array('shipping_method', 'shipping_service', 'payment_method', 'order_subtotal', 'order_discount_subtotal', 'order_shipping', 'order_discount', 'order_discount_coupons', 'order_tax_total', 'order_shipping_tax', 'order_total', 'order_total_prices_per_tax_class_ex_tax'); /* Pre-fill the customer addresses */ foreach ($customerDetails as $key) { $order_fields[] = $key; /* Checks if this is a new order from "Add Order" button */ if (!empty($_POST['auto_draft']) && !empty($_POST['customer_user']) && empty($_POST[$key])) { $data[$key] = get_user_meta($_POST['customer_user'], $key, true); } } //Check EUVAT Field if (!empty($data['billing_euvatno']) && !empty($data['billing_country'])) { $data['billing_euvatno'] = str_replace(' ', '', $data['billing_euvatno']); } //run stripslashes on all valid fields foreach ($order_fields as $field_name) { if (isset($_POST[$field_name])) { $data[$field_name] = stripslashes($_POST[$field_name]); } } // Sanitize numeric values $data['order_total'] = jigoshop_sanitize_num($data['order_total']); $data['order_subtotal'] = jigoshop_sanitize_num($data['order_subtotal']); // if a shipping or payment methods has changed, update the method title for pretty display if (isset($_POST['shipping_method'])) { $data['shipping_service'] = ''; $shipping_methods = jigoshop_shipping::get_all_methods(); if (!empty($shipping_methods)) { foreach ($shipping_methods as $method) { if ($_POST['shipping_method'] == $method->id) { $data['shipping_service'] = $method->title; } } } } if (isset($_POST['payment_method'])) { $data['payment_method_title'] = ''; $payment_methods = jigoshop_payment_gateways::get_available_payment_gateways(); if (!empty($payment_methods)) { foreach ($payment_methods as $method) { if ($_POST['payment_method'] == $method->id) { $data['payment_method_title'] = $method->title; } } } } // if total tax has been modified from order tax, then create a customized tax array // just for the order. At this point, we no longer know about multiple tax classes. // Even if we used the old tax array data, we still don't know how to break down // the amounts since they're customized. if (isset($data['order_tax_total']) && $order->get_total_tax() != $data['order_tax_total']) { $new_tax = $data['order_tax_total']; $data['order_tax'] = jigoshop_tax::create_custom_tax($data['order_total'] - $data['order_tax_total'], $data['order_tax_total'], $data['order_shipping_tax'], isset($data['order_tax_divisor']) ? $data['order_tax_divisor'] : null); } // Customer update_post_meta($post_id, 'customer_user', (int) $_POST['customer_user']); // Order items $order_items = array(); if (isset($_POST['item_id'])) { $item_id = $_POST['item_id']; $item_variation = $_POST['item_variation_id']; $item_name = $_POST['item_name']; $item_quantity = $_POST['item_quantity']; $item_cost = $_POST['item_cost']; $item_tax_rate = $_POST['item_tax_rate']; for ($i = 0; $i < count($item_id); $i++) { if (!isset($item_id[$i]) || !isset($item_name[$i]) || !isset($item_quantity[$i]) || !isset($item_cost[$i]) || !isset($item_tax_rate[$i])) { continue; } $variation_id = ''; $variation = ''; if (!empty($item_variation[$i])) { $variation_id = (int) $item_variation[$i]; // if this is a variation, we should check if it is an old one // and copy the 'variation' field describing details of variation foreach ($old_order_items as $old_item_index => $old_item) { if ($old_item['variation_id'] == $variation_id) { $variation = $old_item['variation']; unset($old_order_items[$old_item_index]); break; } } // override variation with values from $_POST if (isset($_POST['order_attributes'][$i]) && is_array($_POST['order_attributes'][$i])) { foreach ($_POST['order_attributes'][$i] as $var_key => $var_value) { $variation[$var_key] = $var_value; } } } $cost_inc_tax = $jigoshop_options->get('jigoshop_prices_include_tax') == 'yes' ? number_format((double) jigowatt_clean($item_cost[$i]), 2, '.', '') : -1; $order_items[] = apply_filters('update_order_item', array('id' => htmlspecialchars(stripslashes($item_id[$i])), 'variation_id' => $variation_id, 'variation' => $variation, 'name' => htmlspecialchars(stripslashes($item_name[$i])), 'qty' => (int) $item_quantity[$i], 'cost' => number_format((double) jigowatt_clean($item_cost[$i]), 2, '.', ''), 'cost_inc_tax' => $cost_inc_tax, 'taxrate' => number_format((double) jigowatt_clean($item_tax_rate[$i]), 4, '.', ''))); } } // Process custom attributes added with "jigoshop_order_data_panels" $data = apply_filters("jigoshop_order_data_save", $data, $post_id); // Save update_post_meta($post_id, 'order_data', $data); update_post_meta($post_id, 'order_items', $order_items); // Order status $order->update_status($_POST['order_status']); // Handle button actions if (isset($_POST['reduce_stock']) && $_POST['reduce_stock'] && count($order_items) > 0) { $order->add_order_note(__('Manually reducing stock.', 'jigoshop')); foreach ($order_items as $order_item) { $_product = $order->get_product_from_item($order_item); if ($_product->exists) { if ($_product->managing_stock()) { $old_stock = $_product->stock; $new_quantity = $_product->reduce_stock($order_item['qty']); $order->add_order_note(sprintf(__('Item #%s stock reduced from %s to %s.', 'jigoshop'), $order_item['id'], $old_stock, $new_quantity)); if ($new_quantity < 0) { if ($old_stock < 0) { $backorder_qty = $order_item['qty']; } else { $backorder_qty = $old_stock - $order_item['qty']; } do_action('jigoshop_product_on_backorder_notification', $post_id, $_product, $backorder_qty); } // stock status notifications if ($jigoshop_options->get('jigoshop_notify_no_stock') == 'yes' && $jigoshop_options->get('jigoshop_notify_no_stock_amount') >= 0 && $jigoshop_options->get('jigoshop_notify_no_stock_amount') >= $new_quantity) { do_action('jigoshop_no_stock_notification', $_product); } else { if ($jigoshop_options->get('jigoshop_notify_low_stock') == 'yes' && $jigoshop_options->get('jigoshop_notify_low_stock_amount') >= $new_quantity) { do_action('jigoshop_low_stock_notification', $_product); } } } } else { $order->add_order_note(sprintf(__('Item %s %s not found, skipping.', 'jigoshop'), $order_item['id'], $order_item['name'])); } } $order->add_order_note(__('Manual stock reduction complete.', 'jigoshop')); } else { if (isset($_POST['restore_stock']) && $_POST['restore_stock'] && sizeof($order_items) > 0) { $order->add_order_note(__('Manually restoring stock.', 'jigoshop')); foreach ($order_items as $order_item) { $_product = $order->get_product_from_item($order_item); if ($_product->exists) { if ($_product->managing_stock()) { $old_stock = $_product->stock; $new_quantity = $_product->increase_stock($order_item['qty']); $order->add_order_note(sprintf(__('Item #%s stock increased from %s to %s.', 'jigoshop'), $order_item['id'], $old_stock, $new_quantity)); } } else { $order->add_order_note(sprintf(__('Item %s %s not found, skipping.', 'jigoshop'), $order_item['id'], $order_item['name'])); } } $order->add_order_note(__('Manual stock restore complete.', 'jigoshop')); } else { if (isset($_POST['invoice']) && $_POST['invoice']) { // Mail link to customer jigoshop_send_customer_invoice($order->id); } } } // Error Handling if (count($jigoshop_errors) > 0) { $jigoshop_options->set('jigoshop_errors', $jigoshop_errors); } }
function jigoshop_ga_ecommerce_tracking($order_id) { $options = Jigoshop_Base::get_options(); // Skip if disabled if ($options->get('jigoshop_ga_ecommerce_tracking_enabled') != 'yes') { return; } // Don't track the shop owners roaming if (current_user_can('manage_jigoshop')) { return; } $tracking_id = $options->get('jigoshop_ga_id'); if (!$tracking_id) { return; } // Get the order and output tracking code $order = new jigoshop_order($order_id); ?> <script type="text/javascript"> jigoshopGA('require', 'ecommerce'); jigoshopGA('ecommerce:addTransaction', { 'id': '<?php echo $order->get_order_number(); ?> ', // Transaction ID. Required. 'affiliation': '<?php bloginfo('name'); ?> ', // Affiliation or store name. 'revenue': '<?php echo $order->order_total; ?> ', // Grand Total. 'shipping': '<?php echo $order->order_shipping; ?> ', // Shipping. 'tax': '<?php echo $order->get_total_tax(); ?> ' // Tax. }); <?php foreach ($order->items as $item) { $_product = $order->get_product_from_item($item); ?> jigoshopGA('ecommerce:addItem', { 'id': '<?php echo $order->get_order_number(); ?> ', // Transaction ID. Required. 'name': '<?php echo $item['name']; ?> ', // Product name. Required. 'sku': '<?php echo $_product->sku; ?> ', // SKU/code. 'category': '<?php if (isset($_product->variation_data)) { echo jigoshop_get_formatted_variation($_product, $item['variation'], true); } ?> ', // Category or variation. 'price': '<?php echo $item['cost'] / $item['qty']; ?> ', // Unit price. 'quantity': '<?php echo $item['qty']; ?> ' // Quantity. }); <?php } ?> jigoshopGA('ecommerce:send'); </script> <?php }
/** * Generate the futurepay payment iframe */ protected function call_futurepay($order_id) { // Get the order $order = new jigoshop_order($order_id); $data = array('gmid' => $this->gmid, 'reference' => $order_id . '-' . uniqid(), 'email' => $order->billing_email, 'first_name' => $order->billing_first_name, 'last_name' => $order->billing_last_name, 'company' => $order->billing_company, 'address_line_1' => $order->billing_address_1, 'address_line_2' => $order->billing_address_2, 'city' => $order->billing_city, 'state' => $order->billing_state, 'country' => $order->billing_country, 'zip' => $order->billing_postcode, 'phone' => $order->billing_phone, 'shipping_address_line_1' => $order->shipping_address_1, 'shipping_address_line_2' => $order->shipping_address_2, 'shipping_city' => $order->shipping_city, 'shipping_state' => $order->shipping_state, 'shipping_country' => $order->shipping_country, 'shipping_zip' => $order->shipping_postcode, 'shipping_date' => date('Y/m/d g:i:s')); // for Jigoshop 1.7, FuturePay doesn't allow negative prices (or 0.00 ) which affects discounts // with FuturePay doing the calcs, so we will bundle all products into ONE line item with // a quantity of ONE and send it that way using the final order total after shipping // and discounts are applied // all product titles will be comma delimited with their quantities $item_names = array(); if (sizeof($order->items) > 0) { foreach ($order->items as $item) { $_product = $order->get_product_from_item($item); $title = $_product->get_title(); // if variation, insert variation details into product title if ($_product instanceof jigoshop_product_variation) { $title .= ' (' . jigoshop_get_formatted_variation($_product, $item['variation'], true) . ')'; } $item_names[] = $item['qty'] . ' x ' . $title; } } // now add the one line item to the necessary product field arrays $data['sku'][] = "Products"; $data['price'][] = $order->order_total; // futurepay only needs final order amount $data['tax_amount'][] = 0; $data['description'][] = sprintf(__('Order %s', 'jigoshop'), $order->get_order_number()) . ' = ' . implode(', ', $item_names); $data['quantity'][] = 1; try { $response = wp_remote_post(self::$request_url . 'merchant-request-order-token', array('body' => http_build_query($data), 'sslverify' => false)); // Convert error to exception if (is_wp_error($response)) { if (class_exists('WP_Exception') && $response instanceof WP_Exception) { throw $response; } else { jigoshop_log($response->get_error_message()); throw new Exception($response->get_error_message()); } } // Fetch the body from the result, any errors should be caught before proceeding $response = trim(wp_remote_retrieve_body($response)); // we need something to validate the response. Valid transactions begin with 'FPTK' if (!strstr($response, 'FPTK')) { $error_message = isset(self::$futurepay_errorcodes[$response]) ? self::$futurepay_errorcodes[$response] : __('An unknown error has occured with code = ', 'jigoshop') . $response; $order->add_order_note(sprintf(__('FUTUREPAY: %s', 'jigoshop'), $error_message)); jigoshop::add_error(sprintf(__('FUTUREPAY: %s. Please try again or select another gateway for your Order.', 'jigoshop'), $error_message)); wp_safe_redirect(get_permalink(jigoshop_get_page_id('checkout'))); exit; } /** * If we're good to go, haul in FuturePay's javascript and display the payment form * so that the customer can enter his ID and password */ echo '<div id="futurepay"></div>'; echo '<script src="' . self::$request_url . 'cart-integration/' . $response . '"></script>'; echo '<script type="text/javascript"> /*<![CDATA[*/ jQuery(window).load( function() { FP.CartIntegration(); // Need to replace form html jQuery("#futurepay").html(FP.CartIntegration.getFormContent()); FP.CartIntegration.displayFuturePay(); }); function FuturePayResponseHandler(response) { if (response.error) { // TODO: we need something better than this alert(response.code + " " + response.message); } else { window.location.replace("./?futurepay="+response.transaction_id); } } /*]]>*/ </script>'; echo '<input type="button" class="button alt" name="place_order" id="place_order" value="Place Order" onclick="FP.CartIntegration.placeOrder();" />'; } catch (Exception $e) { echo '<div class="jigoshop_error">' . $e->getMessage() . '</div>'; jigoshop_log('FUTUREPAY ERROR: ' . $e->getMessage()); } }