You are here

function commerce_authnet_cim_cardonfile_charge in Commerce Authorize.Net 7

Card on file callback: background charge payment

Parameters

object $payment_method: The payment method instance definition array.

object $card_data: The stored credit card data array to be processed

object $order: The order object that is being processed

array $charge: The price array for the charge amount with keys of 'amount' and 'currency' If null the total value of the order is used.

Return value

TRUE if the transaction was successful

3 calls to commerce_authnet_cim_cardonfile_charge()
commerce_authnet_acceptjs_submit_new_card_form_submit in includes/commerce_authnet.acceptjs.inc
Handles advanced logic relating to creating AcceptJS orders with new card data.
commerce_authnet_cim_submit_form_submit in ./commerce_authnet.module
Imitates the checkout form submission callback for the AIM payment method.
commerce_authnet_cim_submit_new_card_form_submit in ./commerce_authnet.module
Handles advanced logic relating to creating CIM orders with new card data.
1 string reference to 'commerce_authnet_cim_cardonfile_charge'
commerce_authnet_commerce_payment_method_info in ./commerce_authnet.module
Implements hook_commerce_payment_method_info().

File

./commerce_authnet.module, line 1284
Implements Authorize.Net payment services for use in Drupal Commerce.

Code

function commerce_authnet_cim_cardonfile_charge($payment_method, $card_data, $order, $charge = NULL) {

  // Format order total for transaction.
  if (!isset($charge)) {
    $wrapper = entity_metadata_wrapper('commerce_order', $order);
    $charge = commerce_line_items_total($wrapper->commerce_line_items);
  }

  // Extract the Customer Profile and Payment Profile IDs from the remote_id.
  list($cim_customer_profile_id, $cim_payment_profile_id) = explode('|', $card_data->remote_id);

  // Determine the proper transaction element to use inside the XML.
  $element_name = commerce_authnet_cim_transaction_element_name($payment_method['settings']['txn_type']);

  // Build a data array for the transaction API request.
  $api_request_data = array(
    'transaction' => array(
      $element_name => array(
        'amount' => number_format(commerce_currency_amount_to_decimal($charge['amount'], $charge['currency_code']), 2, '.', ''),
        'customerProfileId' => $cim_customer_profile_id,
        'customerPaymentProfileId' => $cim_payment_profile_id,
        'order' => array(
          'invoiceNumber' => $order->order_number,
        ),
      ),
    ),
    'extraOptions' => '<![CDATA[x_delim_data=TRUE&amp;x_delim_char=|&amp;x_encap_char="&amp;x_solution_id=A1000009&amp;x_currency_code=' . $charge['currency_code'] . '&amp;x_customer_ip=' . substr(ip_address(), 0, 15) . '&amp;x_email_customer=' . $payment_method['settings']['email_customer'] . ']]>',
  );

  // If we get a response from the API server...
  $xml_response = commerce_authnet_cim_request($payment_method, 'createCustomerProfileTransactionRequest', $api_request_data);
  if (!empty($xml_response->directResponse)) {

    // Extract the response data from the XML.
    $response = explode('|', (string) $xml_response->directResponse);
    for ($i = 0; $i < count($response); $i++) {
      $response[$i] = substr($response[$i], 1, strlen($response[$i]) - 2);
    }

    // Prepare a transaction object to represent the transaction attempt.
    $transaction = commerce_payment_transaction_new('authnet_aim', $order->order_id);
    $transaction->instance_id = $payment_method['instance_id'];
    $transaction->remote_id = $response[6];
    $transaction->amount = $charge['amount'];
    $transaction->currency_code = $charge['currency_code'];
    $transaction->payload[REQUEST_TIME] = $response;

    // If we didn't get an approval response code...
    if ($response[0] != '1') {

      // Create a failed transaction with the error message.
      $transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
    }
    else {

      // Set the transaction status based on the type of transaction this was.
      switch ($payment_method['settings']['txn_type']) {
        case COMMERCE_CREDIT_AUTH_ONLY:
          $transaction->status = COMMERCE_PAYMENT_STATUS_PENDING;
          break;
        case COMMERCE_CREDIT_AUTH_CAPTURE:
          $transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
          break;
      }
    }

    // Store the type of transaction in the remote status.
    $transaction->remote_status = $response[11];

    // Build a meaningful response message.
    $message = array(
      '<b>' . commerce_authnet_reverse_txn_type(commerce_authnet_txn_type($payment_method['settings']['txn_type'])) . '</b>',
      '<b>' . ($response[0] != '1' ? t('REJECTED') : t('ACCEPTED')) . ':</b> ' . check_plain($response[3]),
      t('AVS response: @avs', array(
        '@avs' => commerce_authnet_avs_response($response[5]),
      )),
    );
    $transaction->message = implode('<br />', $message);

    // Save the transaction information.
    commerce_payment_transaction_save($transaction);

    // If the payment failed, display an error and rebuild the form.
    if ($response[0] != '1') {
      drupal_set_message(t('We received the following error processing your card. Please enter your information again or try a different card.'), 'error');
      drupal_set_message(check_plain($response[3]), 'error');
      return FALSE;
    }
    return isset($transaction->status) ? $transaction->status : TRUE;
  }
  elseif ((string) $xml_response->messages->message->code == 'E00040') {

    // If the response indicated a non-existent profile, deactive it now.
    $card_data->status = 0;
    commerce_cardonfile_save($card_data);
    drupal_set_message(t('The card you selected is no longer valid. Please use a different card to complete payment.'), 'error');
    return FALSE;
  }
  drupal_set_message(t('We could not process your card on file at this time. Please try again or use a different card.'), 'error');
  return FALSE;
}