As anyone who has ever used Zen-cart knows, zen-cart the next step is the following (where the representation in [] is not required):
1. Shopping cart (shopping cart)
2. [Shipping Mode (delivery method)]
3. Mode of payment (payment method)
4. Order Confirmation (Confirmation)
5. [Third party web site payments]
6. Order Processing (checkout process)-This step is more important, because the information in the shopping cart will be written to the order
7. Order success (Checkout success)
Such a process does not have any problems under normal circumstances. However, from the 5th step to the 6th part of the process, the user may think that the payment was successful directly off the page, or because of the network cause can not normal jump to the checkout_process page, this result is very serious, because the order can not be normal to create.
Based on the above analysis, we want to slightly change the process, that is, before the payment of the order has been created, so that even if the payment can not be from the Third-party payment site to jump back, we will not have the user payment success in the background without orders. The revised blueprint is basically the following:
1. After Checkour_confirmation page confirmation order, will be directly proccess, and enter the Checkour_success page, can enter the payment page here. As shown in the following illustration:
2. If the customer has not been able to pay, can also enter their own background to the historical order payment. As shown in the following illustration:
Let's take a look at how to achieve the above function in one step.
1. First, we need to make an alteration to the existing payment module. You need to add a field to the class of payment method Paynow_action_url, which represents the URL of the page to be paid, plus a function, Paynow_button ($order _id), to get the parameter hidden field code of the payment form.
To add the Paynow_action_url field, add the following code to the constructor of the class payment:
Copy Code code as follows:
if (Zen_not_null ($module)) && (In_array ($module. '). php ', $this->modules)) && (Isset ($GLOBALS [$module]->paynow_action_url))] {
$this->paynow_action_url = $GLOBALS [$module]->paynow_action_url;
}
To add the Paynow_button ($order _id) function, add the following code after the last function of the payment class:
Copy Code code as follows:
function Paynow_button ($order _id) {
if (Is_array ($this->modules)) {
if (Is_object ($GLOBALS [$this->selected_module])) {
return $GLOBALS [$this->selected_module]->paynow_button ($order _id);
}
}
}
2. PayPal payment method as an example of how to achieve the specific. In order not to break the original PayPal code, we will paypal.php file copies of a copy out, and named Paypalsimple.php, and the inside of the code to make appropriate changes. As shown in the code below, you can see that this removes the designation for Form_action_url and gives the paynow_action_url because we want the user to enter checkout_process directly after clicking "Confirm Order", so if you do not specify FORM_ Action_url, then the confirmation order form will be submitted directly to the Checkout_process page, and Paynow_action_url is the previous Form_action_url value. The implementation of the Paynow_button function is also simple, where the contents of the original Process_button () function are simply clipped, except that we do not use the global $order variable, but instead use the $order = New Order ($order _id) To reconstruct an object that is prepared for displaying the pay Now button in a history order.
paypalsimple.php
Copy Code code as follows:
<?php
/**
* @package paypalsimple Payment Module
* @copyright Copyright 2003-2006 Zen Cart Development Team
* @copyright Portions Copyright 2003 OsCommerce
* @license http://www.zen-cart.com/license/2_0.txt GNU Public License V2.0
* @version $Id: paypalsimple.php 4960 2009-12-29 11:46:46z Gary $
*/
Ensure dependencies are loaded
Include_once (Is_admin_flag = = true? Dir_fs_catalog_modules:dir_ws_modules). ' payment/paypal/paypal_functions.php ');
Class Paypalsimple {
var $code, $title, $description, $enabled;
Class constructor
function Paypalsimple () {
Global $order;
$this->code = ' paypalsimple ';
$this->title = Module_payment_paypal_simple_text_title;
if (Is_admin_flag = = True) {
$this->title = Module_payment_paypal_simple_text_admin_title;
}
$this->description = module_payment_paypal_simple_text_description;
$this->sort_order = Module_payment_paypal_simple_sort_order;
$this->enabled = ((Module_payment_paypal_simple_status = = ' True ')? true:false);
if ((int) module_payment_paypal_simple_order_status_id > 0) {
$this->order_status = module_payment_paypal_simple_order_status_id;
}
$this->paynow_action_url = ' https://'. Module_payment_paypal_simple_handler;
if (Is_object ($order)) $this->update_status ();
}
Class methods
function Update_status () {
Global $order, $db;
if (($this->enabled = = True) && ((int) module_payment_paypal_simple_zone > 0)) {
$check _flag = false;
$check = $db->execute ("Select zone_id from". Table_zones_to_geo_zones. "Where geo_zone_id = '". Module_payment_paypal_simple_zone. "' and zone_country_id = '". $order->billing[' country ' [' ID ']. "' ORDER by zone_id");
while (! $check->eof) {
if ($check->fields[' zone_id '] < 1) {
$check _flag = true;
Break
} elseif ($check->fields[' zone_id '] = = = $order->billing[' zone_id ']) {
$check _flag = true;
Break
}
$check->movenext ();
}
if ($check _flag = = False) {
$this->enabled = false;
}
}
}
function Javascript_validation () {
return false;
}
function selection () {
$text = Module_payment_simple_paypal_text_catalog_logo. ' '. Module_payment_paypal_simple_text_title. ' <br/><br/> <span class= ' smalltext ' > '. Module_payment_paypal_simple_acceptance_mark_text. ' </span><br/><br/> ';
Return array (' ID ' => $this->code,
' Module ' => $text
);
}
function Pre_confirmation_check () {
return false;
}
Function Confirmation () {
return false;
}
function Process_button () {
return false;
}
function before_process () {
return false;
}
function after_process () {
return false;
}
function Get_error () {
return false;
}
function Check () {
Global $db;
if (!isset ($this->_check)) {
$check _query = $db->execute (select Configuration_value from). Table_configuration. "Where Configuration_key = ' module_payment_paypal_simple_status '");
$this->_check = $check _query->recordcount ();
}
return $this->_check;
}
function Install () {
Global $db;
$db->execute (insert INTO). Table_configuration. "(Configuration_title, Configuration_key, Configuration_value, Configuration_description, configuration_group_id, Sort_order, Set_function, date_added) VALUES (' Enable paypal-simple Module ', ' module_payment_paypal_simple_status ', ' True ', ' Do your want to accept paypal-simple payments? ', ' 6 ', ' 0 ', ' zen_cfg_select_option (array (\ ' true\ ', \ ' false\ '), ', no W ()) ");
$db->execute (insert INTO). Table_configuration. "(Configuration_title, Configuration_key, Configuration_value, Configuration_description, configuration_group_id, Sort_order, date_added) VALUES (' sort order of display; ', ' module_payment_paypal_simple_sort_order ', ' 0 ', ' sort order of D Isplay. Lowest is displayed-A, ' 6 ', ' 8 ', now ());
$db->execute (insert INTO). Table_configuration. "(Configuration_title, Configuration_key, Configuration_value, Configuration_description, configuration_group_id, Sort_order, Use_function, set_function, date_added) VALUES (' Payment Zone ', ' module_payment_paypal_simple_zone ', ' 0 ', ' If a zone is selected, only enable this payment to the for that zone. ', ' 6 ', ' 2 ', ' zen_get_zone_class_title ', ' Zen_cfg_pul L_down_zone_classes (', Now ()) ");
$db->execute (insert INTO). Table_configuration. "(Configuration_title, Configuration_key, Configuration_value, Configuration_description, configuration_group_id, Sort_order, Set_function, use_function, date_added) VALUES (' Set order Status ', ' Module_payment_paypal_simple_order_ status_id ', ' 0 ', ' Set the status ' of orders made with this payment module to this value ', ' 6 ', ' 0 ', ' Zen_cfg_pull_down_orde R_statuses (', ' Zen_get_order_status_name ', now ());
$db->execute (insert INTO). Table_configuration. "(Configuration_title, Configuration_key, Configuration_value, Configuration_description, configuration_group_id, Sort_order, Set_function, date_added) VALUES (' Mode for PayPal web services<br/><br/>default:<br T;CODE>WWW.PAYPAL.COM/CGI-BIN/WEBSCR</CODE><BR/>or<br/><code>www.paypal.com/us/ Cgi-bin/webscr</code><br/>or for the uk,<br/><code>www.paypal.com/uk/cgi-bin/webscr</ Code> ', ' module_payment_paypal_simple_handler ', ' www.paypal.com/cgi-bin/webscr ', ' Choose ' URL for PAYPAL live Processing ', ' 6 ', ' in ', ', Now () ');
}
function Remove () {
Global $db;
$db->execute ("delete from"). Table_configuration. "Where Configuration_key in ('"). Implode ("', '", $this->keys ()). ");
}
function keys () {
Return Array (' Module_payment_paypal_simple_status ', ' module_payment_paypal_simple_sort_order ', ' Module_payment_ Paypal_simple_zone ', ' module_payment_paypal_simple_order_status_id ', ' Module_payment_paypal_simple_handler ');
}
function Paynow_button ($order _id) {
Global $db, $order, $currencies, $currency;
Require_once (dir_ws_classes. ' order.php ');
$order = New Order ($order _id);
$options = Array ();
$optionsCore = Array ();
$optionsPhone = Array ();
$optionsShip = Array ();
$optionsLineItems = Array ();
$optionsAggregate = Array ();
$optionsTrans = Array ();
$buttonArray = Array ();
$this->totalsum = $order->info[' total '];
Save the session stuff permanently in case PayPal loses
$_session[' ppipn_key_to_remove '] = session_id ();
$db->execute ("delete from"). Table_paypal_session. "Where session_id = '". Zen_db_input ($_session[' Ppipn_key_to_remove ')). "'");
$sql = "INSERT INTO". Table_paypal_session. "(session_id, saved_session, expiry) VALUES (
'" . Zen_db_input ($_session[' Ppipn_key_to_remove ')). "',
'" . Base64_encode (Serialize ($_session)). "',
'" . (Time () + (1*60*60*24*2)). "')";
$db->execute ($sql);
$my _currency = Select_pp_currency ();
$this->transaction_currency = $my _currency;
$this->transaction_amount = ($this->totalsum * $currencies->get_value ($my _currency));
$telephone = preg_replace ('/\d/', ', ', $order->customer[' telephone '));
if ($telephone!= ') {
$optionsPhone [' h_phonenumber '] = $telephone;
if (In_array ($order->customer[' country '] [' iso_code_2 '], array (' US ', ' CA ')) {
$optionsPhone [' night_phone_a '] = substr ($telephone, 0, 3);
$optionsPhone [' night_phone_b '] = substr ($telephone, 3, 3);
$optionsPhone [' night_phone_c '] = substr ($telephone, 6,4);
$optionsPhone [' day_phone_a '] = substr ($telephone, 0, 3);
$optionsPhone [' day_phone_b '] = substr ($telephone, 3, 3);
$optionsPhone [' day_phone_c '] = substr ($telephone, 6,4);
} else {
$optionsPhone [' night_phone_b '] = $telephone;
$optionsPhone [' day_phone_b '] = $telephone;
}
}
$optionsCore = Array (
' CharSet ' => charset,
' LC ' => $order->customer[' country '] [' iso_code_2 '],
' Page_style ' => module_payment_paypal_page_style,
' Custom ' => zen_session_name (). '=' . ZEN_SESSION_ID (),
' Business ' => module_payment_paypal_business_id,
' Return ' => zen_href_link (filename_pay_success, ' referer=paypal ', ' SSL '),
' Cancel_return ' => zen_href_link (filename_pay_failed, ', ' SSL '),
' Shopping_url ' => zen_href_link (Filename_shopping_cart, ', ' SSL '),
' Notify_url ' => zen_href_link (' ipn_main_handler.php ', ', ', ' SSL ', false,false,true),
' Redirect_cmd ' => ' _xclick ',
' RM ' => 2,
' Bn ' => ' Zencart ',
' MRB ' => ' r-6c7952342h795591r ',
' Pal ' => ' 9E82WJBKKGPLQ ',
);
$optionsCust = Array (
' First_Name ' => replace_accents ($order->customer[' FirstName '),
' Last_Name ' => replace_accents ($order->customer[' LastName '),
' Address1 ' => replace_accents ($order->customer[' street_address '),
"City" => replace_accents ($order->customer[' city '),
' State ' => zen_get_zone_code ($order->customer[' country '] [' id '], $order->customer[' zone_id '], $order-> customer[' zone_id ']),
' Zip ' => $order->customer[' postcode '],
' Country ' => $order->customer[' country ' [' iso_code_2 '],
' Email ' => $order->customer[' email_address '],
);
if ($order->customer[' suburb ']!= ') $optionsCust [' address2 '] = $order->customer[' suburb '];
if (module_payment_paypal_address_required = 2) $optionsCust = Array (
' Address_name ' => replace_accents ($order->customer[' FirstName '). ' ' . $order->customer[' LastName ']),
' Address_street ' => replace_accents ($order->customer[' street_address '),
' Address_city ' => replace_accents ($order->customer[' city '),
' Address_state ' => zen_get_zone_code ($order->customer[' country '] [' id '], $order->customer[' zone_id '], $ order->customer[' zone_id ']),
' Address_zip ' => $order->customer[' postcode '],
' Address_country ' => $order->customer[' country ' [' title '],
' Address_country_code ' => $order->customer[' country ' [' iso_code_2 '],
' Payer_email ' => $order->customer[' email_address '],
);
$optionsShip = Array (
' Address_override ' => module_payment_paypal_address_override,
' No_shipping ' => module_payment_paypal_address_required,
);
if (Module_payment_paypal_detailed_cart = = ' Yes ') $optionsLineItems = Ipn_getlineitemdetails ();
if (sizeof ($optionsLineItems) > 0) {
$optionsLineItems [' cmd '] = ' _cart ';
$optionsLineItems [' num_cart_items '] = sizeof ($order->products);
if (Isset ($optionsLineItems [' shipping '])) {
$optionsLineItems [' shipping_1 '] = $optionsLineItems [' Shipping '];
unset ($optionsLineItems [' shipping ']);
}
if (Isset ($optionsLineItems [' Handling '])) {
$optionsLineItems [' handling_1 '] = $optionsLineItems [' Handling '];
unset ($optionsLineItems [' Handling ']);
}
unset ($optionsLineItems [' Subtotal ']);
If Line-item details couldn ' t be kept due to calculation mismatches or discounts etc, default to aggregate mode
if (!isset ($optionsLineItems [' item_name_1 ']) $optionsLineItems = Array ();
if ($optionsLineItems [' Amount ']!= $this->transaction_amount) $optionsLineItems = Array ();
Ipn_debug_email ("Line Item Details" (if blank, this means there is a data mismatch, and thus bypassed): '. "\ n". Print_r ($optionsLineItems, true));
}
$products _name_display = "";
/*
For ($i =0, $n =sizeof ($order->products); $i < $n; $i + +) {
if (i > 0) {
$products _name_display.= ', ';
}
$products _name_display.= $order->products[$i [' name ']. ' (' $order->products[$i] [' qty ']. ', '. $order->products[$i] [' Dhisys_web_order_number '].
}*/
$optionsAggregate = Array (
' cmd ' => ' _ext-enter ',
' Item_name ' => $products _name_display,
' Item_Number ' => $order _id,
' Num_cart_items ' => sizeof ($order->products),
' Amount ' => number_format ($this->transaction_amount, $currencies->get_decimal_places ($my _currency)),
' Shipping ' => ' 0.00 ',
);
if (Module_payment_paypal_tax_override = = ' true ') $optionsAggregate [' TAX '] = ' 0.00 ';
if (Module_payment_paypal_tax_override = = ' true ') $optionsAggregate [' tax_cart '] = ' 0.00 ';
$optionsTrans = Array (
' Upload ' => (int) (sizeof ($order->products) > 0),
' Currency_code ' => $my _currency,
' paypal_order_id ' => $paypal _order_id,
' No_note ' => ' 1 ',
' Invoice ' => ',
);
If Line-item info is invalid, use aggregate:
if (sizeof ($optionsLineItems) > 0) $optionsAggregate = $optionsLineItems;
Prepare submission
$options = Array_merge ($optionsCore, $optionsCust, $optionsPhone, $optionsShip, $optionsTrans, $optionsAggregate);
Ipn_debug_email (' Keys for submission: '. Print_r ($options, true));
if (sizeof ($order->products) > 0) {
$options [' cmd '] = ' _cart ';
For ($i =0, $n =sizeof ($order->products); $i < $n; $i + +) {
$options [' item_name_ '.] (string) ($i + 1)] = $order->products[$i] [' name '];
$options [' Item_number_ '.] (string) ($i + 1)] = $order->products[$i] [' Dhisys_web_order_number '];
$options [' Amount_ '.] (string) ($i + 1)] = Number_format ((float) $order->products[$i] [' Final_price '],2);
$options [' quantity_ '.] (string) ($i + 1)] = $order->products[$i] [' qty '];
}
}
Build the button fields
foreach ($options as $name => $value) {
Remove quotation marks
$value = Str_replace (' ",", $value);
Check for invalid chars
if (Preg_match ('/[^a-za-z_0-9]/', $name)) {
Ipn_debug_email (' Datacheck-aborting-preg_match found invalid submission key: '. $name. ' ('. $value. ')');
Break
}
Do we need special handling for & and = symbols?
if (Strpos ($value, ' & ')!== false | | Strpos ($value, ' = ')!== false) $value = UrlEncode ($value);
$buttonArray [] = Zen_draw_hidden_field ($name, $value);
}
$_session[' paypal_transaction_info ' = Array ($this->transaction_amount, $this->transaction_currency);
$process _button_string = implode ("\ n", $buttonArray). "\ n";
return $process _button_string;
}
}
?>
3. Display the Pay Now button in the Checkout_success page. Open the file "includes/modules/pages/checkout_success/header.php" and add the following code at the end of the file (if you already have the notification/Observer mode in the Zen-cart, And do not want to break the Zen-cart core code, you can also create an observation class to monitor the notify_header_end_checkout_success to achieve.
Copy Code code as follows:
Require_once (dir_ws_classes. ' order.php ');
Require_once (dir_ws_classes. ' payment.php ');
$payment _modules = new Payment ($orders->fields[' Payment_module_code '));
Open the file "includes/modules/templates/template_default/templates/tpl_checkout_success_default.php" and add the following code in the appropriate location, Here is a judge of the status of the order, when only the status of the order in the unpaid status, the button is displayed,
Copy Code code as follows:
<div id= "Pay_now" >
<?php
&& $orders->fields[' orders_status '] = = ' 1 '
if (Isset ($payment _modules->paynow_action_url) && $payment _modules->paynow_action_url!= ' && $orders->fields[' orders_status '] = = ' 1 ') {
Echo (' <fieldset id= "csnotifications" > ");
Echo (' <legend> '. Text_paynow. ' </legend> ');
echo zen_draw_form (' Checkout_paynow ', $payment _modules->paynow_action_url, ' post ', ' id= ' checkout_confirmation ') Onsubmit= "Submitonce ();" "');
$selection = $payment _modules->selection ();
Echo (' <div class= ' buttonrow payment_method ' > '. $selection [0][' module ']. ' </div> ');
Echo (' <div class= "Buttonrow forward Paynow" > ");
if (Is_array ($payment _modules->modules)) {
echo $payment _modules->paynow_button ($orders _id);
}
Echo (Zen_image_submit (Button_image_paynow, Button_image_paynow_alt, ' name= "Btn_paynow" id= "Btn_paynow"));
Echo (' </div> ');
Echo (' </form> ');
Echo (' </fieldset> ');
}
?>
</div>
4. Displays the Pay Now button in the history order. There are three pages that need to display the Pay Now button: Account, Account_history,account_history_info, the implementation here is similar to the Checkout_success page, just to $payment_ Modules function Paynow_button parameter is not the same, here is no longer to repeat.
Summarize:
After the above changes, our process is as follows:
1. Shopping cart (shopping cart)
2. [Shipping Mode (delivery method)]
3. Mode of payment (payment method)
4. Order Confirmation (Confirmation)
5. Order Processing (Checkout process)
6. Order success (Checkout success)
7. [Third party web site payments]
Since the order confirmation to the order processing is done on our own website, and before entering the payment site, the order already exists, so there will be no drop out of the list.