You are here

function _commerce_sagepay_encrypted_order in Drupal Commerce SagePay Integration 7

Encrypt the order details ready to send to SagePay Server.

Parameters

array $settings: The payment gateway settings.

commerce_order $order: The Commerce Order being encrypted.

int $total: The total value of the order.

commerce_profile $billing_address: The billing address of the order.

commerce_profile $delivery_address: The delivery address of the order.

string $integration_method: The Sage Pay integration method being used.

array $pane_values: The values from the payment checkout pane.

Return value

array|string Returns a String for Form integration method or an array for Server / Direct.

5 calls to _commerce_sagepay_encrypted_order()
commerce_sagepay_direct_submit_form_submit in includes/commerce_sagepay_direct.inc
Payment method callback: checkout form submission.
commerce_sagepay_order_form in includes/commerce_sagepay_common.inc
Sets up a new form for the submit to Sage Pay button (off site redirect).
commerce_sagepay_paypal_submit_form_validate in modules/commerce_sagepay_paypal/includes/commerce_sagepay_paypal.inc
Payment method callback: checkout form submission.
commerce_sagepay_server_redirect_form in includes/commerce_sagepay_server.inc
Implements hook_redirect_form().
sagepay_token_cardonfile_charge in modules/sagepay_token/sagepay_token.module
Implements Card on File Charge Callback.

File

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

Code

function _commerce_sagepay_encrypted_order($settings, $order, $total, $billing_address, $delivery_address = NULL, $integration_method = SAGEPAY_FORM, $pane_values = NULL) {
  if (!empty($pane_values['credit_card']['type'])) {
    $pane_values['credit_card']['type'] = commerce_sagepay_lookup_sagepay_card_type($pane_values['credit_card']['type']);
  }

  // Check for Commerce Card on File value which indicates someone is trying
  // to reuse a stored payment card.
  // Redirect the request to the sagepay_token module.
  if (module_exists('sagepay_token')) {
    if (isset($pane_values) && array_key_exists('cardonfile', $pane_values) && $pane_values['cardonfile'] != 'new') {
      $saved_card_data = commerce_cardonfile_load($pane_values['cardonfile']);
      if (!array_key_exists('commerce_recurring', $pane_values) && !commerce_cardonfile_access('view', $saved_card_data)) {
        $saved_card_data = NULL;
      }
      if (isset($saved_card_data)) {
        $integration_method = SAGEPAY_TOKEN;
      }
    }
  }

  // generate a unique VendorTxId
  $vendor_tx_code = _commerce_sagepay_vendor_tx_code($order);

  // Update order number in database with the random number we just generated.
  $order->data['VendorTxId'] = $vendor_tx_code;
  commerce_order_save($order);

  // Convert commerce int to decimal.
  $order_amount = number_format(commerce_currency_amount_to_decimal($total['amount'], $total['currency_code']), 2, '.', '');

  // Check if we need to encode cart.
  $cart_setting = variable_get('sagepay_send_basket_contents');
  $encoded_cart = '';
  if ($cart_setting == '1') {
    module_load_include('inc', 'commerce_sagepay', 'includes/commerce_sagepay_formatters');
    $encoded_cart = _commerce_sagepay_cart_to_string($order);
  }
  elseif ($cart_setting == '2') {
    module_load_include('inc', 'commerce_sagepay', 'includes/commerce_sagepay_formatters');
    $encoded_cart = _commerce_sagepay_cart_to_xml($order)
      ->saveXML();
  }

  // Add a default postcode if the address supplied didn't have one.
  // SagePay requires a postcode even if some countries do not have them.
  $billing_address['postal_code'] = _commerce_sagepay_ensure_postal_code($billing_address);

  // Determine the transaction type based on the payment gateway settings.
  switch (variable_get(SAGEPAY_SETTING_TRANSACTION_TYPE)) {
    case COMMERCE_CREDIT_AUTH_CAPTURE:
      $tx_type = 'PAYMENT';
      break;
    case COMMERCE_CREDIT_AUTH_ONLY:
      $tx_type = 'AUTHENTICATE';
      break;
    default:

      // Set to deferred if there is no setting for the payment gateway.
      $tx_type = 'DEFERRED';
  }
  $query = array(
    'VPSProtocol' => SAGEPAY_PROTOCOL,
    'Vendor' => variable_get(SAGEPAY_SETTING_VENDOR_NAME),
    'VendorTxCode' => $vendor_tx_code,
    'Amount' => $order_amount,
    'Currency' => $total['currency_code'],
    'Description' => variable_get(SAGEPAY_SETTING_ORDER_DESCRIPTION),
    'CustomerName' => $billing_address['first_name'] . ' ' . $billing_address['last_name'],
    'CustomerEmail' => $order->mail,
    'VendorEmail' => variable_get(SAGEPAY_SETTING_VENDOR_EMAIL),
    'SendEmail' => variable_get(SAGEPAY_SETTING_SEND_EMAIL),
    'eMailMessage' => variable_get(SAGEPAY_SETTING_EMAIL_MESSAGE),
    'BillingSurname' => substr($billing_address['last_name'], 0, 20),
    'BillingFirstnames' => substr($billing_address['first_name'], 0, 20),
    'BillingAddress1' => $billing_address['thoroughfare'],
    'BillingAddress2' => $billing_address['premise'],
    'BillingCity' => $billing_address['locality'],
    'BillingPostcode' => $billing_address['postal_code'],
    'BillingCountry' => $billing_address['country'],
    'DeliverySurname' => substr($billing_address['last_name'], 0, 20),
    'DeliveryFirstnames' => substr($billing_address['first_name'], 0, 20),
    'DeliveryAddress1' => $billing_address['thoroughfare'],
    'DeliveryAddress2' => $billing_address['premise'],
    'DeliveryCity' => $billing_address['locality'],
    'DeliveryPostcode' => $billing_address['postal_code'],
    'DeliveryCountry' => $billing_address['country'],
    'ApplyAVSCV2' => variable_get(SAGEPAY_SETTING_APPLY_AVS_CV2),
    'Apply3DSecure' => variable_get(SAGEPAY_SETTING_APPLY_3D_SECURE),
  );

  // Add module version to transaction as referrerID to aid debugging.
  $module_info = system_get_info('module', 'commerce_sagepay');
  $version = str_replace('-', '_', $module_info['version']);

  // Sage Pay doesn't like - so replace.
  $arr_version = explode('+', $version);

  // Split the version in case it's a dev version
  $version = $arr_version[0];
  $query['ReferrerID'] = 'commerce_sagepay_' . $version;
  switch ($integration_method) {
    case SAGEPAY_FORM:
      $query['SuccessURL'] = isset($settings['return']) ? $settings['return'] : '';
      $query['FailureURL'] = isset($settings['cancel_return']) ? $settings['cancel_return'] : '';
      break;
    case SAGEPAY_SERVER:
      $query['NotificationURL'] = url('commerce-sagepay-server/vps-callback/' . $order->order_id . '/' . $order->data['payment_redirect_key'], array(
        'absolute' => TRUE,
      ));
      $query['TxType'] = $tx_type;
      if (variable_get(SAGEPAY_SETTING_LOW_PROFILE, 1) == 1) {
        $query['Profile'] = 'LOW';
      }
      else {
        $query['Profile'] = 'NORMAL';
      }
      $query['AccountType'] = variable_get(SAGEPAY_SETTING_ACCOUNT_TYPE, 'E');
      break;
    case SAGEPAY_DIRECT:
      $query['TxType'] = $tx_type;
      $query['CardHolder'] = $billing_address['first_name'] . ' ' . $billing_address['last_name'];
      $query['CardNumber'] = $pane_values['credit_card']['number'];
      $query['ExpiryDate'] = $pane_values['credit_card']['exp_month'] . substr($pane_values['credit_card']['exp_year'], 2, 2);

      // Check if a start date was entered as we have removed the required
      // field flag.
      if ($pane_values['credit_card']['start_month'] != '0' && $pane_values['credit_card']['start_year'] != '0') {
        $query['StartDate'] = $pane_values['credit_card']['start_month'] . substr($pane_values['credit_card']['start_year'], 2, 2);
      }
      $issue_number = isset($query['IssueNumber']) ? $query['IssueNumber'] : '';
      if ($issue_number != '') {
        $query['IssueNumber'] = str_pad($pane_values['credit_card']['issue'], 2, '0', STR_PAD_LEFT);
      }
      $query['CV2'] = $pane_values['credit_card']['code'];
      $query['CardType'] = $pane_values['credit_card']['type'];

      // Add 3D Secure flag only if the 3d Secure module is enabled for DIRECT.
      if (module_exists('sagepay_3d_secure')) {
        $query['Apply3DSecure'] = variable_get(SAGEPAY_SETTING_APPLY_3D_SECURE);
      }
      else {
        $query['Apply3DSecure'] = 2;
      }
      $query['AccountType'] = variable_get(SAGEPAY_SETTING_ACCOUNT_TYPE, 'E');
      break;
    case SAGEPAY_PAYPAL:
      $query['TxType'] = $tx_type;
      $query['CardType'] = 'PAYPAL';
      $query['PayPalCallbackURL'] = url('commerce-sagepay/paypal-callback/' . $order->order_id, array(
        'absolute' => TRUE,
      ));
      break;
    case SAGEPAY_TOKEN:
      $query['TxType'] = $tx_type;
      $query['Token'] = $saved_card_data->remote_id;
      $query['StoreToken'] = 1;

      // Disable CV2 check as we do not store this data in Card on File.
      $query['ApplyAVSCV2'] = 2;
  }
  switch ($cart_setting) {
    case 1:
      $query['Basket'] = $encoded_cart;
      break;
    case 2:
      $query['BasketXML'] = $encoded_cart;
      break;
  }

  // Add check for state for US addresses only.
  if ($billing_address['country'] == 'US') {
    $query['BillingState'] = $billing_address['administrative_area'];
    $query['DeliveryState'] = $billing_address['administrative_area'];
  }

  // Override with supplied delivery address if we have one.
  if (isset($delivery_address)) {
    $query['DeliverySurname'] = substr($delivery_address['last_name'], 0, 20);
    $query['DeliveryFirstnames'] = substr($delivery_address['first_name'], 0, 20);
    $query['DeliveryAddress1'] = $delivery_address['thoroughfare'];
    $query['DeliveryAddress2'] = $delivery_address['premise'];
    $query['DeliveryCity'] = $delivery_address['locality'];
    $query['DeliveryPostcode'] = _commerce_sagepay_ensure_postal_code($delivery_address);
    $query['DeliveryCountry'] = $delivery_address['country'];
    if ($delivery_address['country'] == 'US' && $delivery_address['administrative_area']) {
      $query['DeliveryState'] = $delivery_address['administrative_area'];
    }
  }

  // Call hook to allow other modules to modify order data before it is.
  $query['integration_method'] = $integration_method;
  drupal_alter('sagepay_order_data', $query, $order);

  // Invoke rules events which allow manipulation of the order data array.
  rules_invoke_all('commerce_sagepay_prepare_transaction', $query, $order);

  // Check if rules have added any overrides and merge these into the
  // transaction.
  if (isset($order->data['sagepay_overrides'])) {
    $query = array_merge($query, $order->data['sagepay_overrides']);
  }
  unset($query['integration_method']);

  // For Server mode, we can return the Array now before encryption.
  if (in_array($integration_method, array(
    SAGEPAY_SERVER,
    SAGEPAY_DIRECT,
    SAGEPAY_TOKEN,
    SAGEPAY_PAYPAL,
  ))) {
    return $query;
  }
  $keys = array_keys($query);
  $query_string = '';
  foreach ($keys as $key) {
    $query_string .= $key . '=' . $query[$key] . '&';
  }
  $query_string = substr($query_string, 0, strlen($query_string) - 1);

  // Encrypt order details using base64 and the secret key from the settings.
  switch (variable_get(SAGEPAY_SETTING_TRANSACTION_MODE)) {
    case SAGEPAY_TXN_MODE_LIVE:
      $encoded_string = _commerce_sagepay_encrypt_and_encode($query_string, variable_get(SAGEPAY_SETTING_ENCRYPTION_KEY));
      break;
    default:
      $encoded_string = _commerce_sagepay_encrypt_and_encode($query_string, variable_get(SAGEPAY_SETTING_TEST_ENCRYPTION_KEY));
  }
  return $encoded_string;
}