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: class Mage_PaypalUk_Model_Api_Nvp extends Mage_Paypal_Model_Api_Nvp
31: {
32: 33: 34: 35: 36:
37: const TRXTYPE_AUTH_ONLY = 'A';
38: const TRXTYPE_SALE = 'S';
39: const TRXTYPE_CREDIT = 'C';
40: const TRXTYPE_DELAYED_CAPTURE = 'D';
41: const TRXTYPE_DELAYED_VOID = 'V';
42:
43:
44: 45: 46: 47: 48:
49: const TENDER_CC = 'C';
50: const TENDER_PAYPAL = 'P';
51:
52:
53: 54: 55: 56: 57:
58: const EXPRESS_SET = 'S';
59: const EXPRESS_GET = 'G';
60: const EXPRESS_DO_PAYMENT = 'D';
61:
62:
63: 64: 65: 66: 67:
68: const RESPONSE_CODE_APPROVED = 0;
69: const RESPONSE_CODE_FRAUD = 126;
70:
71:
72: 73: 74: 75: 76:
77: protected $_captureTypeComplete = 'Y';
78: protected $_captureTypeNotcomplete = 'N';
79:
80:
81: 82: 83: 84: 85:
86: protected $_globalMap = array(
87:
88: 'PARTNER' => 'partner',
89: 'VENDOR' => 'vendor',
90: 'USER' => 'user',
91: 'PWD' => 'password',
92: 'BUTTONSOURCE' => 'build_notation_code',
93: 'TENDER' => 'tender',
94:
95: 'RETURNURL' => 'return_url',
96: 'CANCELURL' => 'cancel_url',
97: 'INVNUM' => 'inv_num',
98: 'TOKEN' => 'token',
99: 'CORRELATIONID' => 'correlation_id',
100: 'CUSTIP' => 'ip_address',
101: 'NOTIFYURL' => 'notify_url',
102: 'NOTE' => 'note',
103:
104: 'PAGESTYLE' => 'page_style',
105: 'HDRIMG' => 'hdrimg',
106: 'HDRBORDERCOLOR' => 'hdrbordercolor',
107: 'HDRBACKCOLOR' => 'hdrbackcolor',
108: 'PAYFLOWCOLOR' => 'payflowcolor',
109: 'LOCALECODE' => 'locale_code',
110:
111:
112: 'PPREF' => 'paypal_transaction_id',
113: 'PNREF' => 'transaction_id',
114: 'ORIGID' => 'authorization_id',
115: 'CAPTURECOMPLETE' => 'complete_type',
116: 'AMT' => 'amount',
117: 'AVSADDR' => 'address_verification',
118: 'AVSZIP' => 'postcode_verification',
119:
120:
121: 'CURRENCY' => 'currency_code',
122: 'PENDINGREASON' => 'pending_reason',
123: 'PAYERID' => 'payer_id',
124: 'PAYERSTATUS' => 'payer_status',
125: 'EMAIL' => 'email',
126:
127: 'FIRSTNAME' => 'firstname',
128: 'LASTNAME' => 'lastname',
129:
130: 'ACCT' => 'credit_card_number',
131: 'EXPDATE' => 'credit_card_expiration_date',
132: 'CVV2' => 'credit_card_cvv2',
133: 'CARDSTART' => 'maestro_solo_issue_date',
134: 'CARDISSUE' => 'maestro_solo_issue_number',
135: 'CVV2MATCH' => 'cvv2_check_result',
136:
137: 'AUTHSTATUS3DS' => 'centinel_authstatus',
138: 'MPIVENDOR3DS' => 'centinel_mpivendor',
139: 'CAVV' => 'centinel_cavv',
140: 'ECI' => 'centinel_eci',
141: 'XID' => 'centinel_xid',
142: 'VPAS' => 'centinel_vpas_result',
143: 'ECISUBMITTED3DS' => 'centinel_eci_result',
144: );
145:
146: 147: 148: 149: 150:
151: protected $_debugReplacePrivateDataKeys = array(
152: 'ACCT', 'EXPDATE', 'CVV2',
153: 'PARTNER', 'USER', 'VENDOR', 'PWD',
154: );
155:
156: 157: 158: 159: 160:
161: protected $_doDirectPaymentRequest = array(
162: 'ACCT', 'EXPDATE', 'CVV2', 'CURRENCY', 'EMAIL', 'TENDER', 'NOTIFYURL',
163: 'AMT', 'CUSTIP', 'INVNUM',
164: 'CARDISSUE', 'CARDSTART',
165: 'AUTHSTATUS3DS', 'MPIVENDOR3DS', 'CAVV', 'ECI', 'XID',
166: 'TAXAMT', 'FREIGHTAMT'
167: );
168: protected $_doDirectPaymentResponse = array(
169: 'PNREF', 'PPREF', 'CORRELATIONID', 'CVV2MATCH', 'AVSADDR', 'AVSZIP', 'PENDINGREASON'
170: );
171:
172:
173: 174: 175: 176: 177:
178: protected $_doCaptureRequest = array('ORIGID', 'CAPTURECOMPLETE', 'AMT', 'TENDER', 'NOTE', 'INVNUM');
179: protected $_doCaptureResponse = array('PNREF', 'PPREF');
180:
181:
182: 183: 184: 185: 186:
187: protected $_doVoidRequest = array('ORIGID', 'NOTE', 'TENDER');
188:
189: 190: 191: 192: 193:
194: protected $_eachCallRequest = array('PARTNER', 'USER', 'VENDOR', 'PWD', 'BUTTONSOURCE');
195:
196: 197: 198: 199: 200:
201: protected $_refundTransactionRequest = array('ORIGID', 'TENDER');
202: protected $_refundTransactionResponse = array('PNREF', 'PPREF');
203:
204:
205: 206: 207: 208: 209:
210: protected $_setExpressCheckoutRequest = array(
211: 'TENDER', 'AMT', 'CURRENCY', 'RETURNURL', 'CANCELURL', 'INVNUM',
212: 'PAGESTYLE', 'HDRIMG', 'HDRBORDERCOLOR', 'HDRBACKCOLOR', 'PAYFLOWCOLOR', 'LOCALECODE',
213: );
214: protected $_setExpressCheckoutResponse = array('REPMSG', 'TOKEN');
215:
216:
217: 218: 219: 220: 221:
222: protected $_getExpressCheckoutDetailsRequest = array('TENDER', 'TOKEN');
223:
224: 225: 226: 227: 228:
229: protected $_doExpressCheckoutPaymentRequest = array(
230: 'TENDER', 'TOKEN', 'PAYERID', 'AMT', 'CURRENCY', 'CUSTIP', 'BUTTONSOURCE', 'NOTIFYURL',
231: );
232: protected $_doExpressCheckoutPaymentResponse = array(
233: 'PNREF', 'PPREF', 'REPMSG', 'AMT', 'PENDINGREASON',
234: 'CVV2MATCH', 'AVSADDR', 'AVSZIP', 'CORRELATIONID'
235: );
236:
237:
238: 239: 240: 241: 242:
243: protected $_getTransactionDetailsRequest = array('ORIGID', 'TENDER');
244: protected $_getTransactionDetailsResponse = array(
245: 'PAYERID', 'FIRSTNAME', 'LASTNAME', 'TRANSACTIONID',
246: 'PARENTTRANSACTIONID', 'CURRENCYCODE', 'AMT', 'PAYMENTSTATUS'
247: );
248:
249:
250: 251: 252: 253: 254:
255: protected $_shippingAddressMap = array(
256: 'SHIPTOCOUNTRY' => 'country_id',
257: 'SHIPTOSTATE' => 'region',
258: 'SHIPTOCITY' => 'city',
259: 'SHIPTOSTREET' => 'street',
260: 'SHIPTOSTREET2' => 'street2',
261: 'SHIPTOZIP' => 'postcode',
262: 'SHIPTOPHONENUM' => 'telephone',
263: );
264:
265: 266: 267: 268: 269:
270: protected $_billingAddressMap = array(
271: 'BUSINESS' => 'company',
272: 'NOTETEXT' => 'customer_notes',
273: 'EMAIL' => 'email',
274: 'FIRSTNAME' => 'firstname',
275: 'LASTNAME' => 'lastname',
276: 'MIDDLENAME' => 'middlename',
277: 'SALUTATION' => 'prefix',
278: 'SUFFIX' => 'suffix',
279:
280: 'COUNTRYCODE' => 'country_id',
281: 'STATE' => 'region',
282: 'CITY' => 'city',
283: 'STREET' => 'street',
284: 'STREET2' => 'street2',
285: 'ZIP' => 'postcode',
286: 'PHONENUM' => 'telephone',
287: );
288:
289: 290: 291: 292: 293:
294: protected $_billingAddressMapRequest = array(
295: 'country_id' => 'COUNTRY',
296: );
297:
298: 299: 300: 301: 302:
303: protected $_lineItemTotalExportMap = array(
304: Mage_Paypal_Model_Cart::TOTAL_TAX => 'TAXAMT',
305: Mage_Paypal_Model_Cart::TOTAL_SHIPPING => 'FREIGHTAMT',
306: );
307:
308: protected $_lineItemExportItemsFormat = array(
309: 'name' => 'L_NAME%d',
310: 'qty' => 'L_QTY%d',
311: 'amount' => 'L_COST%d',
312: );
313:
314:
315: 316: 317: 318: 319:
320: protected $_paymentInformationResponse = array(
321: 'PAYERID', 'CORRELATIONID', 'ADDRESSID', 'ADDRESSSTATUS',
322: 'PAYMENTSTATUS', 'PENDINGREASON', 'PROTECTIONELIGIBILITY', 'EMAIL',
323: );
324:
325: 326: 327: 328: 329:
330: protected $_requiredResponseParams = array(
331: self::DO_DIRECT_PAYMENT => array('RESULT', 'PNREF', 'PPREF')
332: );
333:
334: 335: 336: 337: 338:
339: public function getApiEndpoint()
340: {
341: return sprintf('https://%spayflowpro.paypal.com/transaction', $this->_config->sandboxFlag ? 'pilot-' : '');
342: }
343:
344: 345: 346: 347: 348:
349: public function getPartner()
350: {
351: return $this->_getDataOrConfig('partner');
352: }
353:
354: 355: 356: 357: 358:
359: public function getUser()
360: {
361: return $this->_getDataOrConfig('user');
362: }
363:
364: 365: 366: 367: 368:
369: public function getPassword()
370: {
371: return $this->_getDataOrConfig('pwd');
372: }
373:
374: 375: 376: 377: 378:
379: public function getVendor()
380: {
381: return $this->_getDataOrConfig('vendor');
382: }
383:
384: 385: 386: 387: 388:
389: public function getTender()
390: {
391: if ($this->_config->getMethodCode() == Mage_Paypal_Model_Config::METHOD_WPP_PE_EXPRESS) {
392: return self::TENDER_PAYPAL;
393: }
394: return self::TENDER_CC;
395: }
396:
397: 398: 399: 400: 401:
402: public function getPaypalTransactionId()
403: {
404: if ($this->getData('paypal_transaction_id')) {
405: return $this->getData('paypal_transaction_id');
406: }
407: return $this->getTransactionId();
408: }
409:
410: 411: 412: 413: 414: 415: 416:
417: protected function _addMethodToRequest($methodName, $request)
418: {
419: $request['TRXTYPE'] = $this->_mapPaypalMethodName($methodName);
420: if (!is_null($this->_getPaypalUkActionName($methodName))) {
421: $request['ACTION'] = $this->_getPaypalUkActionName($methodName);
422: }
423: return $request;
424: }
425:
426: 427: 428: 429: 430: 431:
432: protected function _getPaypalUkActionName($methodName)
433: {
434: switch($methodName) {
435: case Mage_Paypal_Model_Api_Nvp::SET_EXPRESS_CHECKOUT:
436: return self::EXPRESS_SET;
437: case Mage_Paypal_Model_Api_Nvp::GET_EXPRESS_CHECKOUT_DETAILS:
438: return self::EXPRESS_GET;
439: case Mage_Paypal_Model_Api_Nvp::DO_EXPRESS_CHECKOUT_PAYMENT:
440: return self::EXPRESS_DO_PAYMENT;
441: }
442: return null;
443: }
444:
445: 446: 447: 448: 449: 450:
451: protected function _mapPaypalMethodName($methodName)
452: {
453: switch($methodName) {
454: case Mage_Paypal_Model_Api_Nvp::DO_EXPRESS_CHECKOUT_PAYMENT:
455: case Mage_Paypal_Model_Api_Nvp::GET_EXPRESS_CHECKOUT_DETAILS:
456: case Mage_Paypal_Model_Api_Nvp::SET_EXPRESS_CHECKOUT:
457: case Mage_Paypal_Model_Api_Nvp::DO_DIRECT_PAYMENT:
458: return ($this->_config->payment_action == Mage_Paypal_Model_Config::PAYMENT_ACTION_AUTH)
459: ? self::TRXTYPE_AUTH_ONLY
460: : self::TRXTYPE_SALE;
461: case Mage_Paypal_Model_Api_Nvp::DO_CAPTURE:
462: return self::TRXTYPE_DELAYED_CAPTURE;
463: case Mage_Paypal_Model_Api_Nvp::DO_VOID:
464: return self::TRXTYPE_DELAYED_VOID;
465: case Mage_Paypal_Model_Api_Nvp::REFUND_TRANSACTION:
466: return self::TRXTYPE_CREDIT;
467: }
468: }
469:
470: 471: 472: 473: 474: 475:
476: protected function _isCallSuccessful($response)
477: {
478: $this->_callWarnings = array();
479: if ($response['RESULT'] == self::RESPONSE_CODE_APPROVED) {
480:
481: if (!empty($response['RESPMSG']) && strtoupper($response['RESPMSG']) != 'APPROVED') {
482: $this->_callWarnings[] = $response['RESPMSG'];
483: }
484: return true;
485: }
486: return false;
487: }
488:
489: 490: 491: 492: 493:
494: protected function _handleCallErrors($response)
495: {
496: if ($response['RESULT'] != self::RESPONSE_CODE_APPROVED) {
497: $message = $response['RESPMSG'];
498: $e = new Exception(sprintf('PayPal gateway errors: %s.', $message));
499: Mage::logException($e);
500: Mage::throwException(
501: Mage::helper('paypal')->__('PayPal gateway rejected the request. %s', $message)
502: );
503: }
504: }
505:
506: 507: 508: 509: 510: 511:
512: protected function _buildQuery($request)
513: {
514: $result = '';
515: foreach ($request as $k=>$v) {
516: $result .= '&'.$k.'='.$v;
517: }
518: return trim($result, '&');
519: }
520:
521: 522: 523: 524: 525:
526: protected function getRequestId()
527: {
528: return Mage::helper('core')->uniqHash();
529: }
530:
531: 532: 533:
534: function callGetTransactionDetails()
535: {
536: }
537:
538: 539: 540: 541: 542: 543:
544: protected function _importFraudFiltersResult(array $from, array $collectedWarnings)
545: {
546: if ($from['RESULT'] != self::RESPONSE_CODE_FRAUD) {
547: return;
548: }
549: $this->setIsPaymentPending(true);
550: }
551:
552: 553: 554: 555: 556: 557: 558:
559: protected function _prepareEachCallRequest($methodName)
560: {
561: return $this->_eachCallRequest;
562: }
563:
564: 565: 566: 567: 568: 569: 570:
571: protected function _prepareExpressCheckoutCallRequest(&$requestFields)
572: {
573: return $requestFields;
574: }
575:
576: 577: 578: 579: 580: 581:
582: protected function _applyCountryWorkarounds(&$request)
583: {
584: if (isset($request['SHIPTOCOUNTRY']) && $request['SHIPTOCOUNTRY'] == 'PR') {
585: $request['SHIPTOCOUNTRY'] = 'US';
586: $request['SHIPTOSTATE'] = 'PR';
587: }
588: }
589: }
590: