/**
  * Take the response XML from Litle and does the account updater stuff.
  *
  * @param DOMDocument $response
  *   The XML response document.
  * @param object $order
  *   The order object that has just been charged.
  *   This will be used as the template to create additional donations
  *   if needed.
  *
  * @return bool
  *   TRUE if an account update was detected and attempted.
  *   FALSE if nothing changed or we don't have enough info
  *   to perform the update.
  */
 public function processResponseXML(DOMDocument $response, $order)
 {
     $list = $response->getElementsByTagName('accountUpdater');
     if ($list->length == 0) {
         // No Account Updater tags.
         return FALSE;
     }
     $data = $this->getDataFromXML($list->item(0));
     // Do some error checking.
     if (!isset($data['originalCardTokenInfo']) || !isset($data['newCardTokenInfo'])) {
         return FALSE;
     }
     $changed = $this->cardHasChanged($data['originalCardTokenInfo'], $data['newCardTokenInfo']);
     if ($changed) {
         // Load the card on file card.
         $old_exp_date = $this->convertExpDateString($data['originalCardTokenInfo']['expDate']);
         $card = $this->findMatchingCardonfile($data['originalCardTokenInfo']['litleToken'], $old_exp_date, $order->uid);
         if (!$card) {
             // No card with a matching remote id or exp date or uid.
             // Do nothing even though we have new data.
             return FALSE;
         }
         // Save the new token info to the card on file.
         // A new token implies a new last 4 digits of the card number.
         $new_token = $data['newCardTokenInfo']['litleToken'];
         $new_number = substr($new_token, -4);
         $new_type = _commerce_litle_litle_card_type_to_cc($data['newCardTokenInfo']['type']);
         $card->remote_id = $new_token;
         // The long form of the card_type.
         $card->card_type = $new_type;
         // The card_number, which is the last 4 of the token for credit cards.
         $card->card_number = $new_number;
         // Convert the date format Litle uses to the one we use, and save it.
         $new_exp_date = $this->convertExpDateString($data['newCardTokenInfo']['expDate']);
         $card->card_exp_month = $new_exp_date['month'];
         $card->card_exp_year = $new_exp_date['year'];
         $card->changed = REQUEST_TIME;
         // Update billing info on existing future donations.
         // and create recurring donations through the new expiration date.
         $donation = fundraiser_donation_get_donation($order->order_id);
         if (isset($donation->recurring->master_did)) {
             $master_donation = fundraiser_donation_get_donation($donation->recurring->master_did);
             $submission_fields = $this->formatSubmissionFields($new_number, $new_type, $new_exp_date);
             // Only save the card on file if we are able to update the billing info
             // as well.
             commerce_cardonfile_save($card);
             $this->updateBillingInfo($master_donation, $submission_fields, $donation);
             return TRUE;
         }
     }
     return FALSE;
 }
 /**
  * Save a card on file object
  */
 public function saveCard($card, $billing_profile = NULL, $new_values = array())
 {
     // Remove metadata values
     if (!empty($new_values)) {
         unset($new_values['no_store']);
     }
     // If new card ...
     if (empty($card->card_id)) {
         if (!empty($new_values)) {
             foreach ($new_values as $prop => $new_value) {
                 $card->{$prop} = $new_value;
             }
         }
         // Ensure number is always sanitized
         $card->card_number = !empty($card->card_number) ? substr($card->card_number, -4) : 'XXXX';
         // Save the new card
         return commerce_cardonfile_save($card, $billing_profile);
     }
     // Update to an existing card
     if (empty($new_values)) {
         return 3;
     }
     // Load original card
     $card_original = entity_load_unchanged('commerce_cardonfile', $card->card_id);
     // Detect property changes
     $changes = array();
     foreach ($new_values as $prop => $new_value) {
         if ($card_original->{$prop} != $new_value) {
             $card->{$prop} = $new_value;
             $changes[] = $prop;
         }
     }
     // Detect if billing address changed
     $billing_updated = FALSE;
     if (!empty($billing_profile) && !empty($card->commerce_cardonfile_profile[LANGUAGE_NONE][0]['profile_id'])) {
         if (empty($billing_profile->profile_id) || $billing_profile->profile_id != $card->commerce_cardonfile_profile[LANGUAGE_NONE][0]['profile_id']) {
             $billing_updated = TRUE;
         }
     }
     // No changes
     if (empty($changes) && !$billing_updated) {
         return 3;
     }
     // Create new card if immutable property changed or billing updated
     if (array_intersect($changes, $this->cardImmutableProperties()) || $billing_updated) {
         // Disable the original card
         $card_original->status = 0;
         $card_original->changed = REQUEST_TIME;
         commerce_cardonfile_save($card_original);
         // Save the new card
         unset($card->card_id);
         $card->created = REQUEST_TIME;
         $card->changed = REQUEST_TIME;
     }
     // Ensure number is always sanitized
     $card->card_number = !empty($card->card_number) ? substr($card->card_number, -4) : 'XXXX';
     // Save the updated card
     if ($billing_updated) {
         return commerce_cardonfile_save($card, $billing_profile);
     }
     return commerce_cardonfile_save($card);
 }
 /**
  * This function will process payment for pending orders
  * @return array|bool
  */
 public static function runCron($order, $check_pass = FALSE)
 {
     module_load_include('inc', 'commerce_recurring', 'commerce_recurring.rules');
     module_load_include('inc', 'mp_order', 'mp_order.rules');
     if ($check_pass == FALSE) {
         $payment_method = commerce_payment_method_instance_load('commerce_stripe|commerce_payment_commerce_stripe');
         $card_details = commerce_cardonfile_load_multiple_by_uid($order->uid, $payment_method['instance_id'], TRUE);
         foreach ($card_details as $key) {
             $card_data = commerce_cardonfile_load($key->card_id);
             $card_data->remote_id = '';
             commerce_cardonfile_save($card_data);
         }
     }
     $card_response = commerce_cardonfile_rules_action_order_select_default_card($order);
     $order_total = field_get_items('commerce_order', $order, 'commerce_order_total');
     $response = commerce_cardonfile_rules_action_order_charge_card($order, $order_total[0], $card_response['select_card_response']);
     return new Response(TRUE, $response, "");
 }