/**
* Handle incoming requests/notifications
* @param $args array
* @param $request PKPRequest
*/
function handle($args, $request)
{
$templateMgr = TemplateManager::getManager($request);
$journal = $request->getJournal();
if (!$journal) {
return parent::handle($args, $request);
}
// Just in case we need to contact someone
import('lib.pkp.classes.mail.MailTemplate');
// Prefer technical support contact
$contactName = $journal->getSetting('supportName');
$contactEmail = $journal->getSetting('supportEmail');
if (!$contactEmail) {
// Fall back on primary contact
$contactName = $journal->getSetting('contactName');
$contactEmail = $journal->getSetting('contactEmail');
}
$mail = new MailTemplate('PAYPAL_INVESTIGATE_PAYMENT');
$mail->setReplyTo(null);
$mail->addRecipient($contactEmail, $contactName);
$paymentStatus = $request->getUserVar('payment_status');
switch (array_shift($args)) {
case 'ipn':
// Build a confirmation transaction.
$req = 'cmd=_notify-validate';
if (get_magic_quotes_gpc()) {
foreach ($_POST as $key => $value) {
$req .= '&' . urlencode(stripslashes($key)) . '=' . urlencode(stripslashes($value));
}
} else {
foreach ($_POST as $key => $value) {
$req .= '&' . urlencode($key) . '=' . urlencode($value);
}
}
// Create POST response
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->getSetting($journal->getId(), 'paypalurl'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: PKP PayPal Service', 'Content-Type: application/x-www-form-urlencoded', 'Content-Length: ' . strlen($req)));
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
$ret = curl_exec($ch);
$curlError = curl_error($ch);
curl_close($ch);
// Check the confirmation response and handle as necessary.
if (strcmp($ret, 'VERIFIED') == 0) {
switch ($paymentStatus) {
case 'Completed':
$payPalDao = DAORegistry::getDAO('PayPalDAO');
$transactionId = $request->getUserVar('txn_id');
if ($payPalDao->transactionExists($transactionId)) {
// A duplicate transaction was received; notify someone.
$mail->assignParams(array('journalName' => $journal->getLocalizedName(), 'postInfo' => print_r($_POST, true), 'additionalInfo' => "Duplicate transaction ID: {$transactionId}", 'serverVars' => print_r($_SERVER, true)));
$mail->send();
exit;
} else {
// New transaction succeeded. Record it.
$payPalDao->insertTransaction($transactionId, $request->getUserVar('txn_type'), String::strtolower($request->getUserVar('payer_email')), String::strtolower($request->getUserVar('receiver_email')), $request->getUserVar('item_number'), $request->getUserVar('payment_date'), $request->getUserVar('payer_id'), $request->getUserVar('receiver_id'));
$queuedPaymentId = $request->getUserVar('custom');
import('classes.payment.ojs.OJSPaymentManager');
$ojsPaymentManager = new OJSPaymentManager($request);
// Verify the cost and user details as per PayPal spec.
$queuedPayment =& $ojsPaymentManager->getQueuedPayment($queuedPaymentId);
if (!$queuedPayment) {
// The queued payment entry is missing. Complain.
$mail->assignParams(array('journalName' => $journal->getLocalizedName(), 'postInfo' => print_r($_POST, true), 'additionalInfo' => "Missing queued payment ID: {$queuedPaymentId}", 'serverVars' => print_r($_SERVER, true)));
$mail->send();
exit;
}
//NB: if/when paypal subscriptions are enabled, these checks will have to be adjusted
// because subscription prices may change over time
$queuedAmount = $queuedPayment->getAmount();
$grantedAmount = $request->getUserVar('mc_gross');
$queuedCurrency = $queuedPayment->getCurrencyCode();
$grantedCurrency = $request->getUserVar('mc_currency');
$grantedEmail = String::strtolower($request->getUserVar('receiver_email'));
$queuedEmail = String::strtolower($this->getSetting($journal->getId(), 'selleraccount'));
if ($queuedAmount != $grantedAmount && $queuedAmount > 0 || $queuedCurrency != $grantedCurrency || $grantedEmail != $queuedEmail) {
// The integrity checks for the transaction failed. Complain.
$mail->assignParams(array('journalName' => $journal->getLocalizedName(), 'postInfo' => print_r($_POST, true), 'additionalInfo' => "Granted amount: {$grantedAmount}\n" . "Queued amount: {$queuedAmount}\n" . "Granted currency: {$grantedCurrency}\n" . "Queued currency: {$queuedCurrency}\n" . "Granted to PayPal account: {$grantedEmail}\n" . "Configured PayPal account: {$queuedEmail}", 'serverVars' => print_r($_SERVER, true)));
$mail->send();
exit;
}
// Update queued amount if amount set by user (e.g. donation)
if ($queuedAmount == 0 && $grantedAmount > 0) {
$queuedPaymentDao = DAORegistry::getDAO('QueuedPaymentDAO');
$queuedPayment->setAmount($grantedAmount);
$queuedPayment->setCurrencyCode($grantedCurrency);
$queuedPaymentDao->updateQueuedPayment($queuedPaymentId, $queuedPayment);
}
// Fulfill the queued payment.
if ($ojsPaymentManager->fulfillQueuedPayment($request, $queuedPayment, $this->getName())) {
exit;
}
// If we're still here, it means the payment couldn't be fulfilled.
$mail->assignParams(array('journalName' => $journal->getLocalizedName(), 'postInfo' => print_r($_POST, true), 'additionalInfo' => "Queued payment ID {$queuedPaymentId} could not be fulfilled.", 'serverVars' => print_r($_SERVER, true)));
$mail->send();
}
exit;
case 'Pending':
// Ignore.
exit;
default:
// An unhandled payment status was received; notify someone.
$mail->assignParams(array('journalName' => $journal->getLocalizedName(), 'postInfo' => print_r($_POST, true), 'additionalInfo' => "Payment status: {$paymentStatus}", 'serverVars' => print_r($_SERVER, true)));
$mail->send();
exit;
}
} else {
// An unknown confirmation response was received; notify someone.
$mail->assignParams(array('journalName' => $journal->getLocalizedName(), 'postInfo' => print_r($_POST, true), 'additionalInfo' => "Confirmation return: {$ret}\nCURL error: {$curlError}", 'serverVars' => print_r($_SERVER, true)));
$mail->send();
exit;
}
case 'cancel':
Handler::setupTemplate();
$templateMgr->assign(array('currentUrl' => $request->url(null, 'index'), 'pageTitle' => 'plugins.paymethod.paypal.purchase.cancelled.title', 'message' => 'plugins.paymethod.paypal.purchase.cancelled', 'backLink' => $request->getUserVar('ojsReturnUrl'), 'backLinkLabel' => 'common.continue'));
$templateMgr->display('frontend/pages/message.tpl');
exit;
}
parent::handle($args, $request);
// Don't know what to do with it
}