// Extract information from XML credit card dataprivate function ExtractXml$decryptedData{$xml = simplexml_load_string$decryptedData; $this->_mCardHolder = string $xml->CardHolder; $this
Trang 1// Pack SymmetricCrypt::_msHexaIv into a binary string
$binary_iv = pack('H*', self::$_msHexaIv);
The conversion is done using PHP’s pack() function (learn more about it at http://www.php.net/pack)
The call to mcrypt_encrypt() follows:
// Encrypt $plainString
$binary_encrypted_string = mcrypt_encrypt(
self::$_msCipherAlgorithm,self::$_msSecretKey,
$plainString,MCRYPT_MODE_CBC,
$binary_iv);
This is the call that performs the actual encryption Its parameters are obvious, and you can find more detail about
the mcrypt_encrypt() function at http://www.php.net/mcrypt The MCRYPT_MODE_CBC specifies the
“cipher block chaining” encryption method; this method uses a chaining mechanism in which the encryption of
each block of data depends on the encryption results of preceding blocks, except for the first block in which the IV
is used instead
At the end, the encrypted string is transformed into hexadecimal format, which is easier to work with (for example,
to save in the database or in a configuration file):
// Convert $binary_encrypted_string to hexadecimal format
$hexa_encrypted_string = bin2hex($binary_encrypted_string);
The Decrypt() method is similar to the Encrypt() method First you need the IV to be in a binary form (the
same first step you took in the Encrypt() method)
As the Encrypt() method returns the encrypted string as a hexadecimal string, the input parameter of
Decrypt() is also a hexadecimal string You must convert this string to a byte array, which is the format
that mcrypt_decrypt() needs:
// Convert string in hexadecimal to byte array
$binary_encrypted_string = pack('H*', $encryptedString);
// Decrypt $binary_encrypted_string
$decrypted_string = mcrypt_decrypt(
self::$_msCipherAlgorithm,self::$_msSecretKey,
$binary_encrypted_string,MCRYPT_MODE_CBC,
$binary_iv);
return $decrypted_string;
The test_encryption.php test file for this class simply encrypts and decrypts data, demonstrating that things
are working properly The code for this is very simple, so we won’t detail it here
Now that you have the SymmetricCrypt class code, the last step in creating the security-related classes is to
add the SecureCard class
Trang 2Storing Credit Cart Information Using the SecureCard Class
In the following exercise, you’ll build the SecureCard class, which represents the credit card of
a customer This class will use the functionality you implemented in the previous two exercises
to ensure that its data will be stored securely in the database
Exercise: Implementing the SecureCard Class
1 Create a new file named secure_card.php in the business folder, and add the following code to it:
<?php// Represents a credit cardclass SecureCard
{// Private members containing credit card's detailsprivate $_mIsDecrypted = false;
private $_mIsEncrypted = false;
// Nothing here}
// Decrypt datapublic function LoadEncryptedDataAndDecrypt($newEncryptedData){
$this->_mEncryptedData = $newEncryptedData;
$this->DecryptData();
}// Encrypt datapublic function LoadPlainDataAndEncrypt($newCardHolder, $newCardNumber,
$newIssueDate, $newExpiryDate,
$newIssueNumber, $newCardType){
$this->_mCardHolder = $newCardHolder;
$this->_mCardNumber = $newCardNumber;
$this->_mIssueDate = $newIssueDate;
Trang 3{// Encode card details as XML document
Trang 4// Extract information from XML credit card dataprivate function ExtractXml($decryptedData){
$xml = simplexml_load_string($decryptedData);
$this->_mCardHolder = (string) $xml->CardHolder;
$this->_mCardNumber = (string) $xml->CardNumber;
$this->_mIssueDate = (string) $xml->IssueDate;
$this->_mExpiryDate = (string) $xml->ExpiryDate;
$this->_mIssueNumber = (string) $xml->IssueNumber;
$this->_mCardType = (string) $xml->CardType;
}// Encrypts the XML credit card dataprivate function EncryptData(){
// Put data into XML doc
$this->CreateXml();
// Encrypt data
$this->_mEncryptedData =SymmetricCrypt::Encrypt($this->_mXmlCardData->saveXML());
// Set encrypted flag
$this->_mIsEncrypted = true;
}// Decrypts XML credit card dataprivate function DecryptData(){
// Decrypt data
$decrypted_data = SymmetricCrypt::Decrypt($this->_mEncryptedData);// Extract data from XML
$this->ExtractXml($decrypted_data);
// Set decrypted flag
$this->_mIsDecrypted = true;
}public function get($name){
if ($name == 'EncryptedData'){
if ($this->_mIsEncrypted)return $this->_mEncryptedData;
elsethrow new Exception('Data not encrypted');
}
Trang 5elseif ($name == 'CardNumberX'){
if ($this->_mIsDecrypted)return 'XXXX-XXXX-XXXX-' substr($this->_mCardNumber, strlen($this->_mCardNumber) - 4, 4);
elsethrow new Exception('Data not decrypted');
}elseif (in_array($name, array ('CardHolder', 'CardNumber', 'IssueDate',
'ExpiryDate', 'IssueNumber', 'CardType'))){
$name = '_m' $name;
if ($this->_mIsDecrypted)return $this->$name;
elsethrow new Exception('Data not decrypted');
}else{throw new Exception('Property ' $name ' not found');
}}}
?>
2 Create a new file named test_card.php file in the tshirtshop folder:
<?phprequire_once 'include/config.php';
require_once BUSINESS_DIR 'symmetric_crypt.php';
require_once BUSINESS_DIR 'secure_card.php';
$card_holder = 'John Doe';
Trang 6$credit_card->LoadPlainDataAndEncrypt($card_holder, $card_number,
$issue_date, $expiry_date, $issue_number, $card_type);
$encrypted_data = $credit_card->EncryptedData;
}catch(Exception $e){
echo '<font color="red">Exception: ' $e->getMessage() '</font>';
exit();
}echo '<br />Encrypted data:<br />' $encrypted_data '<br />';
$our_card = new SecureCard();
try{
echo '<font color="red">Exception: ' $e->getMessage() '</font>';
exit();
}
?>
3 Load test_card.php file in your favorite browser to see the results (see Figure 16-3) You can change the
data from this file as you want
Trang 7Figure 16-3. Encrypting and decrypting credit card information
How It Works: The SecureCard Class
There’s a bit more code here than in previous examples, but it’s all quite simple First you have the private member
variables to hold the card details as individual strings, as an encrypted string, and in an intermediate XML
docu-ment You also have Boolean flags indicating whether the data has been successfully encrypted or decrypted:
Next you have two important public methods Public members are part of the public interface of the class, which
provides the functionality for external clients LoadEncryptedDataAndDecrypt() receives an encrypted string
and performs the decryption; LoadPlainDataAndEncrypt() receives the credit card data in plain format and
encrypts it:
Trang 8// Decrypt datapublic function LoadEncryptedDataAndDecrypt($newEncryptedData){
$this->_mEncryptedData = $newEncryptedData;
$this->DecryptData();
}// Encrypt datapublic function LoadPlainDataAndEncrypt($newCardHolder, $newCardNumber,
$newIssueDate, $newExpiryDate,
$newIssueNumber, $newCardType){
to shortly First you have two utility methods for packaging and unpackaging data in XML format (which makes iteasier to get at the bits you want when exchanging data with the encrypted format)
XML is a very powerful, tag-based format in which you can store various kinds of information The SecureCardclass stores a customer’s credit card data in a structure like the following:
■ Tip The World Wide Web Consortium manages the DOM standard; its official web page is
http://www.w3.org/DOM/
Trang 9With the new PHP 5 DOM extension, reading, creating, editing, saving, and searching XML documents from PHP
has never been easier The DOM extension in PHP 5 was entirely rewritten from scratch to fully comply with the
DOM specifications You can see this extension in action in the CreateXml() method, which creates an XML
document with the structure shown earlier by creating nodes and setting their values:
// Create XML with credit card informationprivate function CreateXml()
{// Encode card details as XML document
preferred to use a new and unique feature of PHP 5 called SimpleXML Although less complex and powerful than
DOMDocument, the SimpleXML extension makes parsing XML data a piece of cake by transforming it into a data
structure you can simply iterate through:
// Extract information from XML credit card dataprivate function ExtractXml($decryptedData){
$xml = simplexml_load_string($decryptedData);
$this->_mCardHolder = (string) $xml->CardHolder;
$this->_mCardNumber = (string) $xml->CardNumber;
$this->_mIssueDate = (string) $xml->IssueDate;
$this->_mExpiryDate = (string) $xml->ExpiryDate;
$this->_mIssueNumber = (string) $xml->IssueNumber;
$this->_mCardType = (string) $xml->CardType;
}The EncryptData() method starts by using the CreateXml() method to package the details supplied in the
SecureCard constructor into XML format:
// Encrypts the XML credit card dataprivate function EncryptData(){
// Put data into XML doc
$this->CreateXml();
Trang 10Next, the XML string contained in the resultant XML document is encrypted into a single string and stored in the
$_mEncryptedData member:
// Encrypt data
$this->_mEncryptedData =SymmetricCrypt::Encrypt($this->_mXmlCardData->saveXML());
Finally, the $_mIsEncrypted flag is set to true to indicate that the credit card data has been encrypted:// Set encrypted flag
$this->_mIsEncrypted = true;
}The DecryptData() method gets the XML credit card data from its encrypted form, decrypts it, and populatesclass attributes with the ExtractXml() method:
// Decrypts XML credit card dataprivate function DecryptData(){
is called automatically whenever you try to call a method or read a member that isn’t defined in the class Take, forexample, this code snippet:
$card = new SecureCard();
$encrypted = $card->EncryptedData;
Because there’s no member named EncryptedData in the SecureCard class, the get() function is called
In get(), you can check which property is accessed, and you can include code that returns the value for thatproperty This technique is particularly useful when you want to define “virtual” members of the class whose val-ues need to be calculated on the spot as an alternative to using get functions such as GetEncryptedData()
In our case, the get() function handles eight “virtual” members The first is EncryptedData, whose value isreturned only if $_mIsEncrypted is true:
public function get($name){
if ($name == 'EncryptedData'){
if ($this->_mIsEncrypted)return $this->_mEncryptedData;
Trang 11elsethrow new Exception('Data not encrypted');
}Then there’s CardNumberX, which needs to return a version of the card number where all digits are obfuscated
(replaced with X) except the last four This is handy when showing a user existing details and is becoming
stan-dard practice because it lets customers know what card they have stored without exposing the details to prying
eyes:
elseif ($name == 'CardNumberX'){
if ($this->_mIsDecrypted)return 'XXXX-XXXX-XXXX-' substr($this->_mCardNumber, strlen($this->_mCardNumber) - 4, 4);
elsethrow new Exception('Data not decrypted');
}The last six properties (CardHolder, CardNumber, IssueDate, ExpiryDate, IssueNumber, and CardType)
are handled in a single block:
elseif (in_array($name, array ('CardHolder', 'CardNumber', 'IssueDate',
'ExpiryDate', 'IssueNumber', 'CardType'))){
$name = '_m' $name;
if ($this->_mIsDecrypted)return $this->$name;
elsethrow new Exception('Data not decrypted');
}else{throw new Exception('Property ' $name ' not found');
}}Note that in all cases, the data is accessible only when $_mIsDecrypted is true; otherwise, an exception is
thrown
Also, note that the data isn’t accessible after encryption—the data used to initialize a SecureCard object is
accessi-ble only in encrypted form This is more a use-case decision than anything else because this class is really intended
for encryption and decryption only, not for persistently representing credit card details After a SecureCard instance
has been used to encrypt card details, we shouldn’t subsequently need access to the unencrypted data, only the
encrypted string
Trang 12■ Note Before moving on to the client code, it is worth explaining and emphasizing one important designconsideration that you have probably already noticed At no point are any of the card details validated Infact, this class will work perfectly well with empty strings for any properties This is so the class can remain
as versatile as possible It is more likely that credit card details will be validated as part of the UI used toenter them, or even not at all This isn’t at all dangerous—if invalid details are used, then the credit cardtransaction will simply fail, and we handle that using very similar logic to that required when dealing with
a lack of funds (that is, we notify the customer of failure and ask them to try another card) Of course, thereare also simple data-formatting issues (dates are usually MM/YY, for example), but as noted, these can bedealt with externally to the SecureCardclass
The test page (test_card.php) for this class simply allows you to see how an encrypted card looks As you cansee, quite a lot of data is generated, which is the reason for the rather large column size in the customer database.You can also see that both encryption and decryption are working perfectly, so you can now move on to the cus-tomer account section of this chapter
Adding Customer Accounts Functionality to
Figure 16-4. TShirtShop with a login box
Trang 13The new user registration page looks like Figure 16-5.
Figure 16-5. The new user registration page in TShirtShop
After the user logs in to the site, a new componentized template displays the logged-inuser’s name and a number of links for manipulating the user’s account (see Figure 16-6)
Figure 16-6. Sample TShirtShop page for a logged-in user
Trang 14Clicking the Add CC Details link leads the user to the page shown in Figure 16-7.
Figure 16-7. Adding credit card information
A similar form will be shown to the user when clicking the Add Address link When the useralready has a credit card and an address listed, the Add links in the Welcome box change intoChange links
You’ll start implementing the new functionality by writing the data tier code that will port the UI
sup-Implementing the Data Tier
You’ll create the usual data tier stored procedures supporting customer accounts functionality
in the following exercise, and we’ll comment on each one
Exercise: Creating the Database Functions
1 Use phpMyAdmin to create the stored procedures described in the following steps Don’t forget to set the
$$ delimiter before executing the code of each step
2 Execute this code, which creates the customer_get_login_info stored procedure in your tshirtshop
database:
Create customer_get_login_info stored procedureCREATE PROCEDURE customer_get_login_info(IN inEmail VARCHAR(100))BEGIN
SELECT customer_id, password FROM customer WHERE email = inEmail;
END$$
Trang 15When a user logs in to the site, you must check the user’s password The customer_get_login_infostored procedure returns the customer ID and the hashed password for a user with a specific e-mail.
3 Execute the following code, which creates the customer_add stored procedure in your tshirtshop
SELECT customer_id, name, email, password, credit_card,address_1, address_2, city, region, postal_code, country,shipping_region_id, day_phone, eve_phone, mob_phoneFROM customer
WHERE customer_id = inCustomerId;
END$$
The customer_get_customer stored procedure returns full customer details for a given customer ID
5 Execute the following code, which creates the customer_update_account stored procedure in your
tshirtshop database:
Create customer_update_account stored procedureCREATE PROCEDURE customer_update_account(IN inCustomerId INT,
IN inName VARCHAR(50), IN inEmail VARCHAR(100),
IN inPassword VARCHAR(50), IN inDayPhone VARCHAR(100),
IN inEvePhone VARCHAR(100), IN inMobPhone VARCHAR(100))BEGIN
UPDATE customerSET name = inName, email = inEmail,password = inPassword, day_phone = inDayPhone,eve_phone = inEvePhone, mob_phone = inMobPhoneWHERE customer_id = inCustomerId;
END$$
The customer_update_account stored procedure updates the customer’s account details in the database
Trang 166 Execute this code, which creates the customer_update_credit_card stored procedure in your
END$$
The customer_update_credit_card stored procedure updates the customer’s credit card information inthe database It updates only the credit_card column for the customer, which contains the encrypted ver-sion of the XML document containing the customer’s complete credit card details
7 Execute the following code, which creates the customer_get_shipping_regions stored procedure in
your tshirtshop database:
Create customer_get_shipping_regions stored procedureCREATE PROCEDURE customer_get_shipping_regions()
BEGINSELECT shipping_region_id, shipping_region FROM shipping_region;
IN inAddress1 VARCHAR(100), IN inAddress2 VARCHAR(100),
IN inCity VARCHAR(100), IN inRegion VARCHAR(100),
IN inPostalCode VARCHAR(100), IN inCountry VARCHAR(100),
IN inShippingRegionId INT)BEGIN
UPDATE customerSET address_1 = inAddress1, address_2 = inAddress2, city = inCity,region = inRegion, postal_code = inPostalCode,
country = inCountry, shipping_region_id = inShippingRegionIdWHERE customer_id = inCustomerId;
END$$
The customer_update_address stored procedure updates the customer’s address in the database
Trang 17Implementing the Business Tier
In the business folder, create a new file named customer.php that will contain the Customer
class The Customer class is a little longer and mostly accesses the data tier functionality to
respond to requests that come from the presentation tier Write the following code in the
if (!(isset ($_SESSION['tshirtshop_customer_id'])))return 0;
elsereturn 1;
}// Returns customer_id and password for customer with email $emailpublic static function GetLoginInfo($email)
{// Build the SQL query
$sql = 'CALL customer_get_login_info(:email)';
// Build the parameters array
$params = array (':email' => $email);
// Execute the query and return the resultsreturn DatabaseHandler::GetRow($sql, $params);
}public static function IsValid($email, $password){
$customer = self::GetLoginInfo($email);
if (empty ($customer['customer_id']))return 2;
$customer_id = $customer['customer_id'];
$hashed_password = $customer['password'];
Trang 18if (PasswordHasher::Hash($password) != $hashed_password)return 1;
else{
$_SESSION['tshirtshop_customer_id'] = $customer_id;
return 0;
}}public static function Logout(){
unset($_SESSION['tshirtshop_customer_id']);
}public static function GetCurrentCustomerId(){
if (self::IsAuthenticated())return $_SESSION['tshirtshop_customer_id'];
elsereturn 0;
}/* Adds a new customer account, log him in if $addAndLogin is trueand returns customer_id */
public static function Add($name, $email, $password, $addAndLogin = true){
$hashed_password = PasswordHasher::Hash($password);
// Build the SQL query
$sql = 'CALL customer_add(:name, :email, :password)';
// Build the parameters array
$params = array (':name' => $name, ':email' => $email,
':password' => $hashed_password);
// Execute the query and get the customer_id
$customer_id = DatabaseHandler::GetOne($sql, $params);
if ($addAndLogin)
$_SESSION['tshirtshop_customer_id'] = $customer_id;
return $customer_id;
}
Trang 19public static function Get($customerId = null){
if (is_null($customerId))
$customerId = self::GetCurrentCustomerId();
// Build the SQL query
$sql = 'CALL customer_get_customer(:customer_id)';
// Build the parameters array
$params = array (':customer_id' => $customerId);
// Execute the query and return the resultsreturn DatabaseHandler::GetRow($sql, $params);
}public static function UpdateAccountDetails($name, $email, $password,
$dayPhone, $evePhone, $mobPhone,
$customerId = null){
if (is_null($customerId))
$customerId = self::GetCurrentCustomerId();
$hashed_password = PasswordHasher::Hash($password);
// Build the SQL query
$sql = 'CALL customer_update_account(:customer_id, :name, :email,
:password, :day_phone, :eve_phone, :mob_phone)';
// Build the parameters array
$params = array (':customer_id' => $customerId, ':name' => $name,
':email' => $email, ':password' => $hashed_password,':day_phone' => $dayPhone, ':eve_phone' => $evePhone,':mob_phone' => $mobPhone);
// Execute the queryDatabaseHandler::Execute($sql, $params);
}public static function DecryptCreditCard($encryptedCreditCard){
$secure_card = new SecureCard();
$secure_card->LoadEncryptedDataAndDecrypt($encryptedCreditCard);
$credit_card = array();
$credit_card['card_holder'] = $secure_card->CardHolder;
$credit_card['card_number'] = $secure_card->CardNumber;
Trang 20$customer_data = self::Get();
if (!(empty ($customer_data['credit_card'])))return self::DecryptCreditCard($customer_data['credit_card']);
elsereturn array('card_holder' => '', 'card_number' => '',
'issue_date' => '', 'expiry_date' => '','issue_number' => '', 'card_type' => '','card_number_x' => '');
}public static function UpdateCreditCardDetails($plainCreditCard,
$customerId = null){
// Build the SQL query
$sql = 'CALL customer_update_credit_card(:customer_id, :credit_card)';// Build the parameters array
$params = array (':customer_id' => $customerId,
':credit_card' => $encrypted_card);
// Execute the queryDatabaseHandler::Execute($sql, $params);
}
Trang 21public static function GetShippingRegions(){
// Build the SQL query
$sql = 'CALL customer_get_shipping_regions()';
// Execute the query and return the resultsreturn DatabaseHandler::GetAll($sql);
}public static function UpdateAddressDetails($address1, $address2, $city,
$region, $postalCode, $country,
$shippingRegionId, $customerId = null){
if (is_null($customerId))
$customerId = self::GetCurrentCustomerId();
// Build the SQL query
$sql = 'CALL customer_update_address(:customer_id, :address_1,
:address_2, :city, :region, :postal_code, :country,:shipping_region_id)';
// Build the parameters array
$params = array (':customer_id' => $customerId,
':address_1' => $address1, ':address_2' => $address2,':city' => $city, ':region' => $region,
':postal_code' => $postalCode,':country' => $country,':shipping_region_id' => $shippingRegionId);
// Execute the queryDatabaseHandler::Execute($sql, $params);
}}
?>
Implementing the Presentation Tier
The presentation tier for the TShirtShop customer account system consists of the following
componentized templates:
customer_login: This is the login box
customer_logged: After a user is logged, this componentized template takes the place ofthe customer_login componentized template to show the current logged-in user and dis-plays account management and logout links
customer_details: This is for registering a new user or for editing the basic details of anexisting user
Trang 22customer_address: This allows a user to add/edit address information.
customer_credit_card: This allows a user to add/edit credit card information
Now, take a deep breath, and follow the steps of the next exercise to implement these newcomponentized templates; we’re nearly there!
Exercise: Implementing the Componentized Templates
1 Create a new template file named customer_login.tpl in the presentation/templates folder, and
add the following code to it:
{* customer_login.tpl *}
{load_presentation_object filename="customer_login" assign="obj"}
<div class="box">
<p class="box-title">Login</p>
<form method="post" action="{$obj->mLinkToLogin}">
{if $obj->mErrorMessage}<p class="error">{$obj->mErrorMessage}</p>{/if}
<p>
<label for="email">E-mail address:</label>
<input type="text" maxlength="50" name="email" size="22"
<input type="submit" name="Login" value="Login" /> |
<a href="{$obj->mLinkToRegisterCustomer}">Register user</a>
</p>
</form>
</div>
2 Create a new presentation object file named customer_login.php in the presentation folder, and add
the following to it:
<?phpclass CustomerLogin{
// Public stuffpublic $mErrorMessage;
public $mLinkToLogin;
public $mLinkToRegisterCustomer;
public $mEmail = '';
Trang 23// Class constructorpublic function construct(){
if (USE_SSL == 'yes' && getenv('HTTPS') != 'on')
$this->mLinkToLogin =Link::Build(str_replace(VIRTUAL_LOCATION, '', getenv('REQUEST_URI')),
'https');
else
$this->mLinkToLogin =Link::Build(str_replace(VIRTUAL_LOCATION, '', getenv('REQUEST_URI')));
$this->mLinkToRegisterCustomer = Link::ToRegisterCustomer();
}public function init(){
// Decide if we have submitted
if (isset ($_POST['Login'])){
// Get login status
$login_status = Customer::IsValid($_POST['email'], $_POST['password']);
switch ($login_status){
getenv('REQUEST_URI')));
header('Location:' $redirect_to_link);
exit();
}}}}
?>
Trang 243 Create a new template file named customer_logged.tpl in the presentation/templates folder, and
add the following code to it:
4 Create a new presentation object file named customer_logged.php in the presentation folder, and
add the following to it:
<?phpclass CustomerLogged{
// Public attributespublic $mCustomerName;
public $mCreditCardAction = 'Add';
public $mAddressAction = 'Add';
Trang 25// Class constructorpublic function construct(){
if (isset ($_GET['Logout'])){
?>
5 Create a new template file named customer_details.tpl in the presentation/templates folder,
and add the following code to it:
{* customer_details.tpl *}
{load_presentation_object filename="customer_details" assign="obj"}
<form method="post" action="{$obj->mLinkToAccountDetails}">
<h2>Please enter your details:</h2>
<table class="customer-table">
Trang 26<td>E-mail Address:</td>
<td>
<input type="text" name="email" value="{$obj->mEmail}"
{if $obj->mEditMode}readonly="readonly"{/if} size="32" />
Trang 276 Create a new presentation object file named customer_details.php in the presentation folder, and
add the following to it:
<?phpclass CustomerDetails{
// Public attributespublic $mEditMode = 0;
public $mEmail;
public $mName;
public $mPassword;
public $mDayPhone = null;
public $mEvePhone = null;
public $mMobPhone = null;
Trang 28// Private attributesprivate $_mErrors = 0;
// Class constructorpublic function construct(){
// Check if we have new user or editing existing customer details
// Name cannot be empty
if (empty ($_POST['name'])){
$this->mNameError = 1;
$this->_mErrors++;
}else
$this->mEmail = $_POST['email'];
// Password cannot be empty
if (empty ($_POST['password'])){
$this->mPasswordError = 1;
$this->_mErrors++;
}
Trang 29$this->mPassword = $_POST['password'];
// Password confirm cannot be empty
if (empty ($_POST['passwordConfirm'])){
$this->mPasswordConfirmError = 1;
$this->_mErrors++;
}else
$password_confirm = $_POST['passwordConfirm'];
// Password and password confirm should be the same
if (!isset ($password_confirm) ||
$this->mPassword != $password_confirm){
$this->mPasswordMatchError = 1;
$this->_mErrors++;
}
if ($this->mEditMode == 1){
// If we have submitted data and no errors in submitted data
if ((isset ($_POST['sended'])) && ($this->_mErrors == 0)){
// Check if we have any customer with submitted email
$this->mEmailAlreadyTaken = 1;
Trang 30}// We have a new user or we are updating an existing user's details
if ($this->mEditMode == 0)Customer::Add($this->mName, $this->mEmail, $this->mPassword);
elseCustomer::UpdateAccountDetails($this->mName, $this->mEmail,
$this->mPassword, $this->mDayPhone, $this->mEvePhone,
?>
7 Create a new template file named customer_address.tpl in the presentation/templates folder,
and add the following code to it:
{* customer_address.tpl *}
{load_presentation_object filename="customer_address" assign="obj"}
<form method="post" action="{$obj->mLinkToAddressDetails}">
<h2>Please enter your address details:</h2>
Trang 328 Create a new presentation object file named customer_address.php in the presentation folder, and
add the following to it:
<?phpclass CustomerAddress{
// Public attributespublic $mAddress1 = '';
// Class constructorpublic function construct(){
Trang 33// Set form action target
// Address 1 cannot be empty
if (empty ($_POST['address1'])){
$this->mAddress1Error = 1;
$this->_mErrors++;
}else
$this->mAddress1 = $_POST['address1'];
if (isset ($_POST['address2']))
$this->mAddress2 = $_POST['address2'];
if (empty ($_POST['city'])){
$this->mCityError = 1;
$this->_mErrors++;
}else
$this->mCity = $_POST['city'];
if (empty ($_POST['region'])){
$this->mRegionError = 1;
$this->_mErrors++;
}else
$this->mRegion = $_POST['region'];
if (empty ($_POST['postalCode'])){
$this->mPostalCodeError = 1;
$this->_mErrors++;
}else
$this->mPostalCode = $_POST['postalCode'];
Trang 34if (empty ($_POST['country'])){
$this->mCountryError = 1;
$this->_mErrors++;
}else
$this->mCountry = $_POST['country'];
if ($_POST['shippingRegion'] == 1){
$this->mShippingRegionError = 1;
$this->_mErrors++;
}else
$this->mShippingRegion = $_POST['shippingRegion'];
}}public function init(){
$customer_data = Customer::Get();
if (!(empty ($customer_data))){
}elseif ($this->_mErrors == 0){
Customer::UpdateAddressDetails($this->mAddress1, $this->mAddress2,
$this->mCity, $this->mRegion, $this->mPostalCode,
$this->mCountry, $this->mShippingRegion);
Trang 35header('Location:' $this->mLinkToCancelPage);
exit();
}}}
?>
9 Create a new template file named customer_credit_card.tpl in the presentation/templates
folder, and add the following code to it:
{* customer_credit_card.tpl *}
{load_presentation_object filename="customer_credit_card" assign="obj"}
<form method="post" action="{$obj->mLinkToCreditCardDetails}">
<h2>Please enter your credit card details:</h2>
Trang 3610 Create a new presentation object file named customer_credit_card.php in the presentation folder,
and add the following to it:
<?phpclass CustomerCreditCard{
// Public attributespublic $mCardHolderError;
Trang 37public function construct(){
$this->mPlainCreditCard = array('card_holder' => '','card_number' => '', 'issue_date' => '', 'expiry_date' => '','issue_number' => '', 'card_type' => '', 'card_number_x' => '');
// Set form action target
'American Express' => 'American Express');
// Check if we have submitted data
if (isset ($_POST['sended'])){
// Initialization/validation stuff
if (empty ($_POST['cardHolder'])){
$this->mCardHolderError = 1;
$this->_mErrors++;
}else
$this->mPlainCreditCard['card_holder'] = $_POST['cardHolder'];
if (empty ($_POST['cardNumber'])){
$this->mCardNumberError = 1;
$this->_mErrors++;
}else
$this->mPlainCreditCard['card_number'] = $_POST['cardNumber'];
if (empty ($_POST['expDate'])){
$this->mExpDateError = 1;
$this->_mErrors++;
}else
$this->mPlainCreditCard['expiry_date'] = $_POST['expDate'];