function commerce_paypal_ec_do_payment in Commerce PayPal 7.2
Confirm an Express Checkout payment for an order for the specified charge amount with a DoExpressCheckoutPayment API request.
Parameters
$payment_method: The PayPal Express Checkout payment method instance whose settings should be used to submit the request.
$order: The order the payment is for.
$charge: A price field value array representing the charge amount and currency.
Return value
Boolean indicating the success or failure of the payment request.
2 calls to commerce_paypal_ec_do_payment()
- commerce_paypal_ec_redirect_form_validate in modules/
ec/ commerce_paypal_ec.module - Payment method callback: redirect form return validation.
- commerce_paypal_ec_review_pane_checkout_form_submit in modules/
ec/ includes/ commerce_paypal_ec.checkout_pane.inc - Submit handler for the Express Checkout review and confirm page.
File
- modules/
ec/ commerce_paypal_ec.module, line 1159 - Implements PayPal Express Checkout in Drupal Commerce checkout.
Code
function commerce_paypal_ec_do_payment($payment_method, $order, $charge) {
// Determine the currency code to use to actually process the transaction,
// which will either be the default currency code or the currency code of the
// charge if it's supported by PayPal if that option is enabled.
$currency_code = $payment_method['settings']['currency_code'];
if (!empty($payment_method['settings']['allow_supported_currencies']) && in_array($charge['currency_code'], array_keys(commerce_paypal_currencies('paypal_ec')))) {
$currency_code = $charge['currency_code'];
}
// Convert the charge amount to the specified currency.
$amount = commerce_currency_convert($charge['amount'], $charge['currency_code'], $currency_code);
$nvp = array(
'METHOD' => 'DoExpressCheckoutPayment',
'TOKEN' => $order->data['commerce_paypal_ec']['token'],
'PAYERID' => $order->data['commerce_paypal_ec']['payerid'],
'BUTTONSOURCE' => $payment_method['buttonsource'],
'PAYMENTREQUEST_0_AMT' => commerce_paypal_price_amount($amount, $currency_code),
'PAYMENTREQUEST_0_CURRENCYCODE' => $currency_code,
'PAYMENTREQUEST_0_INVNUM' => commerce_paypal_ipn_invoice($order),
'PAYMENTREQUEST_0_PAYMENTACTION' => commerce_paypal_payment_action($payment_method['settings']['txn_type']),
'PAYMENTREQUEST_0_NOTIFYURL' => commerce_paypal_ipn_url($payment_method['instance_id']),
);
// Add itemized information to the API request.
$nvp += commerce_paypal_ec_itemize_order($order, $currency_code);
// Submit the request to PayPal.
$response = commerce_paypal_api_request($payment_method, $nvp, $order);
// Prepare a transaction object to log the API response.
$transaction = commerce_payment_transaction_new('paypal_ec', $order->order_id);
$transaction->instance_id = $payment_method['instance_id'];
$transaction->amount = $amount;
$transaction->currency_code = $currency_code;
$transaction->payload[REQUEST_TIME] = $response;
// If available, set the remote status and transaction ID.
$key_map = array(
'remote_status' => 'PAYMENTINFO_0_PAYMENTSTATUS',
'remote_id' => 'PAYMENTINFO_0_TRANSACTIONID',
);
foreach ($key_map as $key => $response_key) {
if (!empty($response[$response_key])) {
$transaction->{$key} = $response[$response_key];
}
}
// Store the transaction ID as the parent transaction ID in case subsequent
// API operations alter this transaction's remote ID.
if (!empty($transaction->remote_id)) {
$transaction->data['commerce_paypal_ec']['parenttransactionid'] = $transaction->remote_id;
}
// Check if there is an error code in the response.
if (!empty($response['L_ERRORCODE0'])) {
// Log the error in a payment transaction.
$transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
$transaction->remote_status = '';
$message = array();
$message[] = '<strong>' . t('Payment failed') . '</strong>';
$message[] = t('Error @code: @message', array(
'@code' => $response['L_ERRORCODE0'],
'@message' => $response['L_SHORTMESSAGE0'],
));
$transaction->message = implode('<br />', $message);
commerce_payment_transaction_save($transaction);
// If the response error indicates a funding failure, redirect the customer
// back to PayPal for another attempt.
// @see: https://developer.paypal.com/docs/classic/express-checkout/ht_ec_fundingfailure10486/
if ($response['L_ERRORCODE0'] === '10486') {
// Log the error in watchdog.
watchdog('commerce_paypal_ec', 'PayPal Express Checkout transaction funding failed for order @order_number. Redirecting the user back to PayPal.', array(
'@order_number' => $order->order_number,
), WATCHDOG_NOTICE);
// Update order.
commerce_order_status_update($order, 'checkout_payment', FALSE, NULL, t('Customer payment transaction funding failed. Redirecting customer back to the PayPal Express Checkout page.'));
// Redirect the user back to PayPal.
drupal_goto(commerce_paypal_ec_checkout_url($payment_method['settings']['server'], $order->data['commerce_paypal_ec']['token']));
}
// Log the error in watchdog.
watchdog('commerce_paypal_ec', 'PayPal Express Checkout transaction failed for order @order_number.', array(
'@order_number' => $order->order_number,
), WATCHDOG_ERROR);
return FALSE;
}
// If we received an unknown response status...
if (!isset($response['PAYMENTINFO_0_PAYMENTSTATUS']) || !in_array($response['PAYMENTINFO_0_PAYMENTSTATUS'], array(
'Failed',
'Voided',
'Pending',
'Completed',
'Refunded',
))) {
// Display an error message and remain on the same page.
drupal_set_message(t('We could not complete your payment with PayPal. Please try again or contact us if the problem persists.'), 'error');
// Log the error in a payment transaction and watchdog.
$transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
$transaction->remote_status = '';
$transaction->message = t('Payment failed with unknown status.');
commerce_payment_transaction_save($transaction);
watchdog('commerce_paypal_ec', 'PayPal Express Checkout transaction failed for order @order_number.', array(
'@order_number' => $order->order_number,
), WATCHDOG_ERROR);
return FALSE;
}
// Build a meaningful response message.
$message = array();
// If we didn't get an approval response code...
switch ($response['PAYMENTINFO_0_PAYMENTSTATUS']) {
case 'Failed':
$transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
$message[] = '<strong>' . t('Payment failed') . '</strong>';
$message[] = t('Error @code: @message', array(
'@code' => $response['PAYMENTINFO_0_ERRORCODE'],
'@message' => $response['PAYMENTINFO_0_SHORTMESSAGE'],
));
break;
case 'Voided':
$transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
$message[] = '<strong>' . t('Authorization voided') . '</strong>';
break;
case 'Pending':
$transaction->status = COMMERCE_PAYMENT_STATUS_PENDING;
$transaction->data['commerce_paypal_ec']['paymenttype'] = $response['PAYMENTINFO_0_PAYMENTTYPE'];
$message[] = '<strong>' . t('Payment pending at PayPal') . '</strong>';
$message[] = commerce_paypal_short_pending_reason($response['PAYMENTINFO_0_PENDINGREASON']);
break;
case 'Completed':
$transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
$message[] = t('Payment completed successfully');
break;
case 'Refunded':
$transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
$message[] = t('Refund for transaction @txn_id', array(
'@txn_id' => $response['PAYMENTINFO_0_TRANSACTIONID'],
));
break;
}
// Set the final message.
$transaction->message = implode('<br />', $message);
// Save the transaction information.
commerce_payment_transaction_save($transaction);
// If the payment failed, display an error and rebuild the form.
if (!in_array($response['PAYMENTINFO_0_PAYMENTSTATUS'], array(
'Refunded',
'Completed',
'Pending',
))) {
drupal_set_message(t('We encountered an error processing your payment with PayPal. Please try again or contact us for assistance.'), 'error');
return FALSE;
}
return TRUE;
}