File: /var/www/ojs/classes/payment/ojs/OJSPaymentManager.inc.php
<?php
/**
* @file classes/payment/ojs/OJSPaymentManager.inc.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class OJSPaymentManager
* @ingroup payment
* @see QueuedPayment
*
* @brief Provides payment management functions.
*
*/
import('lib.pkp.classes.payment.QueuedPayment');
import('lib.pkp.classes.payment.PaymentManager');
define('PAYMENT_TYPE_MEMBERSHIP', 0x000000001);
define('PAYMENT_TYPE_RENEW_SUBSCRIPTION', 0x000000002);
define('PAYMENT_TYPE_PURCHASE_ARTICLE', 0x000000003);
define('PAYMENT_TYPE_DONATION', 0x000000004);
define('PAYMENT_TYPE_SUBMISSION', 0x000000005);
define('PAYMENT_TYPE_FASTTRACK', 0x000000006);
define('PAYMENT_TYPE_PUBLICATION', 0x000000007);
define('PAYMENT_TYPE_PURCHASE_SUBSCRIPTION', 0x000000008);
define('PAYMENT_TYPE_PURCHASE_ISSUE', 0x000000009);
class OJSPaymentManager extends PaymentManager {
/**
* Determine whether the payment system is configured.
* @return boolean true iff configured
*/
function isConfigured() {
return parent::isConfigured() && $this->_context->getData('paymentsEnabled');
}
/**
* Create a queued payment.
* @param $request PKPRequest
* @param $type int PAYMENT_TYPE_...
* @param $userId int ID of user responsible for payment
* @param $assocId int ID of associated entity
* @param $amount float Amount of currency $currencyCode
* @param $currencyCode string optional ISO 4217 currency code
* @return QueuedPayment
*/
function createQueuedPayment($request, $type, $userId, $assocId, $amount, $currencyCode = null) {
if (is_null($currencyCode)) $currencyCode = $this->_context->getData('currency');
$payment = new QueuedPayment($amount, $currencyCode, $userId, $assocId);
$payment->setContextId($this->_context->getId());
$payment->setType($type);
$router = $request->getRouter();
$dispatcher = $router->getDispatcher();
switch ($type) {
case PAYMENT_TYPE_PURCHASE_ARTICLE:
$payment->setRequestUrl($dispatcher->url($request, ROUTE_PAGE, null, 'article', 'view', $assocId));
break;
case PAYMENT_TYPE_PURCHASE_ISSUE:
$payment->setRequestUrl($dispatcher->url($request, ROUTE_PAGE, null, 'issue', 'view', $assocId));
break;
case PAYMENT_TYPE_PURCHASE_SUBSCRIPTION:
$payment->setRequestUrl($dispatcher->url($request, ROUTE_PAGE, null, 'issue', 'current'));
break;
case PAYMENT_TYPE_RENEW_SUBSCRIPTION:
$payment->setRequestUrl($dispatcher->url($request, ROUTE_PAGE, null, 'user', 'subscriptions'));
break;
case PAYMENT_TYPE_PUBLICATION:
$submissionDao = DAORegistry::getDAO('SubmissionDAO'); /* @var $submissionDao SubmissionDAO */
$submission = $submissionDao->getById($assocId);
if ($submission->getSubmissionProgress()!=0) {
$payment->setRequestUrl($dispatcher->url($request, ROUTE_PAGE, null, 'submission', 'wizard', $submission->getSubmissionProgress(), array('submissionId' => $assocId)));
} else {
$payment->setRequestUrl($dispatcher->url($request, ROUTE_PAGE, null, 'authorDashboard', 'submission', $submission->getId()));
}
break;
case PAYMENT_TYPE_MEMBERSHIP: // Deprecated
case PAYMENT_TYPE_DONATION: // Deprecated
case PAYMENT_TYPE_FASTTRACK: // Deprecated
case PAYMENT_TYPE_SUBMISSION: // Deprecated
default:
// Invalid payment type
error_log('Invalid payment type "' . $type . '"');
assert(false);
break;
}
return $payment;
}
/**
* Create a completed payment from a queued payment.
* @param $queuedPayment QueuedPayment Payment to complete.
* @param $payMethod string Name of payment plugin used.
* @param $userId int User ID to attribute payment to (if unspecified, will be taken from queued payment)
* @return CompletedPayment
*/
function createCompletedPayment($queuedPayment, $payMethod, $userId = null) {
import('lib.pkp.classes.payment.CompletedPayment');
$payment = new CompletedPayment();
$payment->setContextId($queuedPayment->getContextId());
$payment->setType($queuedPayment->getType());
$payment->setAmount($queuedPayment->getAmount());
$payment->setCurrencyCode($queuedPayment->getCurrencyCode());
if ($userId) $payment->setUserId($userId);
else $payment->setUserId($queuedPayment->getUserId());
$payment->setAssocId($queuedPayment->getAssocId());
$payment->setPayMethodPluginName($payMethod);
return $payment;
}
/**
* Determine whether publication fees are enabled.
* @return boolean true iff this fee is enabled.
*/
function publicationEnabled() {
return $this->isConfigured() && $this->_context->getData('publicationFee') > 0;
}
/**
* Determine whether publication fees are enabled.
* @return boolean true iff this fee is enabled.
*/
function membershipEnabled() {
return $this->isConfigured() && $this->_context->getData('membershipFee') > 0;
}
/**
* Determine whether article purchase fees are enabled.
* @return boolean true iff this fee is enabled.
*/
function purchaseArticleEnabled() {
return $this->isConfigured() && $this->_context->getData('purchaseArticleFee') > 0;
}
/**
* Determine whether issue purchase fees are enabled.
* @return boolean true iff this fee is enabled.
*/
function purchaseIssueEnabled() {
return $this->isConfigured() && $this->_context->getData('purchaseIssueFee') > 0;
}
/**
* Determine whether PDF-only article purchase fees are enabled.
* @return boolean true iff this fee is enabled.
*/
function onlyPdfEnabled() {
return $this->isConfigured() && $this->_context->getData('restrictOnlyPdf');
}
/**
* Get the payment plugin.
* @return PaymethodPlugin
*/
function getPaymentPlugin() {
$paymentMethodPluginName = $this->_context->getData('paymentPluginName');
$paymentMethodPlugin = null;
if (!empty($paymentMethodPluginName)) {
$plugins = PluginRegistry::loadCategory('paymethod');
if (isset($plugins[$paymentMethodPluginName])) $paymentMethodPlugin = $plugins[$paymentMethodPluginName];
}
return $paymentMethodPlugin;
}
/**
* Fulfill a queued payment.
* @param $request PKPRequest
* @param $queuedPayment QueuedPayment
* @param $payMethodPluginName string Name of payment plugin.
* @return mixed Dependent on payment type.
*/
function fulfillQueuedPayment($request, $queuedPayment, $payMethodPluginName = null) {
$returner = false;
$journal = $request->getContext();
if ($queuedPayment) switch ($queuedPayment->getType()) {
case PAYMENT_TYPE_MEMBERSHIP:
$userDao = DAORegistry::getDAO('UserDAO'); /* @var $userDao UserDAO */
$user = $userDao->getById($queuedPayment->getUserId());
$dateEnd = $user->getSetting('dateEndMembership', 0);
if (!$dateEnd) $dateEnd = 0;
// if the membership is expired, extend it to today + 1 year
$time = time();
if ($dateEnd < $time ) $dateEnd = $time;
$dateEnd = mktime(23, 59, 59, date("m", $dateEnd), date("d", $dateEnd), date("Y", $dateEnd)+1);
$user->updateSetting('dateEndMembership', $dateEnd, 'date', 0);
$returner = true;
break;
case PAYMENT_TYPE_PURCHASE_SUBSCRIPTION:
$subscriptionId = $queuedPayment->getAssocId();
$institutionalSubscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO'); /* @var $institutionalSubscriptionDao InstitutionalSubscriptionDAO */
$individualSubscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /* @var $individualSubscriptionDao IndividualSubscriptionDAO */
if ($institutionalSubscriptionDao->subscriptionExists($subscriptionId)) {
$subscription = $institutionalSubscriptionDao->getById($subscriptionId);
$institutional = true;
} else {
$subscription = $individualSubscriptionDao->getById($subscriptionId);
$institutional = false;
}
if (!$subscription || $subscription->getUserId() != $queuedPayment->getUserId() || $subscription->getJournalId() != $queuedPayment->getContextId()) {
fatalError('Subscription integrity checks fail!');
return false;
}
// Update subscription end date now that payment is completed
if ($institutional) {
// Still requires approval from JM/SM since includes domain and IP ranges
import('classes.subscription.InstitutionalSubscription');
$subscription->setStatus(SUBSCRIPTION_STATUS_NEEDS_APPROVAL);
if ($subscription->isNonExpiring()) {
$institutionalSubscriptionDao->updateObject($subscription);
} else {
$institutionalSubscriptionDao->renewSubscription($subscription);
}
// Notify JM/SM of completed online purchase
if ($journal->getData('enableSubscriptionOnlinePaymentNotificationPurchaseInstitutional')) {
import('classes.subscription.SubscriptionAction');
SubscriptionAction::sendOnlinePaymentNotificationEmail($request, $subscription, 'SUBSCRIPTION_PURCHASE_INSTL');
}
} else {
import('classes.subscription.IndividualSubscription');
$subscription->setStatus(SUBSCRIPTION_STATUS_ACTIVE);
if ($subscription->isNonExpiring()) {
$individualSubscriptionDao->updateObject($subscription);
} else {
$individualSubscriptionDao->renewSubscription($subscription);
}
// Notify JM/SM of completed online purchase
if ($journal->getData('enableSubscriptionOnlinePaymentNotificationPurchaseIndividual')) {
import('classes.subscription.SubscriptionAction');
SubscriptionAction::sendOnlinePaymentNotificationEmail($request, $subscription, 'SUBSCRIPTION_PURCHASE_INDL');
}
}
$returner = true;
break;
case PAYMENT_TYPE_RENEW_SUBSCRIPTION:
$subscriptionId = $queuedPayment->getAssocId();
$institutionalSubscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO'); /* @var $institutionalSubscriptionDao InstitutionalSubscriptionDAO */
$individualSubscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /* @var $individualSubscriptionDao IndividualSubscriptionDAO */
if ($institutionalSubscriptionDao->subscriptionExists($subscriptionId)) {
$subscription = $institutionalSubscriptionDao->getById($subscriptionId);
$institutional = true;
} else {
$subscription = $individualSubscriptionDao->getById($subscriptionId);
$institutional = false;
}
if (!$subscription || $subscription->getUserId() != $queuedPayment->getUserId() || $subscription->getJournalId() != $queuedPayment->getContextId()) {
return false;
}
if ($institutional) {
$institutionalSubscriptionDao->renewSubscription($subscription);
// Notify JM/SM of completed online purchase
if ($journal->getData('enableSubscriptionOnlinePaymentNotificationRenewInstitutional')) {
import('classes.subscription.SubscriptionAction');
SubscriptionAction::sendOnlinePaymentNotificationEmail($request, $subscription, 'SUBSCRIPTION_RENEW_INSTL');
}
} else {
$individualSubscriptionDao->renewSubscription($subscription);
// Notify JM/SM of completed online purchase
if ($journal->getData('enableSubscriptionOnlinePaymentNotificationRenewIndividual')) {
import('classes.subscription.SubscriptionAction');
SubscriptionAction::sendOnlinePaymentNotificationEmail($request, $subscription, 'SUBSCRIPTION_RENEW_INDL');
}
}
$returner = true;
break;
case PAYMENT_TYPE_DONATION:
assert(false); // Deprecated
$returner = true;
break;
case PAYMENT_TYPE_PURCHASE_ARTICLE:
case PAYMENT_TYPE_PURCHASE_ISSUE:
case PAYMENT_TYPE_SUBMISSION:
case PAYMENT_TYPE_PUBLICATION:
$returner = true;
break;
default:
// Invalid payment type
assert(false);
}
$completedPaymentDao = DAORegistry::getDAO('OJSCompletedPaymentDAO'); /* @var $completedPaymentDao OJSCompletedPaymentDAO */
$completedPayment = $this->createCompletedPayment($queuedPayment, $payMethodPluginName, $request->getUser()->getId());
$completedPaymentDao->insertObject($completedPayment);
$queuedPaymentDao = DAORegistry::getDAO('QueuedPaymentDAO'); /* @var $queuedPaymentDao QueuedPaymentDAO */
$queuedPaymentDao->deleteById($queuedPayment->getId());
return $returner;
}
/**
* Fetch the name of the description.
* @return string
*/
function getPaymentName($payment) {
switch ($payment->getType()) {
case PAYMENT_TYPE_PURCHASE_SUBSCRIPTION:
case PAYMENT_TYPE_RENEW_SUBSCRIPTION:
$institutionalSubscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO'); /* @var $institutionalSubscriptionDao InstitutionalSubscriptionDAO */
if ($institutionalSubscriptionDao->subscriptionExists($payment->getAssocId())) {
$subscription = $institutionalSubscriptionDao->getById($payment->getAssocId());
} else {
$individualSubscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /* @var $individualSubscriptionDao IndividualSubscriptionDAO */
$subscription = $individualSubscriptionDao->getById($payment->getAssocId());
}
if (!$subscription) return __('payment.type.subscription');
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /* @var $subscriptionTypeDao SubscriptionTypeDAO */
$subscriptionType = $subscriptionTypeDao->getById($subscription->getTypeId());
return __('payment.type.subscription') . ' (' . $subscriptionType->getLocalizedName() . ')';
case PAYMENT_TYPE_DONATION:
// DEPRECATED: This is only for display of OJS 2.x data.
return __('payment.type.donation');
case PAYMENT_TYPE_MEMBERSHIP:
return __('payment.type.membership');
case PAYMENT_TYPE_PURCHASE_ARTICLE:
return __('payment.type.purchaseArticle');
case PAYMENT_TYPE_PURCHASE_ISSUE:
return __('payment.type.purchaseIssue');
case PAYMENT_TYPE_SUBMISSION:
// DEPRECATED: This is only for display of OJS 2.x data.
return __('payment.type.submission');
case PAYMENT_TYPE_FASTTRACK:
// DEPRECATED: This is only for display of OJS 2.x data.
return __('payment.type.fastTrack');
case PAYMENT_TYPE_PUBLICATION:
return __('payment.type.publication');
default:
// Invalid payment type
assert(false);
}
}
}