00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 class Mage_PaypalUk_Model_Api_Pro extends Mage_PaypalUk_Model_Api_Abstract
00036 {
00037 const TRXTYPE_AUTH_ONLY = 'A';
00038 const TRXTYPE_SALE = 'S';
00039 const TRXTYPE_CREDIT = 'C';
00040 const TRXTYPE_DELAYED_CAPTURE = 'D';
00041 const TRXTYPE_DELAYED_VOID = 'V';
00042 const TRXTYPE_DELAYED_VOICE = 'F';
00043 const TRXTYPE_DELAYED_INQUIRY = 'I';
00044
00045 const TENDER_AUTOMATED = 'A';
00046 const TENDER_CC = 'C';
00047 const TENDER_PINLESS_DEBIT = 'D';
00048 const TENDER_ECHEK = 'E';
00049 const TENDER_TELECHECK = 'K';
00050 const TENDER_PAYPAL = 'P';
00051
00052 const ACIONT_SET_EXPRESS = 'S';
00053 const ACIONT_GET_EXPRESS = 'G';
00054 const ACIONT_DO_EXPRESS = 'D';
00055
00056 const RESPONSE_DELIM_CHAR = ',';
00057
00058 protected $_clientTimeout = 45;
00059
00060 const RESPONSE_CODE_APPROVED = 0;
00061 const RESPONSE_CODE_DECLINED = 12;
00062 const RESPONSE_CODE_CAPTURE_ERROR = 111;
00063
00064 protected $_code = 'verisign';
00065
00066
00067
00068
00069 protected $_isGateway = true;
00070 protected $_canAuthorize = true;
00071 protected $_canCapture = true;
00072 protected $_canCapturePartial = false;
00073 protected $_canRefund = false;
00074 protected $_canVoid = true;
00075 protected $_canUseInternal = true;
00076 protected $_canUseCheckout = true;
00077 protected $_canUseForMultishipping = true;
00078
00079
00080
00081
00082
00083
00084 protected $_debugReplacePrivateDataKeys = array('ACCT', 'EXPDATE', 'CVV2',
00085 'CARDISSUE', 'CARDSTART',
00086 'CREDITCARDTYPE', 'USER',
00087 'PWD');
00088
00089
00090
00091
00092
00093
00094 protected $_validVoidTransState = array(3,6,9);
00095
00096
00097 public function callDoDirectPayment()
00098 {
00099 $p = $this->getPayment();
00100 $a = $this->getBillingAddress();
00101 if ($this->getShippingAddress()) {
00102 $s = $this->getShippingAddress();
00103 } else {
00104 $s = $a;
00105 }
00106
00107 $proArr = array(
00108 'TENDER' => self::TENDER_CC,
00109 'AMT' => $this->getAmount(),
00110 'BUTTONSOURCE' => $this->getButtonSourceDp(),
00111 );
00112
00113 if($this->getTrxtype()==self::TRXTYPE_AUTH_ONLY || $this->getTrxtype()==self::TRXTYPE_SALE){
00114 $proArr = array_merge(array(
00115 'ACCT' => $p->getCcNumber(),
00116 'EXPDATE' => sprintf('%02d',$p->getCcExpMonth()).substr($p->getCcExpYear(),-2,2),
00117 'CVV2' => $p->getCcCid(),
00118 'CURRENCY' => $this->getCurrencyCode(),
00119 'EMAIL' => $p->getOrder()->getCustomerEmail(),
00120
00121 'FIRSTNAME' => $a->getFirstname(),
00122 'LASTNAME' => $a->getLastname(),
00123 'STREET' => $a->getStreet(1),
00124 'CITY' => $a->getCity(),
00125 'STATE' => $a->getRegionCode(),
00126 'ZIP' => $a->getPostcode(),
00127 'COUNTRY' => $a->getCountry(),
00128
00129 'SHIPTOFIRSTNAME' => $s->getFirstname(),
00130 'SHIPTOLASTNAME' => $s->getLastname(),
00131 'SHIPTOSTREET' => $s->getStreet(1),
00132 'SHIPTOSTREET2' => $s->getStreet(2),
00133 'SHIPTOCITY' => $s->getCity(),
00134 'SHIPTOSTATE' => $s->getRegion(),
00135 'SHIPTOZIP' => $s->getPostcode(),
00136 'SHIPTOCOUNTRY' => $s->getCountry(),
00137 ), $proArr);
00138
00139 if($p->getCcSsIssue()){
00140 $proArr = array_merge(array(
00141 'CARDISSUE' => $p->getCcSsIssue(),
00142 ), $proArr);
00143 }
00144 if($p->getCcSsStartYear() || $p->getCcSsStartMonth()){
00145 $proArr = array_merge(array(
00146 'CARDSTART' => sprintf('%02d',$p->getCcSsStartMonth()).substr($p->getCcSsStartYear(),-2,2),
00147 ), $proArr);
00148 }
00149
00150 }else{
00151 $proArr = array_merge(array(
00152 'ORIGID' => $this->getTransactionId(),
00153 ), $proArr);
00154 }
00155
00156 $result = $this->postRequest($proArr);
00157
00158 if ($result && $result->getResultCode()==self::RESPONSE_CODE_APPROVED) {
00159 $this->setTransactionId($result->getPnref());
00160 $this->setAvsZip($result->getAvszip());
00161 $this->setAvsCode($result->getAvszip());
00162 $this->setCvv2Match($result->getCvv2match());
00163 } else {
00164 $errorArr['code'] = $result->getResultCode();
00165 $errorArr['message'] = $result->getRespmsg();
00166 $this->setError($errorArr);
00167 return false;
00168 }
00169
00170 return $this;
00171 }
00172
00173
00174
00175 public function getPaypalUrl()
00176 {
00177 if (!$this->hasPaypalUrl()) {
00178 $url=$this->getApiUrl();
00179 if (stripos($url,'pilot') || stripos($url,'test')) {
00180 $default = 'https://www.sandbox.paypal.com/';
00181 } else {
00182 $default = 'https://www.paypal.com/cgi-bin/';
00183 }
00184 $default .= 'webscr?cmd=_express-checkout&useraction='.$this->getUserAction().'&token=';
00185
00186 $url = $this->getConfigData('paypal_url', $default);
00187 } else {
00188 $url = $this->getData('paypal_url');
00189 }
00190 return $url . $this->getToken();
00191 }
00192
00193 public function callSetExpressCheckout()
00194 {
00195 $proArr = array(
00196 'TENDER' => self::TENDER_PAYPAL,
00197 'AMT' => $this->getAmount(),
00198 'ACTION' => self::ACIONT_SET_EXPRESS,
00199 'CURRENCY' => $this->getCurrencyCode(),
00200 "RETURNURL" => $this->getReturnUrl(),
00201 'CANCELURL' => $this->getCancelUrl(),
00202 );
00203
00204 $this->setUserAction(self::USER_ACTION_CONTINUE);
00205
00206
00207 if ($a = $this->getShippingAddress()) {
00208 $proArr = array_merge($proArr, array(
00209 'ADDROVERRIDE' => 1,
00210 'SHIPTONAME' => $a->getName(),
00211 'SHIPTOSTREET' => $a->getStreet(1),
00212 'SHIPTOSTREET2' => $a->getStreet(2),
00213 'SHIPTOCITY' => $a->getCity(),
00214 'SHIPTOSTATE' => $a->getRegionCode(),
00215 'SHIPTOCOUNTRY' => $a->getCountry(),
00216 'SHIPTOZIP' => $a->getPostcode(),
00217 'PHONENUM' => $a->getTelephone(),
00218 ));
00219 $this->setUserAction(self::USER_ACTION_COMMIT);
00220 }
00221
00222 $result = $this->postRequest($proArr);
00223
00224 if ($result && $result->getResultCode()==self::RESPONSE_CODE_APPROVED) {
00225 $this->setToken($result->getToken());
00226 $this->setRedirectUrl($this->getPaypalUrl());
00227 } else if ($result) {
00228 $errorArr['code'] = $result->getResultCode();
00229 $errorArr['message'] = $result->getRespmsg();
00230 $this->setError($errorArr);
00231 return false;
00232 } else {
00233 return false;
00234 }
00235
00236 return $this;
00237 }
00238
00239 public function callGetExpressCheckoutDetails()
00240 {
00241 $proArr = array(
00242 'TENDER' => self::TENDER_PAYPAL,
00243 'ACTION' => self::ACIONT_GET_EXPRESS,
00244 'TOKEN' => $this->getToken(),
00245 );
00246
00247 $result = $this->postRequest($proArr);
00248
00249 if ($result && $result->getResultCode()==self::RESPONSE_CODE_APPROVED) {
00250 $this->setPayerId($result->getPayerid());
00251 $this->setCorrelationId($result->getCorrelationid());
00252 $this->setPayerStatus($result->getPayerstatus());
00253 $this->setPaypalPayerEmail($result->getEmail());
00254
00255
00256
00257
00258 if (!$this->getShippingAddress()) {
00259 $this->setShippingAddress(Mage::getModel('customer/address'));
00260 }
00261
00262 $a = $this->getShippingAddress();
00263 $a->setEmail($result->getEmail());
00264 $a->setFirstname($result->getFirstname());
00265 $a->setLastname($result->getLastname());
00266 $street = array($result->getShiptostreet());
00267 if ($result->getShiptostreet2()) {
00268 $street[] = $result->getShiptostreet2();
00269 }
00270 $a->setStreet($street);
00271 $a->setCity($result->getShiptocity());
00272 $a->setRegion($result->getShiptostate());
00273 $a->setPostcode($result->getShiptozip());
00274 $a->setCountry($result->getShiptocountry());
00275 $a->setTelephone(Mage::helper('paypalUk')->__('N/A'));
00276
00277
00278
00279
00280 } else {
00281 $errorArr['code'] = $result->getResultCode();
00282 $errorArr['message'] = $result->getRespmsg();
00283 $this->setError($errorArr);
00284 return false;
00285 }
00286
00287 return $this;
00288 }
00289
00290 public function callDoExpressCheckoutPayment()
00291 {
00292
00293
00294
00295
00296
00297 $proArr = array(
00298 'TENDER' => self::TENDER_PAYPAL,
00299 'ACTION' => self::ACIONT_DO_EXPRESS,
00300 'TOKEN' => $this->getToken(),
00301 'PAYERID' => $this->getPayerId(),
00302 'AMT' => $this->getAmount(),
00303 'CURRENCY' => $this->getCurrencyCode(),
00304 'BUTTONSOURCE' => $this->getButtonSourceEc(),
00305 );
00306
00307 $result = $this->postRequest($proArr);
00308
00309 if ($result && $result->getResultCode()==self::RESPONSE_CODE_APPROVED) {
00310 $this->setTransactionId($result->getPnref());
00311 } else {
00312
00313
00314
00315 return false;
00316 }
00317
00318 return $this;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 public function deformatNVP($nvpstr)
00331 {
00332 $intial=0;
00333 $nvpArray = array();
00334
00335 $nvpstr = strpos($nvpstr, "\r\n\r\n")!==false ? substr($nvpstr, strpos($nvpstr, "\r\n\r\n")+4) : $nvpstr;
00336
00337 while(strlen($nvpstr)) {
00338
00339 $keypos= strpos($nvpstr,'=');
00340
00341 $valuepos = strpos($nvpstr,'&') ? strpos($nvpstr,'&'): strlen($nvpstr);
00342
00343
00344 $keyval=substr($nvpstr,$intial,$keypos);
00345 $valval=substr($nvpstr,$keypos+1,$valuepos-$keypos-1);
00346
00347 $nvpArray[urldecode($keyval)] =urldecode( $valval);
00348 $nvpstr=substr($nvpstr,$valuepos+1,strlen($nvpstr));
00349 }
00350 return $nvpArray;
00351 }
00352
00353 public function postRequest(array $proArr)
00354 {
00355 $proArr = array_merge(array(
00356 'PARTNER' => $this->getPartner(),
00357 'USER' => $this->getApiUser(),
00358 'VENDOR' => $this->getApiVendor(),
00359 'PWD' => $this->getApiPassword(),
00360 'TRXTYPE' => $this->getTrxtype(),
00361 'REQUEST_ID'=> $this->_generateRequestId()
00362 ), $proArr);
00363
00364 $proReq = '';
00365 $proReqDebug = '';
00366 foreach ($proArr as $k=>$v) {
00367
00368
00369 $proReq .= '&'.$k.'='.$v;
00370 $proReqDebug .= '&'.$k.'=';
00371 if (in_array($k, $this->_debugReplacePrivateDataKeys)) {
00372 $proReqDebug .= '***';
00373 } else {
00374 $proReqDebug .= $v;
00375 }
00376 }
00377 $proReq = substr($proReq, 1);
00378 $proReqDebug = substr($proReqDebug, 1);
00379
00380 if ($this->getDebug()) {
00381 $debug = Mage::getModel('paypaluk/api_debug')
00382 ->setRequestBody($proReqDebug)
00383 ->save();
00384 }
00385 $http = new Varien_Http_Adapter_Curl();
00386 $config = array('timeout' => 30);
00387 $http->setConfig($config);
00388 $http->write(Zend_Http_Client::POST, $this->getApiUrl(), '1.1', array(), $proReq);
00389 $response = $http->read();
00390 $response = preg_split('/^\r?$/m', $response, 2);
00391 $response = trim($response[1]);
00392
00393 if ($this->getDebug()) {
00394 $debug->setResponseBody($response)->save();
00395 }
00396
00397 if ($http->getErrno()) {
00398 $http->close();
00399 $this->setError(array(
00400 'type'=>'CURL',
00401 'code'=>$http->getErrno(),
00402 'message'=>$http->getError()
00403 ));
00404 $this->setRedirectUrl($this->getApiErrorUrl());
00405 return false;
00406 }
00407 $http->close();
00408
00409 $result = Mage::getModel('paypaluk/api_result');
00410 $valArray = $this->deformatNVP($response);
00411
00412 foreach($valArray as $k=>$v) {
00413 $result->setData(strtolower($k), $v);
00414 }
00415 $result->setResultCode($result->getResult())
00416 ->setRespmsg($result->getRespmsg());
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 return $result;
00458 }
00459
00460 protected function _generateRequestId()
00461 {
00462 return md5(microtime() . rand(0, time()));
00463 }
00464
00465
00466
00467
00468
00469
00470
00471 public function canVoid()
00472 {
00473 $payment = $this->getPayment();
00474
00475 $proArr = array(
00476 'TENDER' => self::TENDER_CC,
00477 'ORIGID' => $this->getTransactionId(),
00478 );
00479
00480 $this->getTrxtype(self::TRXTYPE_DELAYED_INQUIRY);
00481 $result = $this->postRequest($proArr);
00482
00483 if ($result && $result->getResultCode()==self::RESPONSE_CODE_APPROVED) {
00484 if ($result->getTransstate()>1000) {
00485 $errorArr['code'] = $result->getResultCode();
00486 $errorArr['message'] = Mage::helper('paypalUk')->__('Voided transaction');
00487 $this->setError($errorArr);
00488 return false;
00489 } elseif(in_array($result->getTransstate(),$this->_validVoidTransState)) {
00490 $this->setStatus(Mage_Payment_Model_Method_Abstract::STATUS_VOID);
00491 return $this;
00492 }
00493 }
00494
00495 $errorArr['code'] = $result->getResultCode();
00496 $errorArr['message'] = $result->getRespmsg() ? $result->getRespmsg() : Mage::helper('paypalUk')->__('Error in inquriing the transaction');
00497 $this->setError($errorArr);
00498 return false;
00499 }
00500
00501
00502
00503
00504
00505
00506 public function void()
00507 {
00508 $payment = $this->getPayment();
00509
00510 $proArr = array(
00511 'TENDER' => self::TENDER_CC,
00512 'ORIGID' => $this->getTransactionId(),
00513 );
00514 $this->getTrxtype(self::TRXTYPE_DELAYED_VOID);
00515 $result = $this->postRequest($proArr);
00516
00517 if ($result && $result->getResultCode()==self::RESPONSE_CODE_APPROVED) {
00518 $this->setTransactionId($result->getPnref());
00519 return $this;
00520 }
00521 $errorArr['code'] = $result->getResultCode();
00522 $errorArr['message'] = $result->getRespmsg() ? $result->getRespmsg() : Mage::helper('paypalUk')->__('Error in voiding the transaction');
00523 $this->setError($errorArr);
00524 return false;
00525 }
00526
00527
00528
00529
00530
00531
00532
00533 public function refund()
00534 {
00535 $payment = $this->getPayment();
00536
00537 $proArr = array(
00538 'TENDER' => self::TENDER_CC,
00539 'ORIGID' => $this->getTransactionId(),
00540 'AMT' => $this->getAmount()
00541 );
00542 $this->getTrxtype(self::TRXTYPE_CREDIT);
00543 $result = $this->postRequest($proArr);
00544
00545 if ($result && $result->getResultCode()==self::RESPONSE_CODE_APPROVED) {
00546 $this->setTransactionId($result->getPnref());
00547 return $this;
00548 }
00549
00550 $errorArr['code'] = $result->getResultCode();
00551 $errorArr['message'] = $result->getRespmsg() ? $result->getRespmsg() : Mage::helper('paypalUk')->__('Error in voiding the transaction');
00552 $this->setError($errorArr);
00553 return false;
00554 }
00555 }