function commerce_worldpay_bg_response_page in Commerce Worldpay 7
Page callback that listens for transaction information from WorldPay.
DRAFT Here we create new transactions and load existing ones.
- First validate the signature fields with md5
- Decide action
-- Create response pages for Worldpay to use --- Success page or cancel page (resultY.html || resultC.html)
1 call to commerce_worldpay_bg_response_page()
- commerce_worldpay_bg_debug_response_page in includes/
commerce_worldpay_bg.debug_page.inc - A debuging callback.
1 string reference to 'commerce_worldpay_bg_response_page'
- commerce_worldpay_bg_menu in ./
commerce_worldpay_bg.module - Implements hook_menu().
File
- includes/
commerce_worldpay_bg.page.inc, line 22 - Various page callback related functions.
Code
function commerce_worldpay_bg_response_page($payment_method = NULL, $debug_wppr = array()) {
$order = NULL;
$skip_process = FALSE;
if (!empty($debug_wppr)) {
$wppr = $debug_wppr;
$debug_mode = TRUE;
}
// Attempt to load payment method from alternative means.
if (!isset($payment_method)) {
if (!empty($wppr['transId']) && ($prior_wppr = commerce_worldpay_bg_txn_load($wppr['transId'], 'wp_txn_id'))) {
if (!empty($prior_wppr['transaction_id'])) {
$transaction = commerce_payment_transaction_load($prior_wppr['transaction_id']);
if (empty($wppr['MC_orderId'])) {
$wppr['MC_orderId'] = $transaction->order_id;
}
elseif ($wppr['MC_orderId'] != $transaction->order_id) {
// Why do we have two different order IDs? Lets bail.
exit('');
}
$payment_method = commerce_payment_method_instance_load($transaction->instance_id);
}
}
// @todo Is this safe? Can we end up with the wrong payment method from the
// Order object?
if (!$payment_method && !empty($wppr['MC_orderId'])) {
if ($order = commerce_order_load($wppr['MC_orderId'])) {
if (!empty($order->data['payment_method'])) {
$payment_method = commerce_payment_method_instance_load($order->data['payment_method']);
}
}
else {
print '';
return;
}
}
}
// Make sure we have a payment method we handle.
if ($payment_method) {
if ($payment_method['method_id'] != 'commerce_worldpay_bg') {
print '';
return;
}
}
else {
// Bail since we have no useful data to work with.
print '';
return;
}
// If the payment method specifies full IPN logging, do it now.
if (!empty($payment_method['settings']['payment_response_logging']) && $payment_method['settings']['payment_response_logging'] == 'full_wppr') {
$full_log = TRUE;
}
else {
$full_log = FALSE;
}
if (empty($debug_wppr)) {
$debug_mode = FALSE;
// WorldPay Payment Response.
$wppr = $_POST;
if (empty($wppr['transId']) && $wppr['transStatus'] != 'C') {
if ($full_log) {
watchdog('commerce_worldpay_bg', 'Request with no transId was sent from <em>@ip</em> with request method <b>@method</b>.', array(
'@ip' => ip_address(),
'@method' => !empty($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '',
), WATCHDOG_NOTICE);
}
return;
}
if (empty($wppr['MC_orderId'])) {
drupal_add_http_header('Status', '404 Not Found');
if ($full_log) {
watchdog('commerce_worldpay_bg', 'Request with no MC_orderId was sent from <em>@ip</em> with request method <b>@method</b>.', array(
'@ip' => ip_address(),
'@method' => !empty($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '',
), WATCHDOG_NOTICE);
}
return;
}
}
if ($full_log) {
watchdog('commerce_worldpay_bg', 'Attempting to process Payment Response @wp_txn_id. !wpr_log', array(
'@wp_txn_id' => $wppr['transId'],
'!wpr_log' => '<pre>' . check_plain(print_r($wppr, TRUE)) . '</pre>',
), WATCHDOG_NOTICE);
}
// If this has been processed before and nothing appears to have changed.
if (!empty($wppr['transId']) && ($prior_wppr = commerce_worldpay_bg_txn_load($wppr['transId'], 'wp_txn_id'))) {
if ($prior_wppr['auth_amount'] == $wppr['authAmount'] && $prior_wppr['transStatus'] == $wppr['transaction_status']) {
if ($full_log) {
watchdog('commerce_worldpay_bg', 'Attempted to process an WorldPay response that has already been processed with transaction ID @txn_id.', array(
'@txn_id' => $wppr['txn_id'],
), WATCHDOG_NOTICE);
}
// Don't process this.
$skip_process = TRUE;
}
}
else {
$prior_wppr = NULL;
}
if (!$order && !($order = commerce_order_load($wppr['MC_orderId']))) {
drupal_add_http_header('Status', '404 Not Found');
return;
}
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
// Authentication.
// @todo Check that the the transId and cartId are part of the same
// transaction.
if ($debug_mode && $debug_wppr['skip_auth']) {
$order->data['payment_redirect_key'] = '123';
}
else {
$authenticated = _commerce_worldpay_bg_payment_response_authenticate($order_wrapper, $wppr, $payment_method, $prior_wppr);
if (!$authenticated) {
return;
}
}
$theme_data = array(
'order' => $order,
'order_id' => $wppr['MC_orderId'],
'order_no' => empty($wppr['cartId']) ? $order->order_number : $wppr['cartId'],
'wp_txn_id' => $wppr['transId'],
'settings' => $payment_method['settings'],
);
$theme_data['installation_id'] = $payment_method ? $payment_method['settings']['installation_id'] : $wppr['instId'];
// Remove parts of the settings a theme need not know about.
unset($theme_data['payment_security']);
$theme_data['settings']['theme_debug'] = $debug_mode;
// Allow themes to adjust based on current context.
$theme_data['settings']['context'] = 'general';
switch ($wppr['transStatus']) {
case 'Y':
$theme_data['settings']['context'] = 'result_success';
if ($debug_mode && $debug_wppr['skip_save']) {
$order->data['payment_redirect_key'] = '123';
// Write a message.
}
elseif (!$skip_process) {
// Create or re-establish a Commerce Transaction.
// This will add the 'transaction_id' to $wppr.
commerce_worldpay_bg_transaction_process($order, $payment_method, $wppr, $prior_wppr);
$tx_data = commerce_worldpay_bg_convert_wppr_to_record($wppr);
$tx_data['transaction_id'] = $wppr['transaction_id'];
$tx_data['order_id'] = $order->order_id;
$tx_data['signature_fields'] = implode(':', _commerce_worldpay_bg_md5_signature_fields());
if ($prior_wppr) {
$tx_data = array_replace($prior_wppr, $tx_data);
}
commerce_worldpay_bg_txn_save($tx_data);
}
if (!empty($payment_method['settings']['debug'])) {
watchdog('commerce_worldpay_bg', 'Creating success HTML for transaction @wp_txn_id.', array(
'@wp_txn_id' => $wppr['transId'],
), WATCHDOG_NOTICE);
}
// Now generate the HTML that WorldPay will pull from to generate its
// custom page.
// This is printed directly as we want to skip the rest of Drupal's HTML
// build. See: drupal_deliver_html_page().
drupal_set_title(t('@site_name payment', array(
'@site_name' => variable_get('site_name', 'Drupal Commerce') . ' WorldPay payment',
)));
print _commerce_worldpay_bg_build_page($theme_data, 'success');
break;
case 'C':
$theme_data['settings']['context'] = 'result_cancel';
if ($prior_wppr) {
// Don't know if WorldPay ever changes transStatus after it's been set
// the first time, but if it does we update our transaction info.
$tx_data = commerce_worldpay_bg_convert_wppr_to_record($wppr);
$tx_data = array_replace($prior_wppr, $tx_data);
commerce_worldpay_bg_txn_save($tx_data);
}
// Not totally sure if this is the right thing to do here?
commerce_payment_redirect_pane_previous_page($order);
if (!empty($payment_method) and !empty($payment_method['settings']['debug'])) {
watchdog('commerce_worldpay_bg', 'Creating cancel HTML for transaction @wp_txn_id.', array(
'@wp_txn_id' => $wppr['transId'],
), WATCHDOG_NOTICE);
}
drupal_set_title(t('@site_name payment', array(
'@site_name' => variable_get('site_name', 'Drupal Commerce') . ' WorldPay payment canceled',
)));
print _commerce_worldpay_bg_build_page($theme_data, 'cancel');
break;
}
}