View source
<?php
module_load_include('inc', 'commerce_sagepay', 'includes/commerce_sagepay_common');
function sagepay_3d_secure_menu() {
$items = array();
$items['sagepay_3d_secure/3d_secure_waiting_page'] = array(
'page callback' => 'sagepay_3d_secure_waiting_page',
'access arguments' => array(
'access content',
),
'type' => MENU_CALLBACK,
);
$items['commerce-sagepay/3d_secure_callback/%'] = array(
'page callback' => 'sagepay_3d_secure_callback',
'page arguments' => array(
2,
),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}
function sagepay_3d_secure_commerce_checkout_router($order, $checkout_page) {
if ($checkout_page['page_id'] == '3d_secure') {
$skip_3d_secure = FALSE;
if (!isset($order->data['extra_authorisation'])) {
$skip_3d_secure = TRUE;
}
else {
if (!isset($order->data['extra_authorisation']['PAReq']) || !isset($order->data['extra_authorisation']['ACSURL']) || !isset($order->data['extra_authorisation']['MD']) || !isset($order->data['extra_authorisation']['TermUrl'])) {
watchdog('commerce_3d_secure', 'Only partial 3D Secure Data present, cannot proceed so skipping this step', array(), WATCHDOG_WARNING);
$skip_3d_secure = TRUE;
}
}
if ($skip_3d_secure) {
$checkout_pages = commerce_checkout_pages();
$next_step = $checkout_pages['3d_secure']['next_page'];
commerce_order_status_update($order, 'checkout_' . $next_step);
if ($next_step == 'complete') {
commerce_checkout_complete($order);
}
drupal_goto('checkout/' . $order->order_id . '/' . $next_step);
}
}
}
function sagepay_3d_secure_commerce_checkout_page_info() {
$checkout_pages = array();
$checkout_pages['3d_secure'] = array(
'title' => t('3D Secure Authentication'),
'help' => t('Your payment card provider has requested some additional security details.'),
'status_cart' => FALSE,
'locked' => TRUE,
'buttons' => FALSE,
'weight' => 22,
);
return $checkout_pages;
}
function sagepay_3d_secure_commerce_checkout_pane_info() {
$checkout_panes = array();
$checkout_panes['3d_secure'] = array(
'title' => t('3D Secure Authentication'),
'module' => 'commerce_3d_secure',
'page' => '3d_secure',
'collapsible' => FALSE,
'collapsed' => FALSE,
'weight' => 0,
'enabled' => TRUE,
'review' => FALSE,
'base' => 'sagepay_3d_secure_pane',
'callbacks' => array(
'checkout_form',
),
);
return $checkout_panes;
}
function sagepay_3d_secure_pane_checkout_form($form, &$form_state, $checkout_pane, $order) {
drupal_add_js("window.onload = function() { document.forms['commerce-checkout-form-3d-secure'].submit(); }", 'inline');
$form['PaReq'] = array(
'#type' => 'hidden',
'#default_value' => $order->data['extra_authorisation']['PAReq'],
);
$form['TermUrl'] = array(
'#type' => 'hidden',
'#default_value' => $order->data['extra_authorisation']['TermUrl'],
);
$form['MD'] = array(
'#type' => 'hidden',
'#default_value' => $order->data['extra_authorisation']['MD'],
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Proceed with 3D Secure Authentication',
);
$form['hidden_action'] = array(
'#type' => 'hidden',
'#value' => $order->data['extra_authorisation']['ACSURL'],
);
$form['iframe_3d_secure'] = array(
'#markup' => '<iframe width="550" height="440" scrolling="auto" frameborder="0" name ="iframe_3d_secure" id ="iframe_3d_secure" src="' . url('sagepay_3d_secure/3d_secure_waiting_page') . '" ></iframe>',
);
return $form;
}
function sagepay_3d_secure_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'commerce_checkout_form_3d_secure') {
$form['#action'] = $form['3d_secure']['hidden_action']['#value'];
$form['#attributes']['target'] = 'iframe_3d_secure';
$form['PaReq'] = $form['3d_secure']['PaReq'];
$form['TermUrl'] = $form['3d_secure']['TermUrl'];
$form['MD'] = $form['3d_secure']['MD'];
$form['submit'] = $form['3d_secure']['submit'];
$form['iframe_3d_secure'] = $form['3d_secure']['iframe_3d_secure'];
unset($form['submit']);
unset($form['3d_secure']);
}
elseif ($form_id == 'commerce_sagepay_settings_form') {
$form['security'][SAGEPAY_SETTING_APPLY_3D_SECURE] = array(
'#type' => 'radios',
'#title' => t('3D Secure Mode'),
'#description' => t('3D Secure mode used by default on all transactions.'),
'#options' => array(
'0' => t('If 3D-Secure checks are possible and rules allow, perform the checks and apply the authorisation rules. (default)'),
'1' => t('Force 3D-Secure checks for this transaction if possible and apply rules for authorisation.'),
'2' => t('Do not perform 3D-Secure checks for this transaction and always authorise.'),
'3' => t('Force 3D-Secure checks for this transaction if possible but ALWAYS obtain an auth code, irrespective of rule base.'),
),
'#default_value' => variable_get(SAGEPAY_SETTING_APPLY_3D_SECURE, 0),
);
}
}
function sagepay_3d_secure_waiting_page() {
print '<html><head><title></title></head><body><p>';
print t('Please wait to be redirected to your card provider for authorisation.');
print '</p></body></html>';
}
function sagepay_3d_secure_callback($order_id) {
if (empty($_POST)) {
drupal_not_found();
}
$order = commerce_order_load($order_id);
if (!isset($order)) {
drupal_not_found();
}
$order_status = commerce_order_status_load($order->status);
if ($order_status['name'] != 'checkout_3d_secure') {
drupal_not_found();
}
if (!isset($_POST['MD']) || !isset($_POST['PaRes'])) {
watchdog('commerce_sagepay_direct', 'Invalid data received in 3D Secure response', array(), WATCHDOG_ERROR);
drupal_not_found();
}
$md = check_plain($_POST['MD']);
$pares = check_plain($_POST['PaRes']);
$post = 'MD=' . $md;
$post .= '&PaRes=' . $pares;
$payment_method_instance = commerce_payment_method_instance_load($order->data['payment_method']);
switch (variable_get(SAGEPAY_SETTING_TRANSACTION_MODE)) {
case SAGEPAY_TXN_MODE_LIVE:
$server_url = SAGEPAY_DIRECT_SERVER_3D_SECURE_CALLBACK_LIVE;
break;
case SAGEPAY_TXN_MODE_TEST:
$server_url = SAGEPAY_DIRECT_SERVER_3D_SECURE_CALLBACK_TEST;
break;
case SAGEPAY_TXN_MODE_SIMULATION:
$server_url = SAGEPAY_DIRECT_SERVER_SIMULATION;
break;
default:
$server_url = SAGEPAY_TXN_MODE_SIMULATION;
}
$response = _commerce_sagepay_request_post($server_url, $post);
$success = commerce_sagepay_process_response($payment_method_instance, $order, $response);
if ($success) {
$checkout_pages = commerce_checkout_pages();
$next_step = $checkout_pages['3d_secure']['next_page'];
$order = commerce_order_status_update($order, 'checkout_' . $next_step);
if ($next_step == 'complete') {
commerce_checkout_complete($order);
}
$redirect = 'checkout/' . $order->order_id . '/' . $next_step;
}
else {
$redirect = 'checkout/' . $order->order_id . '/payment';
}
sagepay_3d_secure_clear_iframe($redirect);
}
function sagepay_3d_secure_clear_iframe($redirect_url) {
print '<html><head><title></title></head><body onload="document.forms[0].submit();">';
print '<form name="3d_secure_callback" method="post" action="' . url($redirect_url) . '" target="_top">';
print '<noscript>';
print '<input type="submit" value="';
print t('Please click here to continue.');
print '" />';
print '</noscript>';
print '</form>';
print '</body></html>';
}
function sagepay_3d_secure_load_transaction($tokens, $order) {
$status_3d_secure = isset($tokens['3DSecureStatus']) ? $tokens['3DSecureStatus'] : '';
if ($status_3d_secure == '') {
return NULL;
}
$cavv_code = isset($tokens['CAVV']) ? $tokens['CAVV'] : '';
$conditions = array(
'order_id' => $order->order_id,
'remote_status' => SAGEPAY_REMOTE_STATUS_3D_SECURE,
);
$transactions = commerce_payment_transaction_load_multiple(array(), $conditions);
if (empty($transactions)) {
return NULL;
}
$transaction = array_pop($transactions);
return $transaction;
}