PageRenderTime 58ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/dso/cielo/Cielo.php

https://bitbucket.org/imasters/cielo
PHP | 431 lines | 202 code | 45 blank | 184 comment | 62 complexity | 95fc1f15a83b6852fab033a177c6683b MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * @author João Batista Neto
  4. * @brief Classes relacionadas ao webservice da Cielo
  5. * @package dso.cielo
  6. */
  7. require_once 'dso/cielo/PaymentProduct.php';
  8. require_once 'dso/cielo/nodes/PaymentMethodNode.php';
  9. require_once 'dso/cielo/nodes/OrderDataNode.php';
  10. require_once 'dso/cielo/nodes/EcDataNode.php';
  11. require_once 'dso/cielo/nodes/CardDataNode.php';
  12. require_once 'dso/cielo/request/AuthorizationRequest.php';
  13. require_once 'dso/cielo/request/TransactionRequest.php';
  14. require_once 'dso/cielo/request/CancellationRequest.php';
  15. require_once 'dso/cielo/request/CaptureRequest.php';
  16. require_once 'dso/cielo/request/QueryRequest.php';
  17. require_once 'dso/cielo/request/TIDRequest.php';
  18. require_once 'dso/http/CURL.php';
  19. /**
  20. * Builder para criação dos objetos da integração com a Cielo
  21. * @ingroup Cielo
  22. * @class Cielo
  23. */
  24. class Cielo {
  25. /**
  26. * @var boolean
  27. */
  28. private $automaticCapture = false;
  29. /**
  30. * @var HTTPRequest
  31. */
  32. private $httpRequester;
  33. /**
  34. * URL do webservice
  35. * @var string
  36. */
  37. private $cieloURL;
  38. /**
  39. * URL de retorno
  40. * @var string
  41. */
  42. private $returnURL;
  43. /**
  44. * Código de afiliação do cliente
  45. * @var string
  46. */
  47. private $affiliationCode;
  48. /**
  49. * Chave de afiliação do cliente
  50. * @var string
  51. */
  52. private $affiliationKey;
  53. /**
  54. * @var AbstractCieloNode
  55. */
  56. private $transaction;
  57. /**
  58. * @brief Constroi o builder
  59. * @details Constroi o builder para integração com o webservice da Cielo
  60. * @param integer $mode Define o modo da integração, os valores possíveis são:
  61. * @li <b>CieloMode::DEPLOYMENT</b> Para o ambiente de testes
  62. * @li <b>CieloMode::PRODUCTION</b> Para o ambiente de produção
  63. * @param string $returnURL URL de retorno
  64. * @param string $affiliationCode Código de afiliação da loja
  65. * @param string $affiliationKey Chave de afiliação
  66. * @see CieloMode::DEPLOYMENT
  67. * @see CieloMode::PRODUCTION
  68. * @throws InvalidArgumentException Se o modo não for um dos especificados acima.
  69. * @throws InvalidArgumentException Se a URL de retorno for inválida.
  70. * @throws InvalidArgumentException Se o código de afiliação for inválido.
  71. * @throws InvalidArgumentException Se a chave de afiliação for inválida.
  72. */
  73. final public function __construct( $mode = CieloMode::PRODUCTION , $returnURL = null , $affiliationCode = null , $affiliationKey = null ) {
  74. switch ( $mode ) {
  75. case CieloMode::DEPLOYMENT :
  76. $this->cieloURL = 'https://qasecommerce.cielo.com.br/servicos/ecommwsec.do';
  77. break;
  78. case CieloMode::PRODUCTION :
  79. $this->cieloURL = 'https://ecommerce.cbmp.com.br/servicos/ecommwsec.do';
  80. break;
  81. default :
  82. throw new InvalidArgumentException( 'Modo inválido' );
  83. }
  84. if ( !is_null( $returnURL ) ) {
  85. $this->setReturnURL( $returnURL );
  86. }
  87. if ( !is_null( $affiliationCode ) ) {
  88. $this->setAffiliationCode( $affiliationCode );
  89. }
  90. if ( !is_null( $affiliationKey ) ) {
  91. $this->setAffiliationKey( $affiliationKey );
  92. }
  93. }
  94. /**
  95. * Recupera o XML da última requisição
  96. * @param boolean $highlight Indica se o retorno deverá ser formatado
  97. * @return string
  98. * @throws BadMethodCallException Se nenhuma transação tiver sido efetuada
  99. */
  100. public function __getLastRequest( $highlight = false ) {
  101. if ( !is_null( $this->transaction ) ) {
  102. return $this->transaction->getRequestXML( $highlight );
  103. } else {
  104. throw new BadMethodCallException( 'Nenhuma transação foi feita ainda' );
  105. }
  106. }
  107. /**
  108. * Recupera o XML da última resposta
  109. * @param boolean $highlight Indica se o retorno deverá ser formatado
  110. * @return string
  111. * @throws BadMethodCallException Se nenhuma transação tiver sido efetuada
  112. */
  113. public function __getLastResponse( $highlight = false ) {
  114. if ( !is_null( $this->transaction ) ) {
  115. return $this->transaction->getResponseXML( $highlight );
  116. } else {
  117. throw new BadMethodCallException( 'Nenhuma transação foi feita ainda' );
  118. }
  119. }
  120. /**
  121. * Define que a captura será feita automaticamente, por padrão a captura é manual.
  122. * @return Cielo
  123. */
  124. public function automaticCapture() {
  125. $this->automaticCapture = true;
  126. return $this;
  127. }
  128. /**
  129. * Cria um objeto de requisição de autorização da transacao
  130. * @param string $tid ID da transação
  131. * @param string $creditCard Tipo do cartão
  132. * @param string $cardNumber Número do cartão de crédito
  133. * @param integer $cardExpiration Data de expiração do cartão no formato <b>yyyymm</b>
  134. * @param integer $indicator Indicador do código de segurança
  135. * @param integer $securityCode Código de segurança do cartão
  136. * @param string $orderNumber Número identificador do pedido
  137. * @param integer $orderValue Valor do pedido
  138. * @param string $paymentProduct Forma de pagamento do pedido, pode ser uma das seguintes:
  139. * @li PaymentMethod::ONE_TIME_PAYMENT - <b>1</b> - Crédito à Vista
  140. * @li PaymentMethod::INSTALLMENTS_BY_AFFILIATED_MERCHANTS - <b>2</b> - Parcelado pela loja
  141. * @li PaymentMethod::INSTALLMENTS_BY_CARD_ISSUERS - <b>3</b> - Parcelado pela administradora
  142. * @li PaymentMethod::DEBIT - <b>A</b> - Débito
  143. * @param $parcels integer Número de parcelas do pedido.
  144. * @attention Se $formaPagamento for 1 (Crédito à Vista) ou A (Débito), $parcelas precisa, <b>necessariamente</b>
  145. * ser igual a <b>1</b>
  146. * @param string $freeField Um valor qualquer que poderá ser enviado à Cielo para ser resgatado posteriormente
  147. * @return AuthorizationRequest
  148. * @throws UnexpectedValueException Se $formaPagamento for 1 (Crédito à Vista) ou A (Débito) e o número de parcelas
  149. * for diferente de 1
  150. */
  151. final public function buildAuthorizationRequest( $tid , $creditCard , $cardNumber , $cardExpiration , $indicator , $securityCode , $orderNumber , $orderValue , $paymentProduct , $parcels = 1 , $freeField = null ) {
  152. if ( ( ( $paymentProduct == PaymentProduct::ONE_TIME_PAYMENT ) || ( $paymentProduct == PaymentProduct::DEBIT ) ) && ( $parcels != 1 ) ) {
  153. throw new UnexpectedValueException( 'Quando a forma de pagamento é Crédito à vista ou Débito, o número de parcelas deve ser 1' );
  154. } else {
  155. if ( $creditCard == CreditCard::MASTER_CARD && $indicator != 1 ) {
  156. throw new UnexpectedValueException( 'Quando o cartão é MasterCard, o indicador deve ser 1' );
  157. }
  158. if ( $indicator == 1 && !preg_match( '/^[0-9]{3}$/' , (string) $securityCode ) ){
  159. throw new UnexpectedValueException( 'Quando o indicador de segurança é 1, o código de segurança deve ser informado' );
  160. }
  161. if ( is_int( $orderValue ) || is_float( $orderValue ) ) {
  162. $this->transaction = new AuthorizationRequest( $this->getHTTPRequester() );
  163. $this->transaction->addNode( new EcDataNode( $this->getAffiliationCode() , $this->getAffiliationKey() ) );
  164. $this->transaction->addNode( new CardDataNode( $cardNumber , $cardExpiration , $indicator , $securityCode ) );
  165. $this->transaction->addNode( new OrderDataNode( $orderNumber , $orderValue ) );
  166. $this->transaction->addNode( new PaymentMethodNode( $paymentProduct , $parcels , $creditCard ) );
  167. $this->transaction->setCapture( $this->automaticCapture );
  168. $this->transaction->setURL( $this->cieloURL );
  169. $this->transaction->setTID( $tid );
  170. if ( !is_null( $freeField ) ) {
  171. $this->transaction->setFreeField( $freeField );
  172. }
  173. return $this->transaction;
  174. } else {
  175. throw new UnexpectedValueException( sprintf( 'O valor do pedido deve ser numérico, %s foi dado.' , gettype( $orderValue ) ) );
  176. }
  177. }
  178. }
  179. /**
  180. * @brief Cria um objeto de requisição de cancelamento de transacao
  181. * @details Constroi o objeto de transação a partir de uma consulta para cancelamento, utilizando o TID (<i>Transaction ID</i>).
  182. * @param string $tid TID da transação que será utilizado para fazer a consulta
  183. * @return CancellationRequest
  184. */
  185. final public function buildCancellationTransaction( $tid ) {
  186. $this->transaction = new CancellationRequest( $this->getHTTPRequester() );
  187. $this->transaction->addNode( new EcDataNode( $this->getAffiliationCode() , $this->getAffiliationKey() ) );
  188. $this->transaction->setTID( $tid );
  189. $this->transaction->setURL( $this->cieloURL );
  190. return $this->transaction;
  191. }
  192. /**
  193. * @brief Cria um objeto Transacao
  194. * @details Constroi o objeto de transação a partir de uma captura, utilizando o TID (<i>Transaction ID</i>).
  195. * @param string $tid TID da transação que será utilizado para fazer a captura
  196. * @param float $value Valor que será capturado
  197. * @return CaptureRequest
  198. * @throws InvalidArgumentException Se o valor for definido mas não for numérico
  199. */
  200. final public function buildCaptureTransaction( $tid , $value = null ) {
  201. $nullValue = is_null( $value );
  202. if ( $nullValue || is_float( $value ) || is_int( $value ) ) {
  203. $this->transaction = new CaptureRequest( $this->getHTTPRequester() );
  204. $this->transaction->addNode( new EcDataNode( $this->getAffiliationCode() , $this->getAffiliationKey() ) );
  205. $this->transaction->setTID( $tid );
  206. $this->transaction->setURL( $this->cieloURL );
  207. if ( !$nullValue ) {
  208. $this->transaction->setValue( $value );
  209. }
  210. return $this->transaction;
  211. } else {
  212. throw new InvalidArgumentException( sprintf( 'O valor deve ser um inteiro ou float, %s foi dado' , gettype( $value ) ) );
  213. }
  214. }
  215. /**
  216. * @brief Cria um objeto Transacao
  217. * @details Constroi o objeto de transação a partir de uma consulta, utilizando o TID (<i>Transaction ID</i>).
  218. * @param string $tid TID da transação que será utilizado para fazer a consulta
  219. * @return QueryRequest
  220. */
  221. final public function buildQueryTransaction( $tid ) {
  222. $this->transaction = new QueryRequest( $this->getHTTPRequester() );
  223. $this->transaction->addNode( new EcDataNode( $this->getAffiliationCode() , $this->getAffiliationKey() ) );
  224. $this->transaction->setTID( $tid );
  225. $this->transaction->setURL( $this->cieloURL );
  226. return $this->transaction;
  227. }
  228. /**
  229. * @brief Cria um objeto de requisição de TID
  230. * @param string $creditCard Tipo do cartão
  231. * @param string $paymentProduct Forma de pagamento do pedido, pode ser uma das seguintes:
  232. * @li PaymentMethod::ONE_TIME_PAYMENT - <b>1</b> - Crédito à Vista
  233. * @li PaymentMethod::INSTALLMENTS_BY_AFFILIATED_MERCHANTS - <b>2</b> - Parcelado pela loja
  234. * @li PaymentMethod::INSTALLMENTS_BY_CARD_ISSUERS - <b>3</b> - Parcelado pela administradora
  235. * @li PaymentMethod::DEBIT - <b>A</b> - Débito
  236. * @param $parcels integer Número de parcelas do pedido.
  237. * @attention Se $formaPagamento for 1 (Crédito à Vista) ou A (Débito), $parcelas precisa, <b>necessariamente</b>
  238. * ser igual a <b>1</b>
  239. * @return TIDRequest
  240. * @throws UnexpectedValueException Se $formaPagamento for 1 (Crédito à Vista) ou A (Débito) e o número de parcelas
  241. * for diferente de 1
  242. */
  243. final public function buildTIDRequest( $creditCard , $paymentProduct , $parcels = 1 ) {
  244. if ( ( ( $paymentProduct == PaymentProduct::ONE_TIME_PAYMENT ) || ( $paymentProduct == PaymentProduct::DEBIT ) ) && ( $parcels != 1 ) ) {
  245. throw new UnexpectedValueException( 'Quando a forma de pagamento é Crédito à vista ou Débito, o número de parcelas deve ser 1' );
  246. } else {
  247. $this->transaction = new TIDRequest( $this->getHTTPRequester() );
  248. $this->transaction->addNode( new EcDataNode( $this->getAffiliationCode() , $this->getAffiliationKey() ) );
  249. $this->transaction->addNode( new PaymentMethodNode( $paymentProduct , $parcels , $creditCard ) );
  250. $this->transaction->setURL( $this->cieloURL );
  251. return $this->transaction;
  252. }
  253. }
  254. /**
  255. * @brief Cria um objeto de requisição de transacao
  256. * @details Constroi um objeto de requisição de transação para autenticação
  257. * @param string $creditCard Tipo do cartão
  258. * @param string $orderNumber Número identificador do pedido
  259. * @param integer $orderValue Valor do pedido
  260. * @param string $paymentProduct Forma de pagamento do pedido, pode ser uma das seguintes:
  261. * @li PaymentMethod::ONE_TIME_PAYMENT - <b>1</b> - Crédito à Vista
  262. * @li PaymentMethod::INSTALLMENTS_BY_AFFILIATED_MERCHANTS - <b>2</b> - Parcelado pela loja
  263. * @li PaymentMethod::INSTALLMENTS_BY_CARD_ISSUERS - <b>3</b> - Parcelado pela administradora
  264. * @li PaymentMethod::DEBIT - <b>A</b> - Débito
  265. * @param $parcels integer Número de parcelas do pedido.
  266. * @attention Se $formaPagamento for 1 (Crédito à Vista) ou A (Débito), $parcelas precisa, <b>necessariamente</b>
  267. * ser igual a <b>1</b>
  268. * @param string $freeField Um valor qualquer que poderá ser enviado à Cielo para ser resgatado posteriormente
  269. * @return TransactionRequest
  270. * @throws UnexpectedValueException Se $formaPagamento for 1 (Crédito à Vista) ou A (Débito) e o número de parcelas
  271. * for diferente de 1
  272. */
  273. final public function buildTransactionRequest( $creditCard , $orderNumber , $orderValue , $paymentProduct , $parcels = 1 , $freeField = null ) {
  274. if ( ( ( $paymentProduct == PaymentProduct::ONE_TIME_PAYMENT ) || ( $paymentProduct == PaymentProduct::DEBIT ) ) && ( $parcels != 1 ) ) {
  275. throw new UnexpectedValueException( 'Quando a forma de pagamento é Crédito à vista ou Débito, o número de parcelas deve ser 1' );
  276. } else {
  277. if ( is_int( $orderValue ) || is_float( $orderValue ) ) {
  278. $this->transaction = new TransactionRequest( $this->getHTTPRequester() );
  279. $this->transaction->addNode( new EcDataNode( $this->getAffiliationCode() , $this->getAffiliationKey() ) );
  280. $this->transaction->addNode( new OrderDataNode( $orderNumber , $orderValue ) );
  281. $this->transaction->addNode( new PaymentMethodNode( $paymentProduct , $parcels , $creditCard ) );
  282. $this->transaction->setReturnURL( $this->getReturnURL() );
  283. $this->transaction->setCapture( $this->automaticCapture );
  284. if ( !is_null( $freeField ) ) {
  285. $this->transaction->setFreeField( $freeField );
  286. }
  287. $this->transaction->setURL( $this->cieloURL );
  288. return $this->transaction;
  289. } else {
  290. throw new UnexpectedValueException( sprintf( 'O valor do pedido deve ser numérico, %s foi dado.' , gettype( $orderValue ) ) );
  291. }
  292. }
  293. }
  294. /**
  295. * Recupera o número de afiliação da loja junto à Cielo
  296. * @return string O código de afiliação
  297. * @throws BadMethodCallException Se não tivermos um código de afiliação
  298. */
  299. public function getAffiliationCode() {
  300. if ( is_null( $this->affiliationCode ) ) {
  301. throw new BadMethodCallException( 'Código de afiliação não definido' );
  302. } else {
  303. return $this->affiliationCode;
  304. }
  305. }
  306. /**
  307. * Recupera a chave da afiliação da loja junto à Cielo
  308. * @return string A chave de afiliação
  309. * @throws BadMethodCallException Se não tivermos uma chave de afiliação
  310. */
  311. public function getAffiliationKey() {
  312. if ( is_null( $this->affiliationKey ) ) {
  313. throw new BadMethodCallException( 'Chave de afiliação não definido' );
  314. } else {
  315. return $this->affiliationKey;
  316. }
  317. }
  318. /**
  319. * Recupera o objeto de requisição HTTP
  320. * @return HTTPRequest
  321. */
  322. public function getHTTPRequester() {
  323. if ( is_null( $this->httpRequester ) ) {
  324. return new CURL();
  325. }
  326. return $this->httpRequester;
  327. }
  328. /**
  329. * @brief Recupera a URL de retorno que será utilizado pela Cielo para retornar à loja
  330. * @details O valor retornado pode utilizar o template <b>{pedido}</b> para compor a URL
  331. * de retorno, esse valor será substituído pelo número do pedido informado.
  332. * @return string
  333. */
  334. public function getReturnURL() {
  335. if ( !is_null( $this->returnURL ) ) {
  336. return $this->returnURL;
  337. } else {
  338. throw new BadMethodCallException( 'Ainda não foi definido a URL de retorno' );
  339. }
  340. }
  341. /**
  342. * Define o código de afiliação
  343. * @param string $affiliationCode Código de afiliação
  344. * @throws InvalidArgumentException Se o código de afiliação não for uma string
  345. */
  346. public function setAffiliationCode( $affiliationCode ) {
  347. if ( is_string( $affiliationCode ) ) {
  348. $this->affiliationCode = & $affiliationCode;
  349. } else {
  350. throw new InvalidArgumentException( 'Código de afiliação inválido' );
  351. }
  352. }
  353. /**
  354. * Define a chave de afiliação
  355. * @param string $affiliationKey Chave de afiliação
  356. * @throws InvalidArgumentException Se a chave de afiliação não for uma string
  357. */
  358. public function setAffiliationKey( $affiliationKey ) {
  359. if ( is_string( $affiliationKey ) ) {
  360. $this->affiliationKey = & $affiliationKey;
  361. } else {
  362. throw new InvalidArgumentException( 'Chave de afiliação inválida' );
  363. }
  364. }
  365. /**
  366. * Define a URL de retorno
  367. * @param string $url
  368. * @throws InvalidArgumentException Se a URL de retorno for inválida
  369. */
  370. public function setReturnURL( $url ) {
  371. if ( filter_var( $url , FILTER_VALIDATE_URL ) ) {
  372. $this->returnURL = & $url;
  373. } else {
  374. throw new InvalidArgumentException( 'URL de retorno inválida' );
  375. }
  376. }
  377. /**
  378. * Define o objeto de requisição HTTP
  379. * @param HTTPRequest $httpRequester
  380. * @return CieloBuilder
  381. */
  382. public function useHttpRequester( HTTPRequest $httpRequester ) {
  383. $this->httpRequester = $httpRequester;
  384. return $this;
  385. }
  386. }