Exercise: Implementing the Order Pipeline Classes

Một phần của tài liệu Beginning PHP and Postgre SQL E-Commerce From Novice to Professional phần 9 ppt (Trang 38 - 50)

1. First modify business/ps_check_funds.phpto work with DataCash:

<?php

class PsCheckFunds implements IPipelineSection {

public function Process($processor) {

// Audit

$processor->CreateAudit('PsCheckFunds started.', 20100);

$order_total_cost = $processor->mOrderInfo['total_amount'];

$order_total_cost += $processor->mOrderInfo['shipping_cost'];

$order_total_cost +=

round((float)$order_total_cost *

(float)$processor->mOrderInfo['tax_percentage'], 2) / 100.00;

$request = new DataCashRequest(DATACASH_URL);

$request->MakeXmlPre(DATACASH_CLIENT, DATACASH_PASSWORD,

$processor->mOrderInfo['order_id'] + 1000006,

$order_total_cost, 'GBP', 'pre',

$processor->mCustomerInfo['credit_card']->CardNumber,

$processor->mCustomerInfo['credit_card']->ExpiryDate,

$processor->mCustomerInfo['credit_card']->IssueDate,

$processor->mCustomerInfo['credit_card']->IssueNumber);

$responseXml = $request->GetResponse();

$xml = simplexml_load_string($responseXml);

if ($xml->status == 1) {

$processor->SetAuthCodeAndReference(

$xml->merchantreference, $xml->datacash_reference);

// Audit

$processor->CreateAudit('Funds available for purchase.', 20102);

// Update order status

$processor->UpdateOrderStatus(2);

// Continue processing

$processor->mContinueNow = true;

} else {

// Audit

$processor->CreateAudit('Funds not available for purchase.', 20103);

throw new Exception('Credit card check funds failed for order ' .

$processor->mOrderInfo['order_id'] . "\n\n" . 'Data exchanged:' . "\n" .

$request->GetResponse() . "\n" . $responseXml);

} // Audit

$processor->CreateAudit('PsCheckFunds finished.', 20101);

} }

?>

2. Modify the business/ps_take_payment.phpfile as follows:

<?php

class PsTakePayment implements IPipelineSection {

public function Process($processor) {

// Audit

$processor->CreateAudit('PsTakePayment started.', 20400);

$request = new DataCashRequest(DATACASH_URL);

$request->MakeXmlFulFill(DATACASH_CLIENT, DATACASH_PASSWORD, 'fulfill',

$processor->mOrderInfo['auth_code'],

$processor->mOrderInfo['reference']);

$responseXml = $request->GetResponse();

$xml = simplexml_load_string($responseXml);

if ($xml->status == 1) {

// Audit

$processor->CreateAudit(

'Funds deducted from customer credit card account.', 20402);

// Update order status

$processor->UpdateOrderStatus(5);

// Continue processing

$processor->mContinueNow = true;

} else {

// Audit

$processor->CreateAudit('Could not deduct funds from credit card.', 20403);

throw new Exception('Credit card take payment failed for order ' .

$processor->mOrderInfo['order_id'] . "\n\n" . 'Data exchanged:' . "\n" .

$request->GetResponse() . "\n" . $responseXml);

} // Audit

$processor->CreateAudit('PsTakePayment finished.', 20401);

} }

?>

3. Add a reference to the business/datacash_request.phpfile in include/app_top.phpas high- lighted:

require_once BUSINESS_DIR . 'ps_ship_ok.php';

require_once BUSINESS_DIR . 'ps_final_notification.php';

require_once BUSINESS_DIR . 'datacash_request.php';

Testing DataCash Integration

Now that you have all this in place, it’s important to test with a few orders. You can do this easily by making sure you create a customer with “magic” credit card details. As mentioned earlier in the chapter, DataCash supplies these numbers for testing purposes and to obtain specific responses from DataCash. A sample of these numbers is shown in Table 15-2; a full list is available on the DataCash web site.

Table 15-2.DataCash Credit Card Test Numbers

Card Type Card Number Return Code Description Sample Message Switch 4936000000000000001 1 Authorized with AUTH CODE ??????

random auth code.

4936000000000000019 7 Decline the DECLINED

transaction.

6333000000000005 1 Authorized with AUTH CODE ??????

random auth code.

6333000000000013 7 Decline the DECLINED

transaction.

6333000000123450 1 Authorized with AUTH CODE ??????

random auth code.

Visa 4242424242424242 7 Decline the DECLINED

transaction.

4444333322221111 1 Authorized with AUTH CODE ??????

random auth code.

4546389010000131 1 Authorized with AUTH CODE ??????

random auth code.

At this moment, you can experiment with your new fully featured e-commerce web site by placing orders with the test credit card numbers, checking the emails the web site sends, and finding out how it reacts in certain situation, such as how it logs errors, how orders are administered using the orders administration page, and so on.

Going Live

Moving from the test account to the live one is now simply a matter of replacing the DataCash login info in include/config.php. After you set up a merchant bank account, you can use the new details to set up a new DataCash account, obtaining new client and password data along the way. You also need to change the URL for the DataCash server that you send data to

because it needs to be the production server instead of the testing server. Other than removing the test user accounts from the database and moving your web site to an Internet location (see Appendix B for more details), this is all you need to do before exposing your newly completed e-commerce application to customers.

Working with Authorize.net

To use Authorize.net, you need to sign up for a developer test account via http://developer.

authorize.net/testaccount/. The main page where developers can get information on Authorize.net integration is http://developer.authorize.net/.

Communicating with Authorize.net is different from communicating with DataCash.

Instead of sending and receiving XML files, you send strings consisting of name-value pairs, separated by ampersands. Effectively, you use a similar syntax to query strings appended to URLs.

Authorize.net returns the transaction results in the form of a string that contains the return values (without their names) separated by a character that you specify when making the initial request. In our examples, we’ll use the pipe (|) character. The return values come in a predetermined order, and their significance is given by their position in the returned string.

Note The complete documentation for the Authorize.net API can be found in the Advanced Integration Method (AIM) Implementation Guide Card-Not-Present Transactions at http://www.authorize.net/

support/AIM_guide.pdf. Even more documents are available in the document library at http://www.authorize.net/resources/documentlibrary/.

The default transaction type is AUTH_CAPTURE, where you request and deduct the funds from the credit card using a single request. For HatShop, we’ll use two other transaction types: AUTH_ONLY, which checks if the necessary funds are available (this happened in the PsCheckFundspipeline stage), and PRIOR_AUTH_CAPTURE, which deducts the amount of money that was previously checked using AUTH_ONLY(this happens in the PsTakePaymentpipeline stage).

To perform an AUTH_ONLYtransaction, you’ll first create an array such as the following, which contains the necessary transaction data.

// Auth

$transaction = array ('x_invoice_num' => '99999', // Invoice number 'x_amount' => '45.99', // Amount

'x_card_num' => '4007000000027', // Credit card number 'x_exp_date' => '1209', // Expiration date

'x_method' => 'CC', // Payment method

'x_type' => 'AUTH_ONLY'); // Transaction type

For PRIOR_AUTH_CAPTUREtransactions, you don’t need to specify all this information again;

instead, you only need to pass the transaction ID that was returned in response of the AUTH_ONLYrequest.

// Capture

$transaction = array (

'x_ref_trans_id' => $ref_trans_id, // Transaction id 'x_method' => 'CC', // Payment method

'x_type' => 'PRIOR_AUTH_CAPTURE'); // Transaction type

We’ll transform these arrays into a string of name-value pairs and submit them to the Authorize.net server. The response comes in the form of a string whose values are separated by a configurable character. In Figure 15-3, you can see a sample response for an AUTH_ONLY request (left part of the window) and a sample response for a PRIOR_AUTH_CAPTURErequest (right part of the window).

We’ll write a simple test with this transaction type before implementing any modifica- tions to HatShop. Follow the steps in the exercise to test Authorize.net.

Exercise: Testing Authorize.net

1. Create a new file named authorize_net_request.phpin the businessfolder, and add the following code to it:

<?php

class AuthorizeNetRequest {

// Authorize Server URL private $_mUrl;

// Will hold the current request to be sent to Authorize.net private $_mRequest;

// Constructor initializes the class with URL of Authorize.net public function __construct($url)

{

// Authorize.net URL

$this->_mUrl = $url;

}

public function SetRequest($request) {

$this->_mRequest = '';

$request_init = array ('x_login' => AUTHORIZE_NET_LOGIN_ID, 'x_tran_key' =>

AUTHORIZE_NET_TRANSACTION_KEY, 'x_version' => '3.1',

'x_test_request' => AUTHORIZE_NET_TEST_REQUEST, 'x_delim_data' => 'TRUE',

'x_delim_char' => '|', 'x_relay_response' => 'FALSE');

$request = array_merge($request_init, $request);

foreach($request as $key => $value )

$this->_mRequest .= $key . '=' . urlencode($value) . '&';

}

// Send an HTTP POST request to Authorize.net using CURL public function GetResponse()

{

// Initialize a CURL session

$ch = curl_init();

// Prepare for an HTTP POST request curl_setopt($ch, CURLOPT_POST, 1);

// Prepare the request to be POSTed

curl_setopt($ch, CURLOPT_POSTFIELDS, rtrim($this->_mRequest, '& '));

// Set the URL where we want to POST our data curl_setopt($ch, CURLOPT_URL, $this->_mUrl);

/* Do not verify the Common name of the peer certificate in the SSL handshake */

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

// Prevent CURL from verifying the peer's certificate curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

/* We want CURL to directly return the transfer instead of printing it */

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// Perform a CURL session

$result = curl_exec($ch);

// Close a CURL session curl_close ($ch);

// Return the response return $result;

} }

?>

2. Add the following at the end of the include/config.phpfile, modifying the constant data with the details of your Authorize.net account:

// Constant definitions for authorize.net

define('AUTHORIZE_NET_URL', 'https://test.authorize.net/gateway/transact.dll');

define('AUTHORIZE_NET_LOGIN_ID', '[Your Login ID]');

define('AUTHORIZE_NET_TRANSACTION_KEY', '[Your Transaction Key]');

define('AUTHORIZE_NET_TEST_REQUEST', 'FALSE');

3. Add the following test_authorize_net.phptest file in your site root folder:

<?php

session_start();

if (empty ($_GET['step'])) {

require_once 'include/config.php';

require_once BUSINESS_DIR . 'authorize_net_request.php';

$request = new AuthorizeNetRequest(AUTHORIZE_NET_URL);

// Auth

$transaction = array ('x_invoice_num' => '99999', // Invoice number 'x_amount' => '45.99', // Amount

'x_card_num' => '4007000000027', // Credit card no 'x_exp_date' => '1209', // Expiration date

'x_method' => 'CC', // Payment method

'x_type' => 'AUTH_ONLY'); // Transaction type

$request->SetRequest($transaction);

$auth_only_response = $request->GetResponse();

$_SESSION['auth_only_response'] = $auth_only_response;

$auth_only_response = explode('|', $auth_only_response);

// Read the transaction ID, which will be necessary for taking the payment

$ref_trans_id = $auth_only_response[6];

// Capture

$transaction = array ('x_ref_trans_id' => $ref_trans_id, // Transaction id 'x_method' => 'CC', // Payment method

'x_type' => 'PRIOR_AUTH_CAPTURE'); //

Transaction type

$request->SetRequest($transaction);

$prior_auth_capture_response = $request->GetResponse();

$_SESSION['prior_auth_capture_response'] = $prior_auth_capture_response;

} else {

switch ($_GET['step']) {

case 1:

print $_SESSION['auth_only_response'];

break;

case 2:

print $_SESSION['prior_auth_capture_response'];

break;

} exit;

}

?>

<frameset cols="50%, 50%">

<frame src="test_authorize_net.php?step=1">

<frame src="test_authorize_net.php?step=2">

</frameset>

4. Load the test_authorize_net.phppage in your favorite browser to see the results (see Figure 15-3).

Figure 15-3.Authorize.net transaction results

5. Go to Authorize.net, log in to Merchant Interface (https://test.authorize.net/), and you can see the transaction you just performed in the Unsettled Transactions section under the Search tab. This report is shown in Figure 15-4.

Figure 15-4.Authorize.net Unsettled Transactions

How It Works: Authorize.net Transactions

The hard work is done by the AuthorizeNetRequestclass, which has two important methods:SetRequestis used to set up transaction details, and GetResponseis used to send the request to, and retrieve the response from, Authorize.net. The following code snippet shows how they are used:

// Auth

$transaction = array ('x_invoice_num' => '99999', // Invoice number 'x_amount' => '45.99', // Amount

'x_card_num' => '4007000000027', // Credit card number 'x_exp_date' => '1209', // Expiration date

'x_method' => 'CC', // Payment method

'x_type' => 'AUTH_ONLY'); // Transaction type

$request->SetRequest($transaction);

$response = $request->GetResponse();

Note The credit card data mentioned in this transaction is one of the “magic card numbers” provided by Authorize.net for testing purposes. Review the AIM Implementation Guide for the complete list of such credit card numbers.

We send an array with transaction details as a parameter to SetRequest.SetRequestthen joins this array with another array that contains the Authorize.net account details:

public function SetRequest($request) {

$this->_mRequest = '';

$request_init = array ('x_login' => AUTHORIZE_NET_LOGIN_ID, 'x_tran_key' => AUTHORIZE_NET_TRANSACTION_KEY, 'x_version' => '3.1',

'x_test_request' => AUTHORIZE_NET_TEST_REQUEST, 'x_delim_data' => 'TRUE',

'x_delim_char' => '|', 'x_relay_response' => 'FALSE');

$request = array_merge($request_init, $request);

The array data is merged into a name-value string that can be sent to Authorize.net. The values are encoded for inclusion in the URL using the urlencode()function:

foreach($request as $key => $value )

$this->_mRequest .= $key . '=' . urlencode($value) . '&';

}

The GetResponse()method of AuthorizeNetRequestdoes the actual request, using the CURL library.

// Send an HTTP POST request to Authorize.net using CURL public function GetResponse()

{ ...

// Perform a CURL session

$result = curl_exec($ch);

// Close a CURL session curl_close ($ch);

// Return the response

return $result;

} }

?>

When executing the GetResponse()function to perform an AUTH_ONLYtransaction, the response will contain a transaction ID. If the authorization is successful, we can then use this transaction ID to perform a

PRIOR_AUTH_CAPTUREtransaction, which effectively takes the money from the customer’s account.

As explained earlier, the response from Authorize.net comes in the form of a string that contains values delimited by a configurable character, which in our case is the pipe character (|). To read a particular value from the string, we transform the string into an array using the explode()PHP function (http://www.php.net/manual/

en/function.explode.php):

$auth_only_response = $request->GetResponse();

$_SESSION['auth_only_response'] = $auth_only_response;

$auth_only_response = explode('|', $auth_only_response);

After this piece of code executes,$auth_only_responsewill contain an array whose elements are the values that were delimited by the pipe character in the original string. From this array, we’re interested in the seventh ele- ment, which, according to the Authorize.net documentation, is the transaction ID. (Read the Gateway Response API details from http://www.authorize.net/support/AIM_guide.pdffor the complete details about the Authorize.net response.)

// Read the transaction ID, which will be necessary for taking the payment

$ref_trans_id = $auth_only_response[6];

Note The $auth_only_responsearray created by explode()is zero-based, so

$auth_only_response[6]represents the seventh element of the array.

The code that takes the money using this transaction ID is straightforward. Because the transaction has already been authorized, we only need to specify the transaction ID received after authorization to complete the transaction:

// Capture

$transaction = array ('x_ref_trans_id' => $ref_trans_id, // Transaction id 'x_method' => 'CC', // Payment method

'x_type' => 'PRIOR_AUTH_CAPTURE'); // Transaction type

$request->SetRequest($transaction);

$prior_auth_capture_response = $request->GetResponse();

Một phần của tài liệu Beginning PHP and Postgre SQL E-Commerce From Novice to Professional phần 9 ppt (Trang 38 - 50)

Tải bản đầy đủ (PDF)

(63 trang)