cancel
Showing results for 
Search instead for 
Did you mean: 

ARB transaction key & login. E00007

We are using Drupal with the Commerce Module to integrate with Authorize.net. Recently, recurring payment subscriptions stopped working, giving E00007. One-time payments are working correctly.We have verified that the API Login ID and transaction key are correct (they match the values used for one-time payments and were typed in manually, not pasted). Removing the API Login ID and transaction key results in E00006, as expected.

 

We have this successfully working with a test account on sandbox.authorize.net. Any help/suggestions would be greatly appreciated!

 

Here is the "Create Subscription Request:"

AuthorizeNetARB::__set_state(array( '_request_type' => 'CreateSubscriptionRequest', '_request_payload' => '<refId>35626</refId><subscription> <name>pioneer_fund_recurring_gift</name> <paymentSchedule> <interval> <length>7</length> <unit>days</unit> </interval> <startDate>2013-12-19</startDate> <totalOccurrences>2</totalOccurrences> </paymentSchedule> <amount>1</amount> <payment> <creditCard> <cardNumber>xxxxxxxxxxxxxxxx</cardNumber> <expirationDate>xxxx-xx</expirationDate> <cardCode>xxx</cardCode> </creditCard> </payment> <order> <invoiceNumber>356</invoiceNumber> <description>fbd39331-9cd1-45ac-9fff-904a8441df48</description> </order> <customer> <id>1</id> <email>admin@example.com</email> </customer> <billTo> <firstName>doug</firstName> <lastName>promet</lastName> <address>1802 w berteau #209</address> <city>Chicago</city> <state>IL</state> <zip>60613</zip> <country>US</country> </billTo> </subscription> ', '_api_login' => 'xxxxxxxx', '_transaction_key' => 'xxxxxxxxxxxxxxxx', '_post_string' => '<?xml version="1.0" encoding="utf-8"?> <ARBCreateSubscriptionRequest xmlns= "AnetApi/xml/v1/schema/AnetApiSchema.xsd"> <merchantAuthentication> <name>xxxxxxxx</name> <transactionKey>xxxxxxxxxxxxxxxx</transactionKey> </merchantAuthentication> <refId>35626</refId><subscription> <name>pioneer_fund_recurring_gift</name> <paymentSchedule> <interval> <length>7</length> <unit>days</unit> </interval> <startDate>2013-12-19</startDate> <totalOccurrences>2</totalOccurrences> </paymentSchedule> <amount>1</amount> <payment> <creditCard> <cardNumber>xxxxxxxxxxxxxxxx</cardNumber> <expirationDate>xxxx-xx</expirationDate> <cardCode>xxx</cardCode> </creditCard> </payment> <order> <invoiceNumber>356</invoiceNumber> <description>fbd39331-9cd1-45ac-9fff-904a8441df48</description> </order> <customer> <id>1</id> <email>admin@example.com</email> </customer> <billTo> <firstName>doug</firstName> <lastName>promet</lastName> <address>1802 w berteau #209</address> <city>Chicago</city> <state>IL</state> <zip>60613</zip> <country>US</country> </billTo> </subscription> </ARBCreateSubscriptionRequest>', 'VERIFY_PEER' => true, '_sandbox' => true, '_log_file' => false, 'setSandbox' => false, ))

 Here is the "Create Subscription Response:"

AuthorizeNetARB_Response::__set_state(array( 'xml' => SimpleXMLElement::__set_state(array( 'refId' => '35626', 'messages' => SimpleXMLElement::__set_state(array( 'resultCode' => 'Error', 'message' => SimpleXMLElement::__set_state(array( 'code' => 'E00007', 'text' => 'User authentication failed due to invalid authentication values.', )), )), )), 'response' => '<?xml version="1.0" encoding="utf-8"?><ARBCreateSubscriptionResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"><refId>35626</refId><messages><resultCode>Error</resultCode><message><code>E00007</code><text>User authentication failed due to invalid authentication values.</text></message></messages></ARBCreateSubscriptionResponse>', 'xpath_xml' => SimpleXMLElement::__set_state(array( 'refId' => '35626', 'messages' => SimpleXMLElement::__set_state(array( 'resultCode' => 'Error', 'message' => SimpleXMLElement::__set_state(array( 'code' => 'E00007', 'text' => 'User authentication failed due to invalid authentication values.', )), )), )), ))

 Here are the commerce_authnet_arb API Calls:

<?php



/*
 * Send a subsription request to Authnet
 *
 * Return a subscription array or show error and return FALSE
 *
 *
 */
function commerce_authnet_arb_create_subscription($order, $pane_values, $charge) {
  if ($charge['currency_code'] != 'USD') {
    drupal_set_message('Only USD payments can be processed by recurring payments system.' ,'error');
    return FALSE;
  }

  $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
  $customer_wrapper = entity_metadata_wrapper('user', user_load($order_wrapper->uid->value()));
  $billing_wrapper = entity_metadata_wrapper('commerce_customer_profile', $order_wrapper->commerce_customer_billing->value());
  $amount = $order_wrapper->commerce_order_total->amount->value();
  $line_items = $order_wrapper->commerce_line_items->value();


  $settings = commerce_authnet_arb_settings();
  require_once commerce_authnet_arb_sdk_path().'/AuthorizeNet.php';


  $subscription                          = new AuthorizeNet_Subscription;
  $subscription->name                    = $order_wrapper->uuid->value(); // @todo smth else.
  $subscription->amount                  = commerce_currency_amount_to_decimal($amount, $charge['currency_code']);
  $subscription->orderInvoiceNumber      = $order->order_id;
  $subscription->orderDescription        = $order_wrapper->uuid->value();

  // Payment Schedule.
  $startDate = date('Y-m-d', strtotime($line_items[0]->field_gift_line_item_arb_start[LANGUAGE_NONE][0]['value']));

  $subscription->intervalLength          = $line_items[0]->field_gift_line_item_int_length[LANGUAGE_NONE][0]['value'];
  $subscription->intervalUnit            = $line_items[0]->field_gift_line_item_int_unit[LANGUAGE_NONE][0]['value'];
  $subscription->startDate               = $startDate;
  $subscription->totalOccurrences        = $line_items[0]->field_gift_line_item_occurences[LANGUAGE_NONE][0]['value'];

  // CC Data.
  // @todo CIM
  $subscription->creditCardExpirationDate = $pane_values['credit_card']['exp_year'] . '-' . $pane_values['credit_card']['exp_month'];
  $subscription->creditCardCardNumber     = $pane_values['credit_card']['number'];
  $subscription->creditCardCardCode       = $pane_values['credit_card']['code'];

  // Customer Data.
  // @todo - CIM;
  $billing_address = $billing_wrapper->commerce_customer_address->value();

  $subscription->customerId = $customer_wrapper->uid->value();
  $subscription->customerEmail = $customer_wrapper->mail->value();

  // mapping default commerce profile fields
  $subscription->billToFirstName = $billing_wrapper->field_name_first->value();
  $subscription->billToLastName = $billing_wrapper->field_name_last->value();

  $subscription->billToAddress = $billing_address['thoroughfare'];
  $subscription->billToCity = $billing_address['locality'];
  $subscription->billToState = $billing_address['administrative_area'];
  $subscription->billToZip = $billing_address['postal_code'];
  $subscription->billToCountry = $billing_address['country'];

  drupal_alter('arb_subscription_request', $subscription, $order, $pane_values);

  // Create the subscription.
  $request = new AuthorizeNetARB($settings['login'], $settings['tran_key']);
  $request->setSandbox = !empty($settings['sandbox']);


  // If RefId included in the request, this value is included in the response.
  //   pass order_id to recognize it in response.
    $request->setRefId($order->order_id . rand(0, 100));

    $response = $request->createSubscription($subscription);

  if ($settings['watchdog_all']) {
    watchdog('commerce_authnet_arb', t('Create subscription request:<br> @var', array('@var' => var_export($request ,TRUE))));
    watchdog('commerce_authnet_arb', t('Create Subscription response:<br> @var', array('@var' => var_export($response ,TRUE))));
  }

  if ($response->isOk()) {
    // ToDo: create and save a commerce transaction
    $subscription_complete = $subscription;
    $subscription_complete->response = array(
      'xml' => $response->response,
      'RefID' => $response->getRefID(),
      'ResultCode' => $response->getResultCode(),
      'SubscriptionId' => $response->getSubscriptionId(),
      'SubscriptionStatus' => $response->getSubscriptionStatus(),
    );


    $order->data['commerce_authnet_arb']['subscription'] = $subscription_complete;
    commerce_order_save($order);

    drupal_set_message(t('Recurring payments is set. First time payment will be charged @startDate.', array('@startDate' => $subscription->startDate)));
    return $subscription_complete;
  }
  else {
    drupal_set_message(t('Recurring payment error: @error', array('@error' => $response->getMessageText())) ,'error');
    return FALSE;
  }
}

// not implemented yet
function commerce_authnet_arb_update_subscription () {

}

// not implemented yet
function commerce_authnet_arb_delete_subscription () {

}


/*
 * Validate is card can be processed by authnet payment gateway
 */
function commerce_authnet_arb_verify_payment ($charge, $card, &$response = array()) {
  if ($charge['currency_code'] != 'USD') {
    drupal_set_message('Only USD payments can be processed by authorize.net.' ,'error');
    return FALSE;
  }

  require_once commerce_authnet_arb_sdk_path().'/AuthorizeNet.php';
  $settings = commerce_authnet_arb_settings();

  //$auth = new AuthorizeNetAIM;
  $auth = new AuthorizeNetAIM($settings['login'], $settings['tran_key']);
  $auth->invoice_num = time();

  if ($settings['sandbox']) {
    $auth->setSandbox(TRUE);
  }
  else {
    $auth->setSandbox(FALSE);
  }

  $auth->amount = $charge['amount']/100;
  $auth->card_num = $card['number'];
  $auth->exp_date = $card['exp_year'].'-'.$card['exp_month'];

  if ($settings['watchdog_all']) {
    watchdog('commerce_authnet_arb', t('CC verification request:<br> @var', array('@var' => var_export($auth ,TRUE))));
  }

  $response = $auth->authorizeOnly();
  if ($settings['watchdog_all']) {
    watchdog('commerce_authnet_arb', t('CC verification response:<br> @var', array('@var' => var_export($response ,TRUE))));
  }
  if ($response->approved) {
    $return = TRUE;
  }
  elseif ($response->error) {
    drupal_set_message($response->error_message , 'error');
    $return = FALSE;
  }
  elseif ($response->declined) {
    drupal_set_message('Credit card declined' , 'error');
    $return = FALSE;
  }

  if ($response->approved || $response->declined) {
    // Cancel authorize transaction by using void:
    //  This transaction type can be used to cancel either an original transaction that is not yet settled or an
    //  entire order composed of more than one transaction. A Void prevents the transaction or the order
    //  from being sent for settlement. A Void can be submitted against any other transaction type.
    $void = new AuthorizeNetAIM($settings['login'], $settings['tran_key']);
    $void_response = $void->void($response->transaction_id);
  }

  return $return;
}

 Code for the payment method form:

<?php
/*
 * Integration with a commerce framework
 */

/**
 * Payment method configuration form.
 */
function commerce_authnet_arb_settings_form($settings = NULL) {

  $settings = (array) $settings + commerce_authnet_arb_settings(TRUE);

  $form = array();

  $form['login'] = array(
    '#title' => t('API Login ID'),
    '#type' => 'textfield',
    '#default_value' => $settings['login'],
    '#description' => t('Your API Login ID is different from the username you use to login to your Authorize.Net account.
      Once you login, browse to your Account tab and click the API Login ID and Transaction Key link to find your API Login ID.
      If you are using a new Authorize.Net account, you may still need to generate an ID.'),
  );

  $form['tran_key'] = array(
    '#title' => t('Transaction Key'),
    '#type' => 'textfield',
    '#default_value' => $settings['tran_key'],
    '#description' => t('Your Transaction Key can be found on the same screen as your API Login ID.
      However, it will not be readily displayed. You must answer your security question and submit a form to see your Transaction Key.'),
  );

  $form['sandbox'] = array(
    '#title' => t('Sandbox Mode'),
    '#type' => 'checkbox',
    '#default_value' => $settings['sandbox'],
    '#description' => t('In sandbox mode the module interact with authnet development test server.'),
  );

  // ToDo: add a status report notification to check is MD5 Hash Secret Value is configured.
  $form['md5_hash'] = array(
    '#title' => t('MD5 Hash Secret Value'),
    '#type' => 'textfield',
    '#default_value' => $settings['md5_hash'],
    '#description' =>
    t('The MD5 Hash Value, which is assigned by the merchant in the account\'s Settings.
      MD5 Hash Value can be up to 20 characters long, including upper- and lower-case letters, numbers, spaces, and punctuation.
      More complex values will be more secure.
      The MD5 Hash option allows your script to verify that the results of a transaction are actually from Authorize.Net.
      If the MD5 Hash the module creates matches the MD5 Hash received, then the module know that the transaction response was sent by Authorize.Net.
      Enter here the same value you have entered in Authorize.Net account settings.
      IT IS NOT REQUIRED, BUT STRONGLY RECOMMENDED TO USE FOR SECURING REASONS.'),
  );

  $form['watchdog_all'] = array(
    '#title' => t('Log all requests, responses and silentpost requests'),
    '#type' => 'checkbox',
    '#default_value' => $settings['watchdog_all'],
  );

  return $form;
}


/**
 * Payment method callback: submit form. -- Payment Pane.
 */
function commerce_authnet_arb_submit_form($payment_method, $pane_values, $checkout_pane, $order) {
  $form = array();
  module_load_include('module', 'commerce_authnet', 'commerce_authnet');
  $form = commerce_authnet_aim_submit_form($payment_method, $pane_values, $checkout_pane, $order);
  $recurring = array();
  // allow hooks to alter the pane,
  //   usefull if you want to set payments period and step based on product or any other order data
  //$recurring = module_invoke_all('commerce_authnet_arb_commerce_set_recurring', $order);
  //$form['recurring_options'] = commerce_authnet_arb_recurring_info_section($recurring);
  return $form;
}

/**
 * Payment method callback: submit form validation. -- Payment Pane
 */
function commerce_authnet_arb_submit_form_validate($payment_method, $pane_form, $pane_values, $order, $form_parents = array()) {
  module_load_include('module', 'commerce_authnet', 'commerce_authnet');

  $valid = TRUE;

  if (commerce_authnet_aim_submit_form_validate($payment_method, $pane_form, $pane_values, $order, $form_parents) === FALSE) {
    return FALSE;
  }

  // Validating recurring settings.
  //if (commerce_authnet_arb_recurring_info_section_validation($pane_values['recurring_options'], $form_parents) === FALSE) {
  //  return FALSE;
 // }

  // Validate card processing
  $charge = commerce_payment_order_balance($order);
  // If the line items was not added yet, set amount to $0.01
  if (empty($charge['amount'])) {
    $charge['amount'] = '1';
  }
  /*if (!commerce_authnet_arb_verify_payment($charge, $pane_values['credit_card'])) {
    $prefix = implode('][', $form_parents) . '][';
    form_set_error($prefix, 'The card can\' be autorized.');
    return FALSE;
  }*/
  return $valid;
}

/**
 * Payment method callback: submit form submission. -- Payment Pane.
 */
function commerce_authnet_arb_submit_form_submit($payment_method, $pane_form, $pane_values, &$order, $charge) {
  module_load_include('inc', 'commerce_authnet_arb', 'commerce_authnet_arb.api_calls');
  return commerce_authnet_arb_create_subscription($order, $pane_values, $charge);
}




/*
 * Form pane to set reccuring settings
 */
function commerce_authnet_arb_recurring_info_section($recurring = array()) {

  // ToDo: use #element_validate
  $form = array();

  $form['commerce_authnet_arb_period'] = array(
    '#type' => 'select',
    '#title' => t('Period'),
    '#options' => array(
      'days' => t('Daily'),
      'months' => t('Monthly')
    ),
    '#default_value' => 'none',
  );
  if (isset($recurring['period']) && !empty($form['commrce_authnet_arb_period']['#options'][$recurring['period']])) {
    $form['commerce_authnet_arb_period']['#value'] = $recurring['period'];
    $form['commerce_authnet_arb_period']['#access'] = FALSE;
  }

  $form['commerce_authnet_arb_interval_step'] = array(
    '#type' => 'textfield',
    '#size' => 3,
    '#title' => t('Interval'),
    '#description' => t('An interval value must be behind 1 and 12 for monthly payments or behind 7 and 365 for daily payments.'),
  );

  if (isset($recurring['step'])) {
    $form['commerce_authnet_arb_interval_step']['#value'] = $recurring['step'];
    $form['commerce_authnet_arb_interval_step']['#access'] = FALSE;
  }

  return $form;
}

/*
 * Validation callback for reccuring settings
 */
function commerce_authnet_arb_recurring_info_section_validation ($pane_values, $form_parents = array()) {
  $prefix = implode('][', $form_parents) . '][recurring_options][';

  $valid = TRUE;

  // if period is set, interval is requered
  if($pane_values['commerce_authnet_arb_period'] == 'days' || $pane_values['commerce_authnet_arb_period'] == 'months') {
    // perform validation only if allowed requring period passed
    if (empty($pane_values['commerce_authnet_arb_interval_step'])) {
      $valid = FALSE;
      form_set_error($prefix.'commerce_authnet_arb_interval_step', t('Recurring interval is required if the Recurring perion is selected.'));
    }

    if ($pane_values['commerce_authnet_arb_period'] == 'days' &&
      ($pane_values['commerce_authnet_arb_interval_step'] < 7 || $pane_values['commerce_authnet_arb_interval_step'] > 365)) {
      $valid = FALSE;
      form_set_error($prefix.'commerce_authnet_arb_interval_step', t('Recurring interval value must be behind 7 and 365 for daily interval.'));
    }

    if ($pane_values['commerce_authnet_arb_period'] == 'months' &&
      ($pane_values['commerce_authnet_arb_interval_step'] < 1 || $pane_values['commerce_authnet_arb_interval_step'] > 12)) {
      $valid = FALSE;
      form_set_error($prefix.'commerce_authnet_arb_interval_step', t('Recurring interval value must be behind 1 and 12 for monthly interval.'));
    }
  }

  return $valid;
}

 Module code:

<?php
/*
 * Names: commerce_authnet_arb
 *
 * ToDo:
 *  - add an option to show errors
 *  - add an option to write errors to watchdog
 *  - silentpost securing using md5 hash authnet feature
 *  - save subscription creation as a commerce transaction
 *
 * Problems:
 *   - fields not passed validation are not highliting
 */

/**
 * Implements hook_commerce_payment_method_info().
 */
function commerce_authnet_arb_commerce_payment_method_info() {
  $payment_methods = array();

  $payment_methods['commerce_authnet_arb'] = array(
    'base' =>  'commerce_authnet_arb',
    'title' => t('Recurring payments with Authorize.Net ARB (with credit card)'),
    'short_title' => t('Authorize.Net ARB CC'),
    'display_title' => t('Recurring payments'),
    'description' => t('Integrates Authorize.Net ARB for transactions.'),
    'callbacks' => array(
      'settings_form' => 'commerce_authnet_arb_settings_form',
      'submit_form' => 'commerce_authnet_arb_submit_form',
      'submit_form_submit' => 'commerce_authnet_arb_submit_form_submit',
      'submit_form_validate' => 'commerce_authnet_arb_submit_form_validate',
    ),
    'file' => 'commerce_authnet_arb.commerce.inc',
  );

  return $payment_methods;
}

/*
 * Implements hook_menu
 */
function commerce_authnet_arb_menu() {
  $items = array();

  $items['authnet-arb-silentpost'] = array(
    'type' => MENU_CALLBACK,
    'page callback' => 'commerce_authnet_arb_silentpost',
    'access callback' => TRUE,
    'file' => 'commerce_authnet_arb.silentpost.inc',
  );

  $items['authnet-arb-silentpost-test'] = array(
    'type' => MENU_CALLBACK,
    'page callback' => 'commerce_authnet_arb_silentpost',
    'page arguments' => array(TRUE),
    'access callback' => TRUE,
    'file' => 'commerce_authnet_arb.silentpost.inc',
  );

  return $items;
}


/**
 * Implements hook_cron_queue_info().
 */
function commerce_authnet_arb_cron_queue_info() {
  $items['authnet_arb_silentpost'] = array(
    'worker callback' => 'commerce_authnet_arb_silentpost_processor',
  );

  return $items;
}

/**
 * Implements hook_advanced_queue_info().
 */
function commerce_authnet_arb_advanced_queue_info() {
  $items['authnet_arb_silentpost'] = array(
    'worker callback' => 'commerce_authnet_arb_silentpost_processor',
  );

  return $items;
}

function commerce_authnet_arb_silentpost_processor($item = NULL) {
  if (isset($item->data)) {
    // advancedqueue module has the data in the 'data' property of the item
    // unlike the simple queue item.
    module_invoke_all('arb_silentpost_process', $item->data);
  }
  else {
    module_invoke_all('arb_silentpost_process', $item);
  }

  return array(
    'status' => ADVANCEDQUEUE_STATUS_SUCCESS,
    'result' => 'Processed ' . $item->item_id,
  );
}


/*
 * Return all module settings including data needed to perform a transactions.
 */
function commerce_authnet_arb_settings($defaults = FALSE) {
  if (!empty($defaults)) {
    $settings = array(
      'login' => '',
      'tran_key' => '',
      'sandbox' => '',
      'md5_hash' => '',
      'watchdog_all' => '',
    );
  }
  else {
    $method = commerce_payment_method_instance_load('commerce_authnet_arb|rules_recurring_installment_gift_payment_method');
    $settings = $method['settings'];
  }
  return $settings;
}





/**
 * Return path to AuthNet SDK, or FALSE if not found.
 */
function commerce_authnet_arb_sdk_path() {
  static $path = NULL;

  if (!isset($path)) {
    $path = FALSE;
    // If Libraries API is installed, we first use that to try and find the
    // library. Otherwise we manually check a few locations.
    $search_dirs = array();
    if (function_exists('libraries_get_path')) {
      $dir = libraries_get_path('anet_php_sdk');
      // Confusingly, Libraries API 1.x will return sites/all/libraries/NAME on
      // failure, while Libraries API 2.x returns FALSE in that case.
      if ($dir) {
        $search_dirs[] = $dir;
      }

    } else {
      $search_dirs[] = 'sites/all/libraries/anet_php_sdk';
    }

    $search_dirs[] = drupal_get_path('module', 'commerce_authnet_arb') . '/anet_php_sdk';

    foreach ($search_dirs as $dir) {
      $dir = DRUPAL_ROOT . '/' . $dir;
      if (is_dir($dir)) {
        $path = $dir;
        break;
      }
    }
  }

  if ($path == FALSE) {
    throw new Exception('authorize.net SDK not found! Please follow the instructions in commerce_authnet_arb/README.txt.');
  }

  return $path;
}

 

1 REPLY 1

Hello dsdobrzynski123

It doesn't look like anyone has responded yet, but someone still may have feedback on what you're looking for. I'd recommend subscribing to this topic so that you'll be alerted via email if anyone else from the community is able to respond with any comments. To subscribe, click Topic Options at the top of this thread and then select Subscribe. You'll then receive an email once anyone replies to your post.

Thanks,

Richard

RichardH
Administrator Administrator
Administrator