You are here

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;
  }
}