You are here

commerce_robokassa.module in Commerce robokassa 7

Same filename and directory in other branches
  1. 7.2 commerce_robokassa.module

File

commerce_robokassa.module
View source
<?php

module_load_include('inc', 'commerce_robokassa', 'includes/commerce_robokassa.admin');

/**
 * Implements hook_menu().
 */
function commerce_robokassa_menu() {
  $items['robokassa/result'] = array(
    'title' => 'Result of payment through robokassa Merchant',
    'page callback' => 'commerce_robokassa_result',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  $items['robokassa/success'] = array(
    'title' => 'Successful payment',
    'page callback' => 'commerce_robokassa_success',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
  );
  $items['robokassa/fail'] = array(
    'title' => 'Unsuccessful payment',
    'page callback' => 'commerce_robokassa_fail',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implements hook_commerce_payment_method_info().
 */
function commerce_robokassa_commerce_payment_method_info() {
  $payment_methods = array();
  $payment_methods['commerce_robokassa'] = array(
    'base' => 'commerce_robokassa',
    'title' => t('Robokassa'),
    'short_title' => t('Robokassa'),
    'display_title' => t('Robokassa'),
    'description' => t('Integrates Robokassa Merchant'),
    'terminal' => FALSE,
    'offsite' => TRUE,
    // @todo Maybe better make it auto?

    //'offsite_autoredirect' => TRUE,
    'active' => TRUE,
  );
  return $payment_methods;
}

/**
 * Payment method callback; generation callback for the payment submission form.
 *
 * @param $payment_method
 *   An array of the current settings.
 * @param $pane_values
 *   The current values of the pane.
 * @param $checkout_pane
 *   The checkout pane array.
 * @param $order
 *   The order object.
 *
 * @return
 *   A form snippet for the checkout pane.
 */
function commerce_robokassa_submit_form($payment_method, $pane_values, $checkout_pane, $order) {
  $build = array();
  $text = theme('image', array(
    'path' => drupal_get_path('module', 'commerce_robokassa') . '/logo.gif',
    'alt' => t('Robokassa'),
    'title' => t('Robokassa'),
    'attributes' => array(
      'class' => 'logo-robokassa',
    ),
  ));
  $text .= '<div class="desc">' . t('Robokassa - Organization of the electronic payments receiving.') . '</div>';
  $build['print_receipt'] = array(
    '#markup' => $text,
  );
  return $build;
}

/**
 * Payment method callback: redirect form.
 *
 * A wrapper around the module's general use function for building a submit form.
 */
function commerce_robokassa_redirect_form($form, &$form_state, $order, $payment_method) {
  return commerce_robokassa_build_redirect_form($form, $form_state, $order, $payment_method['settings']);
}

/**
 * Payment method callback; generation callback for the payment redirect form.
 *
 * Returns form elements that should be submitted to the redirected payment
 * service; because of the array merge that happens upon return, the service’s
 * URL that should receive the POST variables should be set in the #action
 * property of the returned form array.
 */
function commerce_robokassa_build_redirect_form($form, &$form_state, $order, $settings) {

  // Choose a server to redirect.
  $form['#action'] = commerce_robokassa_server_url($settings['server']);
  $wrapper = entity_metadata_wrapper('commerce_order', $order);
  $currency_code = $wrapper->commerce_order_total->currency_code
    ->value();
  $amount = $wrapper->commerce_order_total->amount
    ->value();

  // Get real price.
  $amount = commerce_currency_amount_to_decimal($amount, $currency_code);
  $form["MrchLogin"] = array(
    '#type' => 'hidden',
    '#value' => commerce_robokassa_get_settings('login'),
  );
  $form["OutSum"] = array(
    '#type' => 'hidden',
    '#value' => $amount,
  );
  $form["InvId"] = array(
    '#type' => 'hidden',
    '#value' => $order->order_id,
  );

  // Calculate signature.
  $form["SignatureValue"] = array(
    '#type' => 'hidden',
    '#value' => md5(commerce_robokassa_get_settings('login') . ':' . $amount . ':' . $order->order_id . ':' . commerce_robokassa_get_settings('pass1')),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Pay via robokassa'),
  );
  return $form;
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Removes drupal-related form_ids from final redirect.
 */
function commerce_robokassa_form_commerce_checkout_form_payment_alter(&$form, &$form_state, $form_id) {
  unset($form["#form_id"]);
  unset($form["form_id"]);
  unset($form["form_token"]);
  unset($form["form_build_id"]);
}

/**
 * Helper to returs statuses.
 */
function commerce_robokassa_statuses() {
  $options = array();
  $statuses = commerce_payment_transaction_statuses();
  if (!empty($statuses)) {
    foreach ($statuses as $status) {
      $options[$status['status']] = $status['title'];
    }
  }
  return $options;
}

/**
 * Helper to return setting from variable.
 *
 * @param $settings name of the setting's key.
 *
 * @return setting value.
 */
function commerce_robokassa_get_settings($settings) {
  $output = '';
  $vars = variable_get('commerce_robokassa_settings', '');
  if (!empty($vars)) {
    foreach ($vars as $key => $var) {
      if ($key == $settings) {
        $output = $vars[$key]['#default_value'];
        break;
      }
    }
  }
  return $output;
}

/**
 * Success page callback handler.
 */
function commerce_robokassa_success() {
  $build = array();
  if (isset($_POST['InvId']) && isset($_POST['OutSum']) && isset($_POST['SignatureValue'])) {
    $message = t('Thank you, payment successful. Order #@shop_order,<br />', array(
      '@shop_order' => $_POST['InvId'],
    ));
    drupal_set_message($message, 'status');
    if ($message = commerce_robokassa_get_settings('success_message')) {
      $build['message_success']['#markup'] = $message;
    }
  }
  else {
    $build = MENU_ACCESS_DENIED;
  }
  return $build;
}

/**
 * Fail page callback handler.
 */
function commerce_robokassa_fail() {
  drupal_set_message(t('Payment unsuccessful!'), 'error');
  $build = array();
  if ($message = commerce_robokassa_get_settings('fail_message')) {
    $build['message_fail']['#markup'] = $message;
  }
  return $build;
}

/**
 * Page callback to receive payment notification from robokassa.
 */
function commerce_robokassa_result() {
  if (!empty($_POST)) {

    // @todo check data first.

    //Are we really send OK if no processing happen?
    echo 'OK' . $_POST['InvId'];

    // Get robokassa variables.
    $order_in = $_POST['InvId'];
    $amount_in = $_POST['OutSum'];
    $signature_in = $_POST['SignatureValue'];

    // Calculate the hash.
    $pass = commerce_robokassa_get_settings('pass2');
    $md5string = $amount_in . ':' . $order_in . ':' . $pass;
    $md5 = strtoupper(md5($md5string));
    if ($md5 == $signature_in) {
      $order = commerce_order_load($order_in);
      $wrapper = entity_metadata_wrapper('commerce_order', $order);
      $currency_code = $wrapper->commerce_order_total->currency_code
        ->value();
      $amount = $wrapper->commerce_order_total->amount
        ->value();

      // Get real price.
      $amount = commerce_currency_amount_to_decimal($amount, $currency_code);
      $amount_received = abs($amount_in);
      $amount_stored = abs($amount);
      if ($amount_received == $amount_stored) {
        commerce_robokassa_create_transaction($order_in, commerce_robokassa_get_settings('status'));
        watchdog('commerce_robokassa', 'Order #@order paid successfully.', array(
          '@order' => $order_in,
        ), WATCHDOG_INFO);
      }
      else {
        watchdog('commerce_robokassa', 'Order #@order was not paid: recieved (@am_rec) and real(@am_int) order info do not match.', array(
          '@order' => $order_in,
          '@am_rec' => $amount_in,
          '@am_int' => $amount,
        ), WATCHDOG_ERROR);
      }
    }
    else {
      watchdog('commerce_robokassa', 'Wrong signature received. %sig_int != %sig_in (request data @data)', array(
        '%sig_int' => $md5,
        '%sig_in' => $signature_in,
        '@data' => $md5string,
      ), WATCHDOG_ERROR);
    }
  }
}

/**
 * Creates an robokassa payment transaction for the specified charge amount.
 *
 * @param $payment_method
 *   The payment method instance object used to charge this payment.
 * @param $order
 *   The order object the payment applies to.
 * @param $charge
 *   An array indicating the amount and currency code to charge.
 * @param $name
 *   The name entered on the submission form.
 */
function commerce_robokassa_create_transaction($order_id, $status) {
  $order = commerce_order_load($order_id);
  $payment_method = commerce_payment_method_instance_load($order->data['payment_method']);
  $transaction = commerce_payment_transaction_new('commerce_robokassa', $order->order_id);
  $transaction->instance_id = $payment_method['instance_id'];
  $wrapper = entity_metadata_wrapper('commerce_order', $order);
  $currency_code = $wrapper->commerce_order_total->currency_code
    ->value();
  $amount = $wrapper->commerce_order_total->amount
    ->value();

  //$transaction->amount = $order->commerce_order_total[LANGUAGE_NONE][0]['amount'];

  //$transaction->currency_code = $order->commerce_order_total[LANGUAGE_NONE][0]['currency_code'];

  // @doto Sheck statuses deeper
  $transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
  $transaction->message = '';
  $transaction->message_variables = array();
  commerce_payment_transaction_save($transaction);

  // @doto is this actually need?
  rules_invoke_all('commerce_checkout_complete', $order);
}

/**
 * Returns the URL to the specified Robokassa server.
 *
 * @param $server
 *   Either test or live indicating which server to get the URL for.
 *
 * @return
 *   The URL to use to submit requests to the Robokassa server.
 */
function commerce_robokassa_server_url($server) {
  switch ($server) {
    case 'test':
      return 'http://test.robokassa.ru/Index.aspx';
    case 'live':
      return 'https://merchant.roboxchange.com/Index.aspx';
  }
}

Functions

Namesort descending Description
commerce_robokassa_build_redirect_form Payment method callback; generation callback for the payment redirect form.
commerce_robokassa_commerce_payment_method_info Implements hook_commerce_payment_method_info().
commerce_robokassa_create_transaction Creates an robokassa payment transaction for the specified charge amount.
commerce_robokassa_fail Fail page callback handler.
commerce_robokassa_form_commerce_checkout_form_payment_alter Implements hook_form_FORM_ID_alter().
commerce_robokassa_get_settings Helper to return setting from variable.
commerce_robokassa_menu Implements hook_menu().
commerce_robokassa_redirect_form Payment method callback: redirect form.
commerce_robokassa_result Page callback to receive payment notification from robokassa.
commerce_robokassa_server_url Returns the URL to the specified Robokassa server.
commerce_robokassa_statuses Helper to returs statuses.
commerce_robokassa_submit_form Payment method callback; generation callback for the payment submission form.
commerce_robokassa_success Success page callback handler.