1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27: 28: 29: 30:
31: class Mage_Paypal_Model_Pro
32: {
33: 34: 35: 36: 37:
38: const PAYMENT_REVIEW_ACCEPT = 'accept';
39: const PAYMENT_REVIEW_DENY = 'deny';
40:
41: 42: 43: 44: 45:
46: protected $_config = null;
47:
48: 49: 50: 51: 52:
53: protected $_api = null;
54:
55: 56: 57: 58: 59:
60: protected $_infoInstance = null;
61:
62: 63: 64: 65: 66:
67: protected $_apiType = 'paypal/api_nvp';
68:
69: 70: 71: 72: 73:
74: protected $_configType = 'paypal/config';
75:
76: 77: 78: 79: 80: 81:
82: public function setMethod($code, $storeId = null)
83: {
84: if (null === $this->_config) {
85: $params = array($code);
86: if (null !== $storeId) {
87: $params[] = $storeId;
88: }
89: $this->_config = Mage::getModel($this->_configType, $params);
90: } else {
91: $this->_config->setMethod($code);
92: if (null !== $storeId) {
93: $this->_config->setStoreId($storeId);
94: }
95: }
96: return $this;
97: }
98:
99: 100: 101: 102: 103: 104:
105: public function setConfig(Mage_Paypal_Model_Config $instace, $storeId = null)
106: {
107: $this->_config = $instace;
108: if (null !== $storeId) {
109: $this->_config->setStoreId($storeId);
110: }
111: return $this;
112: }
113:
114: 115: 116: 117: 118:
119: public function getConfig()
120: {
121: return $this->_config;
122: }
123:
124: 125: 126: 127: 128: 129:
130: public function getApi()
131: {
132: if (null === $this->_api) {
133: $this->_api = Mage::getModel($this->_apiType);
134: }
135: $this->_api->setConfigObject($this->_config);
136: return $this->_api;
137: }
138:
139: 140: 141: 142: 143:
144: public function resetApi()
145: {
146: $this->_api = null;
147:
148: return $this;
149: }
150:
151: 152: 153: 154: 155:
156: public function getInfo()
157: {
158: if (null === $this->_infoInstance) {
159: $this->_infoInstance = Mage::getModel('paypal/info');
160: }
161: return $this->_infoInstance;
162: }
163:
164: 165: 166: 167: 168: 169: 170:
171: public function importPaymentInfo(Varien_Object $from, Mage_Payment_Model_Info $to)
172: {
173:
174: $this->getInfo()->importToPayment($from, $to);
175:
176: 177: 178: 179:
180: if ($from->getDataUsingMethod(Mage_Paypal_Model_Info::IS_FRAUD)) {
181: $to->setIsTransactionPending(true);
182: $to->setIsFraudDetected(true);
183: } elseif ($this->getInfo()->isPaymentReviewRequired($to)) {
184: $to->setIsTransactionPending(true);
185: }
186:
187:
188: if ($this->getInfo()->isPaymentSuccessful($to)) {
189: $to->setIsTransactionApproved(true);
190: } elseif ($this->getInfo()->isPaymentFailed($to)) {
191: $to->setIsTransactionDenied(true);
192: }
193:
194: return $this;
195: }
196:
197: 198: 199: 200: 201:
202: public function void(Varien_Object $payment)
203: {
204: if ($authTransactionId = $this->_getParentTransactionId($payment)) {
205: $api = $this->getApi();
206: $api->setPayment($payment)->setAuthorizationId($authTransactionId)->callDoVoid();
207: $this->importPaymentInfo($api, $payment);
208: } else {
209: Mage::throwException(Mage::helper('paypal')->__('Authorization transaction is required to void.'));
210: }
211: }
212:
213: 214: 215: 216: 217: 218: 219: 220:
221: public function capture(Varien_Object $payment, $amount)
222: {
223: $authTransactionId = $this->_getParentTransactionId($payment);
224: if (!$authTransactionId) {
225: return false;
226: }
227: $api = $this->getApi()
228: ->setAuthorizationId($authTransactionId)
229: ->setIsCaptureComplete($payment->getShouldCloseParentTransaction())
230: ->setAmount($amount)
231: ->setCurrencyCode($payment->getOrder()->getBaseCurrencyCode())
232: ->setInvNum($payment->getOrder()->getIncrementId())
233:
234: ;
235:
236: $api->callDoCapture();
237: $this->_importCaptureResultToPayment($api, $payment);
238: }
239:
240: 241: 242: 243: 244: 245:
246: public function refund(Varien_Object $payment, $amount)
247: {
248: $captureTxnId = $this->_getParentTransactionId($payment);
249: if ($captureTxnId) {
250: $api = $this->getApi();
251: $order = $payment->getOrder();
252: $api->setPayment($payment)
253: ->setTransactionId($captureTxnId)
254: ->setAmount($amount)
255: ->setCurrencyCode($order->getBaseCurrencyCode())
256: ;
257: $canRefundMore = $payment->getCreditmemo()->getInvoice()->canRefund();
258: $isFullRefund = !$canRefundMore
259: && (0 == ((float)$order->getBaseTotalOnlineRefunded() + (float)$order->getBaseTotalOfflineRefunded()));
260: $api->setRefundType($isFullRefund ? Mage_Paypal_Model_Config::REFUND_TYPE_FULL
261: : Mage_Paypal_Model_Config::REFUND_TYPE_PARTIAL
262: );
263: $api->callRefundTransaction();
264: $this->_importRefundResultToPayment($api, $payment, $canRefundMore);
265: } else {
266: Mage::throwException(Mage::helper('paypal')->__('Impossible to issue a refund transaction because the capture transaction does not exist.'));
267: }
268: }
269:
270: 271: 272: 273: 274:
275: public function cancel(Varien_Object $payment)
276: {
277: if (!$payment->getOrder()->getInvoiceCollection()->count()) {
278: $this->void($payment);
279: }
280: }
281:
282: 283: 284: 285: 286:
287: public function canReviewPayment(Mage_Payment_Model_Info $payment)
288: {
289: return Mage_Paypal_Model_Info::isPaymentReviewRequired($payment);
290: }
291:
292: 293: 294: 295: 296: 297: 298:
299: public function reviewPayment(Mage_Payment_Model_Info $payment, $action)
300: {
301: $api = $this->getApi()->setTransactionId($payment->getLastTransId());
302:
303:
304: $api->callGetTransactionDetails();
305: $this->importPaymentInfo($api, $payment);
306: if (!$this->getInfo()->isPaymentReviewRequired($payment)) {
307: return false;
308: }
309:
310:
311: $api->setAction($action)->callManagePendingTransactionStatus();
312: $api->callGetTransactionDetails();
313: $this->importPaymentInfo($api, $payment);
314: return true;
315: }
316:
317: 318: 319: 320: 321: 322: 323:
324: public function fetchTransactionInfo(Mage_Payment_Model_Info $payment, $transactionId)
325: {
326: $api = $this->getApi()
327: ->setTransactionId($transactionId)
328: ->setRawResponseNeeded(true);
329: $api->callGetTransactionDetails();
330: $this->importPaymentInfo($api, $payment);
331: $data = $api->getRawSuccessResponseData();
332: return ($data) ? $data : array();
333: }
334:
335: 336: 337: 338: 339: 340:
341: public function validateRecurringProfile(Mage_Payment_Model_Recurring_Profile $profile)
342: {
343: $errors = array();
344: if (strlen($profile->getSubscriberName()) > 32) {
345: $errors[] = Mage::helper('paypal')->__('Subscriber name is too long.');
346: }
347: $refId = $profile->getInternalReferenceId();
348: if (strlen($refId) > 127) {
349: $errors[] = Mage::helper('paypal')->__('Merchant reference ID format is not supported.');
350: }
351: $scheduleDescr = $profile->getScheduleDescription();
352: if (strlen($refId) > 127) {
353: $errors[] = Mage::helper('paypal')->__('Schedule description is too long.');
354: }
355: if ($errors) {
356: Mage::throwException(implode(' ', $errors));
357: }
358: }
359:
360: 361: 362: 363: 364: 365: 366:
367: public function submitRecurringProfile(Mage_Payment_Model_Recurring_Profile $profile,
368: Mage_Payment_Model_Info $paymentInfo
369: ) {
370: $api = $this->getApi();
371: Varien_Object_Mapper::accumulateByMap($profile, $api, array(
372: 'token',
373:
374:
375: 'subscriber_name', 'start_datetime', 'internal_reference_id', 'schedule_description',
376: 'suspension_threshold', 'bill_failed_later', 'period_unit', 'period_frequency', 'period_max_cycles',
377: 'billing_amount' => 'amount', 'trial_period_unit', 'trial_period_frequency', 'trial_period_max_cycles',
378: 'trial_billing_amount', 'currency_code', 'shipping_amount', 'tax_amount', 'init_amount', 'init_may_fail',
379: ));
380: $api->callCreateRecurringPaymentsProfile();
381: $profile->setReferenceId($api->getRecurringProfileId());
382: if ($api->getIsProfileActive()) {
383: $profile->setState(Mage_Sales_Model_Recurring_Profile::STATE_ACTIVE);
384: } elseif ($api->getIsProfilePending()) {
385: $profile->setState(Mage_Sales_Model_Recurring_Profile::STATE_PENDING);
386: }
387: }
388:
389: 390: 391: 392: 393: 394:
395: public function getRecurringProfileDetails($referenceId, Varien_Object $result)
396: {
397: $api = $this->getApi();
398: $api->setRecurringProfileId($referenceId)
399: ->callGetRecurringPaymentsProfileDetails($result)
400: ;
401: }
402:
403: 404: 405: 406: 407:
408: public function updateRecurringProfile(Mage_Payment_Model_Recurring_Profile $profile)
409: {
410:
411: }
412:
413: 414: 415: 416: 417:
418: public function updateRecurringProfileStatus(Mage_Payment_Model_Recurring_Profile $profile)
419: {
420: $api = $this->getApi();
421: $action = null;
422: switch ($profile->getNewState()) {
423: case Mage_Sales_Model_Recurring_Profile::STATE_CANCELED: $action = 'cancel'; break;
424: case Mage_Sales_Model_Recurring_Profile::STATE_SUSPENDED: $action = 'suspend'; break;
425: case Mage_Sales_Model_Recurring_Profile::STATE_ACTIVE: $action = 'activate'; break;
426: }
427: $state = $profile->getState();
428: $api->setRecurringProfileId($profile->getReferenceId())
429: ->setIsAlreadyCanceled($state == Mage_Sales_Model_Recurring_Profile::STATE_CANCELED)
430: ->setIsAlreadySuspended($state == Mage_Sales_Model_Recurring_Profile::STATE_SUSPENDED)
431: ->setIsAlreadyActive($state == Mage_Sales_Model_Recurring_Profile::STATE_ACTIVE)
432: ->setAction($action)
433: ->callManageRecurringPaymentsProfileStatus()
434: ;
435: }
436:
437: 438: 439: 440: 441: 442:
443: protected function _importCaptureResultToPayment($api, $payment)
444: {
445: $payment->setTransactionId($api->getTransactionId())->setIsTransactionClosed(false);
446: $this->importPaymentInfo($api, $payment);
447: }
448:
449: 450: 451: 452: 453: 454: 455:
456: protected function _importRefundResultToPayment($api, $payment, $canRefundMore)
457: {
458: $payment->setTransactionId($api->getRefundTransactionId())
459: ->setIsTransactionClosed(1)
460: ->setShouldCloseParentTransaction(!$canRefundMore)
461: ;
462: $this->importPaymentInfo($api, $payment);
463: }
464:
465: 466: 467: 468: 469: 470:
471: protected function _getParentTransactionId(Varien_Object $payment)
472: {
473: return $payment->getParentTransactionId();
474: }
475: }
476: