/app/code/core/Mage/Paypal/Model/Ipn.php

https://bitbucket.org/MXWest/magento-ce-1.7.0.2 · PHP · 696 lines · 427 code · 66 blank · 203 comment · 55 complexity · 1dc413a04499039d9d09e2282697dae0 MD5 · raw file

  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_Paypal
  23. * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * PayPal Instant Payment Notification processor model
  28. */
  29. class Mage_Paypal_Model_Ipn
  30. {
  31. /**
  32. * Default log filename
  33. *
  34. * @var string
  35. */
  36. const DEFAULT_LOG_FILE = 'paypal_unknown_ipn.log';
  37. /*
  38. * @param Mage_Sales_Model_Order
  39. */
  40. protected $_order = null;
  41. /*
  42. * Recurring profile instance
  43. *
  44. * @var Mage_Sales_Model_Recurring_Profile
  45. */
  46. protected $_recurringProfile = null;
  47. /**
  48. *
  49. * @var Mage_Paypal_Model_Config
  50. */
  51. protected $_config = null;
  52. /**
  53. * PayPal info instance
  54. *
  55. * @var Mage_Paypal_Model_Info
  56. */
  57. protected $_info = null;
  58. /**
  59. * IPN request data
  60. * @var array
  61. */
  62. protected $_request = array();
  63. /**
  64. * Collected debug information
  65. *
  66. * @var array
  67. */
  68. protected $_debugData = array();
  69. /**
  70. * IPN request data getter
  71. *
  72. * @param string $key
  73. * @return array|string
  74. */
  75. public function getRequestData($key = null)
  76. {
  77. if (null === $key) {
  78. return $this->_request;
  79. }
  80. return isset($this->_request[$key]) ? $this->_request[$key] : null;
  81. }
  82. /**
  83. * Get ipn data, send verification to PayPal, run corresponding handler
  84. *
  85. * @param array $request
  86. * @param Zend_Http_Client_Adapter_Interface $httpAdapter
  87. * @throws Exception
  88. */
  89. public function processIpnRequest(array $request, Zend_Http_Client_Adapter_Interface $httpAdapter = null)
  90. {
  91. $this->_request = $request;
  92. $this->_debugData = array('ipn' => $request);
  93. ksort($this->_debugData['ipn']);
  94. try {
  95. if (isset($this->_request['txn_type']) && 'recurring_payment' == $this->_request['txn_type']) {
  96. $this->_getRecurringProfile();
  97. if ($httpAdapter) {
  98. $this->_postBack($httpAdapter);
  99. }
  100. $this->_processRecurringProfile();
  101. } else {
  102. $this->_getOrder();
  103. if ($httpAdapter) {
  104. $this->_postBack($httpAdapter);
  105. }
  106. $this->_processOrder();
  107. }
  108. } catch (Exception $e) {
  109. $this->_debugData['exception'] = $e->getMessage();
  110. $this->_debug();
  111. throw $e;
  112. }
  113. $this->_debug();
  114. }
  115. /**
  116. * Post back to PayPal to check whether this request is a valid one
  117. *
  118. * @param Zend_Http_Client_Adapter_Interface $httpAdapter
  119. */
  120. protected function _postBack(Zend_Http_Client_Adapter_Interface $httpAdapter)
  121. {
  122. $sReq = '';
  123. foreach ($this->_request as $k => $v) {
  124. $sReq .= '&'.$k.'='.urlencode($v);
  125. }
  126. $sReq .= "&cmd=_notify-validate";
  127. $sReq = substr($sReq, 1);
  128. $this->_debugData['postback'] = $sReq;
  129. $this->_debugData['postback_to'] = $this->_config->getPaypalUrl();
  130. $httpAdapter->setConfig(array('verifypeer' => $this->_config->verifyPeer));
  131. $httpAdapter->write(Zend_Http_Client::POST, $this->_config->getPaypalUrl(), '1.1', array(), $sReq);
  132. try {
  133. $response = $httpAdapter->read();
  134. } catch (Exception $e) {
  135. $this->_debugData['http_error'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
  136. throw $e;
  137. }
  138. $this->_debugData['postback_result'] = $response;
  139. $response = preg_split('/^\r?$/m', $response, 2);
  140. $response = trim($response[1]);
  141. if ($response != 'VERIFIED') {
  142. throw new Exception('PayPal IPN postback failure. See ' . self::DEFAULT_LOG_FILE . ' for details.');
  143. }
  144. unset($this->_debugData['postback'], $this->_debugData['postback_result']);
  145. }
  146. /**
  147. * Load and validate order, instantiate proper configuration
  148. *
  149. *
  150. * @return Mage_Sales_Model_Order
  151. * @throws Exception
  152. */
  153. protected function _getOrder()
  154. {
  155. if (empty($this->_order)) {
  156. // get proper order
  157. $id = $this->_request['invoice'];
  158. $this->_order = Mage::getModel('sales/order')->loadByIncrementId($id);
  159. if (!$this->_order->getId()) {
  160. $this->_debugData['exception'] = sprintf('Wrong order ID: "%s".', $id);
  161. $this->_debug();
  162. Mage::app()->getResponse()
  163. ->setHeader('HTTP/1.1','503 Service Unavailable')
  164. ->sendResponse();
  165. exit;
  166. }
  167. // re-initialize config with the method code and store id
  168. $methodCode = $this->_order->getPayment()->getMethod();
  169. $this->_config = Mage::getModel('paypal/config', array($methodCode, $this->_order->getStoreId()));
  170. if (!$this->_config->isMethodActive($methodCode) || !$this->_config->isMethodAvailable()) {
  171. throw new Exception(sprintf('Method "%s" is not available.', $methodCode));
  172. }
  173. $this->_verifyOrder();
  174. }
  175. return $this->_order;
  176. }
  177. /**
  178. * Load recurring profile
  179. *
  180. * @return Mage_Sales_Model_Recurring_Profile
  181. * @throws Exception
  182. */
  183. protected function _getRecurringProfile()
  184. {
  185. if (empty($this->_recurringProfile)) {
  186. // get proper recurring profile
  187. $internalReferenceId = $this->_request['rp_invoice_id'];
  188. $this->_recurringProfile = Mage::getModel('sales/recurring_profile')
  189. ->loadByInternalReferenceId($internalReferenceId);
  190. if (!$this->_recurringProfile->getId()) {
  191. throw new Exception(
  192. sprintf('Wrong recurring profile INTERNAL_REFERENCE_ID: "%s".', $internalReferenceId)
  193. );
  194. }
  195. // re-initialize config with the method code and store id
  196. $methodCode = $this->_recurringProfile->getMethodCode();
  197. $this->_config = Mage::getModel(
  198. 'paypal/config', array($methodCode, $this->_recurringProfile->getStoreId())
  199. );
  200. if (!$this->_config->isMethodActive($methodCode) || !$this->_config->isMethodAvailable()) {
  201. throw new Exception(sprintf('Method "%s" is not available.', $methodCode));
  202. }
  203. }
  204. return $this->_recurringProfile;
  205. }
  206. /**
  207. * Validate incoming request data, as PayPal recommends
  208. *
  209. * @throws Exception
  210. * @link https://cms.paypal.com/cgi-bin/marketingweb?cmd=_render-content&content_ID=developer/e_howto_admin_IPNIntro
  211. */
  212. protected function _verifyOrder()
  213. {
  214. // verify merchant email intended to receive notification
  215. $merchantEmail = $this->_config->businessAccount;
  216. if ($merchantEmail) {
  217. $receiverEmail = $this->getRequestData('business');
  218. if (!$receiverEmail) {
  219. $receiverEmail = $this->getRequestData('receiver_email');
  220. }
  221. if (strtolower($merchantEmail) != strtolower($receiverEmail)) {
  222. throw new Exception(
  223. sprintf(
  224. 'Requested %s and configured %s merchant emails do not match.', $receiverEmail, $merchantEmail
  225. )
  226. );
  227. }
  228. }
  229. }
  230. /**
  231. * IPN workflow implementation
  232. * Everything should be added to order comments. In positive processing cases customer will get email notifications.
  233. * Admin will be notified on errors.
  234. */
  235. protected function _processOrder()
  236. {
  237. $this->_order = null;
  238. $this->_getOrder();
  239. $this->_info = Mage::getSingleton('paypal/info');
  240. try {
  241. // handle payment_status
  242. $paymentStatus = $this->_filterPaymentStatus($this->_request['payment_status']);
  243. switch ($paymentStatus) {
  244. // paid
  245. case Mage_Paypal_Model_Info::PAYMENTSTATUS_COMPLETED:
  246. $this->_registerPaymentCapture();
  247. break;
  248. // the holded payment was denied on paypal side
  249. case Mage_Paypal_Model_Info::PAYMENTSTATUS_DENIED:
  250. $this->_registerPaymentDenial();
  251. break;
  252. // customer attempted to pay via bank account, but failed
  253. case Mage_Paypal_Model_Info::PAYMENTSTATUS_FAILED:
  254. // cancel order
  255. $this->_registerPaymentFailure();
  256. break;
  257. // refund forced by PayPal
  258. case Mage_Paypal_Model_Info::PAYMENTSTATUS_REVERSED: // break is intentionally omitted
  259. case Mage_Paypal_Model_Info::PAYMENTSTATUS_UNREVERSED: // or returned back :)
  260. $this->_registerPaymentReversal();
  261. break;
  262. // refund by merchant on PayPal side
  263. case Mage_Paypal_Model_Info::PAYMENTSTATUS_REFUNDED:
  264. $this->_registerPaymentRefund();
  265. break;
  266. // payment was obtained, but money were not captured yet
  267. case Mage_Paypal_Model_Info::PAYMENTSTATUS_PENDING:
  268. $this->_registerPaymentPending();
  269. break;
  270. // MassPayments success
  271. case Mage_Paypal_Model_Info::PAYMENTSTATUS_PROCESSED:
  272. $this->_registerMasspaymentsSuccess();
  273. break;
  274. // authorization expire/void
  275. case Mage_Paypal_Model_Info::PAYMENTSTATUS_EXPIRED: // break is intentionally omitted
  276. case Mage_Paypal_Model_Info::PAYMENTSTATUS_VOIDED:
  277. $this->_registerPaymentVoid();
  278. break;
  279. default:
  280. throw new Exception("Cannot handle payment status '{$paymentStatus}'.");
  281. }
  282. } catch (Mage_Core_Exception $e) {
  283. $comment = $this->_createIpnComment(Mage::helper('paypal')->__('Note: %s', $e->getMessage()), true);
  284. $comment->save();
  285. throw $e;
  286. }
  287. }
  288. /**
  289. * Process notification from recurring profile payments
  290. */
  291. protected function _processRecurringProfile()
  292. {
  293. $this->_recurringProfile = null;
  294. $this->_getRecurringProfile();
  295. try {
  296. // handle payment_status
  297. $paymentStatus = $this->_filterPaymentStatus($this->_request['payment_status']);
  298. switch ($paymentStatus) {
  299. // paid
  300. case Mage_Paypal_Model_Info::PAYMENTSTATUS_COMPLETED:
  301. $this->_registerRecurringProfilePaymentCapture();
  302. break;
  303. default:
  304. throw new Exception("Cannot handle payment status '{$paymentStatus}'.");
  305. }
  306. } catch (Mage_Core_Exception $e) {
  307. // TODO: add to payment profile comments
  308. // $comment = $this->_createIpnComment(Mage::helper('paypal')->__('Note: %s', $e->getMessage()), true);
  309. // $comment->save();
  310. throw $e;
  311. }
  312. }
  313. /**
  314. * Register recurring payment notification, create and process order
  315. */
  316. protected function _registerRecurringProfilePaymentCapture()
  317. {
  318. $price = $this->getRequestData('mc_gross') - $this->getRequestData('tax') - $this->getRequestData('shipping');
  319. $productItemInfo = new Varien_Object;
  320. $type = trim($this->getRequestData('period_type'));
  321. if ($type == 'Trial') {
  322. $productItemInfo->setPaymentType(Mage_Sales_Model_Recurring_Profile::PAYMENT_TYPE_TRIAL);
  323. } elseif ($type == 'Regular') {
  324. $productItemInfo->setPaymentType(Mage_Sales_Model_Recurring_Profile::PAYMENT_TYPE_REGULAR);
  325. }
  326. $productItemInfo->setTaxAmount($this->getRequestData('tax'));
  327. $productItemInfo->setShippingAmount($this->getRequestData('shipping'));
  328. $productItemInfo->setPrice($price);
  329. $order = $this->_recurringProfile->createOrder($productItemInfo);
  330. $payment = $order->getPayment();
  331. $payment->setTransactionId($this->getRequestData('txn_id'))
  332. ->setPreparedMessage($this->_createIpnComment(''))
  333. ->setIsTransactionClosed(0);
  334. $order->save();
  335. $this->_recurringProfile->addOrderRelation($order->getId());
  336. $payment->registerCaptureNotification($this->getRequestData('mc_gross'));
  337. $order->save();
  338. // notify customer
  339. if ($invoice = $payment->getCreatedInvoice()) {
  340. $message = Mage::helper('paypal')->__('Notified customer about invoice #%s.', $invoice->getIncrementId());
  341. $comment = $order->sendNewOrderEmail()->addStatusHistoryComment($message)
  342. ->setIsCustomerNotified(true)
  343. ->save();
  344. }
  345. }
  346. /**
  347. * Process completed payment (either full or partial)
  348. */
  349. protected function _registerPaymentCapture()
  350. {
  351. if ($this->getRequestData('transaction_entity') == 'auth') {
  352. return;
  353. }
  354. $this->_importPaymentInformation();
  355. $payment = $this->_order->getPayment();
  356. $payment->setTransactionId($this->getRequestData('txn_id'))
  357. ->setPreparedMessage($this->_createIpnComment(''))
  358. ->setParentTransactionId($this->getRequestData('parent_txn_id'))
  359. ->setShouldCloseParentTransaction('Completed' === $this->getRequestData('auth_status'))
  360. ->setIsTransactionClosed(0)
  361. ->registerCaptureNotification($this->getRequestData('mc_gross'));
  362. $this->_order->save();
  363. // notify customer
  364. $invoice = $payment->getCreatedInvoice();
  365. if ($invoice && !$this->_order->getEmailSent()) {
  366. $this->_order->sendNewOrderEmail()->addStatusHistoryComment(
  367. Mage::helper('paypal')->__('Notified customer about invoice #%s.', $invoice->getIncrementId())
  368. )
  369. ->setIsCustomerNotified(true)
  370. ->save();
  371. }
  372. }
  373. /**
  374. * Process denied payment notification
  375. */
  376. protected function _registerPaymentDenial()
  377. {
  378. $this->_importPaymentInformation();
  379. $this->_order->getPayment()
  380. ->setTransactionId($this->getRequestData('txn_id'))
  381. ->setNotificationResult(true)
  382. ->setIsTransactionClosed(true)
  383. ->registerPaymentReviewAction(Mage_Sales_Model_Order_Payment::REVIEW_ACTION_DENY, false);
  384. $this->_order->save();
  385. }
  386. /**
  387. * Treat failed payment as order cancellation
  388. */
  389. protected function _registerPaymentFailure()
  390. {
  391. $this->_importPaymentInformation();
  392. $this->_order
  393. ->registerCancellation($this->_createIpnComment(''), false)
  394. ->save();
  395. }
  396. /**
  397. * Process a refund or a chargeback
  398. */
  399. protected function _registerPaymentRefund()
  400. {
  401. $this->_importPaymentInformation();
  402. $reason = $this->getRequestData('reason_code');
  403. $isRefundFinal = !$this->_info->isReversalDisputable($reason);
  404. $payment = $this->_order->getPayment()
  405. ->setPreparedMessage($this->_createIpnComment($this->_info->explainReasonCode($reason)))
  406. ->setTransactionId($this->getRequestData('txn_id'))
  407. ->setParentTransactionId($this->getRequestData('parent_txn_id'))
  408. ->setIsTransactionClosed($isRefundFinal)
  409. ->registerRefundNotification(-1 * $this->getRequestData('mc_gross'));
  410. $this->_order->save();
  411. // TODO: there is no way to close a capture right now
  412. if ($creditmemo = $payment->getCreatedCreditmemo()) {
  413. $creditmemo->sendEmail();
  414. $comment = $this->_order->addStatusHistoryComment(
  415. Mage::helper('paypal')->__('Notified customer about creditmemo #%s.', $creditmemo->getIncrementId())
  416. )
  417. ->setIsCustomerNotified(true)
  418. ->save();
  419. }
  420. }
  421. /**
  422. * Process payment reversal notification
  423. */
  424. protected function _registerPaymentReversal()
  425. {
  426. /**
  427. * PayPal may send such payment status when triggered IPR denial
  428. * Note that this check is done on the old payment info object, before importing new payment information
  429. */
  430. if ($this->_info->isPaymentReviewRequired($this->_order->getPayment())) {
  431. $this->_registerPaymentDenial();
  432. return;
  433. }
  434. if ('chargeback_reimbursement' == $this->getRequestData('reason_code')) {
  435. // TODO: chargebacks reversals are not implemented
  436. return;
  437. }
  438. // treat as a usual charegeback
  439. $this->_registerPaymentRefund();
  440. }
  441. /**
  442. * Process payment pending notification
  443. *
  444. * @throws Exception
  445. */
  446. public function _registerPaymentPending()
  447. {
  448. $reason = $this->getRequestData('pending_reason');
  449. if ('authorization' === $reason) {
  450. $this->_registerPaymentAuthorization();
  451. return;
  452. }
  453. if ('order' === $reason) {
  454. throw new Exception('The "order" authorizations are not implemented.');
  455. }
  456. // case when was placed using PayPal standard
  457. if (Mage_Sales_Model_Order::STATE_PENDING_PAYMENT == $this->_order->getState()) {
  458. $this->_registerPaymentCapture();
  459. return;
  460. }
  461. $this->_importPaymentInformation();
  462. $this->_order->getPayment()
  463. ->setPreparedMessage($this->_createIpnComment($this->_info->explainPendingReason($reason)))
  464. ->setTransactionId($this->getRequestData('txn_id'))
  465. ->setIsTransactionClosed(0)
  466. ->registerPaymentReviewAction(Mage_Sales_Model_Order_Payment::REVIEW_ACTION_UPDATE, false);
  467. $this->_order->save();
  468. }
  469. /**
  470. * Register authorized payment
  471. */
  472. protected function _registerPaymentAuthorization()
  473. {
  474. $this->_importPaymentInformation();
  475. $this->_order->getPayment()
  476. ->setPreparedMessage($this->_createIpnComment(''))
  477. ->setTransactionId($this->getRequestData('txn_id'))
  478. ->setParentTransactionId($this->getRequestData('parent_txn_id'))
  479. ->setIsTransactionClosed(0)
  480. ->registerAuthorizationNotification($this->getRequestData('mc_gross'));
  481. if (!$this->_order->getEmailSent()) {
  482. $this->_order->sendNewOrderEmail();
  483. }
  484. $this->_order->save();
  485. }
  486. /**
  487. * Process voided authorization
  488. */
  489. protected function _registerPaymentVoid()
  490. {
  491. $this->_importPaymentInformation();
  492. $parentTxnId = $this->getRequestData('transaction_entity') == 'auth'
  493. ? $this->getRequestData('txn_id') : $this->getRequestData('parent_txn_id');
  494. $this->_order->getPayment()
  495. ->setPreparedMessage($this->_createIpnComment(''))
  496. ->setParentTransactionId($parentTxnId)
  497. ->registerVoidNotification();
  498. $this->_order->save();
  499. }
  500. /**
  501. * TODO
  502. * The status "Processed" is used when all Masspayments are successful
  503. */
  504. protected function _registerMasspaymentsSuccess()
  505. {
  506. $comment = $this->_createIpnComment('', true);
  507. $comment->save();
  508. }
  509. /**
  510. * Generate an "IPN" comment with additional explanation.
  511. * Returns the generated comment or order status history object
  512. *
  513. * @param string $comment
  514. * @param bool $addToHistory
  515. * @return string|Mage_Sales_Model_Order_Status_History
  516. */
  517. protected function _createIpnComment($comment = '', $addToHistory = false)
  518. {
  519. $paymentStatus = $this->getRequestData('payment_status');
  520. $message = Mage::helper('paypal')->__('IPN "%s".', $paymentStatus);
  521. if ($comment) {
  522. $message .= ' ' . $comment;
  523. }
  524. if ($addToHistory) {
  525. $message = $this->_order->addStatusHistoryComment($message);
  526. $message->setIsCustomerNotified(null);
  527. }
  528. return $message;
  529. }
  530. /**
  531. * Map payment information from IPN to payment object
  532. * Returns true if there were changes in information
  533. *
  534. * @param Mage_Payment_Model_Info $payment
  535. * @return bool
  536. */
  537. protected function _importPaymentInformation()
  538. {
  539. $payment = $this->_order->getPayment();
  540. $was = $payment->getAdditionalInformation();
  541. // collect basic information
  542. $from = array();
  543. foreach (array(
  544. Mage_Paypal_Model_Info::PAYER_ID,
  545. 'payer_email' => Mage_Paypal_Model_Info::PAYER_EMAIL,
  546. Mage_Paypal_Model_Info::PAYER_STATUS,
  547. Mage_Paypal_Model_Info::ADDRESS_STATUS,
  548. Mage_Paypal_Model_Info::PROTECTION_EL,
  549. Mage_Paypal_Model_Info::PAYMENT_STATUS,
  550. Mage_Paypal_Model_Info::PENDING_REASON,
  551. ) as $privateKey => $publicKey) {
  552. if (is_int($privateKey)) {
  553. $privateKey = $publicKey;
  554. }
  555. $value = $this->getRequestData($privateKey);
  556. if ($value) {
  557. $from[$publicKey] = $value;
  558. }
  559. }
  560. if (isset($from['payment_status'])) {
  561. $from['payment_status'] = $this->_filterPaymentStatus($this->getRequestData('payment_status'));
  562. }
  563. // collect fraud filters
  564. $fraudFilters = array();
  565. for ($i = 1; $value = $this->getRequestData("fraud_management_pending_filters_{$i}"); $i++) {
  566. $fraudFilters[] = $value;
  567. }
  568. if ($fraudFilters) {
  569. $from[Mage_Paypal_Model_Info::FRAUD_FILTERS] = $fraudFilters;
  570. }
  571. $this->_info->importToPayment($from, $payment);
  572. /**
  573. * Detect pending payment, frauds
  574. * TODO: implement logic in one place
  575. * @see Mage_Paypal_Model_Pro::importPaymentInfo()
  576. */
  577. if ($this->_info->isPaymentReviewRequired($payment)) {
  578. $payment->setIsTransactionPending(true);
  579. if ($fraudFilters) {
  580. $payment->setIsFraudDetected(true);
  581. }
  582. }
  583. if ($this->_info->isPaymentSuccessful($payment)) {
  584. $payment->setIsTransactionApproved(true);
  585. } elseif ($this->_info->isPaymentFailed($payment)) {
  586. $payment->setIsTransactionDenied(true);
  587. }
  588. return $was != $payment->getAdditionalInformation();
  589. }
  590. /**
  591. * Filter payment status from NVP into paypal/info format
  592. *
  593. * @param string $ipnPaymentStatus
  594. * @return string
  595. */
  596. protected function _filterPaymentStatus($ipnPaymentStatus)
  597. {
  598. switch ($ipnPaymentStatus) {
  599. case 'Created': // break is intentionally omitted
  600. case 'Completed': return Mage_Paypal_Model_Info::PAYMENTSTATUS_COMPLETED;
  601. case 'Denied': return Mage_Paypal_Model_Info::PAYMENTSTATUS_DENIED;
  602. case 'Expired': return Mage_Paypal_Model_Info::PAYMENTSTATUS_EXPIRED;
  603. case 'Failed': return Mage_Paypal_Model_Info::PAYMENTSTATUS_FAILED;
  604. case 'Pending': return Mage_Paypal_Model_Info::PAYMENTSTATUS_PENDING;
  605. case 'Refunded': return Mage_Paypal_Model_Info::PAYMENTSTATUS_REFUNDED;
  606. case 'Reversed': return Mage_Paypal_Model_Info::PAYMENTSTATUS_REVERSED;
  607. case 'Canceled_Reversal': return Mage_Paypal_Model_Info::PAYMENTSTATUS_UNREVERSED;
  608. case 'Processed': return Mage_Paypal_Model_Info::PAYMENTSTATUS_PROCESSED;
  609. case 'Voided': return Mage_Paypal_Model_Info::PAYMENTSTATUS_VOIDED;
  610. }
  611. return '';
  612. // documented in NVP, but not documented in IPN:
  613. //Mage_Paypal_Model_Info::PAYMENTSTATUS_NONE
  614. //Mage_Paypal_Model_Info::PAYMENTSTATUS_INPROGRESS
  615. //Mage_Paypal_Model_Info::PAYMENTSTATUS_REFUNDEDPART
  616. }
  617. /**
  618. * Log debug data to file
  619. *
  620. * @param mixed $debugData
  621. */
  622. protected function _debug()
  623. {
  624. if ($this->_config && $this->_config->debug) {
  625. $file = $this->_config->getMethodCode() ? "payment_{$this->_config->getMethodCode()}.log"
  626. : self::DEFAULT_LOG_FILE;
  627. Mage::getModel('core/log_adapter', $file)->log($this->_debugData);
  628. }
  629. }
  630. }