├── sdktest.sh ├── tests ├── bootstrap.php ├── Mocks │ ├── TransactionCreateRequestMocks.php │ ├── ShoppingCartMocks.php │ ├── TransactionCommitRequestMocks.php │ ├── TransactionCommitResponseMocks.php │ └── TransactionCreateResponseMocks.php ├── RequestServiceTest.php ├── RefundTest.php ├── OptionsTest.php ├── Webpay │ ├── Modal │ │ └── TransbankWebpayModalTest.php │ ├── WebpayPlus │ │ └── WebpayPlusWithoutMocksTest.php │ └── OneClick │ │ └── TransbankOneclickTest.php └── OnepaySignUtilTest.php ├── .gitignore ├── src ├── Utils │ ├── ResponseCodesEnum.php │ ├── Utils.php │ ├── EnvironmentManager.php │ ├── TransactionStatusEnum.php │ ├── ConfiguresEnvironment.php │ ├── HttpClient.php │ ├── HttpClientRequestService.php │ └── InteractsWithWebpayApi.php ├── Webpay │ ├── Modal │ │ ├── Responses │ │ │ ├── TransactionCommitResponse.php │ │ │ ├── TransactionRefundResponse.php │ │ │ ├── TransactionCreateResponse.php │ │ │ └── TransactionStatusResponse.php │ │ ├── Exceptions │ │ │ ├── TransactionCommitException.php │ │ │ ├── TransactionCreateException.php │ │ │ ├── TransactionRefundException.php │ │ │ └── TransactionStatusException.php │ │ ├── WebpayModal.php │ │ └── Transaction.php │ ├── WebpayPlus │ │ ├── Responses │ │ │ ├── TransactionCommitResponse.php │ │ │ ├── MallTransactionCaptureResponse.php │ │ │ ├── MallTransactionCommitResponse.php │ │ │ ├── MallTransactionCreateResponse.php │ │ │ ├── MallTransactionRefundResponse.php │ │ │ ├── TransactionStatusResponse.php │ │ │ ├── TransactionCreateResponse.php │ │ │ ├── TransactionCaptureResponse.php │ │ │ └── TransactionRefundResponse.php │ │ └── Exceptions │ │ │ ├── MallTransactionCaptureException.php │ │ │ ├── MallTransactionCommitException.php │ │ │ ├── MallTransactionCreateException.php │ │ │ ├── MallTransactionRefundException.php │ │ │ ├── MallTransactionStatusException.php │ │ │ ├── TransactionCaptureException.php │ │ │ ├── TransactionCommitException.php │ │ │ ├── TransactionCreateException.php │ │ │ ├── TransactionRefundException.php │ │ │ └── TransactionStatusException.php │ ├── Oneclick │ │ ├── Responses │ │ │ ├── TransactionDetail.php │ │ │ ├── MallTransactionAuthorizeResponse.php │ │ │ ├── InscriptionDeleteResponse.php │ │ │ ├── InscriptionStartResponse.php │ │ │ ├── MallTransactionCaptureResponse.php │ │ │ ├── InscriptionFinishResponse.php │ │ │ └── MallTransactionRefundResponse.php │ │ ├── Exceptions │ │ │ ├── InscriptionDeleteException.php │ │ │ ├── InscriptionFinishException.php │ │ │ ├── InscriptionStartException.php │ │ │ ├── MallRefundTransactionException.php │ │ │ ├── MallTransactionCaptureException.php │ │ │ ├── MallTransactionStatusException.php │ │ │ └── MallTransactionAuthorizeException.php │ │ ├── Traits │ │ │ └── NeedsConfiguration.php │ │ ├── MallInscription.php │ │ └── MallTransaction.php │ ├── Exceptions │ │ ├── TransbankException.php │ │ ├── WebpayException.php │ │ ├── TransbankApiRequest.php │ │ └── WebpayRequestException.php │ ├── Oneclick.php │ ├── WebpayPlus.php │ └── Options.php ├── Contracts │ ├── HttpClientInterface.php │ └── RequestService.php ├── TransaccionCompleta │ ├── Responses │ │ ├── TransactionCommitResponse.php │ │ ├── MallTransactionCaptureResponse.php │ │ ├── MallTransactionCommitResponse.php │ │ ├── TransactionDetail.php │ │ ├── TransactionCaptureResponse.php │ │ ├── TransactionCreateResponse.php │ │ ├── MallTransactionCreateResponse.php │ │ ├── TransactionStatusResponse.php │ │ ├── MallTransactionStatusResponse.php │ │ ├── MallTransactionInstallmentsResponse.php │ │ ├── TransactionInstallmentsResponse.php │ │ ├── TransactionRefundResponse.php │ │ └── MallTransactionRefundResponse.php │ ├── Exceptions │ │ ├── TransactionCommitException.php │ │ ├── TransactionCreateException.php │ │ ├── TransactionRefundException.php │ │ ├── TransactionStatusException.php │ │ ├── TransactionCaptureException.php │ │ ├── MallTransactionCaptureException.php │ │ ├── MallTransactionCommitException.php │ │ ├── MallTransactionCreateException.php │ │ ├── MallTransactionRefundException.php │ │ ├── MallTransactionStatusException.php │ │ ├── TransactionInstallmentsException.php │ │ ├── MallTransactionInstallmentsException.php │ │ ├── TransaccionCompletaException.php │ │ └── MallTransactionCompletaException.php │ └── TransaccionCompleta.php ├── Patpass │ ├── Exceptions │ │ └── PatpassException.php │ ├── PatpassByWebpay │ │ ├── Responses │ │ │ ├── TransactionStatusResponse.php │ │ │ └── TransactionCreateResponse.php │ │ ├── Exceptions │ │ │ ├── TransactionCommitException.php │ │ │ ├── TransactionCreateException.php │ │ │ └── TransactionStatusException.php │ │ └── Transaction.php │ ├── PatpassComercio │ │ ├── Exceptions │ │ │ ├── InscriptionStartException.php │ │ │ └── InscriptionStatusException.php │ │ ├── Responses │ │ │ ├── InscriptionFinishResponse.php │ │ │ ├── InscriptionStatusResponse.php │ │ │ └── InscriptionStartResponse.php │ │ └── Inscription.php │ ├── Options.php │ ├── PatpassByWebpay.php │ └── PatpassComercio.php └── Onepay │ ├── ChannelEnum.php │ ├── Exceptions │ ├── RefundCreateException.php │ ├── SignException.php │ ├── AmountException.php │ ├── TransbankException.php │ ├── TransactionCreateException.php │ └── TransactionCommitException.php │ ├── BaseRequest.php │ ├── BaseResponse.php │ ├── Refund.php │ ├── TransactionCommitRequest.php │ ├── RefundCreateRequest.php │ ├── RefundCreateResponse.php │ ├── TransactionCreateResponse.php │ ├── ShoppingCart.php │ ├── Utils │ └── OnepayRequestBuilder.php │ ├── Options.php │ ├── TransactionCommitResponse.php │ └── Item.php ├── docker-compose.yml ├── Makefile ├── phpunit.xml ├── Dockerfile ├── SECURITY.md ├── composer.json ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ └── reporte-de-error.md └── workflows │ └── tests.yml ├── .travis.yml ├── LICENSE └── examples ├── index.php └── transaccion-completa └── mall.php /sdktest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./vendor/bin/phpunit 4 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | tests 5 | 6 | 7 | 8 | 9 | lib 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Onepay/Exceptions/SignException.php: -------------------------------------------------------------------------------- 1 | token = $json['token']; 15 | } 16 | 17 | /** 18 | * @return string|null 19 | */ 20 | public function getToken() 21 | { 22 | return $this->token; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Onepay/Exceptions/AmountException.php: -------------------------------------------------------------------------------- 1 | $this->getCommerceCode(), 20 | 'Authorization' => $this->getApiKey(), 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Webpay/Oneclick/Responses/InscriptionDeleteResponse.php: -------------------------------------------------------------------------------- 1 | success = $success; 13 | $this->code = $httpCode; 14 | } 15 | 16 | public function wasSuccessfull() 17 | { 18 | return $this->success === true; 19 | } 20 | 21 | /** 22 | * @return mixed|null 23 | */ 24 | public function getCode() 25 | { 26 | return $this->code; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Patpass/PatpassByWebpay.php: -------------------------------------------------------------------------------- 1 | setToken($token); 15 | } 16 | 17 | /** 18 | * @return mixed 19 | */ 20 | public function getToken() 21 | { 22 | return $this->token; 23 | } 24 | 25 | /** 26 | * @param mixed $token 27 | */ 28 | public function setToken($token) 29 | { 30 | $this->token = $token; 31 | 32 | return $this; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.4-apache-buster 2 | RUN apt-get update && apt-get install -y zip unzip libxml2-dev libzip-dev 3 | RUN mkdir -p /sdk 4 | WORKDIR /sdk 5 | COPY . /sdk 6 | RUN php -r "copy('https://composer.github.io/installer.sig', 'composer-setup.sig');" 7 | RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 8 | RUN php -r "if (hash_file('SHA384', 'composer-setup.php') === trim(file_get_contents('composer-setup.sig'))) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); unlink('composer-setup.sig'); } echo PHP_EOL;" 9 | RUN php composer-setup.php --install-dir=/usr/local/bin --filename=composer 10 | RUN php -r "unlink('composer-setup.php');" 11 | RUN php -r "unlink('composer-setup.sig');" 12 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 1.6.x | :white_check_mark: | 8 | | 1.5.x | :white_check_mark: | 9 | | < 1.5 | :x: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | To report a vulnerability, pleae send an email to soporte@transbankdevelopers.cl 14 | following the next steps: 15 | 16 | **Describe the vulnerability** 17 | 18 | A concise description of the vulnerability. 19 | 20 | **Evidence** 21 | 22 | If you can, sent as much evidence as posible including link and screenshots 23 | 24 | **Desired actions to solve it** 25 | 26 | You can send us all the desired actions or options to solve it 27 | 28 | 29 | We will to review and answer the case as soon as posible 30 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "transbank/transbank-sdk", 3 | "description": "Transbank SDK", 4 | "keywords": ["payments", "transbank", "api", "sdk"], 5 | "require": { 6 | "php": ">=7.0", 7 | "ext-curl": "*", 8 | "ext-json": "*", 9 | "ext-mbstring": "*", 10 | "guzzlehttp/guzzle":"^5|^6|^7" 11 | }, 12 | "require-dev": { 13 | "phpunit/phpunit": "^9", 14 | "squizlabs/php_codesniffer": "~2.0", 15 | "dms/phpunit-arraysubset-asserts": "^0.2.1" 16 | }, 17 | "autoload": { 18 | "psr-4": { 19 | "Transbank\\": [ 20 | "src/" 21 | ] 22 | } 23 | }, 24 | "autoload-dev": { 25 | "psr-4": { 26 | "Tests\\": [ 27 | "tests/" 28 | ] 29 | } 30 | }, 31 | "license": "BSD-3-Clause" 32 | } 33 | -------------------------------------------------------------------------------- /src/Webpay/Modal/Responses/TransactionStatusResponse.php: -------------------------------------------------------------------------------- 1 | setTransactionStatusFields($json); 21 | } 22 | 23 | public function isApproved() 24 | { 25 | return $this->getResponseCode() === ResponseCodesEnum::RESPONSE_CODE_APPROVED && 26 | $this->getStatus() !== TransactionStatusEnum::STATUS_FAILED; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/TransaccionCompleta/Responses/MallTransactionCreateResponse.php: -------------------------------------------------------------------------------- 1 | setToken($token); 15 | } 16 | 17 | /** 18 | * @return mixed 19 | */ 20 | public function getToken() 21 | { 22 | return $this->token; 23 | } 24 | 25 | /** 26 | * @param mixed $token 27 | * 28 | * @return MallTransactionCreateResponse 29 | */ 30 | public function setToken($token) 31 | { 32 | $this->token = $token; 33 | 34 | return $this; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Webpay/Oneclick/Traits/NeedsConfiguration.php: -------------------------------------------------------------------------------- 1 | getCommerceCode(); 17 | $apiKey = $options->getApiKey(); 18 | $baseUrl = Oneclick::getIntegrationTypeUrl($options->getIntegrationType()); 19 | } 20 | 21 | return [ 22 | $commerceCode, 23 | $apiKey, 24 | $baseUrl, 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/TransaccionCompleta/Responses/TransactionStatusResponse.php: -------------------------------------------------------------------------------- 1 | vci = isset($json['vci']) ? $json['vci'] : null; 16 | $this->setTransactionStatusFields($json); 17 | } 18 | 19 | /** 20 | * @return mixed 21 | */ 22 | public function getVci() 23 | { 24 | return $this->vci; 25 | } 26 | 27 | /** 28 | * @param mixed $vci 29 | * 30 | * @return TransactionStatusResponse 31 | */ 32 | public function setVci($vci) 33 | { 34 | $this->vci = $vci; 35 | 36 | return $this; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Onepay/BaseRequest.php: -------------------------------------------------------------------------------- 1 | apiKey = null; 17 | $this->appKey = null; 18 | } 19 | 20 | public function getApiKey() 21 | { 22 | return $this->apiKey; 23 | } 24 | 25 | public function setApiKey($apiKey) 26 | { 27 | $this->apiKey = $apiKey; 28 | 29 | return $this; 30 | } 31 | 32 | public function getAppKey() 33 | { 34 | return $this->appKey; 35 | } 36 | 37 | public function setAppKey($appKey) 38 | { 39 | $this->appKey = $appKey; 40 | 41 | return $this; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org/ 2 | 3 | root = true 4 | 5 | [*.{c,h,awk,w32,bat,mk,frag}] 6 | charset = utf-8 7 | indent_size = 4 8 | indent_style = tab 9 | tab_width = 4 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [*.{php,phpt}] 14 | charset = utf-8 15 | indent_size = 4 16 | indent_style = space 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.{yml,m4,sh}] 21 | charset = utf-8 22 | indent_size = 2 23 | indent_style = space 24 | trim_trailing_whitespace = true 25 | insert_final_newline = true 26 | 27 | [*.md] 28 | charset = utf-8 29 | indent_style = space 30 | trim_trailing_whitespace = false 31 | insert_final_newline = true 32 | -------------------------------------------------------------------------------- /tests/Mocks/TransactionCreateRequestMocks.php: -------------------------------------------------------------------------------- 1 | buildCreateRequest($cart, null); 16 | array_push(self::$transactionCreateRequestMocks, $transactionCreateRequest); 17 | } 18 | 19 | return self::$transactionCreateRequestMocks; 20 | } 21 | 22 | public static function get($indexOfMock = 0) 23 | { 24 | return self::transactionCreateRequestMocks()[$indexOfMock]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Mocks/ShoppingCartMocks.php: -------------------------------------------------------------------------------- 1 | add($firstItem); 26 | $shoppingCart->add($secondItem); 27 | 28 | array_push(self::$shoppingCartMocks, $shoppingCart); 29 | } 30 | 31 | return self::$shoppingCartMocks; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Onepay/BaseResponse.php: -------------------------------------------------------------------------------- 1 | responseCode = null; 17 | $this->description = null; 18 | } 19 | 20 | public function getResponseCode() 21 | { 22 | return $this->responseCode; 23 | } 24 | 25 | public function setResponseCode($responseCode) 26 | { 27 | $this->responseCode = $responseCode; 28 | 29 | return $this; 30 | } 31 | 32 | public function getDescription() 33 | { 34 | return $this->description; 35 | } 36 | 37 | public function setDescription($appKey) 38 | { 39 | $this->description = $appKey; 40 | 41 | return $this; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Webpay/Oneclick.php: -------------------------------------------------------------------------------- 1 | buildCommitRequest( 17 | '1807419329781765', 18 | '8934751b-aa9a-45be-b686-1f45b6c45b02', 19 | null 20 | ); 21 | array_push(self::$transactionCommitRequestMocks, $transactionCommitRequest); 22 | } 23 | 24 | return self::$transactionCommitRequestMocks; 25 | } 26 | 27 | public static function get($indexOfMock = 0) 28 | { 29 | return self::transactionCreateRequestMocks()[$indexOfMock]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - '7.3' 4 | - '7.4' 5 | - '8.0' 6 | 7 | before_script: 8 | - phpenv config-rm xdebug.ini 9 | - composer install 10 | script: "./sdktest.sh" 11 | deploy: 12 | provider: releases 13 | name: "$TRAVIS_TAG" 14 | api_key: 15 | secure: kwsEZ8iFhSzF2Bmk+wA5mjf9UGQ24U5yonZgWwmT05JuxM5JbeKVVEGfrbdfrT4qqksh3LamDvhbnug8qT1EWCOfXdPiYJj16fJR9HJpx7iUwjp+rulGpusfLrZoFu1gyXXMGfsmlTSdYn4jDN22wQgAZtiGD1L/nLHlTSM6fWPAThtF3ySLdqAbNGzIDYxTP+XI/PI91/DaM+EH88eww6bKVTOShGXHbVDu57BHo20RWEpN2KRjDPt/7QvvMUF5YzNNYlZb0WK61vZKwdKPD3f8+ZcqA9g4N6xodnpNbc/h/toh8CeayWNGOwV3pSmVabBiFi0MNoSgTtCFACBdvWpV8AwLOv6+zLyo2rIYJ7AWoDrtRZXqSZ+Qmk7HLoWNWMtH9MMyXuVzJkrWFauKtE7aX5B75xTWpZVQZSUk2lxesz9zmyZ1eViEfBzegAFbMFOK/P7J6bZFOhYEqCGP0+GGQOh8+pvolyEM+U0GHl6VOOgJ8s7XpBdVLw4urfzOUyqeh7lW+MJDDba9SKGO7j9PRyMILPT3K+0Oqtset3ByQZG5VHQlp1V5SxeiAtsF8aLZMmvTFQQMHG97t/FJ72teS2+3OeQ4m4GknA+c1MYcnGb20fLABC6SbWEnBhQcre8o+imyavuAQkHq/Hn7MU19wF7CGmb3pFTJuhGRRvI= 16 | skip_cleanup: true 17 | on: 18 | repo: TransbankDevelopers/transbank-sdk-php 19 | tags: true 20 | php: 8.0 21 | -------------------------------------------------------------------------------- /src/Patpass/PatpassComercio.php: -------------------------------------------------------------------------------- 1 | setCode($httpCode); 19 | 20 | if ($httpCode == 204) { 21 | $this->setStatus('OK'); 22 | 23 | return; 24 | } 25 | if ($httpCode == 404) { 26 | $this->setStatus('Not Found'); 27 | 28 | return; 29 | } 30 | } 31 | 32 | /** 33 | * @return mixed 34 | */ 35 | public function getStatus() 36 | { 37 | return $this->status; 38 | } 39 | 40 | /** 41 | * @param mixed $status 42 | */ 43 | public function setStatus($status) 44 | { 45 | $this->status = $status; 46 | 47 | return $this; 48 | } 49 | 50 | /** 51 | * @return mixed 52 | */ 53 | public function getCode() 54 | { 55 | return $this->code; 56 | } 57 | 58 | /** 59 | * @param mixed $code 60 | */ 61 | public function setCode($code) 62 | { 63 | $this->code = $code; 64 | 65 | return $this; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Patpass/PatpassByWebpay/Responses/TransactionCreateResponse.php: -------------------------------------------------------------------------------- 1 | setToken($token); 19 | $url = isset($json['url']) ? $json['url'] : null; 20 | $this->setUrl($url); 21 | } 22 | 23 | /** 24 | * @return mixed 25 | */ 26 | public function getToken() 27 | { 28 | return $this->token; 29 | } 30 | 31 | /** 32 | * @param mixed $token 33 | * 34 | * @return TransactionCreateResponse 35 | */ 36 | public function setToken($token) 37 | { 38 | $this->token = $token; 39 | 40 | return $this; 41 | } 42 | 43 | /** 44 | * @return mixed 45 | */ 46 | public function getUrl() 47 | { 48 | return $this->url; 49 | } 50 | 51 | /** 52 | * @param mixed $url 53 | * 54 | * @return TransactionCreateResponse 55 | */ 56 | public function setUrl($url) 57 | { 58 | $this->url = $url; 59 | 60 | return $this; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Webpay/Oneclick/Responses/InscriptionStartResponse.php: -------------------------------------------------------------------------------- 1 | setToken($token); 15 | $this->setUrlWebpay($urlWebpay); 16 | } 17 | 18 | public function getRedirectUrl() 19 | { 20 | return $this->getUrlWebpay().'?TBK_TOKEN='.$this->getToken(); 21 | } 22 | 23 | /** 24 | * @return mixed 25 | */ 26 | public function getToken() 27 | { 28 | return $this->token; 29 | } 30 | 31 | /** 32 | * @param mixed $token 33 | * 34 | * @return InscriptionStartResponse 35 | */ 36 | public function setToken($token) 37 | { 38 | $this->token = $token; 39 | 40 | return $this; 41 | } 42 | 43 | /** 44 | * @return mixed 45 | */ 46 | public function getUrlWebpay() 47 | { 48 | return $this->urlWebpay; 49 | } 50 | 51 | /** 52 | * @param mixed $urlWebpay 53 | * 54 | * @return InscriptionStartResponse 55 | */ 56 | public function setUrlWebpay($urlWebpay) 57 | { 58 | $this->urlWebpay = $urlWebpay; 59 | 60 | return $this; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Webpay/WebpayPlus/Responses/TransactionStatusResponse.php: -------------------------------------------------------------------------------- 1 | vci = isset($json['vci']) ? $json['vci'] : null; 17 | $this->setTransactionStatusFields($json); 18 | } 19 | 20 | /** 21 | * Returns true if the transaction was approved. 22 | * 23 | * @return bool 24 | */ 25 | public function isApproved() 26 | { 27 | if ($this->getResponseCode() !== ResponseCodesEnum::RESPONSE_CODE_APPROVED) { 28 | return false; 29 | } 30 | 31 | // Check the status is always not-null and is not a failure status. 32 | return null !== $this->getStatus() && $this->getStatus() !== TransactionStatusEnum::STATUS_FAILED; 33 | } 34 | 35 | /** 36 | * @return mixed 37 | */ 38 | public function getVci() 39 | { 40 | return $this->vci; 41 | } 42 | 43 | /** 44 | * @param mixed $vci 45 | * 46 | * @return TransactionStatusResponse 47 | */ 48 | public function setVci($vci) 49 | { 50 | $this->vci = $vci; 51 | 52 | return $this; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Transbank 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | -------------------------------------------------------------------------------- /src/Patpass/PatpassComercio/Responses/InscriptionStatusResponse.php: -------------------------------------------------------------------------------- 1 | setStatus($status); 22 | $urlVoucher = Utils::returnValueIfExists($json, 'voucherUrl'); 23 | $this->setUrlVoucher($urlVoucher); 24 | } 25 | 26 | /** 27 | * @return mixed 28 | */ 29 | public function getStatus() 30 | { 31 | return $this->status; 32 | } 33 | 34 | /** 35 | * @param mixed $status 36 | * 37 | * @return InscriptionStatusResponse 38 | */ 39 | public function setStatus($status) 40 | { 41 | $this->status = $status; 42 | 43 | return $this; 44 | } 45 | 46 | /** 47 | * @return mixed 48 | */ 49 | public function getUrlVoucher() 50 | { 51 | return $this->urlVoucher; 52 | } 53 | 54 | /** 55 | * @param mixed $urlVoucher 56 | * 57 | * @return InscriptionStatusResponse 58 | */ 59 | public function setUrlVoucher($urlVoucher) 60 | { 61 | $this->urlVoucher = $urlVoucher; 62 | 63 | return $this; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/Mocks/TransactionCommitResponseMocks.php: -------------------------------------------------------------------------------- 1 | setToken($token); 27 | 28 | $url = Utils::returnValueIfExists($json, 'url'); 29 | $this->setUrlWebpay($url); 30 | } 31 | 32 | /** 33 | * @return mixed 34 | */ 35 | public function getToken() 36 | { 37 | return $this->token; 38 | } 39 | 40 | /** 41 | * @param mixed $token 42 | * 43 | * @return InscriptionStartResponse 44 | */ 45 | public function setToken($token) 46 | { 47 | $this->token = $token; 48 | 49 | return $this; 50 | } 51 | 52 | /** 53 | * @return mixed 54 | */ 55 | public function getUrlWebpay() 56 | { 57 | return $this->urlWebpay; 58 | } 59 | 60 | /** 61 | * @param mixed $url 62 | * 63 | * @return InscriptionStartResponse 64 | */ 65 | public function setUrlWebpay($url) 66 | { 67 | $this->urlWebpay = $url; 68 | 69 | return $this; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Webpay/Exceptions/TransbankApiRequest.php: -------------------------------------------------------------------------------- 1 | method = $method; 25 | $this->baseUrl = $baseUrl; 26 | $this->endpoint = $endpoint; 27 | $this->payload = $payload; 28 | $this->headers = $headers; 29 | } 30 | 31 | /** 32 | * @return mixed 33 | */ 34 | public function getMethod() 35 | { 36 | return $this->method; 37 | } 38 | 39 | /** 40 | * @return mixed 41 | */ 42 | public function getBaseUrl() 43 | { 44 | return $this->baseUrl; 45 | } 46 | 47 | /** 48 | * @return mixed 49 | */ 50 | public function getEndpoint() 51 | { 52 | return $this->endpoint; 53 | } 54 | 55 | /** 56 | * @return array 57 | */ 58 | public function getPayload() 59 | { 60 | return $this->payload; 61 | } 62 | 63 | /** 64 | * @return array 65 | */ 66 | public function getHeaders() 67 | { 68 | return $this->headers; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: PHPUnit 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | env: 8 | PHP_EXTENSIONS: 'mbstring, curl, json' 9 | key: cache-v1 # can be any string, change to clear the extension cache. 10 | 11 | jobs: 12 | run: 13 | runs-on: ubuntu-latest 14 | strategy: 15 | matrix: 16 | php-versions: [ '7.3', '7.4', '8.0'] 17 | name: PHP ${{ matrix.php-versions }} 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v2 21 | 22 | - name: Setup cache environment 23 | id: extcache 24 | uses: shivammathur/cache-extensions@v1 25 | with: 26 | php-version: ${{ matrix.php-versions }} 27 | extensions: ${{ env.PHP_EXTENSIONS }} 28 | key: ${{ env.key }} 29 | tools: composer-v2 30 | - name: Setup PHP 31 | uses: shivammathur/setup-php@v2 32 | with: 33 | php-version: ${{ matrix.php-versions }} 34 | tools: composer:v2 35 | coverage: none 36 | env: 37 | runner: ubuntu-latest # Specify the runner. 38 | - name: Get composer cache directory 39 | id: composer-cache 40 | run: echo "::set-output name=dir::$(composer config cache-files-dir)" 41 | 42 | - name: Cache dependencies 43 | uses: actions/cache@v2 44 | with: 45 | path: ${{ steps.composer-cache.outputs.dir }} 46 | key: composer-${{ hashFiles('**/composer.lock') }} 47 | restore-keys: composer- 48 | - name: Install dependencies 49 | run: composer install --prefer-dist 50 | 51 | 52 | - name: 'Run phpunit/phpunit' 53 | run: 'vendor/bin/phpunit' -------------------------------------------------------------------------------- /src/Webpay/Oneclick/Responses/MallTransactionCaptureResponse.php: -------------------------------------------------------------------------------- 1 | setAuthorizationCode(isset($json['authorization_code']) ? $json['authorization_code'] : null); 15 | $this->setAuthorizationDate(isset($json['authorization_date']) ? $json['authorization_date'] : null); 16 | $this->setCapturedAmount(isset($json['captured_amount']) ? $json['captured_amount'] : null); 17 | $this->setResponseCode(isset($json['response_code']) ? $json['response_code'] : null); 18 | } 19 | 20 | public function getAuthorizationCode() 21 | { 22 | return $this->authorizationCode; 23 | } 24 | 25 | public function setAuthorizationCode($authorizationCode) 26 | { 27 | $this->authorizationCode = $authorizationCode; 28 | 29 | return $this; 30 | } 31 | 32 | public function getAuthorizationDate() 33 | { 34 | return $this->authorizationDate; 35 | } 36 | 37 | public function setAuthorizationDate($authorizationDate) 38 | { 39 | $this->authorizationDate = $authorizationDate; 40 | 41 | return $this; 42 | } 43 | 44 | public function getCapturedAmount() 45 | { 46 | return $this->capturedAmount; 47 | } 48 | 49 | public function setCapturedAmount($capturedAmount) 50 | { 51 | $this->capturedAmount = $capturedAmount; 52 | 53 | return $this; 54 | } 55 | 56 | public function getResponseCode() 57 | { 58 | return $this->responseCode; 59 | } 60 | 61 | public function setResponseCode($responseCode) 62 | { 63 | $this->responseCode = $responseCode; 64 | 65 | return $this; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Onepay/Refund.php: -------------------------------------------------------------------------------- 1 | buildRefundRequest( 28 | $amount, 29 | $occ, 30 | $externalUniqueNumber, 31 | $authorizationCode, 32 | $options 33 | ); 34 | $jsonRequest = json_encode($request, JSON_UNESCAPED_SLASHES); 35 | $http = new HttpClient(); 36 | $path = self::TRANSACTION_BASE_PATH.self::REFUND_TRANSACTION; 37 | 38 | $httpResponse = $http->request( 39 | 'POST', 40 | OnepayBase::getCurrentIntegrationTypeUrl().$path, 41 | $jsonRequest 42 | ); 43 | 44 | $httpCode = $httpResponse->getStatusCode(); 45 | $responseJson = json_decode($httpResponse->getBody(), true); 46 | 47 | if ($httpCode != 200 && $httpCode != 204) { 48 | throw new RefundCreateException('Could not obtain the service response'); 49 | } 50 | $refundCreateResponse = new RefundCreateResponse($responseJson); 51 | if (strtolower($responseJson['responseCode']) != 'ok') { 52 | $msg = $responseJson['responseCode'].' : '.$responseJson['description']; 53 | 54 | throw new RefundCreateException($msg, -1); 55 | } 56 | 57 | return $refundCreateResponse; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/TransaccionCompleta/Responses/MallTransactionStatusResponse.php: -------------------------------------------------------------------------------- 1 | buyOrder = $json['buy_order'] ?? null; 18 | $this->cardDetail = $json['card_detail'] ?? null; 19 | $this->cardNumber = $json['card_detail']['card_number'] ?? null; 20 | $this->accountingDate = $json['accounting_date'] ?? null; 21 | $this->transactionDate = $json['transaction_date'] ?? null; 22 | $details = $json['details'] ?? null; 23 | 24 | $this->details = null; 25 | if (is_array($details)) { 26 | $this->details = []; 27 | foreach ($details as $detail) { 28 | $this->details[] = TransactionDetail::createFromArray($detail); 29 | } 30 | } 31 | } 32 | 33 | /** 34 | * @return mixed 35 | */ 36 | public function getBuyOrder() 37 | { 38 | return $this->buyOrder; 39 | } 40 | 41 | /** 42 | * @return mixed 43 | */ 44 | public function getCardDetail() 45 | { 46 | return $this->cardDetail; 47 | } 48 | 49 | /** 50 | * @return mixed 51 | */ 52 | public function getAccountingDate() 53 | { 54 | return $this->accountingDate; 55 | } 56 | 57 | /** 58 | * @return mixed 59 | */ 60 | public function getTransactionDate() 61 | { 62 | return $this->transactionDate; 63 | } 64 | 65 | /** 66 | * @return mixed 67 | */ 68 | public function getDetails() 69 | { 70 | return $this->details; 71 | } 72 | 73 | /** 74 | * @return mixed|null 75 | */ 76 | public function getCardNumber() 77 | { 78 | return $this->cardNumber; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/TransaccionCompleta/Responses/MallTransactionInstallmentsResponse.php: -------------------------------------------------------------------------------- 1 | setInstallmentsAmount($installmentsAmount); 17 | $idQueryInstallments = Utils::returnValueIfExists($json, 'id_query_installments'); 18 | $this->setIdQueryInstallments($idQueryInstallments); 19 | $deferredPeriods = Utils::returnValueIfExists($json, 'deferred_periods'); 20 | $this->setDeferredPeriods($deferredPeriods); 21 | } 22 | 23 | /** 24 | * @return mixed 25 | */ 26 | public function getInstallmentsAmount() 27 | { 28 | return $this->installmentsAmount; 29 | } 30 | 31 | /** 32 | * @param mixed $installmentsAmount 33 | */ 34 | public function setInstallmentsAmount($installmentsAmount) 35 | { 36 | $this->installmentsAmount = $installmentsAmount; 37 | 38 | return $this; 39 | } 40 | 41 | /** 42 | * @return mixed 43 | */ 44 | public function getIdQueryInstallments() 45 | { 46 | return $this->idQueryInstallments; 47 | } 48 | 49 | /** 50 | * @param mixed $idQueryInstallments 51 | */ 52 | public function setIdQueryInstallments($idQueryInstallments) 53 | { 54 | $this->idQueryInstallments = $idQueryInstallments; 55 | 56 | return $this; 57 | } 58 | 59 | /** 60 | * @return mixed 61 | */ 62 | public function getDeferredPeriods() 63 | { 64 | return $this->deferredPeriods; 65 | } 66 | 67 | /** 68 | * @param mixed $deferredPeriods 69 | */ 70 | public function setDeferredPeriods($deferredPeriods) 71 | { 72 | $this->deferredPeriods = $deferredPeriods; 73 | 74 | return $this; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Webpay/WebpayPlus/Responses/TransactionCreateResponse.php: -------------------------------------------------------------------------------- 1 | fromJSON($json); 29 | } 30 | 31 | /** 32 | * @param array $json an associative array with keys 'token', 'url' 33 | * + token (string, required) - the token returned from a successful call 34 | * to 'create' 35 | * + url (string, required) - the url returned from a successful call to 36 | * 'create' 37 | * 38 | * @return $this 39 | */ 40 | public function fromJSON($json) 41 | { 42 | $this->setToken($json['token']); 43 | $this->setUrl($json['url']); 44 | 45 | return $this; 46 | } 47 | 48 | /** 49 | * @return string|null 50 | */ 51 | public function getToken() 52 | { 53 | return $this->token; 54 | } 55 | 56 | /** 57 | * @param string|null $token 58 | * 59 | * @return TransactionCreateResponse 60 | */ 61 | public function setToken($token) 62 | { 63 | $this->token = $token; 64 | 65 | return $this; 66 | } 67 | 68 | /** 69 | * @return string|null 70 | */ 71 | public function getUrl() 72 | { 73 | return $this->url; 74 | } 75 | 76 | /** 77 | * @param string|null $url 78 | * 79 | * @return TransactionCreateResponse 80 | */ 81 | public function setUrl($url) 82 | { 83 | $this->url = $url; 84 | 85 | return $this; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/TransaccionCompleta/Responses/TransactionInstallmentsResponse.php: -------------------------------------------------------------------------------- 1 | setInstallmentsAmount($installmentsAmount); 17 | $idQueryInstallments = Utils::returnValueIfExists($json, 'id_query_installments'); 18 | $this->setIdQueryInstallments($idQueryInstallments); 19 | $deferredPeriods = Utils::returnValueIfExists($json, 'deferred_periods'); 20 | $this->setDeferredPeriods($deferredPeriods); 21 | } 22 | 23 | /** 24 | * @return mixed 25 | */ 26 | public function getInstallmentsAmount() 27 | { 28 | return $this->installmentsAmount; 29 | } 30 | 31 | /** 32 | * @param mixed $installmentsAmount 33 | * 34 | * @return TransactionInstallmentsResponse 35 | */ 36 | public function setInstallmentsAmount($installmentsAmount) 37 | { 38 | $this->installmentsAmount = $installmentsAmount; 39 | 40 | return $this; 41 | } 42 | 43 | /** 44 | * @return mixed 45 | */ 46 | public function getIdQueryInstallments() 47 | { 48 | return $this->idQueryInstallments; 49 | } 50 | 51 | /** 52 | * @param mixed $idQueryInstallments 53 | * 54 | * @return TransactionInstallmentsResponse 55 | */ 56 | public function setIdQueryInstallments($idQueryInstallments) 57 | { 58 | $this->idQueryInstallments = $idQueryInstallments; 59 | 60 | return $this; 61 | } 62 | 63 | /** 64 | * @return mixed 65 | */ 66 | public function getDeferredPeriods() 67 | { 68 | return $this->deferredPeriods; 69 | } 70 | 71 | /** 72 | * @param mixed $deferredPeriods 73 | * 74 | * @return TransactionInstallmentsResponse 75 | */ 76 | public function setDeferredPeriods($deferredPeriods) 77 | { 78 | $this->deferredPeriods = $deferredPeriods; 79 | 80 | return $this; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Onepay/TransactionCommitRequest.php: -------------------------------------------------------------------------------- 1 | occ = $occ; 22 | $this->externalUniqueNumber = $externalUniqueNumber; 23 | $this->issuedAt = $issuedAt; 24 | } 25 | 26 | public function jsonSerialize() 27 | { 28 | return get_object_vars($this); 29 | } 30 | 31 | public function getOcc() 32 | { 33 | return $this->occ; 34 | } 35 | 36 | public function setOcc($occ) 37 | { 38 | if (!$occ) { 39 | throw new \Exception('Occ cannot be set to null.'); 40 | } 41 | 42 | $this->occ = $occ; 43 | 44 | return $this; 45 | } 46 | 47 | public function getExternalUniqueNumber() 48 | { 49 | return $this->externalUniqueNumber; 50 | } 51 | 52 | public function setExternalUniqueNumber($externalUniqueNumber) 53 | { 54 | if (!$externalUniqueNumber) { 55 | throw new \Exception('externalUniqueNumber cannot be null.'); 56 | } 57 | $this->externalUniqueNumber = $externalUniqueNumber; 58 | 59 | return $this; 60 | } 61 | 62 | public function getIssuedAt() 63 | { 64 | return $this->issuedAt; 65 | } 66 | 67 | public function setIssuedAt($issuedAt) 68 | { 69 | if (!$issuedAt) { 70 | throw new \Exception('issuedAt cannot be null.'); 71 | } 72 | $this->issuedAt = $issuedAt; 73 | 74 | return $this; 75 | } 76 | 77 | public function getSignature() 78 | { 79 | return $this->signature; 80 | } 81 | 82 | public function setSignature($signature) 83 | { 84 | $this->signature = $signature; 85 | 86 | return $this; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /examples/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | Ejemplo 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |

SDK PHP 2.0 Proyecto de ejemplo

17 | 18 |
19 |
20 | Transbank Developers 21 |
22 | 23 |
24 |
25 |
26 | 27 |
28 |
29 | 30 |

31 | cd /path/to/transbank-sdk-php
32 | cd examples
33 | php -S 127.0.0.1:8000
34 |             
35 |
36 |

Puedes iniciar este ejemplo usando el servidor web de PHP.

En tu terminal, debes entrar a esta carpeta 37 | examples e iniciar el servidor de PHP.

38 | 39 |

Ahora entra a http://127.0.0.1:8000 para ejecutar el código de ejemplo.

40 |
41 |
42 |
43 | 44 |

Ejemplos

45 | 46 |
47 | Webpay Plus 48 | 49 | Transacción Completa 50 |
51 |
52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /tests/RequestServiceTest.php: -------------------------------------------------------------------------------- 1 | 'commerce_code', 'api_secret' => 'fakeApiKey']; 15 | 16 | $optionsMock = $this->createMock(Options::class); 17 | $optionsMock 18 | ->expects($this->once()) 19 | ->method('getHeaders') 20 | ->willReturn($expectedHeaders); 21 | 22 | $httpClientMock = $this->createMock(HttpClient::class); 23 | $httpClientMock 24 | ->expects($this->once()) 25 | ->method('request') 26 | ->with($this->anything(), $this->anything(), $this->anything(), $this->equalTo([ 27 | 'headers' => $expectedHeaders, 28 | ])) 29 | ->willReturn( 30 | new Response(200, [], json_encode([ 31 | 'token' => 'mock', 32 | 'url' => 'http://mock.cl/', 33 | ])) 34 | ); 35 | 36 | $request = (new HttpClientRequestService($httpClientMock))->request('POST', '/transactions', [], $optionsMock); 37 | } 38 | 39 | /** @test */ 40 | public function it_uses_the_base_url_provided_by_the_given_options() 41 | { 42 | $expectedBaseUrl = 'http://mock.mock/'; 43 | $endpoint = '/transactions'; 44 | 45 | $optionsMock = $this->createMock(Options::class); 46 | $optionsMock 47 | ->expects($this->once()) 48 | ->method('getApiBaseUrl') 49 | ->willReturn($expectedBaseUrl); 50 | 51 | $httpClientMock = $this->createMock(HttpClient::class); 52 | $httpClientMock 53 | ->expects($this->once()) 54 | ->method('request') 55 | ->with($this->anything(), $expectedBaseUrl.$endpoint, $this->anything()) 56 | ->willReturn( 57 | new Response(200, [], json_encode([ 58 | 'token' => 'mock', 59 | 'url' => 'http://mock.cl/', 60 | ])) 61 | ); 62 | 63 | $request = (new HttpClientRequestService($httpClientMock)) 64 | ->request('POST', $endpoint, [], $optionsMock); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/RefundTest.php: -------------------------------------------------------------------------------- 1 | externalUniqueNumber = '1532376544050'; 15 | $this->occ = '1807829988419927'; 16 | $this->authorizationCode = '497490'; 17 | } 18 | 19 | public function testRefundWithOptionsWorks() 20 | { 21 | $apiKey = OnepayBase::getApiKey(); 22 | $sharedSecret = OnepayBase::getSharedSecret(); 23 | $options = new Options($apiKey, $sharedSecret); 24 | 25 | $httpResponse = Refund::create( 26 | 27500, 27 | $this->occ, 28 | $this->externalUniqueNumber, 29 | $this->authorizationCode, 30 | $options 31 | ); 32 | $this->assertEquals($httpResponse->getResponseCode(), 'OK'); 33 | $this->assertEquals($httpResponse->getDescription(), 'OK'); 34 | } 35 | 36 | public function testRefundWithoutOptionsWorks() 37 | { 38 | $apiKey = OnepayBase::getApiKey(); 39 | $sharedSecret = OnepayBase::getSharedSecret(); 40 | 41 | $httpResponse = Refund::create( 42 | 27500, 43 | $this->occ, 44 | $this->externalUniqueNumber, 45 | $this->authorizationCode 46 | ); 47 | $this->assertEquals($httpResponse->getResponseCode(), 'OK'); 48 | $this->assertEquals($httpResponse->getDescription(), 'OK'); 49 | } 50 | 51 | public function testRefundRaisesExceptionWhenInvalid() 52 | { 53 | $apiKey = OnepayBase::getApiKey(); 54 | $sharedSecret = OnepayBase::getSharedSecret(); 55 | $options = new Options($apiKey, $sharedSecret); 56 | 57 | // It should raise an exception when failing 58 | $this->expectException(\Transbank\Onepay\Exceptions\RefundCreateException::class); 59 | $httpResponse = Refund::create( 60 | 27500, 61 | 'INVALID OCC', 62 | '12345someextuniqnum', 63 | 'f506a955-800c-4185-8818-4ef9fca97aae', 64 | $options 65 | ); 66 | 67 | $this->assertEquals($httpResponse->getResponseCode(), 'INVALID_PARAMS'); 68 | $this->assertEquals($httpResponse->getDescription(), 'Parametros invalidos'); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/OptionsTest.php: -------------------------------------------------------------------------------- 1 | assertSame($options->getApiKey(), 'a'); 13 | $this->assertSame($options->getCommerceCode(), 'b'); 14 | $this->assertSame($options->getIntegrationType(), 'c'); 15 | } 16 | 17 | /** @test */ 18 | public function it_returns_the_right_headers_based_on_configuration() 19 | { 20 | $options = new Options('ApiKey', 'CommerceCode', 'TEST'); 21 | $this->assertSame($options->getHeaders(), [ 22 | 'Tbk-Api-Key-Id' => 'CommerceCode', 23 | 'Tbk-Api-Key-Secret' => 'ApiKey', 24 | ]); 25 | } 26 | 27 | public function it_creates_an_option_using_static_factory_method_for_integration_credentials() 28 | { 29 | $options = Options::forIntegration('commerceCode', 'ApiKey'); 30 | $this->assertSame($options->getCommerceCode(), 'commerceCode'); 31 | $this->assertSame($options->getApiKey(), 'ApiKey'); 32 | $this->assertSame($options->getIntegrationType(), Options::ENVIRONMENT_INTEGRATION); 33 | } 34 | 35 | public function it_creates_an_option_using_static_factory_method_for_production_credentials() 36 | { 37 | $options = Options::forProduction('commerceCode', 'ApiKey'); 38 | $this->assertSame($options->getCommerceCode(), 'commerceCode'); 39 | $this->assertSame($options->getApiKey(), 'ApiKey'); 40 | $this->assertSame($options->getIntegrationType(), Options::ENVIRONMENT_PRODUCTION); 41 | } 42 | 43 | /** @test */ 44 | public function it_check_if_the_current_object_represent_production_credentials() 45 | { 46 | $options = Options::forProduction('CommerceCode', 'ApiKey'); 47 | $this->assertTrue($options->isProduction()); 48 | } 49 | 50 | /** @test */ 51 | public function it_return_the_correct_base_url_for_production_credentials() 52 | { 53 | $options = Options::forProduction('CommerceCode', 'ApiKey'); 54 | $this->assertSame(Options::BASE_URL_PRODUCTION, $options->getApiBaseUrl()); 55 | } 56 | 57 | /** @test */ 58 | public function it_return_the_correct_base_url_for_integration_credentials() 59 | { 60 | $options = Options::forIntegration('CommerceCode', 'ApiKey'); 61 | $this->assertSame(Options::BASE_URL_INTEGRATION, $options->getApiBaseUrl()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tests/Mocks/TransactionCreateResponseMocks.php: -------------------------------------------------------------------------------- 1 | nullifyAmount = $nullifyAmount; 27 | 28 | $this->occ = $occ; 29 | $this->externalUniqueNumber = $externalUniqueNumber; 30 | $this->authorizationCode = $authorizationCode; 31 | $this->issuedAt = $issuedAt; 32 | $this->signature = $signature; 33 | } 34 | 35 | public function jsonSerialize() 36 | { 37 | return get_object_vars($this); 38 | } 39 | 40 | public function getnullifyAmount() 41 | { 42 | return $this->nullifyAmount; 43 | } 44 | 45 | public function setnullifyAmount($nullifyAmount) 46 | { 47 | $this->nullifyAmount = $nullifyAmount; 48 | 49 | return $this; 50 | } 51 | 52 | public function getOcc() 53 | { 54 | return $this->occ; 55 | } 56 | 57 | public function setOcc($occ) 58 | { 59 | $this->occ = $occ; 60 | 61 | return $this; 62 | } 63 | 64 | public function getExternalUniqueNumber() 65 | { 66 | return $this->externalUniqueNumber; 67 | } 68 | 69 | public function setExternalUniqueNumber($externalUniqueNumber) 70 | { 71 | $this->externalUniqueNumber = $externalUniqueNumber; 72 | 73 | return $this; 74 | } 75 | 76 | public function getAuthorizationCode() 77 | { 78 | return $this->authorizationCode; 79 | } 80 | 81 | public function setAuthorizationCode($authorizationCode) 82 | { 83 | $this->authorizationCode = $authorizationCode; 84 | 85 | return $this; 86 | } 87 | 88 | public function getIssuedAt() 89 | { 90 | return $this->issuedAt; 91 | } 92 | 93 | public function setIssuedAt($issuedAt) 94 | { 95 | $this->issuedAt = $issuedAt; 96 | 97 | return $this; 98 | } 99 | 100 | public function getSignature() 101 | { 102 | return $this->signature; 103 | } 104 | 105 | public function setSignature($signature) 106 | { 107 | $this->signature = $signature; 108 | 109 | return $this; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Onepay/RefundCreateResponse.php: -------------------------------------------------------------------------------- 1 | fromJSON($json); 20 | } 21 | 22 | public function jsonSerialize() 23 | { 24 | return get_object_vars($this); 25 | } 26 | 27 | public function getOcc() 28 | { 29 | return $this->occ; 30 | } 31 | 32 | public function setOcc($occ) 33 | { 34 | $this->occ = $occ; 35 | 36 | return $this; 37 | } 38 | 39 | public function getExternalUniqueNumber() 40 | { 41 | return $this->externalUniqueNumber; 42 | } 43 | 44 | public function setExternalUniqueNumber($externalUniqueNumber) 45 | { 46 | $this->externalUniqueNumber = $externalUniqueNumber; 47 | 48 | return $this; 49 | } 50 | 51 | public function getReverseCode() 52 | { 53 | return $this->reverseCode; 54 | } 55 | 56 | public function setReverseCode($reverseCode) 57 | { 58 | $this->reverseCode = $reverseCode; 59 | 60 | return $this; 61 | } 62 | 63 | public function getIssuedAt() 64 | { 65 | return $this->issuedAt; 66 | } 67 | 68 | public function setIssuedAt($issuedAt) 69 | { 70 | $this->issuedAt = $issuedAt; 71 | 72 | return $this; 73 | } 74 | 75 | public function getSignature() 76 | { 77 | return $this->signature; 78 | } 79 | 80 | public function setSignature($signature) 81 | { 82 | $this->signature = $signature; 83 | 84 | return $this; 85 | } 86 | 87 | public function fromJSON($json) 88 | { 89 | if (is_string($json)) { 90 | $json = json_decode($json, true); 91 | } 92 | if (!is_array($json)) { 93 | throw new \Exception('Given value must be an associative array or a string that can be converted to an associative array with json_decode()'); 94 | } 95 | 96 | $this->setResponseCode($json['responseCode']); 97 | $this->setDescription($json['description']); 98 | if ($json['result']) { 99 | $this->setOcc($json['result']['occ']); 100 | $this->setExternalUniqueNumber($json['result']['externalUniqueNumber']); 101 | $this->setReverseCode($json['result']['reverseCode']); 102 | $this->setIssuedAt($json['result']['issuedAt']); 103 | $this->setSignature($json['result']['signature']); 104 | } 105 | 106 | return $this; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Utils/HttpClient.php: -------------------------------------------------------------------------------- 1 | 'application/json', 36 | 'User-Agent' => 'SDK-PHP/'.$installedVersion, 37 | ]; 38 | 39 | $givenHeaders = isset($options['headers']) ? $options['headers'] : []; 40 | $headers = array_merge($baseHeaders, $givenHeaders); 41 | if (!$payload) { 42 | $payload = null; 43 | } 44 | if (is_array($payload)) { 45 | $payload = json_encode($payload); 46 | } 47 | 48 | if (defined('\GuzzleHttp\Client::VERSION') && version_compare(Client::VERSION, '6', '<')) { 49 | return $this->sendGuzzle5Request($method, $url, $headers, $payload); 50 | } 51 | 52 | return $this->sendGuzzleRequest($method, $url, $headers, $payload); 53 | } 54 | 55 | /** 56 | * @param $method 57 | * @param $url 58 | * @param array $headers 59 | * @param array $payload 60 | * 61 | * @throws \GuzzleHttp\Exception\GuzzleException 62 | * 63 | * @return \Psr\Http\Message\ResponseInterface 64 | */ 65 | protected function sendGuzzle5Request($method, $url, array $headers, $payload) 66 | { 67 | $client = new Client(); 68 | 69 | $request = $client->createRequest($method, $url, [ 70 | 'headers' => $headers, 71 | 'body' => $payload, 72 | ]); 73 | 74 | return $client->send($request); 75 | } 76 | 77 | /** 78 | * @param $method 79 | * @param $url 80 | * @param array $headers 81 | * @param string|null $payload 82 | * 83 | * @throws \GuzzleHttp\Exception\GuzzleException 84 | * 85 | * @return \Psr\Http\Message\ResponseInterface 86 | */ 87 | protected function sendGuzzleRequest($method, $url, array $headers, $payload) 88 | { 89 | $request = new Request($method, $url, $headers, $payload); 90 | 91 | $client = new Client(['http_errors' => false]); 92 | 93 | return $client->send($request); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /tests/Webpay/Modal/TransbankWebpayModalTest.php: -------------------------------------------------------------------------------- 1 | create(1500, 'BuyOrder1', 'Session2312'); 17 | $this->assertInstanceOf(\Transbank\Webpay\Modal\Responses\TransactionCreateResponse::class, $response); 18 | $this->assertNotEmpty($response->getToken()); 19 | } 20 | 21 | /** @test */ 22 | public function it_creates_a_modal_transaction_without_givin_a_session_id() 23 | { 24 | $response = (new Transaction())->create(1500, 'BuyOrder1'); 25 | $this->assertInstanceOf(\Transbank\Webpay\Modal\Responses\TransactionCreateResponse::class, $response); 26 | $this->assertNotEmpty($response->getToken()); 27 | } 28 | 29 | /** @test */ 30 | public function it_fails_when_creates_a_modal_transaction_with_invalid_data() 31 | { 32 | $this->expectException(TransactionCreateException::class); 33 | $response = (new Transaction())->create('hola', ''); 34 | } 35 | 36 | /** @test */ 37 | public function it_get_the_status_of_a_transction() 38 | { 39 | $response = (new Transaction())->create(1500, 'BuyOrder1', 'Session2312'); 40 | $status = Transaction::build()->status($response->getToken()); 41 | $this->assertInstanceOf(TransactionStatusResponse::class, $status); 42 | $this->assertEquals($status->getStatus(), 'INITIALIZED'); 43 | } 44 | 45 | /** @test */ 46 | public function it_fails_when_using_invalid_credentials() 47 | { 48 | $this->expectException(TransactionCreateException::class, 'Not Authorized'); 49 | $transaction = new Transaction(Options::forIntegration('commerceCode', 'fakeApiKey')); 50 | $response = $transaction->create(1500, 'BuyOrder1', 'Session2312'); 51 | } 52 | 53 | /** @test */ 54 | public function it_cannot_commit_a_recently_created_transaction() 55 | { 56 | WebpayModal::configureForTesting(); 57 | $this->expectException(TransactionCommitException::class, "Invalid status '0' for transaction while authorizing"); 58 | $response = (new Transaction())->create(1500, 'BuyOrder1', 'Session2312'); 59 | $response = Transaction::build()->commit($response->getToken()); 60 | } 61 | 62 | /** @test */ 63 | public function it_cannot_refund_a_recently_created_transaction() 64 | { 65 | $this->expectException(TransactionRefundException::class, 'Transaction is unfinished, it is not possible to refund it yet'); 66 | $response = (new Transaction())->create(1500, 'BuyOrder1', 'Session2312'); 67 | $response = Transaction::build()->refund($response->getToken(), 1500); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Patpass/PatpassByWebpay/Transaction.php: -------------------------------------------------------------------------------- 1 | $buyOrder, 30 | 'session_id' => $sessionId, 31 | 'amount' => $amount, 32 | 'return_url' => $returnUrl, 33 | 'wpm_detail' => $details, 34 | ]; 35 | $endpoint = static::CREATE_TRANSACTION_ENDPOINT; 36 | 37 | try { 38 | $response = $this->sendRequest('POST', $endpoint, $payload); 39 | } catch (WebpayRequestException $exception) { 40 | throw TransactionCreateException::raise($exception); 41 | } 42 | 43 | return new TransactionCreateResponse($response); 44 | } 45 | 46 | public function commit($token) 47 | { 48 | $payload = []; 49 | $endpoint = static::COMMIT_TRANSACTION_ENDPOINT; 50 | 51 | try { 52 | $response = $this->sendRequest('PUT', $endpoint, $payload); 53 | } catch (WebpayRequestException $exception) { 54 | throw TransactionCommitException::raise($exception); 55 | } 56 | 57 | return new TransactionCommitResponse($response); 58 | } 59 | 60 | public function status($token) 61 | { 62 | $payload = []; 63 | $endpoint = str_replace('{token}', $token, self::GET_TRANSACTION_STATUS_ENDPOINT); 64 | 65 | try { 66 | $response = $this->sendRequest('GET', $endpoint, $payload); 67 | } catch (WebpayRequestException $exception) { 68 | throw TransactionStatusException::raise($exception); 69 | } 70 | 71 | return new TransactionStatusResponse($response); 72 | } 73 | 74 | /** 75 | * Get the default options if none are given. 76 | * 77 | * @return Options|null 78 | */ 79 | public static function getGlobalOptions() 80 | { 81 | return PatpassByWebpay::getOptions(); 82 | } 83 | 84 | public static function getDefaultOptions() 85 | { 86 | return PatpassByWebpay::getDefaultOptions(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Onepay/TransactionCreateResponse.php: -------------------------------------------------------------------------------- 1 | fromJSON($json); 22 | } 23 | 24 | public function jsonSerialize() 25 | { 26 | return get_object_vars($this); 27 | } 28 | 29 | public function fromJSON($json) 30 | { 31 | if (is_string($json)) { 32 | $json = json_decode($json, true); 33 | } 34 | if (!is_array($json)) { 35 | throw new \Exception('Given value must be an associative array or a string that can be converted to an associative array with json_decode()'); 36 | } 37 | $this->setResponseCode($json['responseCode']); 38 | $this->setDescription($json['description']); 39 | $this->setOcc($json['result']['occ']); 40 | $this->setOtt($json['result']['ott']); 41 | $this->setExternalUniqueNumber($json['result']['externalUniqueNumber']); 42 | $this->setQrCodeAsBase64($json['result']['qrCodeAsBase64']); 43 | $this->setIssuedAt($json['result']['issuedAt']); 44 | $this->setSignature($json['result']['signature']); 45 | 46 | return $this; 47 | } 48 | 49 | public function getOcc() 50 | { 51 | return $this->occ; 52 | } 53 | 54 | public function setOcc($occ) 55 | { 56 | $this->occ = $occ; 57 | 58 | return $this; 59 | } 60 | 61 | public function getOtt() 62 | { 63 | return $this->ott; 64 | } 65 | 66 | public function setOtt($ott) 67 | { 68 | $this->ott = $ott; 69 | 70 | return $this; 71 | } 72 | 73 | public function getExternalUniqueNumber() 74 | { 75 | return $this->externalUniqueNumber; 76 | } 77 | 78 | public function setExternalUniqueNumber($externalUniqueNumber) 79 | { 80 | $this->externalUniqueNumber = $externalUniqueNumber; 81 | 82 | return $this; 83 | } 84 | 85 | public function getQrCodeAsBase64() 86 | { 87 | return $this->qrCodeAsBase64; 88 | } 89 | 90 | public function setQrCodeAsBase64($qrCodeAsBase64) 91 | { 92 | $this->qrCodeAsBase64 = $qrCodeAsBase64; 93 | 94 | return $this; 95 | } 96 | 97 | public function getIssuedAt() 98 | { 99 | return $this->issuedAt; 100 | } 101 | 102 | public function setIssuedAt($issuedAt) 103 | { 104 | $this->issuedAt = $issuedAt; 105 | 106 | return $this; 107 | } 108 | 109 | public function getSignature() 110 | { 111 | return $this->signature; 112 | } 113 | 114 | public function setSignature($signature) 115 | { 116 | $this->signature = $signature; 117 | 118 | return $this; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/Webpay/Oneclick/Responses/InscriptionFinishResponse.php: -------------------------------------------------------------------------------- 1 | setResponseCode($responseCode); 19 | 20 | $tbkUser = isset($json['tbk_user']) ? $json['tbk_user'] : null; 21 | $this->setTbkUser($tbkUser); 22 | 23 | $authorizationCode = isset($json['authorization_code']) ? $json['authorization_code'] : null; 24 | $this->setAuthorizationCode($authorizationCode); 25 | 26 | $cardType = isset($json['card_type']) ? $json['card_type'] : null; 27 | $this->setCardType($cardType); 28 | 29 | $cardNumber = isset($json['card_number']) ? $json['card_number'] : null; 30 | $this->setCardNumber($cardNumber); 31 | } 32 | 33 | public function isApproved() 34 | { 35 | return $this->getResponseCode() === ResponseCodesEnum::RESPONSE_CODE_APPROVED; 36 | } 37 | 38 | /** 39 | * @return mixed 40 | */ 41 | public function getResponseCode() 42 | { 43 | return (int) $this->responseCode; 44 | } 45 | 46 | /** 47 | * @param mixed $responseCode 48 | * 49 | * @return InscriptionFinishResponse 50 | */ 51 | public function setResponseCode($responseCode) 52 | { 53 | $this->responseCode = $responseCode; 54 | 55 | return $this; 56 | } 57 | 58 | /** 59 | * @return mixed 60 | */ 61 | public function getTbkUser() 62 | { 63 | return $this->tbkUser; 64 | } 65 | 66 | /** 67 | * @param mixed $tbkUser 68 | * 69 | * @return InscriptionFinishResponse 70 | */ 71 | public function setTbkUser($tbkUser) 72 | { 73 | $this->tbkUser = $tbkUser; 74 | 75 | return $this; 76 | } 77 | 78 | /** 79 | * @return mixed 80 | */ 81 | public function getAuthorizationCode() 82 | { 83 | return $this->authorizationCode; 84 | } 85 | 86 | /** 87 | * @param mixed $authorizationCode 88 | * 89 | * @return InscriptionFinishResponse 90 | */ 91 | public function setAuthorizationCode($authorizationCode) 92 | { 93 | $this->authorizationCode = $authorizationCode; 94 | 95 | return $this; 96 | } 97 | 98 | /** 99 | * @return mixed 100 | */ 101 | public function getCardType() 102 | { 103 | return $this->cardType; 104 | } 105 | 106 | /** 107 | * @param mixed $cardType 108 | * 109 | * @return InscriptionFinishResponse 110 | */ 111 | public function setCardType($cardType) 112 | { 113 | $this->cardType = $cardType; 114 | 115 | return $this; 116 | } 117 | 118 | /** 119 | * @return mixed 120 | */ 121 | public function getCardNumber() 122 | { 123 | return $this->cardNumber; 124 | } 125 | 126 | /** 127 | * @param mixed $cardNumber 128 | * 129 | * @return InscriptionFinishResponse 130 | */ 131 | public function setCardNumber($cardNumber) 132 | { 133 | $this->cardNumber = $cardNumber; 134 | 135 | return $this; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/Webpay/WebpayPlus/Responses/TransactionCaptureResponse.php: -------------------------------------------------------------------------------- 1 | token = isset($json['token']) ? $json['token'] : null; 23 | $this->authorizationCode = isset($json['authorization_code']) ? $json['authorization_code'] : null; 24 | $this->authorizationDate = isset($json['authorization_date']) ? $json['authorization_date'] : null; 25 | $this->capturedAmount = isset($json['captured_amount']) ? $json['captured_amount'] : null; 26 | $this->responseCode = isset($json['response_code']) ? $json['response_code'] : null; 27 | } 28 | 29 | public function isApproved() 30 | { 31 | return $this->responseCode === ResponseCodesEnum::RESPONSE_CODE_APPROVED; 32 | } 33 | 34 | /** 35 | * @return mixed 36 | */ 37 | public function getToken() 38 | { 39 | return $this->token; 40 | } 41 | 42 | /** 43 | * @param mixed $token 44 | * 45 | * @return TransactionCaptureResponse 46 | */ 47 | public function setToken($token) 48 | { 49 | $this->token = $token; 50 | 51 | return $this; 52 | } 53 | 54 | /** 55 | * @return mixed 56 | */ 57 | public function getAuthorizationCode() 58 | { 59 | return $this->authorizationCode; 60 | } 61 | 62 | /** 63 | * @param mixed $authorizationCode 64 | * 65 | * @return TransactionCaptureResponse 66 | */ 67 | public function setAuthorizationCode($authorizationCode) 68 | { 69 | $this->authorizationCode = $authorizationCode; 70 | 71 | return $this; 72 | } 73 | 74 | /** 75 | * @return mixed 76 | */ 77 | public function getAuthorizationDate() 78 | { 79 | return $this->authorizationDate; 80 | } 81 | 82 | /** 83 | * @param mixed $authorizationDate 84 | * 85 | * @return TransactionCaptureResponse 86 | */ 87 | public function setAuthorizationDate($authorizationDate) 88 | { 89 | $this->authorizationDate = $authorizationDate; 90 | 91 | return $this; 92 | } 93 | 94 | /** 95 | * @return mixed 96 | */ 97 | public function getCapturedAmount() 98 | { 99 | return $this->capturedAmount; 100 | } 101 | 102 | /** 103 | * @param mixed $capturedAmount 104 | * 105 | * @return TransactionCaptureResponse 106 | */ 107 | public function setCapturedAmount($capturedAmount) 108 | { 109 | $this->capturedAmount = $capturedAmount; 110 | 111 | return $this; 112 | } 113 | 114 | /** 115 | * @return mixed 116 | */ 117 | public function getResponseCode() 118 | { 119 | return $this->responseCode; 120 | } 121 | 122 | /** 123 | * @param mixed $responseCode 124 | * 125 | * @return TransactionCaptureResponse 126 | */ 127 | public function setResponseCode($responseCode) 128 | { 129 | $this->responseCode = $responseCode; 130 | 131 | return $this; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/Webpay/WebpayPlus.php: -------------------------------------------------------------------------------- 1 | getExceptionMessage($message, $tbkErrorMessage, $httpCode, $failedRequest); 51 | } 52 | 53 | $this->message = $theMessage; 54 | $this->transbankErrorMessage = $tbkErrorMessage; 55 | $this->httpCode = $httpCode; 56 | $this->failedRequest = $failedRequest; 57 | 58 | parent::__construct($theMessage, $httpCode); 59 | } 60 | 61 | /** 62 | * @return mixed 63 | */ 64 | public function getTransbankErrorMessage() 65 | { 66 | return $this->transbankErrorMessage; 67 | } 68 | 69 | /** 70 | * @param WebpayRequestException $exception 71 | * 72 | * @return static 73 | */ 74 | public static function raise(WebpayRequestException $exception) 75 | { 76 | return new static($exception->getMessage(), $exception->getTransbankErrorMessage(), $exception->getHttpCode(), 77 | $exception->getFailedRequest()); 78 | } 79 | 80 | /** 81 | * @return int 82 | */ 83 | public function getHttpCode() 84 | { 85 | return $this->httpCode; 86 | } 87 | 88 | /** 89 | * @return TransbankApiRequest|null 90 | */ 91 | public function getFailedRequest() 92 | { 93 | return $this->failedRequest; 94 | } 95 | 96 | /** 97 | * @param $message 98 | * @param $tbkErrorMessage 99 | * @param $httpCode 100 | * @param TransbankApiRequest|null $failedRequestCapturedData 101 | * 102 | * @return string 103 | */ 104 | protected function getExceptionMessage( 105 | $message, 106 | $tbkErrorMessage, 107 | $httpCode, 108 | TransbankApiRequest $failedRequestCapturedData = null 109 | ) { 110 | if (!$tbkErrorMessage) { 111 | $theMessage = $message; 112 | } else { 113 | $theMessage = 'API Response: "'.$tbkErrorMessage.'" ['.$httpCode.'] - '.static::$defaultMessage; 114 | } 115 | 116 | if ($possibleCause = $this->getPossibleCause($httpCode, $tbkErrorMessage, $failedRequestCapturedData)) { 117 | return $theMessage.' - '.$possibleCause; 118 | } 119 | 120 | return $theMessage; 121 | } 122 | 123 | /** 124 | * @param $httpCode 125 | * @param $tbkErrorMessage 126 | * @param TransbankApiRequest|null $failedRequestCapturedData 127 | * 128 | * @return null 129 | */ 130 | protected function getPossibleCause($httpCode, $tbkErrorMessage, TransbankApiRequest $failedRequestCapturedData = null) 131 | { 132 | return null; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/TransaccionCompleta/Responses/TransactionRefundResponse.php: -------------------------------------------------------------------------------- 1 | setType($type); 20 | $authorizationCode = Utils::returnValueIfExists($json, 'authorization_code'); 21 | $this->setAuthorizationCode($authorizationCode); 22 | $authorizationDate = Utils::returnValueIfExists($json, 'authorization_date'); 23 | $this->setAuthorizationDate($authorizationDate); 24 | $nullifiedAmount = Utils::returnValueIfExists($json, 'nullified_amount'); 25 | $this->setNullifiedAmount($nullifiedAmount); 26 | $balance = Utils::returnValueIfExists($json, 'balance'); 27 | $this->setBalance($balance); 28 | $responseCode = Utils::returnValueIfExists($json, 'response_code'); 29 | $this->setResponseCode($responseCode); 30 | } 31 | 32 | /** 33 | * @return mixed 34 | */ 35 | public function getType() 36 | { 37 | return $this->type; 38 | } 39 | 40 | /** 41 | * @param mixed $type 42 | * 43 | * @return TransactionRefundResponse 44 | */ 45 | public function setType($type) 46 | { 47 | $this->type = $type; 48 | 49 | return $this; 50 | } 51 | 52 | /** 53 | * @return mixed 54 | */ 55 | public function getAuthorizationCode() 56 | { 57 | return $this->authorizationCode; 58 | } 59 | 60 | /** 61 | * @param mixed $authorizationCode 62 | * 63 | * @return TransactionRefundResponse 64 | */ 65 | public function setAuthorizationCode($authorizationCode) 66 | { 67 | $this->authorizationCode = $authorizationCode; 68 | 69 | return $this; 70 | } 71 | 72 | /** 73 | * @return mixed 74 | */ 75 | public function getAuthorizationDate() 76 | { 77 | return $this->authorizationDate; 78 | } 79 | 80 | /** 81 | * @param mixed $authorizationDate 82 | * 83 | * @return TransactionRefundResponse 84 | */ 85 | public function setAuthorizationDate($authorizationDate) 86 | { 87 | $this->authorizationDate = $authorizationDate; 88 | 89 | return $this; 90 | } 91 | 92 | /** 93 | * @return mixed 94 | */ 95 | public function getNullifiedAmount() 96 | { 97 | return $this->nullifiedAmount; 98 | } 99 | 100 | /** 101 | * @param mixed $nullifiedAmount 102 | * 103 | * @return TransactionRefundResponse 104 | */ 105 | public function setNullifiedAmount($nullifiedAmount) 106 | { 107 | $this->nullifiedAmount = $nullifiedAmount; 108 | 109 | return $this; 110 | } 111 | 112 | /** 113 | * @return mixed 114 | */ 115 | public function getBalance() 116 | { 117 | return $this->balance; 118 | } 119 | 120 | /** 121 | * @param mixed $balance 122 | * 123 | * @return TransactionRefundResponse 124 | */ 125 | public function setBalance($balance) 126 | { 127 | $this->balance = $balance; 128 | 129 | return $this; 130 | } 131 | 132 | /** 133 | * @return mixed 134 | */ 135 | public function getResponseCode() 136 | { 137 | return (int) $this->responseCode; 138 | } 139 | 140 | /** 141 | * @param mixed $responseCode 142 | * 143 | * @return TransactionRefundResponse 144 | */ 145 | public function setResponseCode($responseCode) 146 | { 147 | $this->responseCode = $responseCode; 148 | 149 | return $this; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/Utils/HttpClientRequestService.php: -------------------------------------------------------------------------------- 1 | setHttpClient($httpClient !== null ? $httpClient : new HttpClient()); 32 | } 33 | 34 | /** 35 | * @return HttpClientInterface 36 | */ 37 | public function getHttpClient() 38 | { 39 | return $this->httpClient; 40 | } 41 | 42 | /** 43 | * @param HttpClientInterface $httpClient 44 | */ 45 | public function setHttpClient($httpClient) 46 | { 47 | $this->httpClient = $httpClient; 48 | } 49 | 50 | /** 51 | * @param $method 52 | * @param $endpoint 53 | * @param $payload 54 | * @param Options $options 55 | * 56 | * @throws GuzzleException 57 | * @throws WebpayRequestException 58 | * 59 | * @return array 60 | */ 61 | public function request( 62 | $method, 63 | $endpoint, 64 | $payload, 65 | Options $options 66 | ) { 67 | $headers = $options->getHeaders(); 68 | $client = $this->httpClient; 69 | if ($client == null) { 70 | $client = new HttpClient(); 71 | } 72 | 73 | $baseUrl = $options->getApiBaseUrl(); 74 | $request = new TransbankApiRequest($method, $baseUrl, $endpoint, $payload, $headers); 75 | 76 | $this->setLastRequest($request); 77 | $response = $client->request($method, $baseUrl.$endpoint, $payload, ['headers' => $headers]); 78 | 79 | $this->setLastResponse($response); 80 | $responseStatusCode = $response->getStatusCode(); 81 | 82 | if (!in_array($responseStatusCode, [200, 204])) { 83 | $reason = $response->getReasonPhrase(); 84 | $message = "Could not obtain a response from Transbank API: $reason (HTTP code $responseStatusCode)"; 85 | $body = json_decode($response->getBody(), true); 86 | $tbkErrorMessage = null; 87 | if (isset($body['error_message'])) { 88 | $tbkErrorMessage = $body['error_message']; 89 | $message = "Transbank API REST Error: $tbkErrorMessage | $message"; 90 | } 91 | 92 | throw new WebpayRequestException($message, $tbkErrorMessage, $responseStatusCode, $request); 93 | } 94 | 95 | return json_decode($response->getBody(), true); 96 | } 97 | 98 | /** 99 | * @return ResponseInterface|null 100 | */ 101 | public function getLastResponse() 102 | { 103 | return $this->lastResponse; 104 | } 105 | 106 | /** 107 | * @param ResponseInterface|null $lastResponse 108 | */ 109 | protected function setLastResponse($lastResponse) 110 | { 111 | $this->lastResponse = $lastResponse; 112 | } 113 | 114 | /** 115 | * @return TransbankApiRequest|null 116 | */ 117 | public function getLastRequest() 118 | { 119 | return $this->lastRequest; 120 | } 121 | 122 | /** 123 | * @param TransbankApiRequest|null $lastRequest 124 | */ 125 | protected function setLastRequest($lastRequest) 126 | { 127 | $this->lastRequest = $lastRequest; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/TransaccionCompleta/Responses/MallTransactionRefundResponse.php: -------------------------------------------------------------------------------- 1 | setType($type); 20 | $authorizationCode = Utils::returnValueIfExists($json, 'authorization_code'); 21 | $this->setAuthorizationCode($authorizationCode); 22 | $authorizationDate = Utils::returnValueIfExists($json, 'authorization_date'); 23 | $this->setAuthorizationDate($authorizationDate); 24 | $nullifiedAmount = Utils::returnValueIfExists($json, 'nullified_amount'); 25 | $this->setNullifiedAmount($nullifiedAmount); 26 | $balance = Utils::returnValueIfExists($json, 'balance'); 27 | $this->setBalance($balance); 28 | $responseCode = Utils::returnValueIfExists($json, 'response_code'); 29 | $this->setResponseCode($responseCode); 30 | } 31 | 32 | /** 33 | * @return mixed 34 | */ 35 | public function getType() 36 | { 37 | return $this->type; 38 | } 39 | 40 | /** 41 | * @param mixed $type 42 | * 43 | * @return MallTransactionRefundResponse 44 | */ 45 | public function setType($type) 46 | { 47 | $this->type = $type; 48 | 49 | return $this; 50 | } 51 | 52 | /** 53 | * @return mixed 54 | */ 55 | public function getAuthorizationCode() 56 | { 57 | return $this->authorizationCode; 58 | } 59 | 60 | /** 61 | * @param mixed $authorizationCode 62 | * 63 | * @return MallTransactionRefundResponse 64 | */ 65 | public function setAuthorizationCode($authorizationCode) 66 | { 67 | $this->authorizationCode = $authorizationCode; 68 | 69 | return $this; 70 | } 71 | 72 | /** 73 | * @return mixed 74 | */ 75 | public function getAuthorizationDate() 76 | { 77 | return $this->authorizationDate; 78 | } 79 | 80 | /** 81 | * @param mixed $authorizationDate 82 | * 83 | * @return MallTransactionRefundResponse 84 | */ 85 | public function setAuthorizationDate($authorizationDate) 86 | { 87 | $this->authorizationDate = $authorizationDate; 88 | 89 | return $this; 90 | } 91 | 92 | /** 93 | * @return mixed 94 | */ 95 | public function getNullifiedAmount() 96 | { 97 | return $this->nullifiedAmount; 98 | } 99 | 100 | /** 101 | * @param mixed $nullifiedAmount 102 | * 103 | * @return MallTransactionRefundResponse 104 | */ 105 | public function setNullifiedAmount($nullifiedAmount) 106 | { 107 | $this->nullifiedAmount = $nullifiedAmount; 108 | 109 | return $this; 110 | } 111 | 112 | /** 113 | * @return mixed 114 | */ 115 | public function getBalance() 116 | { 117 | return $this->balance; 118 | } 119 | 120 | /** 121 | * @param mixed $balance 122 | * 123 | * @return MallTransactionRefundResponse 124 | */ 125 | public function setBalance($balance) 126 | { 127 | $this->balance = $balance; 128 | 129 | return $this; 130 | } 131 | 132 | /** 133 | * @return mixed 134 | */ 135 | public function getResponseCode() 136 | { 137 | return (int) $this->responseCode; 138 | } 139 | 140 | /** 141 | * @param mixed $responseCode 142 | * 143 | * @return MallTransactionRefundResponse 144 | */ 145 | public function setResponseCode($responseCode) 146 | { 147 | $this->responseCode = $responseCode; 148 | 149 | return $this; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/Webpay/Oneclick/MallInscription.php: -------------------------------------------------------------------------------- 1 | $username, 49 | 'email' => $email, 50 | 'response_url' => $responseUrl, 51 | ]; 52 | 53 | try { 54 | $response = $this->sendRequest( 55 | 'POST', 56 | static::INSCRIPTION_START_ENDPOINT, 57 | $payload 58 | ); 59 | } catch (WebpayRequestException $e) { 60 | throw InscriptionStartException::raise($e); 61 | } 62 | 63 | return new InscriptionStartResponse($response); 64 | } 65 | 66 | public function finish($token) 67 | { 68 | try { 69 | $response = $this->sendRequest( 70 | 'PUT', 71 | str_replace('{token}', $token, static::INSCRIPTION_FINISH_ENDPOINT), 72 | null 73 | ); 74 | } catch (WebpayRequestException $e) { 75 | throw InscriptionFinishException::raise($e); 76 | } 77 | 78 | return new InscriptionFinishResponse($response); 79 | } 80 | 81 | public function delete($tbkUser, $username) 82 | { 83 | $payload = [ 84 | 'tbk_user' => $tbkUser, 85 | 'username' => $username, 86 | ]; 87 | 88 | try { 89 | $this->sendRequest( 90 | 'DELETE', 91 | static::INSCRIPTION_DELETE_ENDPOINT, 92 | $payload 93 | ); 94 | } catch (WebpayRequestException $e) { 95 | if ($e->getHttpCode() !== 204) { 96 | return new InscriptionDeleteResponse(false, $e->getHttpCode()); 97 | } 98 | 99 | throw InscriptionDeleteException::raise($e); 100 | } 101 | 102 | return new InscriptionDeleteResponse(true); 103 | } 104 | 105 | public static function getDefaultOptions() 106 | { 107 | return Options::forIntegration(Oneclick::DEFAULT_COMMERCE_CODE); 108 | } 109 | 110 | public static function getGlobalOptions() 111 | { 112 | return Oneclick::getOptions(); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/Webpay/Options.php: -------------------------------------------------------------------------------- 1 | setApiKey($apiKey); 38 | $this->setCommerceCode($commerceCode); 39 | $this->setIntegrationType($integrationType); 40 | } 41 | 42 | public static function forProduction($commerceCode, $apiKey) 43 | { 44 | return new static($apiKey, $commerceCode, static::ENVIRONMENT_PRODUCTION); 45 | } 46 | 47 | public static function forIntegration($commerceCode, $apiKey = Options::DEFAULT_API_KEY) 48 | { 49 | return new static($apiKey, $commerceCode, static::ENVIRONMENT_INTEGRATION); 50 | } 51 | 52 | public function isProduction() 53 | { 54 | return $this->getIntegrationType() === static::ENVIRONMENT_PRODUCTION; 55 | } 56 | 57 | /** 58 | * @return string 59 | */ 60 | public function getIntegrationType() 61 | { 62 | return $this->integrationType; 63 | } 64 | 65 | /** 66 | * @param string $integrationType 67 | * 68 | * @return Options 69 | */ 70 | public function setIntegrationType($integrationType) 71 | { 72 | $this->integrationType = $integrationType; 73 | 74 | return $this; 75 | } 76 | 77 | /** 78 | * @return mixed 79 | */ 80 | public function getApiKey() 81 | { 82 | return $this->apiKey; 83 | } 84 | 85 | /** 86 | * @param string $apiKey 87 | * 88 | * @return Options 89 | */ 90 | public function setApiKey($apiKey) 91 | { 92 | $this->apiKey = $apiKey; 93 | 94 | return $this; 95 | } 96 | 97 | /** 98 | * @return mixed 99 | */ 100 | public function getCommerceCode() 101 | { 102 | return $this->commerceCode; 103 | } 104 | 105 | /** 106 | * @param mixed $commerceCode 107 | * 108 | * @return Options 109 | */ 110 | public function setCommerceCode($commerceCode) 111 | { 112 | $this->commerceCode = $commerceCode; 113 | 114 | return $this; 115 | } 116 | 117 | /** 118 | * @return string Returns the base URL used for making requests, depending on which 119 | * integration types 120 | */ 121 | public function getApiBaseUrl() 122 | { 123 | if ($this->isProduction()) { 124 | return static::BASE_URL_PRODUCTION; 125 | } 126 | 127 | return static::BASE_URL_INTEGRATION; 128 | } 129 | 130 | /** 131 | * @return array 132 | */ 133 | public function getHeaders() 134 | { 135 | return [ 136 | 'Tbk-Api-Key-Id' => $this->getCommerceCode(), 137 | 'Tbk-Api-Key-Secret' => $this->getApiKey(), 138 | ]; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/Webpay/Oneclick/Responses/MallTransactionRefundResponse.php: -------------------------------------------------------------------------------- 1 | setType($type); 18 | 19 | $authorizationCode = isset($json['authorization_code']) ? $json['authorization_code'] : null; 20 | $this->setAuthorizationCode($authorizationCode); 21 | 22 | $authorizationDate = isset($json['authorization_date']) ? $json['authorization_date'] : null; 23 | $this->setAuthorizationDate($authorizationDate); 24 | 25 | $nullifiedAmount = isset($json['nullified_amount']) ? $json['nullified_amount'] : null; 26 | $this->setNullifiedAmount($nullifiedAmount); 27 | 28 | $balance = isset($json['balance']) ? $json['balance'] : null; 29 | $this->setBalance($balance); 30 | 31 | $responseCode = isset($json['response_code']) ? $json['response_code'] : null; 32 | $this->setResponseCode($responseCode); 33 | } 34 | 35 | /** 36 | * @return mixed 37 | */ 38 | public function getType() 39 | { 40 | return $this->type; 41 | } 42 | 43 | /** 44 | * @param mixed $type 45 | * 46 | * @return MallTransactionRefundResponse 47 | */ 48 | public function setType($type) 49 | { 50 | $this->type = $type; 51 | 52 | return $this; 53 | } 54 | 55 | /** 56 | * @return mixed 57 | */ 58 | public function getAuthorizationCode() 59 | { 60 | return $this->authorizationCode; 61 | } 62 | 63 | /** 64 | * @param mixed $authorizationCode 65 | * 66 | * @return MallTransactionRefundResponse 67 | */ 68 | public function setAuthorizationCode($authorizationCode) 69 | { 70 | $this->authorizationCode = $authorizationCode; 71 | 72 | return $this; 73 | } 74 | 75 | /** 76 | * @return mixed 77 | */ 78 | public function getAuthorizationDate() 79 | { 80 | return $this->authorizationDate; 81 | } 82 | 83 | /** 84 | * @param mixed $authorizationDate 85 | * 86 | * @return MallTransactionRefundResponse 87 | */ 88 | public function setAuthorizationDate($authorizationDate) 89 | { 90 | $this->authorizationDate = $authorizationDate; 91 | 92 | return $this; 93 | } 94 | 95 | /** 96 | * @return mixed 97 | */ 98 | public function getNullifiedAmount() 99 | { 100 | return $this->nullifiedAmount; 101 | } 102 | 103 | /** 104 | * @param mixed $nullifiedAmount 105 | * 106 | * @return MallTransactionRefundResponse 107 | */ 108 | public function setNullifiedAmount($nullifiedAmount) 109 | { 110 | $this->nullifiedAmount = $nullifiedAmount; 111 | 112 | return $this; 113 | } 114 | 115 | /** 116 | * @return mixed 117 | */ 118 | public function getBalance() 119 | { 120 | return $this->balance; 121 | } 122 | 123 | /** 124 | * @param mixed $balance 125 | * 126 | * @return MallTransactionRefundResponse 127 | */ 128 | public function setBalance($balance) 129 | { 130 | $this->balance = $balance; 131 | 132 | return $this; 133 | } 134 | 135 | /** 136 | * @return mixed 137 | */ 138 | public function getResponseCode() 139 | { 140 | return $this->responseCode; 141 | } 142 | 143 | /** 144 | * @param mixed $responseCode 145 | * 146 | * @return MallTransactionRefundResponse 147 | */ 148 | public function setResponseCode($responseCode) 149 | { 150 | $this->responseCode = $responseCode; 151 | 152 | return $this; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/Onepay/ShoppingCart.php: -------------------------------------------------------------------------------- 1 | items = []; 21 | $this->total = 0; 22 | } 23 | 24 | public function getTotal() 25 | { 26 | return $this->total; 27 | } 28 | 29 | public function getItems() 30 | { 31 | /** 32 | * Returns a copy of $this->items so it cannot be modified from the 33 | * outside. 34 | */ 35 | if (empty($this->items)) { 36 | return []; 37 | } 38 | $newItems = []; 39 | 40 | foreach ($this->items as $item) { 41 | $newItem = clone $item; 42 | array_push($newItems, $newItem); 43 | } 44 | 45 | return $newItems; 46 | } 47 | 48 | public function add($item) 49 | { 50 | $newTotal = $this->total + $item->getAmount() * $item->getQuantity(); 51 | if ($newTotal < 0) { 52 | throw new \Exception('Total amount cannot be less than zero.'); 53 | } 54 | array_push($this->items, $item); 55 | $this->total = $newTotal; 56 | 57 | return true; 58 | } 59 | 60 | public function remove($item) 61 | { 62 | $newTotal = $this->total - $item->getAmount() * $item->getQuantity(); 63 | $itemKey = array_search($item, $this->items); 64 | if ($itemKey === false) { 65 | throw new \Exception('Item not found.'); 66 | } 67 | 68 | if ($newTotal < 0) { 69 | throw new \Exception('Total amount cannot be less than zero.'); 70 | } 71 | array_splice($this->items, $itemKey, 1); 72 | $this->total = $newTotal; 73 | 74 | return true; 75 | } 76 | 77 | public function removeAll() 78 | { 79 | $this->total = 0; 80 | $this->items = []; 81 | } 82 | 83 | public function getItemQuantity() 84 | { 85 | $quantity = 0; 86 | foreach ($this->items as $item) { 87 | $quantity += $item->getQuantity(); 88 | } 89 | 90 | return $quantity; 91 | } 92 | 93 | /** 94 | * Creates a ShoppingCart from an associative array (or json_decode-able string) 95 | * with the following shape. 96 | * 97 | * $cart = array( 98 | * "items" => [ 99 | * ["amount"=> "MANDATORY - A number", 100 | * "quantity" => "MANDATORY - A number", 101 | * "description" => "MANDATORY - A string", 102 | * "additionalData" => "OPTIONAL - A string", 103 | * "expire" => "OPTIONAL - A number"], 104 | * ...plus whichever number of Item shaped associative arrays you want 105 | * to include 106 | * ] 107 | * ); 108 | */ 109 | public static function fromJSON($cart) 110 | { 111 | if (is_string($cart)) { 112 | $cart = json_decode($cart, true); 113 | } 114 | if (!is_array($cart)) { 115 | throw new \Exception('Shopping Cart must be a JSON string or an associative array that is transformable to an associative array using json_decode'); 116 | } 117 | 118 | if (!isset($cart['items'])) { 119 | throw new \Exception('Shopping Cart must have an "items" key (even if null/empty)'); 120 | } 121 | 122 | if (!$cart['items']) { 123 | return new ShoppingCart(); 124 | } 125 | 126 | if (empty($cart['items'])) { 127 | return new ShoppingCart(); 128 | } 129 | 130 | $shoppingCartObject = new ShoppingCart(); 131 | foreach ($cart['items'] as $cartItem) { 132 | $item = Item::fromJSON($cartItem); 133 | $shoppingCartObject->add($item); 134 | } 135 | 136 | return $shoppingCartObject; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/Utils/InteractsWithWebpayApi.php: -------------------------------------------------------------------------------- 1 | loadOptions($options); 34 | 35 | $this->setRequestService($requestService !== null ? $requestService : 36 | new HttpClientRequestService()); 37 | } 38 | 39 | /** 40 | * @param $method 41 | * @param $endpoint 42 | * @param array|null $payload 43 | * 44 | * @throws WebpayRequestException 45 | * 46 | * @return mixed 47 | */ 48 | public function sendRequest($method, $endpoint, $payload = []) 49 | { 50 | return $this->getRequestService()->request( 51 | $method, 52 | $endpoint, 53 | $payload, 54 | $this->getOptions() 55 | ); 56 | } 57 | 58 | /** 59 | * @param Options $options 60 | * 61 | * @return $this 62 | */ 63 | public function loadOptions(Options $options = null) 64 | { 65 | $defaultOptions = method_exists($this, 'getGlobalOptions') && $this::getGlobalOptions() !== null ? 66 | $this::getGlobalOptions() : $this->getDefaultOptions(); 67 | if (!$options) { 68 | $options = $defaultOptions; 69 | } 70 | 71 | if ($options === null) { 72 | throw new \InvalidArgumentException('No options configuration given'); 73 | } 74 | 75 | $this->setOptions($options); 76 | 77 | return $this; 78 | } 79 | 80 | /** 81 | * @return Options 82 | */ 83 | public function getOptions() 84 | { 85 | return $this->options; 86 | } 87 | 88 | /** 89 | * @param Options $options 90 | */ 91 | public function setOptions(Options $options) 92 | { 93 | $this->options = $options; 94 | 95 | return $this; 96 | } 97 | 98 | /** 99 | * @return RequestService |null 100 | */ 101 | public function getRequestService() 102 | { 103 | return $this->requestService; 104 | } 105 | 106 | /** 107 | * @param RequestService |null $requestService 108 | */ 109 | public function setRequestService(RequestService $requestService = null) 110 | { 111 | $this->requestService = $requestService; 112 | 113 | return $this; 114 | } 115 | 116 | /** 117 | * @param Options|null $options 118 | * @param RequestService|null $requestService 119 | * 120 | * @return static 121 | */ 122 | public static function build(Options $options = null, RequestService $requestService = null) 123 | { 124 | return new static($options, $requestService); 125 | } 126 | 127 | /** 128 | * @return string 129 | */ 130 | protected function getBaseUrl() 131 | { 132 | return $this->getOptions()->getApiBaseUrl(); 133 | } 134 | 135 | /** 136 | * @param $commerceCode 137 | * @param $apiKey 138 | * 139 | * @return $this 140 | */ 141 | public function configureForIntegration($commerceCode, $apiKey) 142 | { 143 | $this->setOptions(Options::forIntegration($commerceCode, $apiKey)); 144 | 145 | return $this; 146 | } 147 | 148 | /** 149 | * @param $commerceCode 150 | * @param $apiKey 151 | * 152 | * @return $this 153 | */ 154 | public function configureForProduction($commerceCode, $apiKey) 155 | { 156 | $this->setOptions(Options::forProduction($commerceCode, $apiKey)); 157 | 158 | return $this; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/Patpass/PatpassComercio/Inscription.php: -------------------------------------------------------------------------------- 1 | $url, 68 | 'nombre' => $name, 69 | 'pApellido' => $lastName, 70 | 'sApellido' => $secondLastName, 71 | 'rut' => $rut, 72 | 'serviceId' => $serviceId, 73 | 'finalUrl' => $finalUrl, 74 | 'commerceCode' => $this->getOptions()->getCommerceCode(), 75 | 'montoMaximo' => $maxAmount, 76 | 'telefonoFijo' => $phone, 77 | 'telefonoCelular' => $cellPhone, 78 | 'nombrePatPass' => $patpassName, 79 | 'correoPersona' => $personEmail, 80 | 'correoComercio' => $commerceEmail, 81 | 'direccion' => $address, 82 | 'ciudad' => $city, 83 | ]; 84 | $endpoint = static::INSCRIPTION_START_ENDPOINT; 85 | 86 | try { 87 | $response = $this->sendRequest('POST', $endpoint, $payload); 88 | } catch (WebpayRequestException $exception) { 89 | throw InscriptionStartException::raise($exception); 90 | } 91 | 92 | return new InscriptionStartResponse($response); 93 | } 94 | 95 | /** 96 | * @param $token 97 | * @param null $options 98 | * 99 | * @throws InscriptionStatusException 100 | * @throws GuzzleException 101 | * 102 | * @return InscriptionStatusResponse 103 | */ 104 | public function status($token) 105 | { 106 | $payload = [ 107 | 'token' => $token, 108 | ]; 109 | 110 | $endpoint = str_replace('{token}', $token, static::INSCRIPTION_STATUS_ENDPOINT); 111 | 112 | try { 113 | $response = $this->sendRequest('POST', $endpoint, $payload); 114 | } catch (WebpayRequestException $exception) { 115 | throw InscriptionStatusException::raise($exception); 116 | } 117 | 118 | return new InscriptionStatusResponse($response); 119 | } 120 | 121 | public static function getDefaultOptions() 122 | { 123 | return Options::forIntegration(PatpassComercio::DEFAULT_COMMERCE_CODE, PatpassComercio::DEFAULT_API_KEY); 124 | } 125 | 126 | public static function getGlobalOptions() 127 | { 128 | return PatpassComercio::getOptions(); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/Onepay/Utils/OnepayRequestBuilder.php: -------------------------------------------------------------------------------- 1 | getTotal(), 60 | $shoppingCart->getItemQuantity(), 61 | $issuedAt, 62 | $shoppingCart->getItems(), 63 | OnepayBase::getCallBackUrl(), 64 | $channel, // Channel, can be 'WEB', 'MOBILE' or 'APP' 65 | OnepayBase::getAppScheme(), 66 | $options->getQrWidthHeight(), 67 | $options->getCommerceLogoUrl() 68 | ); 69 | 70 | self::setKeys($request, $options); 71 | 72 | return OnepaySignUtil::getInstance()->sign($request, $options->getSharedSecret()); 73 | } 74 | 75 | public function buildCommitRequest($occ, $externalUniqueNumber, $options = null) 76 | { 77 | $options = self::buildOptions($options); 78 | 79 | $issuedAt = time(); 80 | $request = new TransactionCommitRequest($occ, $externalUniqueNumber, $issuedAt); 81 | self::setKeys($request, $options); 82 | 83 | return OnepaySignUtil::getInstance()->sign($request, $options->getSharedSecret()); 84 | } 85 | 86 | public function buildRefundRequest( 87 | $refundAmount, 88 | $occ, 89 | $externalUniqueNumber, 90 | $authorizationCode, 91 | $options = null 92 | ) { 93 | $options = self::buildOptions($options); 94 | $issuedAt = time(); 95 | $request = new RefundCreateRequest( 96 | $refundAmount, 97 | $occ, 98 | (string) $externalUniqueNumber, 99 | $authorizationCode, 100 | $issuedAt 101 | ); 102 | self::setKeys($request, $options); 103 | 104 | return OnepaySignUtil::getInstance()->sign( 105 | $request, 106 | $options->getSharedSecret() 107 | ); 108 | } 109 | 110 | public static function buildOptions($options) 111 | { 112 | if (!$options) { 113 | return Options::getDefaults(); 114 | } 115 | 116 | if (!$options->getApiKey()) { 117 | $options->setApiKey(OnepayBase::getApiKey()); 118 | } 119 | 120 | if (!$options->getAppKey()) { 121 | $options->setAppKey(OnepayBase::getCurrentIntegrationTypeAppKey()); 122 | } 123 | if (!$options->getSharedSecret()) { 124 | $options->setSharedSecret(OnepayBase::getSharedSecret()); 125 | } 126 | 127 | return $options; 128 | } 129 | 130 | public static function setKeys($request, $options) 131 | { 132 | $request->setAppKey($options->getAppKey()); 133 | $request->setApiKey($options->getApiKey()); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/Onepay/Options.php: -------------------------------------------------------------------------------- 1 | setApiKey($apiKey); 41 | $this->setSharedSecret($sharedSecret); 42 | $this->setQrWidthHeight($qrWidthHeight); 43 | $this->setCommerceLogoUrl($commerceLogoUrl); 44 | 45 | $this->setAppKey(OnepayBase::getCurrentIntegrationTypeAppKey()); 46 | } 47 | 48 | public static function getDefaults() 49 | { 50 | return new Options( 51 | OnepayBase::getApiKey(), 52 | OnepayBase::getSharedSecret(), 53 | OnepayBase::getQrWidthHeight(), 54 | OnepayBase::getCommerceLogoUrl() 55 | ); 56 | } 57 | 58 | public function jsonSerialize() 59 | { 60 | return get_object_vars($this); 61 | } 62 | 63 | public function getApiKey() 64 | { 65 | return $this->apiKey; 66 | } 67 | 68 | public function setApiKey($apiKey) 69 | { 70 | $this->apiKey = $apiKey; 71 | 72 | return $this; 73 | } 74 | 75 | public function getAppKey() 76 | { 77 | return $this->appKey; 78 | } 79 | 80 | public function setAppKey($appKey) 81 | { 82 | $this->appKey = $appKey; 83 | 84 | return $this; 85 | } 86 | 87 | public function getSharedSecret() 88 | { 89 | return $this->sharedSecret; 90 | } 91 | 92 | public function setSharedSecret($sharedSecret) 93 | { 94 | $this->sharedSecret = $sharedSecret; 95 | 96 | return $this; 97 | } 98 | 99 | /** 100 | * @return int|null 101 | */ 102 | public function getQrWidthHeight() 103 | { 104 | return $this->qrWidthHeight; 105 | } 106 | 107 | /** 108 | * @param int|null $qrWidthHeight 109 | * 110 | * @return $this 111 | */ 112 | public function setQrWidthHeight($qrWidthHeight) 113 | { 114 | if ($qrWidthHeight == self::__DEFAULT_QR_WIDTH_HEIGHT__) { 115 | $qrWidthHeight = OnepayBase::getQrWidthHeight(); 116 | } 117 | $this->qrWidthHeight = $qrWidthHeight; 118 | 119 | return $this; 120 | } 121 | 122 | /** 123 | * @return string|null 124 | */ 125 | public function getCommerceLogoUrl() 126 | { 127 | return $this->commerceLogoUrl; 128 | } 129 | 130 | /** 131 | * @param string|null $commerceLogoUrl 132 | * 133 | * @return $this 134 | */ 135 | public function setCommerceLogoUrl($commerceLogoUrl) 136 | { 137 | if ($commerceLogoUrl == self::__DEFAULT_COMMERCE_LOGO_URL__) { 138 | $commerceLogoUrl = OnepayBase::getCommerceLogoUrl(); 139 | } 140 | $this->commerceLogoUrl = $commerceLogoUrl; 141 | 142 | return $this; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/Onepay/TransactionCommitResponse.php: -------------------------------------------------------------------------------- 1 | fromJSON($json); 25 | } 26 | 27 | public function jsonSerialize() 28 | { 29 | return get_object_vars($this); 30 | } 31 | 32 | public function getOcc() 33 | { 34 | return $this->occ; 35 | } 36 | 37 | public function setOcc($occ) 38 | { 39 | $this->occ = $occ; 40 | 41 | return $this; 42 | } 43 | 44 | public function getAuthorizationCode() 45 | { 46 | return $this->authorizationCode; 47 | } 48 | 49 | public function setAuthorizationCode($authorizationCode) 50 | { 51 | $this->authorizationCode = $authorizationCode; 52 | 53 | return $this; 54 | } 55 | 56 | public function getSignature() 57 | { 58 | return $this->signature; 59 | } 60 | 61 | public function setSignature($signature) 62 | { 63 | $this->signature = $signature; 64 | 65 | return $this; 66 | } 67 | 68 | public function getTransactionDesc() 69 | { 70 | return $this->transactionDesc; 71 | } 72 | 73 | public function setTransactionDesc($transactionDesc) 74 | { 75 | $this->transactionDesc; 76 | 77 | return $this; 78 | } 79 | 80 | public function getBuyOrder() 81 | { 82 | return $this->buyOrder; 83 | } 84 | 85 | public function setBuyOrder($buyOrder) 86 | { 87 | $this->buyOrder = $buyOrder; 88 | 89 | return $this; 90 | } 91 | 92 | public function getIssuedAt() 93 | { 94 | return $this->issuedAt; 95 | } 96 | 97 | public function setIssuedAt($issuedAt) 98 | { 99 | $this->issuedAt = $issuedAt; 100 | 101 | return $this; 102 | } 103 | 104 | public function getAmount() 105 | { 106 | return $this->amount; 107 | } 108 | 109 | public function setAmount($amount) 110 | { 111 | $this->amount = $amount; 112 | 113 | return $this; 114 | } 115 | 116 | public function getInstallmentsAmount() 117 | { 118 | return $this->installmentsAmount; 119 | } 120 | 121 | public function setInstallmentsAmount($installmentsAmount) 122 | { 123 | $this->installmentsAmount = $installmentsAmount; 124 | 125 | return $this; 126 | } 127 | 128 | public function getInstallmentsNumber() 129 | { 130 | return $this->installmentsNumber; 131 | } 132 | 133 | public function setInstallmentsNumber($installmentsNumber) 134 | { 135 | $this->installmentsNumber = $installmentsNumber; 136 | 137 | return $this; 138 | } 139 | 140 | public function fromJSON($json) 141 | { 142 | if (is_string($json)) { 143 | $json = json_decode($json, true); 144 | } 145 | if (!is_array($json)) { 146 | throw new \Exception('Given value must be an associative array or a string that can be converted to an associative array with json_decode()'); 147 | } 148 | $responseResult = $json['result']; 149 | 150 | $this->setResponseCode($json['responseCode']); 151 | $this->setDescription($json['description']); 152 | $this->setOcc($responseResult['occ']); 153 | $this->setAuthorizationCode($responseResult['authorizationCode']); 154 | $this->setSignature($responseResult['signature']); 155 | $this->setTransactionDesc($responseResult['transactionDesc']); 156 | $this->setBuyOrder($responseResult['buyOrder']); 157 | $this->setIssuedAt($responseResult['issuedAt']); 158 | $this->setAmount($responseResult['amount']); 159 | $this->setInstallmentsAmount($responseResult['installmentsAmount']); 160 | $this->setInstallmentsNumber($responseResult['installmentsNumber']); 161 | 162 | return $this; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/Webpay/WebpayPlus/Responses/TransactionRefundResponse.php: -------------------------------------------------------------------------------- 1 | type = isset($json['type']) ? $json['type'] : null; 42 | $this->authorizationCode = isset($json['authorization_code']) ? $json['authorization_code'] : null; 43 | $this->authorizationDate = isset($json['authorization_date']) ? $json['authorization_date'] : null; 44 | $this->nullifiedAmount = isset($json['nullified_amount']) ? $json['nullified_amount'] : null; 45 | $this->balance = isset($json['balance']) ? $json['balance'] : null; 46 | $this->responseCode = isset($json['response_code']) ? $json['response_code'] : null; 47 | } 48 | 49 | public function success() 50 | { 51 | return $this->getType() === static::TYPE_REVERSED || 52 | ($this->getType() === self::TYPE_NULLIFY && $this->getResponseCode() === 0); 53 | } 54 | 55 | /** 56 | * @return mixed|null 57 | */ 58 | public function getNullifiedAmount() 59 | { 60 | return $this->nullifiedAmount; 61 | } 62 | 63 | /** 64 | * @param mixed|null $nullifiedAmount 65 | * 66 | * @return TransactionRefundResponse 67 | */ 68 | public function setNullifiedAmount($nullifiedAmount) 69 | { 70 | $this->nullifiedAmount = $nullifiedAmount; 71 | 72 | return $this; 73 | } 74 | 75 | /** 76 | * @return mixed|null 77 | */ 78 | public function getBalance() 79 | { 80 | return $this->balance; 81 | } 82 | 83 | /** 84 | * @param mixed|null $balance 85 | * 86 | * @return TransactionRefundResponse 87 | */ 88 | public function setBalance($balance) 89 | { 90 | $this->balance = $balance; 91 | 92 | return $this; 93 | } 94 | 95 | /** 96 | * @return mixed|null 97 | */ 98 | public function getResponseCode() 99 | { 100 | return (int) $this->responseCode; 101 | } 102 | 103 | /** 104 | * @param mixed|null $responseCode 105 | * 106 | * @return TransactionRefundResponse 107 | */ 108 | public function setResponseCode($responseCode) 109 | { 110 | $this->responseCode = $responseCode; 111 | 112 | return $this; 113 | } 114 | 115 | /** 116 | * @return mixed|null 117 | */ 118 | public function getType() 119 | { 120 | return $this->type; 121 | } 122 | 123 | /** 124 | * @param mixed|null $type 125 | * 126 | * @return TransactionRefundResponse 127 | */ 128 | public function setType($type) 129 | { 130 | $this->type = $type; 131 | 132 | return $this; 133 | } 134 | 135 | /** 136 | * @return mixed|null 137 | */ 138 | public function getAuthorizationCode() 139 | { 140 | return $this->authorizationCode; 141 | } 142 | 143 | /** 144 | * @param mixed|null $authorizationCode 145 | * 146 | * @return TransactionRefundResponse 147 | */ 148 | public function setAuthorizationCode($authorizationCode) 149 | { 150 | $this->authorizationCode = $authorizationCode; 151 | 152 | return $this; 153 | } 154 | 155 | /** 156 | * @return mixed|null 157 | */ 158 | public function getAuthorizationDate() 159 | { 160 | return $this->authorizationDate; 161 | } 162 | 163 | /** 164 | * @param mixed|null $authorizationDate 165 | * 166 | * @return TransactionRefundResponse 167 | */ 168 | public function setAuthorizationDate($authorizationDate) 169 | { 170 | $this->authorizationDate = $authorizationDate; 171 | 172 | return $this; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/Webpay/Oneclick/MallTransaction.php: -------------------------------------------------------------------------------- 1 | $userName, 34 | 'tbk_user' => $tbkUser, 35 | 'buy_order' => $parentBuyOrder, 36 | 'details' => $details, 37 | ]; 38 | 39 | try { 40 | $response = $this->sendRequest( 41 | 'POST', 42 | static::AUTHORIZE_TRANSACTION_ENDPOINT, 43 | $payload 44 | ); 45 | } catch (WebpayRequestException $e) { 46 | throw MallTransactionAuthorizeException::raise($e); 47 | } 48 | 49 | return new MallTransactionAuthorizeResponse($response); 50 | } 51 | 52 | public function capture($childCommerceCode, $childBuyOrder, $authorizationCode, $amount) 53 | { 54 | $payload = [ 55 | 'commerce_code' => $childCommerceCode, 56 | 'buy_order' => $childBuyOrder, 57 | 'authorization_code' => $authorizationCode, 58 | 'capture_amount' => $amount, 59 | ]; 60 | 61 | try { 62 | $response = $this->sendRequest( 63 | 'PUT', 64 | static::TRANSACTION_CAPTURE_ENDPOINT, 65 | $payload 66 | ); 67 | } catch (WebpayRequestException $e) { 68 | throw MallTransactionCaptureException::raise($e); 69 | } 70 | 71 | return new MallTransactionCaptureResponse($response); 72 | } 73 | 74 | public function status($buyOrder) 75 | { 76 | try { 77 | $response = $this->sendRequest( 78 | 'GET', 79 | str_replace('{buy_order}', $buyOrder, static::TRANSACTION_STATUS_ENDPOINT), 80 | null 81 | ); 82 | } catch (WebpayRequestException $e) { 83 | throw MallTransactionStatusException::raise($e); 84 | } 85 | 86 | return new MallTransactionStatusResponse($response); 87 | } 88 | 89 | public function refund($buyOrder, $childCommerceCode, $childBuyOrder, $amount, $options = null) 90 | { 91 | $payload = [ 92 | 'detail_buy_order' => $childBuyOrder, 93 | 'commerce_code' => $childCommerceCode, 94 | 'amount' => $amount, 95 | ]; 96 | 97 | try { 98 | $response = $this->sendRequest( 99 | 'POST', 100 | str_replace('{buy_order}', $buyOrder, static::TRANSACTION_REFUND_ENDPOINT), 101 | $payload 102 | ); 103 | } catch (WebpayRequestException $e) { 104 | throw MallRefundTransactionException::raise($e); 105 | } 106 | 107 | return new MallTransactionRefundResponse($response); 108 | } 109 | 110 | public static function getDefaultOptions() 111 | { 112 | return Options::forIntegration(Oneclick::DEFAULT_COMMERCE_CODE); 113 | } 114 | 115 | public static function getGlobalOptions() 116 | { 117 | return Oneclick::getOptions(); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Webpay/Modal/Transaction.php: -------------------------------------------------------------------------------- 1 | $buyOrder, 46 | 'session_id' => $sessionId, 47 | 'amount' => $amount, 48 | ]; 49 | 50 | try { 51 | $response = $this->sendRequest('POST', static::CREATE_TRANSACTION_ENDPOINT, $payload); 52 | } catch (WebpayRequestException $exception) { 53 | throw TransactionCreateException::raise($exception); 54 | } 55 | 56 | return new TransactionCreateResponse($response); 57 | } 58 | 59 | /** 60 | * @param string $token 61 | * 62 | * @throws TransactionCommitException|GuzzleException 63 | * 64 | * @return TransactionCommitResponse 65 | ** 66 | */ 67 | public function commit($token) 68 | { 69 | $endpoint = str_replace('{token}', $token, static::COMMIT_TRANSACTION_ENDPOINT); 70 | 71 | try { 72 | $response = $this->sendRequest('PUT', $endpoint, []); 73 | } catch (WebpayRequestException $exception) { 74 | throw TransactionCommitException::raise($exception); 75 | } 76 | 77 | return new TransactionCommitResponse($response); 78 | } 79 | 80 | /** 81 | * @param $token 82 | * 83 | * @throws GuzzleException 84 | * @throws TransactionStatusException 85 | * 86 | * @return TransactionStatusResponse 87 | */ 88 | public function status($token) 89 | { 90 | $endpoint = str_replace('{token}', $token, static::STATUS_TRANSACTION_ENDPOINT); 91 | 92 | try { 93 | $response = $this->sendRequest('GET', $endpoint, []); 94 | } catch (WebpayRequestException $exception) { 95 | throw TransactionStatusException::raise($exception); 96 | } 97 | 98 | return new TransactionStatusResponse($response); 99 | } 100 | 101 | /** 102 | * @param $token 103 | * @param $amount 104 | * @param Options|null $options 105 | * 106 | * @throws GuzzleException|TransactionRefundException 107 | * 108 | * @return TransactionRefundResponse 109 | */ 110 | public function refund($token, $amount) 111 | { 112 | $endpoint = str_replace('{token}', $token, static::REFUND_TRANSACTION_ENDPOINT); 113 | 114 | try { 115 | $response = $this->sendRequest( 116 | 'POST', 117 | $endpoint, 118 | ['amount' => $amount] 119 | ); 120 | } catch (WebpayRequestException $exception) { 121 | throw TransactionRefundException::raise($exception); 122 | } 123 | 124 | return new TransactionRefundResponse($response); 125 | } 126 | 127 | public static function getDefaultOptions() 128 | { 129 | return Options::forIntegration(WebpayModal::DEFAULT_COMMERCE_CODE, WebpayModal::DEFAULT_API_KEY); 130 | } 131 | 132 | public static function getGlobalOptions() 133 | { 134 | return WebpayModal::getOptions(); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /tests/Webpay/WebpayPlus/WebpayPlusWithoutMocksTest.php: -------------------------------------------------------------------------------- 1 | amount = 1000; 34 | $this->sessionId = 'some_session_id_'.uniqid(); 35 | $this->buyOrder = '123999555'; 36 | $this->returnUrl = 'https://comercio.cl/callbacks/transaccion_creada_exitosamente'; 37 | $this->mockBaseUrl = 'http://mockurl.cl'; 38 | } 39 | 40 | /** @test */ 41 | public function it_creates_a_real_transaction_without_options() 42 | { 43 | $transactionResult = Transaction::build()->create($this->buyOrder, $this->sessionId, $this->amount, $this->returnUrl); 44 | 45 | $this->assertNotNull($transactionResult->getToken()); 46 | $this->assertNotNull($transactionResult->getUrl()); 47 | } 48 | 49 | /** @test */ 50 | public function it_creates_a_real_transaction_with_options() 51 | { 52 | $options = new Options(WebpayPlus::DEFAULT_API_KEY, WebpayPlus::DEFAULT_COMMERCE_CODE); 53 | $transaction = (new Transaction()); 54 | $transaction->setOptions($options); 55 | $transactionResult = $transaction->create( 56 | $this->buyOrder, 57 | $this->sessionId, 58 | $this->amount, 59 | $this->returnUrl 60 | ); 61 | 62 | $this->assertNotNull($transactionResult->getToken()); 63 | $this->assertNotNull($transactionResult->getUrl()); 64 | } 65 | 66 | public function testCreateTransactionWithIncorrectCredentialsShouldFail() 67 | { 68 | $options = new Options('fakeApiKey', 'fakeCommerceCode'); 69 | 70 | $this->expectException(\Exception::class, 'Not Authorized'); 71 | $transaction = (new Transaction()); 72 | $transaction->setOptions($options); 73 | $transaction->create($this->buyOrder, $this->sessionId, $this->amount, $this->returnUrl); 74 | } 75 | 76 | /** @test */ 77 | public function it_can_get_the_status_of_a_transaction() 78 | { 79 | $response = (new Transaction())->create($this->buyOrder, $this->sessionId, $this->amount, $this->returnUrl); 80 | 81 | $response = (new Transaction())->status($response->getToken()); 82 | $this->assertEquals('INITIALIZED', $response->getStatus()); 83 | $this->assertEquals($this->amount, $response->getAmount()); 84 | $this->assertEquals($this->buyOrder, $response->getBuyOrder()); 85 | $this->assertEquals($this->sessionId, $response->getSessionId()); 86 | } 87 | 88 | /** @test */ 89 | public function it_can_not_commit_a_recently_created_transaction() 90 | { 91 | $response = $this->createTransaction(); 92 | 93 | $this->expectException(TransactionCommitException::class, "Invalid status '0' for transaction while authorizing"); 94 | (new Transaction())->commit($response->getToken()); 95 | } 96 | 97 | /** @test */ 98 | public function it_can_not_capture_a_recently_created_transaction() 99 | { 100 | WebpayPlus::configureForTestingDeferred(); 101 | $response = $this->createTransaction(); 102 | $this->expectException(TransactionCaptureException::class, 'Transaction not found'); 103 | (new Transaction())->capture($response->getToken(), $this->buyOrder, 'authCode', $this->amount); 104 | } 105 | 106 | /** @test */ 107 | public function it_can_not_capture_a_transaction_with_simultaneous_capture_commerce_code() 108 | { 109 | WebpayPlus::configureForTesting(); 110 | $response = $this->createTransaction(); 111 | $this->expectException(TransactionCaptureException::class, 'Operation not allowed'); 112 | WebpayPlus::transaction()->capture($response->getToken(), $this->buyOrder, 'authCode', $this->amount); 113 | 114 | $this->assertTrue(true); 115 | } 116 | 117 | /** 118 | * @throws WebpayPlus\Exceptions\TransactionCreateException 119 | * 120 | * @return \Transbank\Webpay\WebpayPlus\Responses\TransactionCreateResponse 121 | */ 122 | public function createTransaction() 123 | { 124 | $response = (new Transaction())->create($this->buyOrder, $this->sessionId, $this->amount, $this->returnUrl); 125 | 126 | return $response; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /examples/transaccion-completa/mall.php: -------------------------------------------------------------------------------- 1 | 10000, 16 | 'commerce_code' => TransaccionCompleta::DEFAULT_MALL_CHILD_COMMERCE_CODE_1, 17 | 'buy_order' => '123456789', 18 | ], 19 | [ 20 | 'amount' => 12000, 21 | 'commerce_code' => TransaccionCompleta::DEFAULT_MALL_CHILD_COMMERCE_CODE_2, 22 | 'buy_order' => '123456790', 23 | ], 24 | ]; 25 | $cardNumber = '4051885600446623'; 26 | $cardExpirationDate = '22/12'; 27 | $cvv = '123'; 28 | 29 | $transaction = new MallTransaction(); 30 | $response = $transaction->create('buyOrder1', // ordenCompra12345678 31 | 'sessionId', // sesion1234564 32 | $cardNumber, // 4239000000000000 33 | $cardExpirationDate, // 22/10 34 | $transaction_details, $cvv); 35 | 36 | echo 'Create transaction'."\n"; 37 | print_r($response); 38 | 39 | $token = $response->getToken(); 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Installments 43 | |-------------------------------------------------------------------------- 44 | */ 45 | 46 | $installments_details = [ 47 | [ 48 | 'commerce_code' => TransaccionCompleta::DEFAULT_MALL_CHILD_COMMERCE_CODE_1, 49 | 'buy_order' => '123456789', 50 | 'installments_number' => 2, 51 | ], 52 | [ 53 | 'commerce_code' => TransaccionCompleta::DEFAULT_MALL_CHILD_COMMERCE_CODE_2, 54 | 'buy_order' => '123456790', 55 | 'installments_number' => 2, 56 | ], 57 | ]; 58 | 59 | $response = $transaction->installments($token, $installments_details); 60 | echo 'Installments'."\n"; 61 | print_r($response); 62 | 63 | $firstInstallmentResponse = $response[0]; 64 | $secondInstallmentResponse = $response[0]; 65 | $firstInstallmentResponse->getInstallmentsAmount(); 66 | $firstInstallmentResponse->getIdQueryInstallments(); 67 | $deferredPeriods = $firstInstallmentResponse->getDeferredPeriods(); 68 | if (isset($deferredPeriods[0])) { 69 | $deferredPeriod = $deferredPeriods[0]; 70 | $deferredPeriod->getAmount(); 71 | $deferredPeriod->getPeriod(); 72 | } 73 | 74 | /* 75 | |-------------------------------------------------------------------------- 76 | | Commit 77 | |-------------------------------------------------------------------------- 78 | */ 79 | 80 | $details = [ 81 | [ 82 | 'commerce_code' => TransaccionCompleta::DEFAULT_MALL_CHILD_COMMERCE_CODE_1, 83 | 'buy_order' => '123456789', 84 | 'id_query_installments' => $firstInstallmentResponse->getIdQueryInstallments(), 85 | 'deferred_period_index' => null, 86 | 'grace_period' => false, 87 | ], 88 | [ 89 | 'commerce_code' => TransaccionCompleta::DEFAULT_MALL_CHILD_COMMERCE_CODE_2, 90 | 'buy_order' => '123456790', 91 | 'id_query_installments' => $secondInstallmentResponse->getIdQueryInstallments(), 92 | 'deferred_period_index' => null, 93 | 'grace_period' => false, 94 | ], 95 | ]; 96 | 97 | $response = $transaction->commit($token, $details); 98 | echo 'Commit '."\n"; 99 | print_r($response); 100 | 101 | $response->getBuyOrder(); 102 | $response->getCardNumber(); 103 | $response->getAccountingDate(); 104 | $response->getTransactionDate(); 105 | $detail = $response->getDetails()[0]; 106 | $detail->getAuthorizationCode(); 107 | $detail->getPaymentTypeCode(); 108 | $detail->getResponseCode(); 109 | $detail->getInstallmentsAmount(); 110 | $detail->getInstallmentsNumber(); 111 | $detail->getAmount(); 112 | $detail->getCommerceCode(); 113 | $detail->getBuyOrder(); 114 | $detail->getStatus(); 115 | 116 | /* 117 | |-------------------------------------------------------------------------- 118 | | Refund 119 | |-------------------------------------------------------------------------- 120 | */ 121 | 122 | $response = $transaction->refund($token, '123456789', TransaccionCompleta::DEFAULT_MALL_CHILD_COMMERCE_CODE_1, 10000); 123 | 124 | echo 'Refund '."\n"; 125 | print_r($response); 126 | 127 | $response->getType(); 128 | $response->getAuthorizationCode(); 129 | $response->getAuthorizationDate(); 130 | $response->getNullifiedAmount(); 131 | $response->getBalance(); 132 | $response->getResponseCode(); 133 | 134 | /* 135 | |-------------------------------------------------------------------------- 136 | | Status 137 | |-------------------------------------------------------------------------- 138 | */ 139 | 140 | $response = $transaction->status($token); 141 | 142 | echo 'Status '."\n"; 143 | print_r($response); 144 | -------------------------------------------------------------------------------- /tests/OnepaySignUtilTest.php: -------------------------------------------------------------------------------- 1 | secret = OnepayBase::getSharedSecret(); 21 | 22 | $this->transactionCreateRequestTestObject = TransactionCreateRequestMocks::get(); 23 | $this->transactionCreateResponseTestObject = TransactionCreateResponseMocks::get(); 24 | 25 | $this->transactionCommitRequestTestObject = TransactionCommitRequestMocks::get(); 26 | $this->transactionCommitResponseTestObject = TransactionCommitResponseMocks::get(); 27 | 28 | $this->shoppingCartTestObject = ShoppingCartMocks::get(); 29 | } 30 | 31 | public function testCreatesOrReturnsSingleton() 32 | { 33 | $refClass = new \ReflectionClass(OnepaySignUtil::class); 34 | 35 | $this->assertTrue($refClass->hasProperty('instance')); 36 | 37 | $singleton = OnepaySignUtil::getInstance(); 38 | 39 | $this->assertTrue($singleton instanceof OnepaySignUtil); 40 | 41 | $shouldBeTheSameObject = OnepaySignUtil::getInstance(); 42 | 43 | $this->assertTrue($singleton === $shouldBeTheSameObject); 44 | } 45 | 46 | public function testBuildsValidSignatureForTransactionCreate() 47 | { 48 | $transactionCreateRequestTestObject = $this->transactionCreateRequestTestObject; 49 | // Sanity check, mock object signature should not be null. 50 | $this->assertNotNull($transactionCreateRequestTestObject); 51 | 52 | $originalSignature = $transactionCreateRequestTestObject->getSignature(); 53 | 54 | // Reset the testObject's signature 55 | $transactionCreateRequestTestObject->setSignature(null); 56 | 57 | OnepaySignUtil::getInstance()->sign($transactionCreateRequestTestObject, $this->secret); 58 | 59 | // Does the signer sign correctly? 60 | $this->assertEquals($originalSignature, $transactionCreateRequestTestObject->getSignature()); 61 | } 62 | 63 | public function testBuildsValidSignatureForTransactionCommit() 64 | { 65 | $transactionCommitRequestTestObject = $this->transactionCommitRequestTestObject; 66 | // Sanity check, mock object signature should not be null. 67 | $this->assertNotNull($transactionCommitRequestTestObject); 68 | 69 | $originalSignature = $transactionCommitRequestTestObject->getSignature(); 70 | 71 | // Reset the test object's signature 72 | $transactionCommitRequestTestObject->setSignature(null); 73 | OnepaySignUtil::getInstance()->sign($transactionCommitRequestTestObject, $this->secret); 74 | 75 | $this->assertEquals($originalSignature, $transactionCommitRequestTestObject->getSignature()); 76 | } 77 | 78 | public function testTryingToSignWhateverElseShouldRaiseSignException() 79 | { 80 | $this->expectException(\Transbank\Onepay\Exceptions\SignException::class); 81 | OnepaySignUtil::getInstance()->sign('a string', $this->secret); 82 | } 83 | 84 | public function testValidatesValidSignatureOnTransactionCreateResponse() 85 | { 86 | $transactionCreateResponse = $this->transactionCreateResponseTestObject; 87 | $signatureIsValid = OnepaySignUtil::getInstance()->validate($transactionCreateResponse, $this->secret); 88 | $this->assertTrue($signatureIsValid); 89 | } 90 | 91 | public function testValidatesInvalidSignatureOnTransactionCreateResponse() 92 | { 93 | $transactionCreateResponse = $this->transactionCreateResponseTestObject; 94 | $transactionCreateResponse->setSignature('totally not a valid signature'); 95 | $signatureIsValid = OnepaySignUtil::getInstance()->validate($transactionCreateResponse, $this->secret); 96 | $this->assertFalse($signatureIsValid); 97 | } 98 | 99 | public function testValidatesValidSignatureOnTransactionCommitResponse() 100 | { 101 | $transactionCommitResponse = $this->transactionCommitResponseTestObject; 102 | $signatureIsValid = OnepaySignUtil::getInstance()->validate($transactionCommitResponse, $this->secret); 103 | $this->assertTrue($signatureIsValid); 104 | } 105 | 106 | public function testValidatesInvalidSignatureOnTransactionCommitResponse() 107 | { 108 | $transactionCommitResponse = $this->transactionCommitResponseTestObject; 109 | $transactionCommitResponse->setSignature('totally not a valid signature.'); 110 | $signatureIsValid = OnepaySignUtil::getInstance()->validate($transactionCommitResponse, $this->secret); 111 | $this->assertFalse($signatureIsValid); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/Onepay/Item.php: -------------------------------------------------------------------------------- 1 | setDescription($description); 27 | $this->setQuantity($quantity); 28 | $this->setAmount($amount); 29 | $this->setAdditionalData($additionalData); 30 | $this->setExpire($expire); 31 | } 32 | 33 | public function jsonSerialize() 34 | { 35 | return get_object_vars($this); 36 | } 37 | 38 | public function setDescription($description) 39 | { 40 | if (!is_string($description)) { 41 | throw new \Exception('Description is not a string'); 42 | } 43 | $this->description = $description; 44 | } 45 | 46 | /** 47 | * Get Description for an instance of Item. 48 | */ 49 | public function getDescription() 50 | { 51 | return $this->description; 52 | } 53 | 54 | /** 55 | * Set the quantity for an instance of Item. 56 | */ 57 | public function setQuantity($quantity) 58 | { 59 | if (!is_integer($quantity)) { 60 | throw new \Exception('quantity must be an Integer'); 61 | } 62 | if ($quantity < 0) { 63 | throw new \Exception('quantity cannot be less than zero'); 64 | } 65 | $this->quantity = $quantity; 66 | } 67 | 68 | /** 69 | * Get the quantity for an instance of Item. 70 | */ 71 | public function getQuantity() 72 | { 73 | return $this->quantity; 74 | } 75 | 76 | /** 77 | * Set the quantity for an instance of Item. 78 | */ 79 | public function setAmount($amount) 80 | { 81 | if (!is_integer($amount)) { 82 | throw new \Exception('amount must be an Integer'); 83 | } 84 | $this->amount = $amount; 85 | } 86 | 87 | /** 88 | * Get the quantity for an instance of Item. 89 | */ 90 | public function getAmount() 91 | { 92 | return $this->amount; 93 | } 94 | 95 | /** 96 | * Set the additional data for an instance of Item. 97 | */ 98 | public function setAdditionalData($additionalData) 99 | { 100 | if (is_null($additionalData)) { 101 | $additionalData = ''; 102 | } 103 | if (!is_string($additionalData)) { 104 | throw new \Exception('Additional Data must be a String'); 105 | } 106 | $this->additionalData = $additionalData; 107 | } 108 | 109 | /** 110 | * Get the additional data for an instance of Item. 111 | */ 112 | public function getAdditionalData() 113 | { 114 | return $this->additionalData; 115 | } 116 | 117 | /** 118 | * Set expire for an instance of Item. 119 | */ 120 | public function setExpire($expire) 121 | { 122 | if (!is_long($expire)) { 123 | throw new \Exception('expire must be a Long'); 124 | } 125 | $this->expire = $expire; 126 | } 127 | 128 | /** 129 | * Get expire for an instance of Item. 130 | */ 131 | public function getExpire() 132 | { 133 | return $this->expire; 134 | } 135 | 136 | /** 137 | * Takes a associative array (or JSON string) 138 | * with the following shape: 139 | * $item = ("description" => "MANDATORY - A string", 140 | * "amount" => "MANDATORY - A number", 141 | * "quantity" => "MANDATORY - A number", 142 | * "additionalData" => "OPTIONAL - A string", 143 | * "expire" => "OPTIONAL - A number") 144 | * and creates a new instance of Item. 145 | */ 146 | public static function fromJSON($item) 147 | { 148 | if (is_string($item)) { 149 | $item = json_decode($item, true); 150 | } 151 | if (!is_array($item)) { 152 | throw new \Exception('Item must be a JSON string or an associative array that is transformable to an associative array using json_decode'); 153 | } 154 | /** 155 | * Define default values. 156 | */ 157 | $defaultValues = ['amount' => null, 158 | 'description' => null, 159 | 'quantity' => null, 160 | 'expire' => 0, 161 | 'additionalData' => null, ]; 162 | 163 | /** 164 | * Have the default values for all keys, event if they are not included 165 | * in the $item associative array originally. 166 | */ 167 | $item = array_merge($defaultValues, $item); 168 | 169 | return new Item( 170 | $item['description'], 171 | $item['quantity'], 172 | $item['amount'], 173 | $item['additionalData'], 174 | $item['expire'] 175 | ); 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /tests/Webpay/OneClick/TransbankOneclickTest.php: -------------------------------------------------------------------------------- 1 | createDemoData(); 26 | } 27 | 28 | /** @test */ 29 | public function it_creates_an_inscription() 30 | { 31 | $response = MallInscription::build()->start($this->username, $this->email, $this->responseUrl); 32 | $this->assertInstanceOf(InscriptionStartResponse::class, $response); 33 | $this->assertNotEmpty($response->getToken()); 34 | $this->assertNotEmpty($response->getUrlWebpay()); 35 | $this->assertStringContainsString($response->getToken(), $response->getRedirectUrl()); 36 | $this->assertStringContainsString($response->getUrlWebpay(), $response->getRedirectUrl()); 37 | } 38 | 39 | /** @test */ 40 | public function it_fails_creating_an_inscription_with_invalid_email() 41 | { 42 | $this->expectException(InscriptionStartException::class, 'Invalid value for parameter: email'); 43 | $response = MallInscription::build()->start($this->username, 'not_an_email', $this->responseUrl); 44 | } 45 | 46 | /** @test */ 47 | public function it_fails_creating_an_inscription_with_invalid_data() 48 | { 49 | $this->expectException(InscriptionStartException::class, 'username is required'); 50 | $response = MallInscription::build()->start('', $this->email, $this->responseUrl); 51 | } 52 | 53 | /** @test */ 54 | public function it_fails_trying_to_finish_inscription() 55 | { 56 | $this->createDemoData(); 57 | $startResponse = MallInscription::build()->start($this->username, $this->email, $this->responseUrl); 58 | $response = MallInscription::build()->finish($startResponse->getToken()); 59 | $this->assertInstanceOf(InscriptionFinishResponse::class, $response); 60 | 61 | // -96 means the inscription has not finished yet. 62 | $this->assertEquals(-96, $response->getResponseCode()); 63 | } 64 | 65 | /** @test */ 66 | public function it_fails_authorizing_a_transaction_with_a_fake_token() 67 | { 68 | $mallTransaction = new MallTransaction(); 69 | 70 | try { 71 | $response = $mallTransaction->authorize($this->username, 'fakeToken', 'buyOrder2132312', [ 72 | [ 73 | 'commerce_code' => MallInscription::DEFAULT_CHILD_COMMERCE_CODE_1, 74 | 'buy_order' => 'buyOrder122412', 75 | 'amount' => 1000, 76 | 'installments_number' => 1, 77 | ], 78 | ]); 79 | $this->assertTrue(false, 'Should not be executed this line'); 80 | } catch (MallTransactionAuthorizeException $exception) { 81 | $lastResponse = $mallTransaction->getRequestService()->getLastResponse(); 82 | $lastRequest = $mallTransaction->getRequestService()->getLastRequest(); 83 | $this->assertNotNull($lastResponse); 84 | $this->assertEquals($exception->getFailedRequest(), $lastRequest); 85 | $this->assertEquals(500, $lastResponse->getStatusCode()); 86 | 87 | $this->assertArraySubset([ 88 | 'username' => $this->username, 89 | 'tbk_user' => 'fakeToken', 90 | 'buy_order' => 'buyOrder2132312', 91 | 'details' => [ 92 | [ 93 | 'commerce_code' => MallInscription::DEFAULT_CHILD_COMMERCE_CODE_1, 94 | 'amount' => 1000, 95 | 'buy_order' => 'buyOrder122412', 96 | ], 97 | ], 98 | ], $lastRequest->getPayload()); 99 | } 100 | } 101 | 102 | /** @test */ 103 | public function it_fails_authorizing_a_transaction_with_no_username() 104 | { 105 | $this->expectException(MallTransactionAuthorizeException::class, 'username is required'); 106 | $response = MallTransaction::build()->authorize('', 'fakeToken', 'buyOrder2132312', [ 107 | [ 108 | 'commerce_code' => Oneclick::DEFAULT_CHILD_COMMERCE_CODE_1, 109 | 'buy_order' => 'buyOrder122412', 110 | 'amount' => 1000, 111 | 'installments_number' => 1, 112 | ], 113 | ]); 114 | } 115 | 116 | protected function createDemoData() 117 | { 118 | $this->username = 'demo_'.rand(100000, 999999); 119 | $this->email = 'demo_'.rand(100000, 999999).'@demo.cl'; 120 | $this->responseUrl = 'http://demo.cl/return'; 121 | } 122 | } 123 | --------------------------------------------------------------------------------