function commerce_sagepay_paypal_handle_callback in Drupal Commerce SagePay Integration 7
Handle a POST callback from Pay Pal to confirm the transaction.
Callback will contain the following: VPSProtocol Status (PAYPALOK, MALFORMED, INVALID, ERROR) StatusDetail VPSTxId AddressStatus (NONE, CONFIRMED, UNCONFIRMED) PayerStatus (VERIFIED, UNVERIFIED) DeliverySurname DeliveryFirstNames DeliveryAddress1 DeliveryAddress2 DeliveryCity DeliveryPostCode DeliveryCountry DeliveryState DeliveryPhone CustomerEMail PayerID
Depending on the status code, we then post back to Sage Pay with the following values: VPSProtocol TxType (COMPLETE) VPSTxId Amount Accept (YES, NO)
Parameters
$order_id:
$key:
1 string reference to 'commerce_sagepay_paypal_handle_callback'
- commerce_sagepay_paypal_menu in modules/
commerce_sagepay_paypal/ commerce_sagepay_paypal.module - Implements hook_menu().
File
- modules/
commerce_sagepay_paypal/ includes/ commerce_sagepay_paypal.inc, line 143
Code
function commerce_sagepay_paypal_handle_callback($order_id) {
$order = commerce_order_load($order_id);
// $payment_key = $order->data['payment_redirect_key'];
// // Check key against supplied value.
// if (!$payment_key === $key) {
// $notification['status'] = 'INVALID';
// $notification['message'] = t('Payment Redirect key did not match.');
// }
if (empty($_POST)) {
$notification['status'] = 'ERROR';
$notification['message'] = t('No Payload returned in the notification POST.');
watchdog('commerce_sagepay', 'VPS Callback URL accessed with no POST data
submitted.', array(), WATCHDOG_WARNING);
}
if (empty($notification)) {
// Load transactions with a matching order id, remote transaction id
// and the status "Started".
// We need to load the original transaction to identify the charge total.
$conditions = array(
'order_id' => $order_id,
'remote_id' => $_POST['VPSTxId'],
'remote_status' => 'PPREDIRECT',
);
$transactions = commerce_payment_transaction_load_multiple(array(), $conditions);
// We expect a transaction to be found, so fail if there isn't one.
if (empty($transactions)) {
$notification['status'] = 'INVALID';
$notification['message'] = t('No matching transaction found');
watchdog('commerce_sagepay', 'No Matching transaction found in
SagePay Server VPS Callback for order %order_id', array(
'%order_id' => $order_id,
), WATCHDOG_ERROR);
}
// We expect only ONE transaction to be found, so fail if there are more.
if (count($transactions) > 1) {
$notification['status'] = 'INVALID';
$notification['message'] = t('Multiple matching transaction found');
watchdog('commerce_sagepay', 'Multiple matching transaction found in
SagePay Server VPS Callback for order %order_id', array(
'%order_id' => $order_id,
), WATCHDOG_ERROR);
}
// Verify the transaction.
$transaction_values = array_values($transactions);
$transaction = $transaction_values[0];
$payment_method = commerce_payment_method_instance_load($transaction->instance_id);
}
// Modify the transaction depending on the PayPal Status
$response_callback = array(
'VPSProtocol' => '2.23',
'TxType' => 'COMPLETE',
'VPSTxId' => $transaction->remote_id,
'Amount' => commerce_currency_amount_to_decimal($transaction->amount, $transaction->currency_code),
);
switch ($_POST['Status']) {
case 'PAYPALOK':
$response_callback['Accept'] = 'YES';
break;
case 'MALFORMED':
case 'INVALID':
case 'ERROR':
default:
$response_callback['Accept'] = 'NO';
watchdog('commerce_sagepay', 'FAILED Payment callback received from
PayPal for order %order_id with status code %status', array(
'%order_id' => $order_id,
'%status' => $_POST['Status'],
));
commerce_sagepay_transaction($payment_method, $order, array(), $_POST, COMMERCE_PAYMENT_STATUS_FAILURE, SAGEPAY_REMOTE_STATUS_INVALID, $transaction);
}
switch (variable_get(SAGEPAY_SETTING_TRANSACTION_MODE)) {
case SAGEPAY_TXN_MODE_LIVE:
$server_url = SAGEPAY_PAYPAL_COMPLETION_LIVE;
break;
case SAGEPAY_TXN_MODE_TEST:
$server_url = SAGEPAY_PAYPAL_COMPLETION_TEST;
break;
}
$query = _commerce_sagepay_array_to_post($response_callback);
$response = _commerce_sagepay_request_post($server_url, $query);
// Amount doesn't come back in this callback - but we have it in the
// previous one.
$response['Amount'] = $response_callback['Amount'] * 100;
// @todo need to get payment method.
$result = commerce_sagepay_process_response($payment_method, $order, $response);
$checkout_pages = commerce_checkout_pages();
$checkout_page = $checkout_pages['payment'];
if ($checkout_page['next_page']) {
// Update the order status to reflect the next checkout page.
$order = commerce_order_status_update($order, 'checkout_' . $checkout_page['next_page'], FALSE, TRUE, t('Customer continued to the next checkout page via a submit button.'));
// If it happens to be the complete page, process completion now.
if ($checkout_page['next_page'] == 'complete') {
commerce_checkout_complete($order);
}
// Redirect to the next checkout page.
drupal_goto('checkout/' . $order->order_id . '/' . $checkout_page['next_page']);
}
}