You are here

function commerce_sagepay_process_response in Drupal Commerce SagePay Integration 7

Helper function to process the response from SagePay of any transaction type.

Return TRUE for a successful transaction.

Parameters

array $payment_method: The payment method being used.

commerce_order $order: The Commerce Order to match against the response.

array $tokens: Tokens available to the response.

Return value

bool Return TRUE is the payment was successful. Return FALSE if payment is rejected or fails for any reason.

5 calls to commerce_sagepay_process_response()
commerce_sagepay_direct_submit_form_submit in includes/commerce_sagepay_direct.inc
Payment method callback: checkout form submission.
commerce_sagepay_paypal_handle_callback in modules/commerce_sagepay_paypal/includes/commerce_sagepay_paypal.inc
Handle a POST callback from Pay Pal to confirm the transaction.
commerce_sagepay_paypal_submit_form_validate in modules/commerce_sagepay_paypal/includes/commerce_sagepay_paypal.inc
Payment method callback: checkout form submission.
sagepay_3d_secure_callback in modules/sagepay_3d_secure/sagepay_3d_secure.module
Process callback response from merchant server.
sagepay_token_cardonfile_charge in modules/sagepay_token/sagepay_token.module
Implements Card on File Charge Callback.

File

includes/commerce_sagepay_common.inc, line 203
Common utility functions shared by all SagePay modules.

Code

function commerce_sagepay_process_response($payment_method, $order, $tokens, $transaction = NULL) {

  // Default no charge for failed transactions.
  // (these values will not be in the callback for a failed or cancelled).
  $def_charge = array(
    'amount' => 0,
    'currency_code' => '',
  );
  $order_id = $order->order_id;

  // Check for a valid status callback.
  switch ($tokens['Status']) {
    case 'ABORT':
      watchdog('commerce_sagepay', 'ABORT error from SagePay for order %order_id with message %msg', array(
        '%order_id' => $order_id,
        '%msg' => $tokens['StatusDetail'],
      ), WATCHDOG_ALERT);
      commerce_sagepay_transaction($payment_method, $order, $def_charge, $tokens, COMMERCE_PAYMENT_STATUS_FAILURE, SAGEPAY_REMOTE_STATUS_FAIL, $transaction);
      drupal_set_message(t('Your SagePay transaction was aborted.'), 'error');
      return FALSE;
    case 'NOTAUTHED':
      watchdog('commerce_sagepay', 'NOTAUTHED error from SagePay for order %order_id with message %msg', array(
        '%order_id' => $order_id,
        '%msg' => $tokens['StatusDetail'],
      ), WATCHDOG_ALERT);
      commerce_sagepay_transaction($payment_method, $order, $def_charge, $tokens, COMMERCE_PAYMENT_STATUS_FAILURE, SAGEPAY_REMOTE_STATUS_FAIL, $transaction);
      drupal_set_message(t('Your transaction was not authorised.'), 'error');
      return FALSE;
    case 'REJECTED':
      watchdog('commerce_sagepay', 'REJECTED error from SagePay for order %order_id with message %msg', array(
        '%order_id' => $order_id,
        '%msg' => $tokens['StatusDetail'],
      ), WATCHDOG_ALERT);
      commerce_sagepay_transaction($payment_method, $order, $def_charge, $tokens, COMMERCE_PAYMENT_STATUS_FAILURE, SAGEPAY_REMOTE_STATUS_FAIL, $transaction);
      drupal_set_message(t('Your transaction was rejected. Reason: 3D-Authentication failed.'), 'warning');
      $target_step = 'checkout_review';
      drupal_alter('commerce_sagepay_3dsecure_fail_destination', $target_step);
      commerce_order_status_update($order, $target_step);
      return FALSE;
    case 'MALFORMED':
      watchdog('commerce_sagepay', 'MALFORMED error from SagePay for order %order_id with message %msg', array(
        '%order_id' => $order_id,
        '%msg' => $tokens['StatusDetail'],
      ), WATCHDOG_ALERT);
      commerce_sagepay_transaction($payment_method, $order, $def_charge, $tokens, COMMERCE_PAYMENT_STATUS_FAILURE, SAGEPAY_REMOTE_STATUS_FAIL, $transaction);
      drupal_set_message(t('Sorry the transaction has failed.'), 'error');
      return FALSE;
    case 'INVALID':
      watchdog('commerce_sagepay', 'INVALID error from SagePay for order %order_id with message %msg', array(
        '%order_id' => $order_id,
        '%msg' => $tokens['StatusDetail'],
      ), WATCHDOG_ERROR);
      commerce_sagepay_transaction($payment_method, $order, $def_charge, $tokens, COMMERCE_PAYMENT_STATUS_FAILURE, SAGEPAY_REMOTE_STATUS_FAIL, $transaction);
      drupal_set_message(t('Sorry an error occurred while processing your transaction. %message', array(
        '%message' => $tokens['StatusDetail'],
      )), 'error');
      $target_step = 'checkout_review';

      // Allow custom modules to change which page you end up at when the order
      // is invalid.
      drupal_alter('commerce_sagepay_invalid_destination', $target_step);
      commerce_order_status_update($order, $target_step);
      return FALSE;
    case 'ERROR':
      watchdog('commerce_sagepay', 'System ERROR from SagePay for order %order_id with message %msg', array(
        '%order_id' => $order_id,
        '%msg' => $tokens['StatusDetail'],
      ), WATCHDOG_ERROR);
      commerce_sagepay_transaction($payment_method, $order, $def_charge, $tokens, COMMERCE_PAYMENT_STATUS_FAILURE, SAGEPAY_REMOTE_STATUS_FAIL, $transaction);
      drupal_set_message(t('Sorry an error occurred while processing your transaction. %message', array(
        '%message' => $tokens['StatusDetail'],
      )), 'error');
      return FALSE;
    case 'FAIL':
      watchdog('commerce_sagepay', 'System FAIL from SagePay for order %order_id with message %msg', array(
        '%order_id' => $order_id,
        '%msg' => $tokens['StatusDetail'],
      ), WATCHDOG_ERROR);
      commerce_sagepay_transaction($payment_method, $order, $def_charge, $tokens, COMMERCE_PAYMENT_STATUS_FAILURE, SAGEPAY_REMOTE_STATUS_FAIL, $transaction);
      drupal_set_message(t('Sorry an error occurred while processing your transaction. %message', array(
        '%message' => $tokens['StatusDetail'],
      )), 'error');
      return FALSE;
    case 'OK':
      $arr_charge = array();
      $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
      if (array_key_exists('Amount', $tokens)) {
        $arr_charge['amount'] = $tokens['Amount'];
        $arr_charge['currency_code'] = $order_wrapper->commerce_order_total->currency_code
          ->value();
      }

      /* As we have already created a transaction, we no longer need to reset this and reload
         $transaction = NULL; */

      // If 3D secure is in use, we may have to load a partial transaction.
      if (module_exists('sagepay_3d_secure')) {
        $transaction_3d = sagepay_3d_secure_load_transaction($tokens, $order);
        if ($transaction_3d) {
          $transaction = $transaction_3d;
        }
      }
      $remote_status = SAGEPAY_REMOTE_STATUS_PAYMENT;
      if (isset($transaction->remote_status)) {
        if ($transaction->remote_status == 'DEFERRED') {
          $remote_status = SAGEPAY_REMOTE_STATUS_DEFERRED;
        }
      }

      // Check for the scenario where we stored the original requested remote
      // status prior to 3d Secure.
      if (isset($transaction->payload['original_remote_status'])) {
        $remote_status = $transaction->payload['original_remote_status'];
        unset($transaction->payload['original_remote_status']);
      }
      commerce_sagepay_transaction($payment_method, $order, $arr_charge, $tokens, COMMERCE_PAYMENT_STATUS_SUCCESS, $remote_status, $transaction);
      break;
    case 'AUTHENTICATED':
      $arr_charge = array();
      $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
      $arr_charge['amount'] = $tokens['Amount'];
      $arr_charge['currency_code'] = $order_wrapper->commerce_order_total->currency_code
        ->value();
      watchdog('commerce_sagepay', 'AUTHENTICATED Payment callback received from SagePay for order %order_id with status code %status', array(
        '%order_id' => $order_id,
        '%status' => $tokens['Status'],
      ));
      commerce_sagepay_transaction($payment_method, $order, $arr_charge, $tokens, COMMERCE_PAYMENT_STATUS_PENDING, SAGEPAY_REMOTE_STATUS_AUTHENTICATE, $transaction);
      break;
    case 'REGISTERED':
      $arr_charge = array();
      $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
      $arr_charge['amount'] = $tokens['Amount'];
      $arr_charge['currency_code'] = $order_wrapper->commerce_order_total->currency_code
        ->value();
      watchdog('commerce_sagepay', 'REGISTERED Payment callback received from SagePay for order %order_id with status code %status', array(
        '%order_id' => $order_id,
        '%status' => $tokens['Status'],
      ));
      commerce_sagepay_transaction($payment_method, $order, $arr_charge, $tokens, COMMERCE_PAYMENT_STATUS_PENDING, SAGEPAY_REMOTE_STATUS_REGISTERED, $transaction);
      break;
    case 'PPREDIRECT':

      // Card type was PayPal and the server has responded with a PayPal
      // redirect URL.
      $arr_charge = array();
      $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
      $arr_charge['amount'] = $tokens['Amount'];
      $arr_charge['currency_code'] = $order_wrapper->commerce_order_total->currency_code
        ->value();
      watchdog('commerce_sagepay', 'REGISTERED PAYPAL Payment callback
      received
      from SagePay for order %order_id with status code %status', array(
        '%order_id' => $order_id,
        '%status' => $tokens['Status'],
      ));
      commerce_sagepay_transaction($payment_method, $order, $arr_charge, $tokens, COMMERCE_PAYMENT_STATUS_PENDING, SAGEPAY_REMOTE_STATUS_PAYPAL_REDIRECT);
      break;
    case '3DAUTH':

      // Server has replied with a 3D Secure authentication request.
      // Store the returned variables in the order object for processing
      // by the 3D Secure module.
      // The returned variables should be:
      // 1) PAReq.
      // 2) ACSURL.
      // 3) MD.
      $tds_data = array();
      $tds_data['PAReq'] = $tokens['PAReq'];
      $tds_data['ACSURL'] = $tokens['ACSURL'];
      $tds_data['MD'] = $tokens['MD'];
      $tds_data['TermUrl'] = url('commerce-sagepay/3d_secure_callback/' . $order->order_id, array(
        'absolute' => TRUE,
      ));
      $order->data['extra_authorisation'] = $tds_data;
      $arr_charge = array();
      $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
      $arr_charge['amount'] = $tokens['Amount'];
      $arr_charge['currency_code'] = $order_wrapper->commerce_order_total->currency_code
        ->value();

      // Store the original remote status in the payload otherwise we lose it
      // when we change the remote status to 3D Secure.
      $tokens['original_remote_status'] = $transaction->remote_status;
      commerce_sagepay_transaction($payment_method, $order, $arr_charge, $tokens, COMMERCE_PAYMENT_STATUS_PENDING, SAGEPAY_REMOTE_STATUS_3D_SECURE, $transaction);
      break;
    default:

      // Something has gone wrong so log an error and fail.
      watchdog('commerce_sagepay', 'Unrecognised Status response from SagePay for order %order_id (%response_code)', array(
        '%order_id' => $order_id,
        '%response_code' => $tokens['Status'],
      ), WATCHDOG_ERROR);
      drupal_set_message(t('Sorry an error occurred while processing your transaction. %message', array(
        '%message' => $tokens['StatusDetail'],
      )), 'error');
      return FALSE;
  }
  return TRUE;
}