From efcb7c801cb871ba255d8e284f8cda7a59f6ea45 Mon Sep 17 00:00:00 2001
From: Rahul Bile <rahul.rmcet@gmail.com>
Date: Fri, 24 Jan 2014 19:25:43 +0530
Subject: [PATCH] RealVault system support

---
 commerce_realex.module              |   15 ++
 includes/commerce_realex_remote.inc |  310 ++++++++++++++++++++++++++++++++++-
 2 files changed, 324 insertions(+), 1 deletion(-)

diff --git a/commerce_realex.module b/commerce_realex.module
index 4d8aca1..600f78f 100644
--- a/commerce_realex.module
+++ b/commerce_realex.module
@@ -127,6 +127,21 @@ function _commerce_realex_build_request_sha1hash($request, $type = 'auth') {
       $hash = $request['timestamp'] . '.' . $request['merchantid'] . '.' . $request['orderid'] . '.' . $request['result'] . '.' . $request['message'] . '.' . $request['pasref'] . '.' . $request['authcode'];
       break;
 
+    case 'payer-new':
+      // timestamp.merchantid.orderid...payerref
+      $hash = $request['timestamp'] . '.' . $request['merchantid'] . '.' . $request['orderid'] . '.' . '.' . '.' . $request['payerref'];
+      break;
+
+    case 'card-new':
+      // timestamp.merchantid.orderid...payerref.chname.(card)number
+      $hash = $request['timestamp'] . '.' . $request['merchantid'] . '.' . $request['orderid'] . '.'  . '.'  . '.' . $request['payerref'] . '.' . $request['chname'] . '.' . $request['ccnumber'];
+      break;
+      
+    case 'receipt-in':
+      // timestamp.merchantid.orderid.amount.currency.payerref
+      $hash = $request['timestamp'] . '.' . $request['merchantid'] . '.' . $request['orderid'] . '.' . $request['amount'] . '.' . $request['currency'] . '.' . $request['payerref'];
+      break;
+
     case '3ds-verifysig':
     case 'auth':
     default:
diff --git a/includes/commerce_realex_remote.inc b/includes/commerce_realex_remote.inc
index 31ec6d3..050da9d 100644
--- a/includes/commerce_realex_remote.inc
+++ b/includes/commerce_realex_remote.inc
@@ -129,6 +129,34 @@ function commerce_realex_remote_commerce_payment_method_settings_form($settings
     '#required' => TRUE,
   );
 
+  $form['card_enable_realvault_request'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Enable RealVault request to create payer and card registration'),
+    '#default_value' => isset($settings['card_enable_realvault_request']) ? $settings['card_enable_realvault_request'] : FALSE,
+  );
+
+  $form['card_realvault_capture_first_payment'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Capture first payment by RealVault method.'),
+    '#default_value' => isset($settings['card_realvault_capture_first_payment']) ? $settings['card_realvault_capture_first_payment'] : FALSE,
+    '#states' => array(
+      'visible' => array(
+        ':input[name="parameter[payment_method][settings][payment_method][settings][card_enable_realvault_request]"]' =>  array('checked' => TRUE)
+      ),
+    ),
+  );
+
+  $form['card_realvault_request_url'] = array(
+    '#type' => 'textfield',
+    '#title' => t('The RealVault request URL'),
+    '#default_value' => isset($settings['card_realvault_request_url']) ?  $settings['card_realvault_request_url'] : 'https://epage.payandshop.com/epage-remote-plugins.cgi',
+     '#states' => array(
+      'visible' => array(
+        ':input[name="parameter[payment_method][settings][payment_method][settings][card_enable_realvault_request]"]' =>  array('checked' => TRUE)
+      ),
+    )
+  );
+
   $form['cctype_subaccounts_enabled'] = array(
     '#type' => 'checkbox',
     '#title' => t('Use separate accounts for each card type'),
@@ -328,6 +356,18 @@ function commerce_realex_remote_commerce_payment_method_submit_form_submit($paym
     }
   }
 
+  preg_match('/^(.+?)?([^\s,]+)$/', $request['chname'], $full_name);
+  $request['firstname'] = trim($full_name[1]);
+  $request['lastname'] = trim($full_name[2]);
+  $request['payerref'] = $request['lastname'] . substr($request['ccnumber'], -4);
+  $request['paymentmethod'] = $request['payerref'];
+  if(empty($request['amount'])) {
+    $request['amount'] = $order->commerce_order_total[LANGUAGE_NONE][0]['amount'];
+  }
+  if(empty($request['currency'])) {
+    $request['currency'] = $order->commerce_order_total[LANGUAGE_NONE][0]['currency_code'];
+  }  
+
   $request['products'] = implode(',', $products);
   $request['comments'][0] = t('Products purchased:') . ' ' . implode(', ', $comments);
   $request['log_message'] = '';
@@ -352,7 +392,21 @@ function commerce_realex_remote_commerce_payment_method_submit_form_submit($paym
       watchdog('commerce_realex', 'Card does not support 3D Secure, no liability shift (orderid: @order_id)', array('@order_id' => $order->order_id));
       $request['3dsecure'] = FALSE;
     }
-    commerce_realex_remote_do_auth_request($payment_method, $request, $order);
+    // If realVault system is enable, do the request
+    if ($payment_method['settings']['card_enable_realvault_request']) {
+      // Do new payer registration
+     commerce_realex_remote_do_payer_new_request($payment_method, $request, $order);
+ 
+     // Do new card registration
+     commerce_realex_remote_do_card_new_request($payment_method, $request, $order);
+ 
+     // If set to capture first payment, do the request receipt-in method.
+    if ($payment_method['settings']['card_realvault_capture_first_payment']) {
+       commerce_realex_remote_do_receipt_in_request($payment_method, $request, $order);
+     }
+    } else {
+      commerce_realex_remote_do_auth_request($payment_method, $request, $order);
+    }
   }
 
   return;
@@ -530,6 +584,107 @@ function commerce_realex_remote_get_dcc_offer($payment_method, $pane_values, &$o
 }
 
 /**
+ * Do a payer-new request.
+ */
+function commerce_realex_remote_do_payer_new_request($payment_method, $request, &$order) {
+  // Send the request.
+  $type = 'payer-new';
+  $url = $payment_method['settings']['card_realvault_request_url'];
+  $request['sha1hash'] = _commerce_realex_build_request_sha1hash($request, $type);
+  $xml = _commerce_realex_remote_build_xml_request($request, $type);
+  $response = _commerce_realex_send_request($url, $xml);
+
+  // Verify response.
+  $success = _commerce_realex_remote_verify_response($type, $request, $response, $order, $payment_method);
+
+  // Successful payer registration.
+  if ($success) {
+    $order->data['commerce_realex_remote']['payer-new'] = $response;
+  }
+
+  // New payer registration failure.
+  else {
+    drupal_set_message(t('We were unable to create new payer registration; reason provided by bank: %message. If the problem persists, contact us to complete your order.', array('%message' => $response['message'])), 'warning');
+    watchdog('commerce_realex', 'Payer registration  failed: %message', array('%message' => $response['message']), WATCHDOG_WARNING);
+    if (empty($_SESSION['realex_failures'])) {
+      $_SESSION['realex_failures'] = 0;
+    }
+    $_SESSION['realex_failures']++;
+    drupal_goto('checkout');
+  }
+}
+
+/**
+ * Do a card-new request.
+ */
+function commerce_realex_remote_do_card_new_request($payment_method, $request, &$order) {
+  // Send the request.
+  $type = 'card-new';
+  $url = $payment_method['settings']['card_realvault_request_url'];
+  $request['sha1hash'] = _commerce_realex_build_request_sha1hash($request, $type);
+  $xml = _commerce_realex_remote_build_xml_request($request, $type);
+  $response = _commerce_realex_send_request($url, $xml);
+
+  // Verify response.
+  $success = _commerce_realex_remote_verify_response($type, $request, $response, $order, $payment_method);
+
+  // Successful card registration.
+  if ($success) {
+    if(!$payment_method['settings']['card_realvault_capture_first_payment']) {
+      $response['payerref'] = $request['payerref'];
+      $response['cardref'] = $request['payerref'];
+      $transaction = commerce_realex_card_realvault_request_transaction_save($payment_method, $order, $response);
+    }
+    $order->data['commerce_realex_remote']['card-new'] = $response;
+  }
+
+  // Card registration failed
+  else {
+    drupal_set_message(t('We were unable to create new card registration; reason provided by bank: %message. If the problem persists, contact us to complete your order.', array('%message' => $response['message'])), 'warning');
+    watchdog('commerce_realex', 'Card registration  failed: %message', array('%message' => $response['message']), WATCHDOG_WARNING);
+    if (empty($_SESSION['realex_failures'])) {
+      $_SESSION['realex_failures'] = 0;
+    }
+    $_SESSION['realex_failures']++;
+    drupal_goto('checkout');
+  }
+}
+
+/**
+ * Do a payment receipt_in request.
+ */
+function commerce_realex_remote_do_receipt_in_request($payment_method, $request, &$order) {
+  // Send the request.
+  $type = 'receipt-in';
+  $url = $payment_method['settings']['card_realvault_request_url'];
+  $request['sha1hash'] = _commerce_realex_build_request_sha1hash($request, $type);
+  $xml = _commerce_realex_remote_build_xml_request($request, $type);
+  $response = _commerce_realex_send_request($url, $xml);
+  // Verify response.
+  $success = _commerce_realex_remote_verify_response($type, $request, $response, $order, $payment_method);
+
+  // Successful payment.
+  if ($success) {
+    $response['payerref'] = $request['payerref'];
+    $response['cardref'] = $request['payerref'];
+    // Save the transaction.
+    $transaction = commerce_realex_realvault_remote_transaction_save($payment_method, $order, $response);
+    $order->data['commerce_realex_realvault_remote']['transaction'] = $transaction;
+  }
+
+  // Payment failure.
+  else {
+    drupal_set_message(t('We were unable to process your credit card payment; reason provided by bank: %message. If the problem persists, contact us to complete your order.', array('%message' => $response['message'])), 'warning');
+    watchdog('commerce_realex', 'Payment failed: %message', array('%message' => $response['message']), WATCHDOG_WARNING);
+    if (empty($_SESSION['realex_failures'])) {
+      $_SESSION['realex_failures'] = 0;
+    }
+    $_SESSION['realex_failures']++;
+    drupal_goto('checkout');
+  }
+}
+
+/**
  * Process the Realex response.
  *
  * @param $type
@@ -601,6 +756,12 @@ function _commerce_realex_remote_build_xml_request($request, $type) {
       return _commerce_realex_remote_build_xml_request_3dsecure_verifysig($request);
     case '3ds-verifyenrolled':
       return _commerce_realex_remote_build_xml_request_3dsecure_verifyenrolled($request);
+    case 'payer-new':
+      return _commerce_realex_remote_build_xml_request_payer_new($request);
+    case 'card-new':
+      return _commerce_realex_remote_build_xml_request_card_new($request);
+    case 'receipt-in':
+      return _commerce_realex_remote_build_xml_request_receipt_in($request);
     case 'auth':
     default:
       return _commerce_realex_remote_build_xml_request_auth($request);
@@ -740,6 +901,64 @@ function _commerce_realex_remote_build_xml_request_dccrate($request) {
   return $xml;
 }
 
+/**
+ * Generate an "payer-new" xml request.
+ */
+function _commerce_realex_remote_build_xml_request_payer_new($request) {
+  $xml = "<request type='payer-new' timestamp='" . $request['timestamp'] . "'>
+    <merchantid>" . $request['merchantid'] . "</merchantid>
+    <account>" . $request['account'] . "</account>
+    <orderid>" . $request['orderid'] . "</orderid>
+    <payer type='Business' ref='" . $request['payerref'] . "'>
+      <firstname>" . $request['firstname'] . "</firstname>
+      <lastname>" . $request['lastname'] . "</lastname>
+    </payer>
+    <sha1hash>" . $request['sha1hash'] . "</sha1hash>
+  </request>";
+
+  return $xml;
+}
+
+/**
+ * Generate an "receipt-in" xml request.
+ */
+function _commerce_realex_remote_build_xml_request_receipt_in($request) {
+  $xml = "<request type='receipt-in' timestamp='" . $request['timestamp'] . "'>
+    <merchantid>" . $request['merchantid'] . "</merchantid>
+    <account>" . $request['account'] . "</account>
+    <orderid>" . $request['orderid'] . "</orderid>
+    <autosettle flag='1'/>
+    <amount currency='" . $request['currency'] . "'>" . $request['amount'] . "</amount>
+    <payerref>" . $request['payerref'] . "</payerref>
+    <paymentmethod>" . $request['paymentmethod'] . "</paymentmethod>
+    <sha1hash>" . $request['sha1hash'] . "</sha1hash>
+  </request>";
+
+  return $xml;
+}
+
+/**
+ * Generate an "card-new" xml request.
+ */
+function _commerce_realex_remote_build_xml_request_card_new($request) {
+  $xml = "<request type='card-new' timestamp='" . $request['timestamp'] . "'>
+    <merchantid>" . $request['merchantid'] . "</merchantid>
+    <account>" . $request['account'] . "</account>
+    <orderid>" . $request['orderid'] . "</orderid>
+    <card>
+      <ref>" . $request['payerref'] . "</ref>
+      <payerref>" . $request['payerref'] . "</payerref>
+      <number>" . $request['ccnumber'] . "</number>
+      <expdate>" . $request['expiry_date'] ."</expdate>
+      <chname>" . $request['chname'] . "</chname>
+      <type>" . $request['cctype'] . "</type>
+      <issueno/>
+    </card>
+    <sha1hash>" . $request['sha1hash'] . "</sha1hash>
+  </request>";
+
+  return $xml;
+}
 
 /**
  * Save the transaction and update the order.
@@ -792,3 +1011,92 @@ function commerce_realex_remote_transaction_save($payment_method, $order, $respo
   return $transaction;
 }
 
+/**
+ * Save the realvault transaction and update the order.
+ *
+ * @param $payment_method
+ *   Payment method array.
+ * @param $order
+ *   Commerce order object.
+ * @param $response
+ *   Response data.
+ */
+function commerce_realex_realvault_remote_transaction_save($payment_method, $order, $response) {
+  $transaction = commerce_payment_transaction_new('commerce_realex_remote', $order->order_id);
+  $transaction->amount = $order->commerce_order_total['und'][0]['amount'];
+  $transaction->currency_code = $order->commerce_order_total['und'][0]['currency_code'];
+  $transaction->instance_id = $payment_method['instance_id'];
+  $transaction->remote_id = $response['orderid'];
+
+  // Set the payment status.
+  switch ($response['result']) {
+    case '00':
+      $transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
+      break;
+    default:
+      $transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
+  }
+
+  // Log the response variables.
+  $transaction->message = 'Status @resultcode, @message. Order ID: @orderid, Auth code: @authcode, Timestamp: @timestamp, Card ref: @cardref, Payer ref: @payerref, Pasref: @pasref, Address check: @address, Postcode check: @postcode, CVN result: @cvn';
+  $transaction->message_variables = array(
+    '@resultcode' => $response['result'],
+    '@message' => $response['message'],
+    '@orderid' => $response['orderid'],
+    '@authcode' => $response['authcode'],
+    '@payerref' => $response['payerref'],
+    '@cardref' => $response['cardref'],
+    '@timestamp' => $response['timestamp'],
+    '@pasref' => $response['pasref'],
+    '@address' => $response['avsaddressresponse'],
+    '@postcode' => $response['avspostcoderesponse'],
+    '@cvn' => $response['cvnresult'],
+  );
+
+  commerce_payment_transaction_save($transaction);
+
+  return $transaction;
+}
+
+/**
+ * Save the realvault transaction and update the order.
+ *
+ * @param $payment_method
+ *   Payment method array.
+ * @param $order
+ *   Commerce order object.
+ * @param $response
+ *   Response data.
+ */
+function commerce_realex_card_realvault_request_transaction_save($payment_method, $order, $response) {
+  $transaction = commerce_payment_transaction_new('commerce_realex_remote', $order->order_id);
+  $transaction->amount = $order->commerce_order_total['und'][0]['amount'];
+  $transaction->currency_code = $order->commerce_order_total['und'][0]['currency_code'];
+  $transaction->instance_id = $payment_method['instance_id'];
+  $transaction->remote_id = $response['orderid'];
+
+  // Set the payment status.
+  switch ($response['result']) {
+    case '00':
+      $transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
+      break;
+    default:
+      $transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
+  }
+
+  // Log the response variables.
+  $transaction->message = 'Status @resultcode, @message. Order ID: @orderid, Card ref: @cardref, Payer ref: @payerref,Timestamp: @timestamp, Pasref: @pasref';
+  $transaction->message_variables = array(
+    '@resultcode' => $response['result'],
+    '@message' => $response['message'],
+    '@payerref' => $response['payerref'],
+    '@cardref' => $response['cardref'],
+    '@orderid' => $response['orderid'],
+    '@timestamp' => $response['timestamp'],
+    '@pasref' => $response['pasref'],
+  );
+
+  commerce_payment_transaction_save($transaction);
+
+  return $transaction;
+}
\ No newline at end of file
-- 
1.7.10.4

