View source
<?php
module_load_include('inc', 'commerce_sagepay', 'includes/commerce_sagepay_constants');
module_load_include('inc', 'commerce_sagepay', 'includes/commerce_sagepay_common');
function sagepay_token_form_commerce_sagepay_settings_form_alter(&$form, &$form_state, $form_id) {
$form['tokens'] = array(
'#type' => 'fieldset',
'#title' => t('Token'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['tokens'][SAGEPAY_SETTING_REQUEST_TOKEN] = array(
'#type' => 'checkbox',
'#title' => t('Request a token by default when a transaction is created.'),
'#description' => t('This behaviour can be changed on a per-order basis using <code>hook_sagepay_order_data_alter</code>.'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#default_value' => variable_get(SAGEPAY_SETTING_REQUEST_TOKEN, 0),
);
}
function sagepay_token_sagepay_order_data_alter(&$query) {
switch ($query['integration_method']) {
case SAGEPAY_SERVER:
$query['CreateToken'] = variable_get(SAGEPAY_SETTING_REQUEST_TOKEN, 0);
break;
case SAGEPAY_DIRECT:
$query['CreateToken'] = variable_get(SAGEPAY_SETTING_REQUEST_TOKEN, 0);
break;
}
}
function sagepay_token_commerce_payment_method_info_alter(&$payment_methods) {
if (array_key_exists('commerce_sagepay_direct', $payment_methods)) {
$payment_methods['commerce_sagepay_direct']['cardonfile'] = array(
'update callback' => 'sagepay_token_cardonfile_update',
'delete callback' => 'sagepay_token_cardonfile_delete',
'charge callback' => 'sagepay_token_cardonfile_charge',
);
}
if (array_key_exists('commerce_sagepay_server', $payment_methods)) {
$payment_methods['commerce_sagepay_server']['cardonfile'] = array(
'update callback' => 'sagepay_token_cardonfile_update',
'delete callback' => 'sagepay_token_cardonfile_delete',
'charge callback' => 'sagepay_token_cardonfile_charge',
);
}
}
function sagepay_token_commerce_payment_transaction_presave($transaction) {
switch ($transaction->payment_method) {
case 'commerce_sagepay_server':
case 'commerce_sagepay_direct':
if (!isset($transaction->payload['Token'])) {
return FALSE;
}
if ($transaction->payload['Status'] != 'OK') {
return FALSE;
}
$save_cardonfile = FALSE;
$cardonfile_store = isset($transaction->payload['cardonfile_store']) ? $transaction->payload['cardonfile_store'] : FALSE;
if (!empty($cardonfile_store)) {
$save_cardonfile = TRUE;
}
else {
if ($cardonfile_store === 0) {
$save_cardonfile = FALSE;
}
else {
if (variable_get('commerce_cardonfile_storage', '') == 'required') {
$save_cardonfile = TRUE;
}
}
}
if (!$save_cardonfile) {
return;
}
$order = commerce_order_load($transaction->order_id);
$uid = $order->uid;
if ($uid == 0) {
return FALSE;
}
$wrapper = entity_metadata_wrapper('commerce_order', $order);
$address = $wrapper->commerce_customer_billing->commerce_customer_address
->value();
$card_data = array(
'uid' => $uid,
'payment_method' => $transaction->payment_method,
'instance_id' => $transaction->instance_id,
'remote_id' => $transaction->payload['Token'],
'card_type' => $transaction->payload['CardType'],
'card_number' => $transaction->payload['Last4Digits'],
'card_name' => $address['first_name'] . ' ' . $address['last_name'],
'status' => '1',
);
$expiry_date = $transaction->payload['ExpiryDate'];
$expiry_month = substr($expiry_date, 0, 2);
$expiry_year = '20' . substr($expiry_date, 2, 2);
$card_data['card_exp_month'] = $expiry_month;
$card_data['card_exp_year'] = $expiry_year;
$card_entity = commerce_cardonfile_new($card_data);
commerce_cardonfile_save($card_entity);
if ($transaction->payload['cardonfile_instance_default']) {
commerce_cardonfile_set_default_card($card_entity->card_id);
}
return TRUE;
break;
default:
return FALSE;
}
}
function sagepay_token_cardonfile_update($form, $form_state, $payment_method, $card_data) {
return TRUE;
}
function sagepay_token_cardonfile_delete($form, $form_state, $payment_method, $card_data) {
$query = array();
$query['VPSProtocol'] = SAGEPAY_PROTOCOL;
$query['TxType'] = 'REMOVETOKEN';
$query['Vendor'] = variable_get(SAGEPAY_SETTING_VENDOR_NAME);
$query['Token'] = $card_data->remote_id;
switch (variable_get(SAGEPAY_SETTING_TRANSACTION_MODE)) {
case SAGEPAY_TXN_MODE_LIVE:
$url = SAGEPAY_TOKEN_REMOVE_LIVE;
break;
case SAGEPAY_TXN_MODE_TEST:
$url = SAGEPAY_TOKEN_REMOVE_TEST;
break;
}
$query = _commerce_sagepay_array_to_post($query);
$response = _commerce_sagepay_request_post($url, $query);
switch ($response['Status']) {
case 'OK':
return TRUE;
case 'MALFORMED':
case 'INVALID':
drupal_set_message(t('Error removing saved card. %detail', array(
'%detail' => $response['StatusDetail'],
)));
return FALSE;
}
return FALSE;
}
function sagepay_token_cardonfile_charge($payment_method, $card_data, $order, $charge = NULL) {
$wrapper = entity_metadata_wrapper('commerce_order', $order);
$profile = commerce_customer_profile_load($order->commerce_customer_billing[LANGUAGE_NONE][0]['profile_id']);
$billing_address = $profile->commerce_customer_address[LANGUAGE_NONE][0];
$delivery_address = NULL;
if (isset($order->commerce_customer_shipping)) {
$delivery_profile = commerce_customer_profile_load($order->commerce_customer_shipping[LANGUAGE_NONE][0]['profile_id']);
$delivery_address = $delivery_profile->commerce_customer_address[LANGUAGE_NONE][0];
}
$pane_values = array();
$pane_values['cardonfile'] = $card_data->card_id;
$pane_values['commerce_recurring'] = TRUE;
$settings = array();
$query = _commerce_sagepay_encrypted_order($settings, $order, $charge, $billing_address, $delivery_address, SAGEPAY_DIRECT, $pane_values);
$query['ApplyAVSCV2'] = '2';
$query['Apply3DSecure'] = '2';
$post = '';
foreach ($query as $name => $value) {
$post .= urlencode($name) . '=' . urlencode($value) . '&';
}
$post = substr($post, 0, -1);
switch (variable_get(SAGEPAY_SETTING_TRANSACTION_MODE)) {
case SAGEPAY_TXN_MODE_LIVE:
$server_url = SAGEPAY_DIRECT_SERVER_LIVE;
break;
case SAGEPAY_TXN_MODE_TEST:
$server_url = SAGEPAY_DIRECT_SERVER_TEST;
break;
case SAGEPAY_TXN_MODE_SHOWPOST:
$server_url = SAGEPAY_DIRECT_SERVER_SHOWPOST;
break;
case SAGEPAY_TXN_MODE_SIMULATION:
$server_url = SAGEPAY_DIRECT_SERVER_SIMULATION;
break;
default:
$server_url = SAGEPAY_DIRECT_SERVER_SIMULATION;
}
drupal_alter('sagepay_url', $server_url, $pane_values);
$response = _commerce_sagepay_request_post($server_url, $post);
if (isset($pane_values['credit_card'])) {
$response['Last4Digits'] = substr($pane_values['credit_card']['number'], 12, 16);
$response['ExpMonth'] = $pane_values['credit_card']['exp_month'];
$response['ExpYear'] = $pane_values['credit_card']['exp_year'];
$response['cardonfile_store'] = isset($pane_values['credit_card']['cardonfile_store']) ? $pane_values['credit_card']['cardonfile_store'] : '0';
$response['CardType'] = $pane_values['credit_card']['type'];
}
$response['Amount'] = $wrapper->commerce_order_total->amount
->value();
$result = commerce_sagepay_process_response($payment_method, $order, $response);
switch ($response['Status']) {
case 'NOTAUTHED':
case 'REJECTED':
case 'MALFORMED':
case 'INVALID':
case 'ERROR':
$cardonfile_response['code'] = COMMERCE_COF_PROCESS_CODE_CARD_NOT_CHARGEABLE;
$cardonfile_response['message'] = $response['StatusDetail'];
break;
case 'OK':
case 'AUTHENTICATED':
$cardonfile_response['code'] = COMMERCE_COF_PROCESS_CODE_METHOD_SUCCESS;
$cardonfile_response['message'] = $response['StatusDetail'];
break;
default:
$cardonfile_response['code'] = COMMERCE_COF_PROCESS_CODE_CARD_NOT_CHARGEABLE;
$cardonfile_response['message'] = $response['StatusDetail'];
}
return $cardonfile_response;
}