function commerce_cardonfile_order_charge_card in Commerce Card on File 7.2
Process a charge for a given an order
Wrapper function for _commerce_cardonfile_order_invoke_process_card() to trigger rules events
Parameters
$order: An order object
$charge: Charge array of amount, currency_code
$card: The card entity.
$forced_instance_id: Payment instance ID to enforce the usage of a specific payment gateway
Return value
TRUE if the order was processed successfully
1 call to commerce_cardonfile_order_charge_card()
- commerce_cardonfile_rules_action_order_charge_card in ./
commerce_cardonfile.rules.inc - Rules action callback for commerce_cardonfile_order_charge_card
1 string reference to 'commerce_cardonfile_order_charge_card'
- commerce_cardonfile_recurring_default_rules_configuration in modules/
recurring/ commerce_cardonfile_recurring.rules_defaults.inc - Implements hook_default_rules_configuration().
File
- ./
commerce_cardonfile.module, line 1221 - Supports card on file functionality for credit card payment methods by associating card data reference IDs from payment gateways with user accounts.
Code
function commerce_cardonfile_order_charge_card($order, $charge = array(), $card = NULL, $forced_instance_id = NULL) {
$response = array(
'status' => FALSE,
'code' => COMMERCE_COF_PROCESS_CODE_INSUFFICIENT_DATA,
'message' => '',
'message_variables' => array(),
);
// Exit if no order id
if (empty($order->order_id)) {
$response['message'] = 'Order ID is not provided.';
return $response;
}
$response['message_variables'] += array(
'@order_id' => $order->order_id,
);
// Exit if no user associated with the order
if (empty($order->uid)) {
$response['message'] = 'Order owner not provided for order @order_id.';
return $response;
}
$response['message_variables'] += array(
'@uid' => $order->uid,
);
// determine charge amount
// set charge to order balance if none provided
if (empty($charge)) {
$charge = commerce_payment_order_balance($order);
}
// exit if no charge
if (empty($charge) || empty($charge['amount']) || empty($charge['currency_code'])) {
$response['message'] = 'Charge amount not provided for order @order_id.';
return $response;
}
$response['message_variables'] += array(
'@charge' => commerce_currency_format($charge['amount'], $charge['currency_code']),
);
// exit if no card data provided
if (empty($card)) {
$response['message'] = 'Card data not provided for order @order_id.';
return $response;
}
$response['card_chosen'] = $card;
if (!commerce_cardonfile_order_can_charge_card($order, $card)) {
// check for expiration to set a specific code
if (!commerce_cardonfile_validate_card_expiration($card)) {
$response['code'] = COMMERCE_COF_PROCESS_CODE_CARD_EXPIRED;
$response['message'] = 'Card on file has expired for user @uid\'s card @card_id when attempting to process order @order_id.';
}
else {
$response['code'] = COMMERCE_COF_PROCESS_CODE_CARD_NOT_CHARGEABLE;
$response['message'] = 'Card provided cannot be charged for the order @order_id and user @uid.';
}
return $response;
}
// resolve payment method instance input
$instance_is_forced = FALSE;
if (!empty($forced_instance_id)) {
$instance_is_forced = TRUE;
// set the order data so chargeable hook can use to determine the card
$order->data['payment_method'] = $forced_instance_id;
$response['message_variables'] += array(
'@instance_id' => $forced_instance_id,
);
}
else {
$forced_instance_id = NULL;
}
if ($instance_is_forced && isset($card->instance_id) && $card->instance_id != $forced_instance_id) {
$response['code'] = COMMERCE_COF_PROCESS_CODE_CARD_NOT_CHARGEABLE;
$response['message'] = 'Card provided is not registered with the requested payment method: Order @order_id, user @uid, payment instance @instance_id';
return $response;
}
// Wrap up the order
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
// load payment method
$payment_method = commerce_payment_method_instance_load($card->instance_id);
if (empty($payment_method)) {
$response['code'] = COMMERCE_COF_PROCESS_CODE_METHOD_EMPTY;
$response['message'] = 'The payment method instance (@instance_id) is not available on the system.';
return $response;
}
$response['message_variables'] += array(
'@method' => isset($payment_method['short_title']) ? $payment_method['short_title'] : $payment_method['method_id'],
);
// determine payment method's callback function
$func = commerce_cardonfile_payment_method_callback($payment_method, 'charge callback');
// Exit if no callback - sanity check since it should have this if "can charge"
if (empty($func)) {
$response['code'] = COMMERCE_COF_PROCESS_CODE_METHOD_NOT_CAPABLE;
$response['message'] = 'The payment method @method instance (@instance_id) does not implement a valid card on file "charge callback".';
return $response;
}
// invoke callback function
$method_return = $func($payment_method, $card, $order, $charge);
// process return from gateway module
// Backwards compatibility: returned value can be a boolean FALSE or a
// specified failure code.
if ($method_return === FALSE || !in_array($method_return, array(
COMMERCE_PAYMENT_STATUS_SUCCESS,
COMMERCE_PAYMENT_STATUS_PENDING,
))) {
// Failure
$response['status'] = FALSE;
// If the returned value doesn't specify the failure code, save a generic
// one.
$response['code'] = $method_return === FALSE ? COMMERCE_COF_PROCESS_CODE_METHOD_FAILURE : $method_return;
$response['message'] = 'The payment method @method instance (@instance_id) failed for order @order_id, user @uid, card @card_id, charge amount @charge.';
}
else {
// Success
$response['status'] = TRUE;
$response['code'] = $method_return;
$response['message'] = 'The payment method @method instance (@instance_id) was successful for order @order_id, user @uid, card @card_id, charge amount @charge.';
// load a fresh order in case it was modified during method callback
$order = commerce_order_load($order->order_id);
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
// Store the last processed card on the order card reference field
if (isset($order_wrapper->commerce_cardonfile)) {
$order_ref_card_id = $order_wrapper->commerce_cardonfile
->value();
if (empty($order_ref_card_id) || $order_ref_card_id != $card->card_id) {
$order_wrapper->commerce_cardonfile = array(
'card_id' => $card->card_id,
);
$order_wrapper
->save();
}
}
}
if (!empty($response['card_chosen'])) {
$card_chosen = $response['card_chosen'];
}
elseif (!empty($card)) {
$card_chosen = $card;
}
if (empty($response) || empty($response['status'])) {
rules_invoke_all('commerce_cardonfile_charge_failed', $card_chosen, $order, $charge, $response);
}
else {
rules_invoke_all('commerce_cardonfile_charge_success', $card_chosen, $order, $charge, $response);
}
return $response;
}