There is a feature request for Commerce Card on File to provide the ability to add a card BEFORE checkout #1812740: Give user the ability to add a card on file BEFORE checkout. And a forked/sandboxed version of this module (which may get merged into the official project) has added this functionality (see "Add a new card" at http://drupal.org/sandbox/recrit/1810130). The only issue is that the individual payment gateways must provide a "create callback". This module provides and "update callback" and a "delete callback."

Therefore, I'm submitting this as a feature request to add in this callback. I can potentially work on this, but I'm still evaluating the level of effort/difficulty required to take this on.

Comments

rickmanelius’s picture

Title: Create Callback » Add "create callback" functionality for Commerce Authorize.net

Updating the title...

rickmanelius’s picture

Status: Active » Needs review
StatusFileSize
new2.48 KB

Alright, this patch requires the SANDBOX version of commerce_cardonfile (http://drupal.org/sandbox/recrit/1810130) as noted in this issue #1812740: Give user the ability to add a card on file BEFORE checkout in the official project. Basically it adds the "create callback" function so that a person can add a card on file prior to actually going through the order process. It appears that authorize.net charges $1 in order to do this, so we may want to add that little warning so developers/users/customers are not surprised.

I know this is an edge case... so I'll notify the maintainer of the cardonfile module because it'll probably take them way less time to review and provide feedback!

As a side note: the code in this patch could probably use a little bit of streamlining and/or error checking (but most of that is handled by the form validate functions).

rickmanelius’s picture

Ping :)

iLLin’s picture

Status: Needs review » Needs work

This patch works if its your first card you are adding that has a unique description. If you add the same description for a different card it fails. If you delete one card and add a new card under the same description it fails.

I have updated the create hook to either create the whole profile or if it exists then add to the existing profile id. I haven't done a patch only provide code for review.

/**
 * Card on file callback: creates the associated customer payment profile.
 */
function commerce_authnet_cim_cardonfile_create($payment_method, $pane_form, $pane_values, $billing_addressfield, $card_data = array()) {
  $pieces = explode(" ", $card_data['card_name']);
  $firstName = $pieces[0];
  $lastName = isset($pieces[1]) ? $pieces[1] : "";

  $billing_address = $pane_values['commerce_customer_address']['und'][0];
  $card_number = $pane_values['credit_card']['number'];
  $card_expire = $card_data['card_exp_year'] . '-' . $card_data['card_exp_month'];
  $card_code= $pane_values['credit_card']['code'];

  $api_request_data = array(
    'profile' => array(
      'merchantCustomerId' => $card_data['uid'],
      'description' => $card_data['card_name'],
      'email' => $pane_values['card_owner']->mail,
      'paymentProfiles' => array(
        'billTo' => array(
          'firstName' => $firstName,
          'lastName' => $lastName,
          'address' => $billing_address['thoroughfare'],
          'city' => $billing_address['locality'],
          'state' => $billing_address['administrative_area'],
          'zip' => $billing_address['postal_code'],
          'country' => $billing_address['country'],
        ),
       'payment' => array(
         'creditCard' => array(
           'cardNumber' => $card_number,
           'expirationDate' => $card_expire,
           'cardCode' => $card_code,
         ),
       ),
     ),
    ),
  );

  $xml_response = commerce_authnet_cim_request($payment_method, 'createCustomerProfileRequest', $api_request_data);

  // Successfull creation of the CIM Profile
  if((string) $xml_response->messages->message->code == 'I00001') {
    return (string) $xml_response->customerProfileId . '|' . (string) $xml_response->customerPaymentProfileIdList->numericString;
  }

  // If we get a duplicate error then lets parse our our customer Profile ID and resend the information to
  // add to an existing profile ID.
  if((string) $xml_response->messages->message->code == 'E00039') {
    $msg = (string) $xml_response->messages->message->text;
    $matches = array();
    // Extract our profile id from the message text.
    $txt = preg_match('/^A duplicate record with ID (.*?) already exists./s', $msg, $matches);
    if(isset($matches[1])) {
      // Lets make another call and pass in our found profile id.
      $pid = $matches[1];

      $api_request_data = array(
        'customerProfileId' => $pid,
        'paymentProfile' => array(
          'billTo' => array(
            'firstName' => $firstName,
            'lastName' => $lastName,
            'address' => $billing_address['thoroughfare'],
            'city' => $billing_address['locality'],
            'state' => $billing_address['administrative_area'],
            'zip' => $billing_address['postal_code'],
            'country' => $billing_address['country'],
          ),
          'payment' => array(
            'creditCard' => array(
              'cardNumber' => $card_number,
              'expirationDate' => $card_expire,
              'cardCode' => $card_code,
            ),
          ),
        ),
      );

      $xml_response = commerce_authnet_cim_request($payment_method, 'createCustomerPaymentProfileRequest', $api_request_data);

      // Successfull creation of the CIM Profile
      if((string) $xml_response->messages->message->code == 'I00001') {
        return (string) $pid . '|' . (string) $xml_response->customerPaymentProfileId->numericString;
      }

      if((string) $xml_response->messages->message->code == 'E00039') {
        drupal_set_message(t('This card currently exists on your profile.  You can not add it twice.'), 'error');
      }
    }
  }


  return FALSE;
}
oadaeh’s picture

#1812740: Give user the ability to add a card on file BEFORE checkout is now in the 2.x branch of Commerce Card on File. The patch should probably be rewritten to depend on that.

oadaeh’s picture

Actually, after reviewing what really went into the 2.x branch, it doesn't look like the code this patch depends on made the cut.

andyg5000’s picture

Issue summary: View changes
Status: Needs work » Closed (duplicate)