PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/paymethod/paypal/PayPalPlugin.inc.php

https://github.com/jksrecko/ojs
PHP | 326 lines | 222 code | 32 blank | 72 comment | 27 complexity | 50327cb2bee958c07ee1046664e4da05 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /**
  3. * @file plugins/paymethod/paypal/PayPalPlugin.inc.php
  4. *
  5. * Copyright (c) 2006-2009 Gunther Eysenbach, Juan Pablo Alperin, MJ Suhonos
  6. * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
  7. *
  8. * @class PayPalPlugin
  9. * @ingroup plugins_paymethod_paypal
  10. *
  11. * @brief PayPal Paymethod plugin class
  12. *
  13. */
  14. import('classes.plugins.PaymethodPlugin');
  15. class PayPalPlugin extends PaymethodPlugin {
  16. /**
  17. * Get the Plugin's internal name
  18. * @return String
  19. */
  20. function getName() {
  21. return 'Paypal';
  22. }
  23. /**
  24. * Get the Plugin's display name
  25. * @return String
  26. */
  27. function getDisplayName() {
  28. return Locale::translate('plugins.paymethod.paypal.displayName');
  29. }
  30. /**
  31. * Get a description of the plugin
  32. * @return String
  33. */
  34. function getDescription() {
  35. return Locale::translate('plugins.paymethod.paypal.description');
  36. }
  37. /**
  38. * Register plugin
  39. * @return bool
  40. */
  41. function register($category, $path) {
  42. if (parent::register($category, $path)) {
  43. if (!Config::getVar('general', 'installed') || defined('RUNNING_UPGRADE')) return true;
  44. $this->addLocaleData();
  45. $this->import('PayPalDAO');
  46. $payPalDao = new PayPalDAO();
  47. DAORegistry::registerDAO('PayPalDAO', $payPalDao);
  48. return true;
  49. }
  50. return false;
  51. }
  52. /**
  53. * Get an array of the fields in the settings form
  54. * @return array
  55. */
  56. function getSettingsFormFieldNames() {
  57. return array('paypalurl', 'selleraccount');
  58. }
  59. /**
  60. * return if required Curl is installed
  61. * @return bool
  62. */
  63. function isCurlInstalled() {
  64. return (function_exists('curl_init'));
  65. }
  66. /**
  67. * Check if plugin is configured and ready for use
  68. * @return bool
  69. */
  70. function isConfigured() {
  71. $journal =& Request::getJournal();
  72. if (!$journal) return false;
  73. // Make sure CURL support is included.
  74. if (!$this->isCurlInstalled()) return false;
  75. // Make sure that all settings form fields have been filled in
  76. foreach ($this->getSettingsFormFieldNames() as $settingName) {
  77. $setting = $this->getSetting($journal->getId(), $settingName);
  78. if (empty($setting)) return false;
  79. }
  80. return true;
  81. }
  82. /**
  83. * Display the settings form
  84. * @param $params
  85. * @param $smarty Smarty
  86. */
  87. function displayPaymentSettingsForm(&$params, &$smarty) {
  88. $smarty->assign('isCurlInstalled', $this->isCurlInstalled());
  89. return parent::displayPaymentSettingsForm($params, $smarty);
  90. }
  91. /**
  92. * Display the payment form
  93. * @param $queuedPaymentId int
  94. * @param $queuedPayment QueuedPayment
  95. */
  96. function displayPaymentForm($queuedPaymentId, &$queuedPayment) {
  97. if (!$this->isConfigured()) return false;
  98. $journal =& Request::getJournal();
  99. $user =& Request::getUser();
  100. $params = array(
  101. 'charset' => Config::getVar('i18n', 'client_charset'),
  102. 'business' => $this->getSetting($journal->getId(), 'selleraccount'),
  103. 'item_name' => $queuedPayment->getName(),
  104. 'item_description' => $queuedPayment->getDescription(), // not a paypal parameter (PayPal uses item_name)
  105. 'amount' => $queuedPayment->getAmount(),
  106. 'quantity' => 1,
  107. 'no_note' => 1,
  108. 'no_shipping' => 1,
  109. 'currency_code' => $queuedPayment->getCurrencyCode(),
  110. 'lc' => String::substr(Locale::getLocale(), 3),
  111. 'custom' => $queuedPaymentId,
  112. 'notify_url' => Request::url(null, 'payment', 'plugin', array($this->getName(), 'ipn')),
  113. 'return' => $queuedPayment->getRequestUrl(),
  114. 'cancel_return' => Request::url(null, 'payment', 'plugin', array($this->getName(), 'cancel')),
  115. 'first_name' => ($user)?$user->getFirstName():'',
  116. 'last_name' => ($user)?$user->getLastname():'',
  117. 'item_number' => $queuedPayment->getAssocId(),
  118. 'cmd' => '_xclick'
  119. );
  120. Locale::requireComponents(array(LOCALE_COMPONENT_APPLICATION_COMMON));
  121. $templateMgr =& TemplateManager::getManager();
  122. $templateMgr->assign('params', $params);
  123. $templateMgr->assign('paypalFormUrl', $this->getSetting($journal->getId(), 'paypalurl'));
  124. $templateMgr->display($this->getTemplatePath() . 'paymentForm.tpl');
  125. }
  126. /**
  127. * Handle incoming requests/notifications
  128. */
  129. function handle($args) {
  130. $templateMgr =& TemplateManager::getManager();
  131. $journal =& Request::getJournal();
  132. if (!$journal) return parent::handle($args);
  133. // Just in case we need to contact someone
  134. import('classes.mail.MailTemplate');
  135. $contactName = $journal->getSetting('contactName');
  136. $contactEmail = $journal->getSetting('contactEmail');
  137. $mail = new MailTemplate('PAYPAL_INVESTIGATE_PAYMENT');
  138. $mail->setFrom($contactEmail, $contactName);
  139. $mail->addRecipient($contactEmail, $contactName);
  140. $paymentStatus = Request::getUserVar('payment_status');
  141. switch (array_shift($args)) {
  142. case 'ipn':
  143. // Build a confirmation transaction.
  144. $req = 'cmd=_notify-validate';
  145. if (get_magic_quotes_gpc()) {
  146. foreach ($_POST as $key => $value) $req .= '&' . urlencode(stripslashes($key)) . '=' . urlencode(stripslashes($value));
  147. } else {
  148. foreach ($_POST as $key => $value) $req .= '&' . urlencode($key) . '=' . urlencode($value);
  149. }
  150. // Create POST response
  151. $ch = curl_init();
  152. curl_setopt($ch, CURLOPT_URL, $this->getSetting($journal->getId(), 'paypalurl'));
  153. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  154. curl_setopt($ch, CURLOPT_POST, 1);
  155. curl_setopt($ch, CURLOPT_HTTPHEADER, Array('Content-Type: application/x-www-form-urlencoded', 'Content-Length: ' . strlen($req)));
  156. curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
  157. $ret = curl_exec ($ch);
  158. curl_close ($ch);
  159. // Check the confirmation response and handle as necessary.
  160. if (strcmp($ret, 'VERIFIED') == 0) switch ($paymentStatus) {
  161. case 'Completed':
  162. $payPalDao =& DAORegistry::getDAO('PayPalDAO');
  163. $transactionId = Request::getUserVar('txn_id');
  164. if ($payPalDao->transactionExists($transactionId)) {
  165. // A duplicate transaction was received; notify someone.
  166. $mail->assignParams(array(
  167. 'journalName' => $journal->getLocalizedTitle(),
  168. 'postInfo' => print_r($_POST, true),
  169. 'additionalInfo' => "Duplicate transaction ID: $transactionId",
  170. 'serverVars' => print_r($_SERVER, true)
  171. ));
  172. $mail->send();
  173. exit();
  174. } else {
  175. // New transaction succeeded. Record it.
  176. $payPalDao->insertTransaction(
  177. $transactionId,
  178. Request::getUserVar('txn_type'),
  179. Request::getUserVar('payer_email'),
  180. Request::getUserVar('receiver_email'),
  181. Request::getUserVar('item_number'),
  182. Request::getUserVar('payment_date'),
  183. Request::getUserVar('payer_id'),
  184. Request::getUserVar('receiver_id')
  185. );
  186. $queuedPaymentId = Request::getUserVar('custom');
  187. import('classes.payment.ojs.OJSPaymentManager');
  188. $ojsPaymentManager =& OJSPaymentManager::getManager();
  189. // Verify the cost and user details as per PayPal spec.
  190. $queuedPayment =& $ojsPaymentManager->getQueuedPayment($queuedPaymentId);
  191. if (!$queuedPayment) {
  192. // The queued payment entry is missing. Complain.
  193. $mail->assignParams(array(
  194. 'journalName' => $journal->getLocalizedTitle(),
  195. 'postInfo' => print_r($_POST, true),
  196. 'additionalInfo' => "Missing queued payment ID: $queuedPaymentId",
  197. 'serverVars' => print_r($_SERVER, true)
  198. ));
  199. $mail->send();
  200. exit();
  201. }
  202. //NB: if/when paypal subscriptions are enabled, these checks will have to be adjusted
  203. // because subscription prices may change over time
  204. if (
  205. (($queuedAmount = $queuedPayment->getAmount()) != ($grantedAmount = Request::getUserVar('mc_gross')) && $queuedAmount > 0) ||
  206. ($queuedCurrency = $queuedPayment->getCurrencyCode()) != ($grantedCurrency = Request::getUserVar('mc_currency')) ||
  207. ($grantedEmail = Request::getUserVar('receiver_email')) != ($queuedEmail = $this->getSetting($journal->getId(), 'selleraccount'))
  208. ) {
  209. // The integrity checks for the transaction failed. Complain.
  210. $mail->assignParams(array(
  211. 'journalName' => $journal->getLocalizedTitle(),
  212. 'postInfo' => print_r($_POST, true),
  213. 'additionalInfo' =>
  214. "Granted amount: $grantedAmount\n" .
  215. "Queued amount: $queuedAmount\n" .
  216. "Granted currency: $grantedCurrency\n" .
  217. "Queued currency: $queuedCurrency\n" .
  218. "Granted to PayPal account: $grantedEmail\n" .
  219. "Configured PayPal account: $queuedEmail",
  220. 'serverVars' => print_r($_SERVER, true)
  221. ));
  222. $mail->send();
  223. exit();
  224. }
  225. // Update queued amount if amount set by user (e.g. donation)
  226. if ($queuedAmount == 0 && $grantedAmount > 0) {
  227. $queuedPaymentDao =& DAORegistry::getDAO('QueuedPaymentDAO');
  228. $queuedPayment->setAmount($grantedAmount);
  229. $queuedPayment->setCurrencyCode($grantedCurrency);
  230. $queuedPaymentDao->updateQueuedPayment($queuedPaymentId, $queuedPayment);
  231. }
  232. // Fulfill the queued payment.
  233. if ($ojsPaymentManager->fulfillQueuedPayment($queuedPayment, $this->getName())) exit();
  234. // If we're still here, it means the payment couldn't be fulfilled.
  235. $mail->assignParams(array(
  236. 'journalName' => $journal->getLocalizedTitle(),
  237. 'postInfo' => print_r($_POST, true),
  238. 'additionalInfo' => "Queued payment ID $queuedPaymentId could not be fulfilled.",
  239. 'serverVars' => print_r($_SERVER, true)
  240. ));
  241. $mail->send();
  242. }
  243. exit();
  244. case 'Pending':
  245. // Ignore.
  246. exit();
  247. default:
  248. // An unhandled payment status was received; notify someone.
  249. $mail->assignParams(array(
  250. 'journalName' => $journal->getLocalizedTitle(),
  251. 'postInfo' => print_r($_POST, true),
  252. 'additionalInfo' => "Payment status: $paymentStatus",
  253. 'serverVars' => print_r($_SERVER, true)
  254. ));
  255. $mail->send();
  256. exit();
  257. } else {
  258. // An unknown confirmation response was received; notify someone.
  259. $mail->assignParams(array(
  260. 'journalName' => $journal->getLocalizedTitle(),
  261. 'postInfo' => print_r($_POST, true),
  262. 'additionalInfo' => "Confirmation return: $ret",
  263. 'serverVars' => print_r($_SERVER, true)
  264. ));
  265. $mail->send();
  266. exit();
  267. }
  268. break;
  269. case 'cancel':
  270. Handler::setupTemplate();
  271. $templateMgr->assign(array(
  272. 'currentUrl' => Request::url(null, 'index'),
  273. 'pageTitle' => 'plugins.paymethod.paypal.purchase.cancelled.title',
  274. 'message' => 'plugins.paymethod.paypal.purchase.cancelled',
  275. 'backLink' => Request::getUserVar('ojsReturnUrl'),
  276. 'backLinkLabel' => 'common.continue'
  277. ));
  278. $templateMgr->display('common/message.tpl');
  279. exit();
  280. break;
  281. }
  282. parent::handle($args); // Don't know what to do with it
  283. }
  284. function getInstallSchemaFile() {
  285. return ($this->getPluginPath() . DIRECTORY_SEPARATOR . 'schema.xml');
  286. }
  287. function getInstallEmailTemplatesFile() {
  288. return ($this->getPluginPath() . DIRECTORY_SEPARATOR . 'emailTemplates.xml');
  289. }
  290. function getInstallEmailTemplateDataFile() {
  291. return ($this->getPluginPath() . '/locale/{$installedLocale}/emailTemplates.xml');
  292. }
  293. }
  294. ?>