function commerce_paypal_process_ipn in Commerce PayPal 7
Same name and namespace in other branches
- 7.2 commerce_paypal.module \commerce_paypal_process_ipn()
Processes an incoming IPN.
Parameters
$payment_method: The payment method instance array that originally made the payment.
$debug_ipn: Optionally specify an IPN array for debug purposes; if left empty, the IPN be pulled from the $_POST. If an IPN is passed in, validation of the IPN at PayPal will be bypassed.
Return value
TRUE or FALSE indicating whether the IPN was successfully processed or not.
1 string reference to 'commerce_paypal_process_ipn'
- commerce_paypal_menu in ./
commerce_paypal.module - Implements hook_menu().
File
- ./
commerce_paypal.module, line 66 - Implements PayPal payment services for use with Drupal Commerce.
Code
function commerce_paypal_process_ipn($payment_method = NULL, $debug_ipn = array()) {
// Retrieve the IPN from $_POST if the caller did not supply an IPN array.
// Note that Drupal has already run stripslashes() on the contents of the
// $_POST array at this point, so we don't need to worry about them.
if (empty($debug_ipn)) {
$ipn = $_POST;
// Exit now if the $_POST was empty.
if (empty($ipn)) {
watchdog('commerce_paypal', 'IPN URL accessed with no POST data submitted.', array(), WATCHDOG_WARNING);
return FALSE;
}
// Prepare an array to POST back to PayPal to validate the IPN.
$variables = array(
'cmd=_notify-validate',
);
foreach ($ipn as $key => $value) {
$variables[] = $key . '=' . urlencode($value);
}
// Determine the proper PayPal server to POST to.
if (!empty($ipn['test_ipn']) && $ipn['test_ipn'] == 1) {
$host = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
}
else {
$host = 'https://www.paypal.com/cgi-bin/webscr';
}
// Process the HTTP request to validate the IPN.
$response = drupal_http_request($host, array(
'method' => 'POST',
'data' => implode('&', $variables),
));
// If an error occurred during processing, log the message and exit.
if (property_exists($response, 'error')) {
watchdog('commerce_paypal', 'Attempt to validate IPN failed with error @code: @error', array(
'@code' => $response->code,
'@error' => $response->error,
), WATCHDOG_ERROR);
return FALSE;
}
// If the IPN was invalid, log a message and exit.
if ($response->data == 'INVALID') {
watchdog('commerce_paypal', 'Invalid IPN received and ignored.', array(), WATCHDOG_ALERT);
return FALSE;
}
}
else {
$ipn = $debug_ipn;
}
// If the payment method specifies full IPN logging, do it now.
if (!empty($payment_method['settings']['ipn_logging']) && $payment_method['settings']['ipn_logging'] == 'full_ipn') {
if (!empty($ipn['txn_id'])) {
watchdog('commerce_paypal', 'Attempting to process IPN @txn_id. !ipn_log', array(
'@txn_id' => $ipn['txn_id'],
'!ipn_log' => '<pre>' . check_plain(print_r($ipn, TRUE)) . '</pre>',
), WATCHDOG_NOTICE);
}
else {
watchdog('commerce_paypal', 'Attempting to process an IPN. !ipn_log', array(
'!ipn_log' => '<pre>' . check_plain(print_r($ipn, TRUE)) . '</pre>',
), WATCHDOG_NOTICE);
}
}
// Exit if the IPN has already been processed.
if (!empty($ipn['txn_id']) && ($prior_ipn = commerce_paypal_ipn_load($ipn['txn_id']))) {
if ($prior_ipn['payment_status'] == $ipn['payment_status']) {
watchdog('commerce_paypal', 'Attempted to process an IPN that has already been processed with transaction ID @txn_id.', array(
'@txn_id' => $ipn['txn_id'],
), WATCHDOG_NOTICE);
return FALSE;
}
}
// Load the order based on the IPN's invoice number.
if (!empty($ipn['invoice']) && strpos($ipn['invoice'], '-') !== FALSE) {
list($ipn['order_id'], $timestamp) = explode('-', $ipn['invoice']);
}
else {
$ipn['order_id'] = 0;
$timestamp = 0;
}
if (!empty($ipn['order_id'])) {
$order = commerce_order_load($ipn['order_id']);
}
else {
$order = FALSE;
}
// Give the payment method module an opportunity to validate the receiver
// e-mail address and amount of the payment if possible. If a validate
// function exists, it is responsible for setting its own watchdog message.
if (!empty($payment_method)) {
$callback = $payment_method['base'] . '_paypal_ipn_validate';
// If a validator function existed...
if (function_exists($callback)) {
// Only exit if the function explicitly returns FALSE.
if ($callback($order, $payment_method, $ipn) === FALSE) {
return FALSE;
}
}
}
// Give the payment method module an opportunity to process the IPN.
if (!empty($payment_method)) {
$callback = $payment_method['base'] . '_paypal_ipn_process';
// If a processing function existed...
if (function_exists($callback)) {
// Skip saving if the function explicitly returns FALSE, meaning the IPN
// wasn't actually processed.
if ($callback($order, $payment_method, $ipn) !== FALSE) {
// Save the processed IPN details.
commerce_paypal_ipn_save($ipn);
}
}
}
// Invoke the hook here so implementations have access to the order and
// payment method if available and a saved IPN array that includes the payment
// transaction ID if created in the payment method's default process callback.
module_invoke_all('commerce_paypal_ipn_process', $order, $payment_method, $ipn);
}