├── .gitignore
├── credentials
├── production
│ ├── onepay-keys.php
│ └── webpay.cert
└── integration
│ ├── onepay-keys.php
│ ├── webpay-plus-normal
│ ├── 597020000540.cert
│ └── 597020000540.key
│ ├── webpay-plus-mall
│ ├── 597044444401.cert
│ └── 597044444401.key
│ ├── webpay-oneclick-normal
│ ├── 597044444405.cert
│ └── 597044444405.key
│ ├── webpay-plus-capture
│ ├── 597044444404.cert
│ └── 597044444404.key
│ ├── webpay-patpass-normal
│ ├── 597020000548.cert
│ └── 597020000548.key
│ └── webpay.cert
├── .github
├── FUNDING.yml
└── workflows
│ └── php.yml
├── src
├── Exceptions
│ ├── Onepay
│ │ ├── OnepayException.php
│ │ ├── OnepayValidationException.php
│ │ ├── CartEmptyException.php
│ │ ├── CartNegativeAmountException.php
│ │ ├── OnepayResponseException.php
│ │ └── OnepayClientException.php
│ ├── Webpay
│ │ ├── WebpayException.php
│ │ ├── InvalidSignatureException.php
│ │ ├── TransactionTypeNullException.php
│ │ ├── ServiceSdkUnavailableException.php
│ │ ├── InvalidWebpayTransactionException.php
│ │ └── ErrorResponseException.php
│ ├── TransbankException.php
│ ├── TransbankUnavailableException.php
│ ├── Transbank
│ │ └── InvalidServiceException.php
│ └── Credentials
│ │ ├── CredentialInvalidException.php
│ │ └── CredentialsNotReadableException.php
├── Transactions
│ ├── Item.php
│ ├── Concerns
│ │ ├── HasSecrets.php
│ │ └── HasItems.php
│ ├── WebpayMallTransaction.php
│ ├── OnepayNullifyTransaction.php
│ ├── WebpayTransaction.php
│ └── AbstractTransaction.php
├── Responses
│ ├── WebpayPlusResponse.php
│ ├── WebpayPatpassResponse.php
│ ├── OnepayResponse.php
│ ├── WebpayOneclickResponse.php
│ ├── AbstractResponse.php
│ └── WebpayPlusMallResponse.php
├── Contracts
│ ├── README.md
│ ├── ResponseInterface.php
│ ├── AdapterInterface.php
│ ├── TransactionInterface.php
│ └── ServiceInterface.php
├── ResponseFactories
│ ├── AbstractResponseFactory.php
│ └── WebpayResponseFactory.php
├── Clients
│ ├── Webpay
│ │ ├── Concerns
│ │ │ ├── CommitsTransactions.php
│ │ │ ├── RetrievesResults.php
│ │ │ └── AcknowledgesTransactions.php
│ │ ├── PlusCapture.php
│ │ ├── SoapImplementation.php
│ │ ├── PlusNullify.php
│ │ ├── classmaps.php
│ │ ├── PlusNormal.php
│ │ └── WebpayClient.php
│ └── AbstractClient.php
├── Adapters
│ ├── AbstractAdapter.php
│ └── OnepayAdapter.php
├── TransactionFactories
│ ├── AbstractTransactionFactory.php
│ └── OnepayTransactionFactory.php
├── Helpers
│ └── Helpers.php
├── Concerns
│ ├── HasCredentialOperations.php
│ └── HasServiceGettersAndSetters.php
└── Onepay.php
├── results
├── translation.php
├── webpay.oneclick.php
└── onepay.php
├── examples
├── webpay-mall-normal
│ ├── final.php
│ ├── return.php
│ └── start.php
├── webpay-oneclick
│ ├── unregister.php
│ ├── reverse.php
│ ├── response.php
│ ├── charge.php
│ └── start.php
├── webpay-defer-capture-nullify
│ ├── nullify.php
│ ├── start.php
│ ├── return.php
│ └── capture.php
├── webpay-normal
│ ├── final.php
│ ├── return.php
│ └── start.php
├── _master
│ └── header.php
├── load.php
├── README.md
├── onepay
│ ├── nullify.php
│ ├── confirm.php
│ └── start.php
└── index.php
├── load.php
├── html
└── webpayRedirect.php
├── tests
├── Unit
│ ├── Clients
│ │ ├── AbstractClientTest.php
│ │ └── Webpay
│ │ │ ├── WebpayClientTest.php
│ │ │ ├── PlusCaptureTest.php
│ │ │ └── PlusNullifyTest.php
│ ├── Responses
│ │ ├── OnepayResponseTest.php
│ │ ├── WebpayPatpassResponseTest.php
│ │ ├── WebpayPlusResponseTest.php
│ │ ├── WebpayOneclickResponseTest.php
│ │ ├── AbstractResponseTest.php
│ │ └── WebpayPlusMallResponseTest.php
│ ├── Adapters
│ │ ├── AbstractAdapterTest.php
│ │ └── OnepayAdapterTest.php
│ ├── Helpers
│ │ └── HelpersTest.php
│ ├── Transactions
│ │ ├── Concerns
│ │ │ └── HasSecretsTest.php
│ │ ├── WebpayMallTransactionTest.php
│ │ ├── AbstractTransactionTest.php
│ │ └── WebpayTransactionTest.php
│ ├── Services
│ │ └── OnepayTest.php
│ └── TransactionFactories
│ │ └── OnepayTransactionFactoryTest.php
└── Feature
│ └── Integration
│ └── OnepayIntegrationTransactionsTest.php
├── phpunit.xml
├── LICENSE
├── LICENCIA
├── composer.json
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | composer.phar
3 | composer.lock
4 | vendor/
5 | logs/
6 | examples/webpay-oneclick/username.txt
7 |
--------------------------------------------------------------------------------
/credentials/production/onepay-keys.php:
--------------------------------------------------------------------------------
1 | '2B571C49-C1B6-4AD1-9806-592AC68023B7',
5 | ];
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # Help me support this package
2 |
3 | ko_fi: DarkGhostHunter
4 | custom: ['https://paypal.me/darkghosthunter']
5 |
--------------------------------------------------------------------------------
/src/Exceptions/Onepay/OnepayException.php:
--------------------------------------------------------------------------------
1 | include_once 'webpay.oneclick.php',
5 | 'webpay.plus' => include_once 'webpay.plus.php',
6 | 'onepay' => include_once 'onepay.php',
7 | ];
--------------------------------------------------------------------------------
/examples/webpay-mall-normal/final.php:
--------------------------------------------------------------------------------
1 | webpay();
6 |
7 | echo '
26 |
27 |
Información de pago enviado
28 |
toArray()); ?>
29 |
Resultado devuelto
30 |
toArray()); ?>
31 |
32 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/.github/workflows/php.yml:
--------------------------------------------------------------------------------
1 | name: PHP Composer
2 |
3 | on:
4 | push:
5 | pull_request:
6 |
7 | jobs:
8 | test:
9 |
10 | runs-on: ubuntu-latest
11 | strategy:
12 | fail-fast: true
13 | matrix:
14 | php: [7.4, 8.0]
15 | dependency-version: [prefer-stable, prefer-lowest]
16 |
17 | name: PHP ${{ matrix.php }} - ${{ matrix.dependency-version }}
18 |
19 | steps:
20 | - name: Checkout
21 | uses: actions/checkout@v2
22 |
23 | - name: Setup PHP
24 | uses: shivammathur/setup-php@v2
25 | with:
26 | php-version: ${{ matrix.php }}
27 | extensions: mbstring, intl
28 | coverage: xdebug
29 |
30 | - name: Cache dependencies
31 | uses: actions/cache@v2
32 | with:
33 | path: ~/.composer/cache/files
34 | key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
35 | restore-keys: ${{ runner.os }}-php-${{ matrix.php }}-composer-
36 |
37 | - name: Install dependencies
38 | run: composer update --${{ matrix.dependency-version }} --prefer-dist --no-progress --no-suggest
39 |
40 | - name: Run Tests
41 | run: composer run-script test
42 |
43 | - name: Upload Coverage to Coveralls
44 | env:
45 | COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
46 | COVERALLS_SERVICE_NAME: github
47 | run: |
48 | rm -rf composer.* vendor/
49 | composer require php-coveralls/php-coveralls
50 | vendor/bin/php-coveralls --coverage_clover=build/logs/clover.xml
51 |
--------------------------------------------------------------------------------
/src/Transactions/WebpayMallTransaction.php:
--------------------------------------------------------------------------------
1 | null,
18 | ];
19 |
20 | /**
21 | * OnepayTransaction constructor.
22 | *
23 | * @param array $attributes
24 | */
25 | public function __construct(array $attributes = [])
26 | {
27 | if (isset($attributes['items'])) {
28 | $this->setItemsFromConstruct($attributes['items']);
29 | unset($attributes['items']);
30 | }
31 |
32 | parent::__construct($attributes);
33 | }
34 |
35 | /**
36 | * Dynamically call the Items helpers as *Order* methods
37 | *
38 | * @param string $method
39 | * @param array $parameters
40 | * @return WebpayTransaction
41 | */
42 | public function __call($method, $parameters)
43 | {
44 | if (strpos($method, 'Order') !== false) {
45 | return $this->{str_replace('Order', 'Item', $method)}(...$parameters);
46 | }
47 |
48 | return parent::__call($method, $parameters);
49 | }
50 |
51 | /**
52 | * Transform the object to an array.
53 | *
54 | * @return array
55 | */
56 | public function toArray()
57 | {
58 | return array_merge(
59 | $this->attributes,
60 | ['items' => $this->items]
61 | );
62 | }
63 |
64 | }
--------------------------------------------------------------------------------
/src/Transactions/OnepayNullifyTransaction.php:
--------------------------------------------------------------------------------
1 | issuedAt = $this->issuedAt ?? time();
32 | }
33 |
34 | /*
35 | |--------------------------------------------------------------------------
36 | | Custom Array representation
37 | |--------------------------------------------------------------------------
38 | */
39 |
40 | /**
41 | * Transform the object to an array.
42 | *
43 | * @return array
44 | */
45 | public function toArray()
46 | {
47 | if ($this->hideSecrets) {
48 | return Helpers::arrayExcept($this->attributes, ['appKey', 'apiKey', 'signature']);
49 | }
50 |
51 | return $this->attributes;
52 | }
53 | }
--------------------------------------------------------------------------------
/src/Contracts/AdapterInterface.php:
--------------------------------------------------------------------------------
1 | count() === 1 && (Helpers::arrayFirst($this->attributes) === true)) {
30 | $this->isSuccess = true;
31 | $this->attributes = [];
32 | }
33 |
34 | if ($this->{$this->tokenName} || $this->reversed) {
35 | $this->isSuccess = true;
36 | }
37 |
38 | if (($this->attributes['responseCode'] ?? null) === 0) {
39 | $this->isSuccess = true;
40 | }
41 | }
42 |
43 | /*
44 | |--------------------------------------------------------------------------
45 | | Getters and Setters
46 | |--------------------------------------------------------------------------
47 | */
48 |
49 | /**
50 | * Catch the `urlWebpay` from Oneclick responses and fill it as `url`
51 | *
52 | * @param string $urlWebpay
53 | */
54 | public function setUrlWebpayAttribute(string $urlWebpay)
55 | {
56 | $this->attributes['url'] = $urlWebpay;
57 | }
58 | }
--------------------------------------------------------------------------------
/tests/Unit/Responses/WebpayOneclickResponseTest.php:
--------------------------------------------------------------------------------
1 | $url = 'http://webpay4g.this.com/is-a-test/',
14 | 'TBK_TOKEN' => $token = 'test-token',
15 | ]);
16 |
17 | $this->assertEquals($url, $response->url);
18 | $this->assertEquals($token, $response->TBK_TOKEN);
19 |
20 | }
21 |
22 | public function testDynamicallySetSuccessStatus()
23 | {
24 | $foo = new WebpayOneclickResponse([true]);
25 | $foo->dynamicallySetSuccessStatus();
26 |
27 | $this->assertTrue($foo->isSuccess());
28 |
29 | $bar = new WebpayOneclickResponse([
30 | 'urlWebpay' => $url = 'http://webpay4g.this.com/is-a-test/',
31 | 'TBK_TOKEN' => $token = 'test-token',
32 | ]);
33 | $bar->dynamicallySetSuccessStatus();
34 |
35 | $this->assertTrue($bar->isSuccess());
36 |
37 | $quz = new WebpayOneclickResponse(['responseCode' => 0]);
38 | $quz->dynamicallySetSuccessStatus();
39 |
40 | $this->assertTrue($quz->isSuccess());
41 |
42 | $qux = new WebpayOneclickResponse(['responseCode' => 1]);
43 | $qux->dynamicallySetSuccessStatus();
44 |
45 | $this->assertFalse($qux->isSuccess());
46 |
47 | $quuz = new WebpayOneclickResponse(['reversed' => 'anything']);
48 | $quuz->dynamicallySetSuccessStatus();
49 |
50 | $this->assertTrue($quuz->isSuccess());
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/credentials/integration/webpay-plus-mall/597044444401.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEowIBAAKCAQEAq5x8P9EIq8xT6UtRAL6pmNpcgYuIXHUvtPuY+Ao28LtbsJQV
3 | gPXJ2CrMYtq3GH1kPAajdF0tdfMOSQgxTnnWsMFdY6jel2vhF1vfKvm79yLMrqIR
4 | X7l/fZbldWJdoSuq1b3xTPYBKKGFhe/SvYpO88dvOuH4WIiAfRT1gFXkEW9xyA70
5 | vK/4RZR93f220ELh8sHBMwP39XnNp7c52A+f1fkJVP5F8G5UTAC/g/jDZMCrtnCw
6 | xu37jyXTEpQATXUN1XrsjJirpvNBfIvXQlk4AeXEj5a7PYE4nASZfNwSc1kpDm7G
7 | 6PheDkUXN1JEFscC/x9BpVvZIAjaXML/QCFV7wIDAQABAoIBAF/oGoBHwELS9GpD
8 | D0gNRhcIof48Dr8tNrY8jebBPqcW7k0m1UW3F1DZylPMy9rB6Qyq4RqdIFT0ux0R
9 | mQy0hslNp3WU4KFbRvaY/4Wy/9tD9YP7Sx5mOtvjQuVxTcZO8zB08LAEI+2jJ04N
10 | E4eeDjWrVXxg4TwJPVWqKvHIDqe26CfMlKohSpcCpmq3HQknnFfuxGGlNGdrX4YR
11 | v4BeoSsAG8Ak+cCkGBJ2LcrZpw+GJjs0SkvOVO1+G+vixYPDcor1moB1AnQ/tkrz
12 | gSrRIl+Et3nq5XmmxQejOgMMWaXR2RXutdgXq4w3s4FSwABv5Zw1zAA/yapfk1uH
13 | zJ/OpuECgYEA22kVGXhoR0onMSKKHnbtO3s3tmrgLwVQAMaEwYy8KNnIWkCLszlT
14 | KtJ7nmEDdMysbHpb1EeNAoKg/DKY0YgneWrmmh3JozUp18dXEeHqEVPH1X9XT017
15 | M24nqe65deFu9SKhZv9SQdj69iJLnRxPHSae/p5wb2ORr/XG+9ZX6OkCgYEAyDrK
16 | 95yH2b5CcZXvT+9laIO8OZvppTP923a8stofPfBXRmqRZdhLLOVMJhBiQtRSGz4w
17 | Tk0T1LC9FN9Y5y4HLbyYDuYxqda+MqdBoYgsvep4ozVNyE7UDdRTKOjin8xIArAn
18 | mPvhjVBtpvQE+r9A4CfLe2smyHUtW48nAxgugRcCgYAjgfgGLTRDBT8edoZ/s6Nk
19 | 0uYLQXSSZ3uxBG+LmykAO25vHK7/DDHnZjTXRr/2cQEedRbTXdj2JQnEhrOwhSZO
20 | QfybyGJPZVUmNH5kyHjG4RYf+QG6NcHQau1EVPvylc8NINOaBYvcWC8VEivGe0Ra
21 | ZVupvR5ZCHYVUeMn8mI7sQKBgQDG5cgq8Z3tSVbdWBAyOl9k07+NBniwt5XLhQZr
22 | L8trDqzTcRbfsVzzyw66nPnO4vRwxXTcwyoY1DvvWPIKKynMYBQ4cKgSyxOCY60J
23 | VakEOr79ePy8Jrn0xt6Yu8Yq8JTzvqKHEGZ8ptFVz/6GSqeaQ02ZWtZauDOHSQt6
24 | wnGnnwKBgFbTBEwXl89uZZ/25z1mA5D9nqHTj/A0GYc9762xc/bvkvi59DeYbNSH
25 | J7jKHS50kE4sS/E4p7e9/G4jZTe/nvEsstfFZprRF31xlVY9Y/1OPysGYIJPOTAg
26 | EBEKSypPpswFcn/jSeIGii7aEb5h6OyNpnSMbBvFxhhUJ1PPpUQG
27 | -----END RSA PRIVATE KEY-----
--------------------------------------------------------------------------------
/tests/Unit/Adapters/AbstractAdapterTest.php:
--------------------------------------------------------------------------------
1 | adapter = new class extends AbstractAdapter {
19 | public function getCredentials() { return $this->credentials; }
20 | public function commit(TransactionInterface $transaction, $options = null) {}
21 | public function retrieveAndConfirm($transaction, $options = null) {}
22 |
23 | public function __construct()
24 | {
25 | }
26 | };
27 | }
28 |
29 | public function testSetAndGetClient()
30 | {
31 | $this->adapter->setClient(new Fluid(['foo' => 'bar']));
32 |
33 | $this->assertEquals('bar', $this->adapter->getClient()->foo);
34 | }
35 |
36 | public function testSetCredentials()
37 | {
38 | $this->adapter->setCredentials(new Fluid(['foo' => 'bar']));
39 |
40 | $this->assertEquals('bar', $this->adapter->getCredentials()->foo);
41 | }
42 |
43 | public function testIsProduction()
44 | {
45 | $this->assertFalse($this->adapter->isProduction());
46 | }
47 |
48 | public function testSetIsProduction()
49 | {
50 | $this->adapter->setIsProduction(false);
51 | $this->assertFalse($this->adapter->isProduction());
52 | $this->adapter->setIsProduction(true);
53 | $this->assertTrue($this->adapter->isProduction());
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/credentials/integration/webpay-plus-normal/597020000540.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEowIBAAKCAQEAvuNgBxMAOBlNI7Fw5sHGY1p6DB6EMK83SL4b1ZILSJs/8/MC
3 | X8Pkys3CvJmSIiKU7fnWkgXchEdqXJV+tzgoED/y99tXgoMssi0ma+u9YtPvpT7B
4 | a5rk5HpLuaFNeuE3l+mpkXDZZKFSZJ1fV/Hyn3A1Zz+7+X2qiGrAWWdjeGsIkz4r
5 | uuMFLQVdPVrdAxEWoDRybEUhraQJ1kwmx92HFfRlsbNAmEljG9ngx/+/JLA28cs9
6 | oULy4/M7fVUzioKsBJmjRJd6s4rI2YIDpul6dmgloWgEfzfLNnAsZhJryJNBr2Wb
7 | E6DL5x/U2XQchjishMbDIPjmDgS0HLLMjRCMpQIDAQABAoIBAEkSwa/zliHjjaQc
8 | SRwNEeT2vcHl7LS2XnN6Uy1uuuMQi2rXnBEM7Ii2O9X28/odQuXWvk0n8UKyFAVd
9 | NSTuWmfeEyTO0rEjhfivUAYAOH+coiCf5WtL4FOWfWaSWRaxIJcG2+LRUGc1WlUp
10 | 6VXBSR+/1LGxtEPN13phY0DWUz3FEfGBd4CCPLpzq7HyZWEHUvbaw89xZJSr/Zwh
11 | BDZZyTbuwSHc9X9LlQsbaDuW/EyOMmDvSxmSRJO10FRMxyg8qbE4edtUK4jd61i0
12 | kGFqdDu9sj5k8pDxOsN2F270SMlIwejZ1uunB87w9ezIcR9YLq9aa22cT8BZdOxb
13 | uZ3PAAECgYEA6xfgRtcvpJUBWBVNsxrSg6Ktx2848eQne9NnbWHdZuNjH8OyN7SW
14 | Fn0r4HsTw59/NJ1L5F3co5L5baEtRbRLWRpD72xjrXsQSsoKliCik1xgDIplMvOh
15 | teA2GdeSv9wglqnotGcj5B/8+vn3tEzMjy+UUsyFn0fIaDC3zK3W2qUCgYEAz90g
16 | va+FCcU8cnykb5Yn1u1izdK1c6S++v1bQFf6590ZMNy3p0uGrwAk/MzuBkJ421GK
17 | p4pInUvO/Mb2BCcoHtr3ON3v0DCLl6Ae2Gb7lG0dLgcZ1EK7MDpMvKCqNHAv8Qu8
18 | QBZOA08L8buVkkRt7jxJrPuOFDI5JAaWCmMOSgECgYEA3GvzfZgu9Go862B2DJL+
19 | hCuYMiCHTM01c/UfyT/z/Y7/ln2+8FniS02rQPtE6ar28tb0nDahM8EPGon/T5ae
20 | +vkUbzy6LKLxAJ501JPeurnm2Hs+LUqe+U8yioJD9p2m9Hx0UglOborLgGm0pRlI
21 | xou+zu8x7ci5D292NXNcun0CgYAVKV378bKJnBrbTPUwpwjHSMOWUK1IaK1IwCJa
22 | GprgoBHAd7f6wCWmC024ruRMntfO/C4xgFKEMQORmG/TXGkpOwGQOIgBme+cMCDz
23 | xwg1xCYEWZS3l1OXRVgqm/C4BfPbhmZT3/FxRMrigUZo7a6DYn/drH56b+KBWGpO
24 | BGegAQKBgGY7Ikdw288DShbEVi6BFjHKDej3hUfsTwncRhD4IAgALzaatuta7JFW
25 | NrGTVGeK/rE6utA/DPlP0H2EgkUAzt8x3N0MuVoBl/Ow7y5sqIQKfEI7h0aRdXH5
26 | ecefOL6iiJWQqX2+237NOd0fJ4E1+BCMu/+HnyCX+cFM2FgoE6tC
27 | -----END RSA PRIVATE KEY-----
--------------------------------------------------------------------------------
/credentials/integration/webpay-oneclick-normal/597044444405.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEA48S877GUtjlYrqIQDlZAMqg5kfNrrZlCZckC1LGzCfcPu7Lm
3 | za2c2F1Q7zKELqVTo1wuZUS1inhYmtg4PexDKak/uryARR3uy2kqq3yG3IQNIdQY
4 | RpAUl8SvNyJvUVtA0N6nwjaqsTv1EacOLsfR+9HNvRXaWSitXNFa7i2G0iN/pnXb
5 | a796mUMVMwJPkV6Si6608566mvqkSnvzulAaC/eev1KIyH5oF22yjyWRIM+K9ZNx
6 | 7Cosnxgmt6e/8AazGBxA7gXxV6DQtOvL6k4AottUro2hMXLUZRS3x4GjtJDUjpLj
7 | UIHpK5Tz66D8dGN+Kv/f/Y7bAWMHUQqrPHkAcQIDAQABAoIBAEEcqeJfwqKBLE/n
8 | 9m0SzRFuM978VmjvKiMM3qlND2Cm5zGCSCa+HdtgedWXfGAVVR6bKIw8oyUtmC7T
9 | 5ugU1XJgdt58KrMXhn9R1ifl1mvNuC9WgYYShECKsogxaN86FgJf1FdZ51v5Ruq/
10 | 9fb7mpTBem42hA/+5+hj1PnHvAXwI9/erX8nZIixtj9PVJOzUW/izlJVm9DoT2vM
11 | JZAt/HXZqovvsSet5tRfTPTuFH+NTXnfpHbDGPDqQrC+fqTaZCFJXU0lgWemBdM2
12 | HIafstxFhY5cbgYKl6nW8SQNQQUG7ifJ5ttz7jNqZ3X9hk2yIvK+0Dd1NKTlJoAS
13 | 5V8FL00CgYEA96jBRG4I2P0rbQl7Elf5A4xS9ruFgQtS6//9g5ezLmxtiVQhryl4
14 | 4PKKWY1nRPhQBQaQdp6H9w8rU5ccyAFjW4hDfD8jwTCE1On1dSfBWcrBir4LL/Dm
15 | WbOgrh2jotvAmInkl6GohwRZIF77kRQXc+Zv2Xle2o+JMv4keBmuk+sCgYEA63B9
16 | yoV0qhuTnrFNW99rQTQ8WnfUYdmau/4W2CSkNVgZ04j5xKe2FzBkQHnvCDX5THkW
17 | YVsq0J/F3BBApKvKwACVdri19odJRi2JgbJarMZb+xro8kqAZ3KvXkXTYpxkBk7S
18 | hkHBrj6sXe+I3usNN3iH80z6ZTsg2dBU7cp4khMCgYEA0amCBKaKwviBnQubr0ne
19 | vAw96DeUrEyj5LuRKahxvul4Sfx5j8qyVO3ABlRZiuAVDkwiXOmU/alP6rJRYVkb
20 | fk/7oeHqKREkQwPWE1qWq6ek9goxemKdAG+7pevdrnAPupNyfJQVEkiyE1+V5Zp2
21 | yF3bbub7UFiXtB3HTg2f6AUCgYEAt9DQ9TAywKjdHRXyfts1IuhEgqFx2J+LNmEP
22 | ttsMtXU+XLBhyQ7jlME8VDaez/tL00/qkEIccFt9n+20epyBpFwQVWuq7Xn8VGUz
23 | KWZ1ctU/dRIycxCFpb6dem3rtt7BHUenCBkIvSDDdGeSpfBAFmHtSqB8ElMSt9v2
24 | otzkO68CgYBhIDz4rTMuOxmt9yily7rcd9J7RrbC7hPHMjM5EwPyOmawAYjTRM8X
25 | rxe1w4MtKrXxn11EncMJuH0hLQ12MwmrTui7gllTi8IPkfe+e7yhgHzzB5Mnhax0
26 | 92jL5rYiTenvy/wIjmF3TDHwyX6dB6QuozltdYBE2rv/oXOrE19qCQ==
27 | -----END RSA PRIVATE KEY-----
--------------------------------------------------------------------------------
/credentials/integration/webpay-patpass-normal/597020000548.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpQIBAAKCAQEA0t4cnHnAr/05KYwk+2ziYKUAxk/E0LhpG8KSyJp9Kl1G09I8
3 | xBhSnF23XpEm6grgKmxzbGtj8t8u9P54sNxNrcs0tawV0qHfzsS63hAJ1254LeZA
4 | uTVpWXUnEl4DWI9Pq67OWUovUPL/mQzcZBJShspC6zX0unfWRnoDeNtx07aj/xq0
5 | PXXtqOEJhyY6EyRsO9XWPVKIm5ZnVCBg9mtrZZkwwROETlD65meCE6gYC6WFrB5F
6 | UvjS72CnA0ZynFj/Vb4Ymi6Ot5M3f0NmGG9q0kweOQfNyv+e/QoB7KVHLrpMdcKO
7 | 70D+ItPK4wdUlOfbTZJYWUaK6F/z2LkF0APD0QIDAQABAoIBAFrSRZpzqjViqHMn
8 | pGoSLLKZfurrQobvVn4ZYOU7/Pr5L99d5sRDAZnNl4QImq0lQAWlrlUdL/BUhkIJ
9 | NGxghqh7JFm3I7MT+3RwMVghqkt6jhKe4HOk+JoKJmj3yxMirprwcHnuxNBlyQbf
10 | jjEf3yGlDguGssB5ivXR6ZrtUWpwsK9OBiRctSeceFE4r68ldDKRFVLNURkK1AEd
11 | lCbhWp1a8W5CKvPjj6Rpq9r1kmTJA1h9NSkLum4f7aewvFhG6bHWEcjA6EWieipj
12 | 2zk74/1HBDpujHJSUzTcXbiIsOVtY2Qh+74CMzHUUS41dGQNk/l/qUk7tRljwjFm
13 | PerH1FECgYEA6IKDDTbaLNsK4BefqlXZvCXbm0irxCb3XvvcsTqcDyZG0KWOCoXw
14 | B24xrsMfbheR0L6x4JUS6RM4bvTEhK4gJzDDeFhfPj2Kuav9nl1oEOZaJ5rxLlz7
15 | 90g/f6kqjW3qlBVSFtz/jVrAk+lju9piHudwerjLA7TXLLm0tJZf7N0CgYEA6Cvc
16 | HzDhxdNYVakWsTBKI/uOUwt7cbHUr7OfoQA5dTxqHvFKBjrY3rgcI3/4vU3cEwRm
17 | a4X6RRSljyKAel54h4eJndP9+dB3VrOOkvuHXOLEVwwzfdaO+4FRQXR+0i9T46RK
18 | 7FJy6XLfhPwZozebXbSTg/WZJ5UczVmxBYzquYUCgYEAu1t/0wQiZwbTCqS+qnmn
19 | jK9M+SJkFxn3N/joa3/5BVQouDTP8rbfJn2rV1IwX3xqqbUgjQJTTLGKRg7C1M+j
20 | ZTEsMiu0A+l/ggKPyi8mjoewmj2Gn3+aIjd7w5lDitfJsS5FCdtnqjY4/HeTQGrH
21 | qnOA9cM3BHOS+J1keii6f5kCgYEAofbO9bdtGUuJySBPY0azwgxgSlCtSjBrljLx
22 | vihg7Qc7ZOCg6l2tIxo/DwjcZntldqLQLFxnrj9sC8Fe7X7wCGQmPcNA30BtsD9M
23 | y/7KfKL5o1wwo63FS3D4VXhGbKx1kk3vspMF9ROdGLGh1Poa2bD6Y8k2kaV1VVAn
24 | rR6UNN0CgYEAgWw0NRz9X3V5K0WfrXnqBEvDiJ9MnsO3Y0SmV+zbTVYQ2zf2iYT+
25 | Wp4Tpjfc2k8s1dU33YnsrLaecB3gEFeEHJdN9qOPkk/yElVrcCKfFEUmPu7wvHZI
26 | yCLqC4NXGoXossGlQ2XPCSYacEQ5JJTtv+sBufhJZTwuqEBSGS7PurA=
27 | -----END RSA PRIVATE KEY-----
--------------------------------------------------------------------------------
/credentials/integration/webpay-plus-capture/597044444404.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpQIBAAKCAQEAq62F11DVV2ciL/S/zKr8NmesZNUoI3t/9EbZ5m97LjH/R1s2
3 | 0MxJWjmy0f+I64PvJkGOvQauBdJoGiiCeiV3qY+PppgOQmMo8xXaPzErrVr0F9bx
4 | 3gbqSuqi/uwJNJRWUs3tYmlQ/WQrKHSMxpRkVthWoIpyR3UEBpr9N9MhAdDarJCv
5 | /df9Hyu3RpE7ULFCnCHi/y3DVPYi3TnXa4xo9fE3iVuxMNjCUO93GqETYVCRoIW/
6 | 237frd8tgZ3biNmYRqbxO6jIv/1uEJs2mxPaW+FmdpW4+yM1tK8e8mWV/OrqpslZ
7 | O0mqUVY16phJJW7ad4fi0V3+TCRwgY0MC6x6uwIDAQABAoIBAQCktQoflXHZNR1b
8 | nRkWp0TqfXSsGMU1pZsRJZiQuIwZueYM87oXgKcvZQPm7Z7TNfUPYv4q5Gm5NDCk
9 | SBFGVwQDLbTIREIJ91CmR2ToE6iv3P8qkBHkzgWicpKGuLXsOBTJxL/nFtuY/61Y
10 | Vtlo+514pH4X8DvLyrxeCfy+vlSAg+mcs+35wnxC+qvAESYXQKODorGljmthkqyd
11 | P/ONKef+PsyJuUevne2YSkiqaDywGBe5JRS+Ij74UH7d+/+hDS9AMwj+nrlVE/Bj
12 | Y1zCw0BijKNuwnoF9oHMZvshfV2GkpS237tmXDbn+fJOqWfonb/CkBtWsF86N79h
13 | /x+gJQ8hAoGBANeQ8/fDA8azfh6z6Ar6C0XIxgZppLtGPac65JhyKCYtvH1kzhJU
14 | dnBqcMOxj9K3zbK3A21Y3gBMZvNS9Wja8Pk7r0R6aHU7eMOlEiOoEdeoVtlOpj4p
15 | Y87Yc8vojd0nnuWJpxw6R8MvzJBm750tIE0/rv2+vfDeaxiWUexhrq0FAoGBAMvh
16 | I5saf9OTJLvBfu8gqldLGdlkG1+1eyxnJbQuHq6o+WsaxjFEwS5a8MOlD7my0tom
17 | zm98fiFHpGX3HGoG9RQuvRKmWRCdj5qb7Bep3gWb9HOKYG+6DKGPPpmJ6fdjV9zh
18 | o5ru5iFJoWHcE60/kVbOJsh6ugVXFzF6DJaBkRS/AoGBAK3Bv4VkgjS2FeD1rwK6
19 | DkAP197vZMM3mRalGAHxcn9jul1w1dJclqOCiKaVB5MYaQu3DWIkkb231/wmUH5W
20 | jIq5G0udR3nHmE5LTlXDca5dmLPM+597iWH/g0dHiqJK/3+R90t/hrzEWKXE8zvE
21 | VhcuUAVkrIHtJnJJKHvbOQtpAoGAXEqPVrAZO0p5r3C5KECOO7PogKs7ZQj/OCt9
22 | OuJBy2j8d0qIe1cXaAeMw9PdmX9kyZIVkww1AJWwyuOg/jImETvTJTUeTlI05pU8
23 | u72OntVpREBYxVrgSuZQPSrcObvD015lNEZ+8ISnRGhek+eZwETT857yxGYXPrN0
24 | LVF7vnsCgYEApWvaUImePJDN50+nExK6TWHGFNnlZPlqFuyEHCSIlC0moGkcdl1D
25 | uILlje5JjmCI6hUreePcpFbyuiWcFcRJPdTgPWAcuWpPqFk3TyMVg8RQjZ4nIb4e
26 | TB3lRTP7u4t4emHHeNZhSeakRMOUYWiylCgSLmmf1OKd/bWTQ6G7lk0=
27 | -----END RSA PRIVATE KEY-----
--------------------------------------------------------------------------------
/examples/onepay/start.php:
--------------------------------------------------------------------------------
1 | setDefaults('onepay', [
8 | 'channel' => 'web',
9 | 'generateOttQrCode' => true,
10 | 'callbackUrl' => currentUrlPath('confirm.php'),
11 | ]);
12 |
13 | $onepay = $transbank->onepay();
14 |
15 | $cart = $onepay->makeCart([
16 | 'items' => [
17 | 'description' => 'Producto de Prueba',
18 | 'quantity' => 2,
19 | 'amount' => 9990,
20 | ]
21 | ]);
22 |
23 | $result = $cart->commit();
24 | ?>
25 |
26 |
27 |
28 |
29 |
Conectando con Onepay...
30 |
31 |
32 |
33 |
34 |
Cesta enviada:
35 |
toArray()) ?>
36 |
Respuesta:
37 |
toArray()) ?>
38 |
39 |
40 | 1) Procesar compra de prueba en dashboard
41 |
42 |
43 | - E-mail: test@onepay.cl
44 | - Código de compra: ott ?>
45 |
46 |
47 |
2) Confirmar compra internamente:
48 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/examples/index.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
Ejemplos de integración de Servicios Transbank
9 |
10 |
11 |
12 |
13 |
14 |
Ejemplos de integración de Servicios Transbank
15 |
16 | Todos estos ejemplos usan las credenciales de integración suministradas por Transbank, así que no es necesario hacer nada más que probar cómo funcionan las transacciones.
17 |
18 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/Adapters/AbstractAdapter.php:
--------------------------------------------------------------------------------
1 | client = $client;
39 | }
40 |
41 | /**
42 | * Returns the Client used to communicate with Transbank
43 | *
44 | * @return object
45 | */
46 | public function getClient()
47 | {
48 | return $this->client;
49 | }
50 |
51 | /**
52 | * Sets credentials to use against Transbank SDK
53 | *
54 | * @param Fluid $credentials
55 | * @return mixed
56 | */
57 | public function setCredentials(Fluid $credentials)
58 | {
59 | $this->credentials = $credentials;
60 | }
61 |
62 | /**
63 | * Returns if the environment is Production
64 | *
65 | * @return bool
66 | */
67 | public function isProduction()
68 | {
69 | return $this->isProduction;
70 | }
71 |
72 | /**
73 | * Sets if the the environment is Production
74 | *
75 | * @param bool $isProduction
76 | */
77 | public function setIsProduction(bool $isProduction)
78 | {
79 | $this->isProduction = $isProduction;
80 | }
81 | }
--------------------------------------------------------------------------------
/src/Clients/Webpay/PlusCapture.php:
--------------------------------------------------------------------------------
1 | $transaction->authorizationCode,
31 | 'buyOrder' => $transaction->buyOrder,
32 | 'captureAmount' => $transaction->captureAmount,
33 | 'commerceId' => $transaction->commerceId ?? $this->credentials->commerceCode,
34 | ];
35 |
36 | try {
37 | // Perform the capture with the data, and return if validates
38 | $response = $this->performCapture($capture);
39 | } catch (Exception $e) {
40 | throw new ErrorResponseException($e->getMessage(), $e->getCode(), $e);
41 | }
42 |
43 | if ($this->validate()) {
44 | return $response;
45 | };
46 |
47 | throw new InvalidSignatureException();
48 | }
49 |
50 | /**
51 | * Performs the Webpay Soap Capture operation
52 | *
53 | * @param $capture
54 | * @return array
55 | */
56 | protected function performCapture($capture)
57 | {
58 | return (array)($this->connector->capture([
59 | 'captureInput' => $capture
60 | ]))->return;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/tests/Unit/Responses/AbstractResponseTest.php:
--------------------------------------------------------------------------------
1 | response = new class extends AbstractResponse {
16 | protected $tokenName = 'old-token';
17 | protected $listKey = 'webpay.plus';
18 | protected $errorCode = -8;
19 | public function dynamicallySetSuccessStatus()
20 | {
21 | $this->isSuccess = true;
22 | }
23 | };
24 | }
25 |
26 | public function testGetAndSetTokenName()
27 | {
28 | $this->assertEquals('old-token', $this->response->getTokenName());
29 | $this->response->setTokenName('new-token');
30 | $this->assertEquals('new-token', $this->response->getTokenName());
31 | }
32 |
33 | public function testDynamicallySetSuccessStatus()
34 | {
35 | $this->response->dynamicallySetSuccessStatus();
36 | $this->assertTrue($this->response->isSuccess());
37 | }
38 |
39 | public function testGetErrorForHumans()
40 | {
41 | $errorCode = 'Rubro no autorizado.';
42 |
43 | $this->assertEquals($errorCode, $this->response->getErrorForHumans());
44 | }
45 |
46 | public function testSuccess()
47 | {
48 | $this->response->dynamicallySetSuccessStatus();
49 |
50 | $this->assertTrue($this->response->isSuccess());
51 | $this->assertFalse($this->response->isFailed());
52 | }
53 |
54 | public function testGetAndSetType()
55 | {
56 | $this->response->setType('mock-type');
57 | $this->assertEquals('mock-type', $this->response->getType());
58 | }
59 |
60 | public function testGetErrorCode()
61 | {
62 | $this->assertEquals(-8, $this->response->getErrorCode());
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/TransactionFactories/AbstractTransactionFactory.php:
--------------------------------------------------------------------------------
1 | service = $service;
32 | $this->defaults = $defaults;
33 | }
34 |
35 | /**
36 | * Returns an instance of a Transaction
37 | *
38 | * @param string $type
39 | * @param array $attributes
40 | * @return AbstractTransaction
41 | */
42 | abstract protected function makeTransaction(string $type, array $attributes = []);
43 |
44 | /**
45 | * Injects Service, Defaults and Type to the Transaction
46 | *
47 | * @param string $type
48 | * @param AbstractTransaction $transaction
49 | * @return AbstractTransaction
50 | */
51 | protected function prepareTransaction(string $type, AbstractTransaction $transaction)
52 | {
53 | // The Type of the transaction, so the Adapter can differentiate how
54 | // to commit it to Transbank if there is more than one.
55 | $transaction->setType($type);
56 |
57 | // Setting the services allows to commit it using the Service's Adapter.
58 | $transaction->setService($this->service);
59 |
60 | // If it has defaults, they will be appended
61 | $transaction->setDefaults($this->defaults);
62 |
63 | return $transaction;
64 | }
65 |
66 | }
--------------------------------------------------------------------------------
/src/Contracts/TransactionInterface.php:
--------------------------------------------------------------------------------
1 | 'bar',
16 | 'baz' => 'qux',
17 | 'quuz' => 'quux',
18 | ];
19 |
20 | $only = Helpers::arrayOnly($array, ['baz', 'quuz']);
21 |
22 | $this->assertArrayHasKey('baz', $only);
23 | $this->assertArrayHasKey('quuz', $only);
24 | $this->assertArrayNotHasKey('foo', $only);
25 | }
26 |
27 | public function testClassBasename()
28 | {
29 | $name = Helpers::classBasename(self::class);
30 |
31 | $this->assertEquals('HelpersTest', $name);
32 |
33 | $name = Helpers::classBasename('anything');
34 |
35 | $this->assertNull($name);
36 | }
37 |
38 | public function testArrayExcept()
39 | {
40 | $array = [
41 | 'foo' => 'bar',
42 | 'baz' => 'qux',
43 | 'quuz' => 'quux',
44 | ];
45 |
46 | $except = Helpers::arrayExcept($array, ['foo']);
47 |
48 | $this->assertArrayNotHasKey('foo', $except);
49 | $this->assertArrayHasKey('baz', $except);
50 | $this->assertArrayHasKey('quuz', $except);
51 | }
52 |
53 | public function testDirContents()
54 | {
55 | $contents = Helpers::dirContents(__DIR__);
56 |
57 | $this->assertIsArray($contents);
58 | $this->assertTrue(in_array('HelpersTest.php', $contents));
59 | }
60 |
61 | public function testIsNumericArray()
62 | {
63 | $arrayNumeric = [
64 | 'foo', 'bar', 'baz'
65 | ];
66 |
67 | $arrayNotNumeric = [
68 | 'foo' => 'bar',
69 | 'baz' => 'qux',
70 | 'quuz' => 'quux',
71 | ];
72 |
73 | $this->assertTrue(Helpers::isNumericArray($arrayNumeric));
74 | $this->assertFalse(Helpers::isNumericArray($arrayNotNumeric));
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/Clients/Webpay/SoapImplementation.php:
--------------------------------------------------------------------------------
1 | privateKey = $privateKey;
48 | $this->publicCert = $publicCert;
49 |
50 | parent::__construct($wsdl, $options);
51 | }
52 |
53 | /**
54 | * Makes a Request and validates it
55 | *
56 | * @param string $request
57 | * @param string $location
58 | * @param string $saction
59 | * @param int $version
60 | * @param null $one_way
61 | * @return string
62 | */
63 | public function __doRequest($request, $location, $saction, $version, $one_way = null)
64 | {
65 | $process = new Process($request);
66 | $process->sign($this->privateKey);
67 | $process->addIssuer($this->publicCert);
68 | $signedRequest = $process->getXML();
69 |
70 | $retVal = parent::__doRequest(
71 | $signedRequest,
72 | $location,
73 | $saction,
74 | $version,
75 | $one_way
76 | );
77 |
78 | $doc = new DOMDocument();
79 | $doc->loadXML($retVal);
80 | return $doc->saveXML();
81 | }
82 |
83 | }
--------------------------------------------------------------------------------
/tests/Unit/Transactions/Concerns/HasSecretsTest.php:
--------------------------------------------------------------------------------
1 | fluent = new class extends Fluid {
19 | use HasSecrets;
20 | protected $attributes = [
21 | 'foo' => 'bar',
22 | 'baz' => 'qux'
23 | ];
24 |
25 | public function toArray()
26 | {
27 | if ($this->hideSecrets) {
28 | return Helpers::arrayExcept($this->attributes, ['foo']);
29 | }
30 | return $this->attributes;
31 | }
32 | };
33 | }
34 |
35 | public function testHideSecrets()
36 | {
37 | $this->fluent->hideSecrets();
38 | $this->assertTrue($this->fluent->isHidingSecrets());
39 | $this->fluent->showSecrets();
40 | $this->assertFalse($this->fluent->isHidingSecrets());
41 | }
42 |
43 | public function testManipulatesSerialization()
44 | {
45 | $this->fluent->hideSecrets();
46 |
47 | $this->assertEquals('bar', $this->fluent->foo);
48 | $this->assertEquals('qux', $this->fluent->baz);
49 | $this->assertStringNotContainsString('bar', $this->fluent->toJson());
50 | $this->assertStringContainsString('qux', $this->fluent->toJson());
51 | $this->assertArrayNotHasKey('foo', $this->fluent->toArray());
52 | $this->assertArrayHasKey('baz', $this->fluent->toArray());
53 |
54 | $this->fluent->showSecrets();
55 |
56 | $this->assertEquals('bar', $this->fluent->foo);
57 | $this->assertEquals('qux', $this->fluent->baz);
58 | $this->assertStringContainsString('bar', $this->fluent->toJson());
59 | $this->assertStringContainsString('qux', $this->fluent->toJson());
60 | $this->assertArrayHasKey('foo', $this->fluent->toArray());
61 | $this->assertArrayHasKey('baz', $this->fluent->toArray());
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/tests/Unit/Transactions/WebpayMallTransactionTest.php:
--------------------------------------------------------------------------------
1 | $items = [
17 | ['foo' => 'bar'],
18 | ['baz' => 'qux']
19 | ]
20 | ]);
21 |
22 | foreach ($items as &$item) {
23 | $item = new Item(array_merge($item, ['sessionId' => null]));
24 | }
25 |
26 | $this->assertEquals($items, $transaction->getItems());
27 | }
28 |
29 | public function testToArray()
30 | {
31 | $transaction = new WebpayMallTransaction([
32 | 'items' => $items = [
33 | ['foo' => 'bar'],
34 | ['baz' => 'qux']
35 | ]
36 | ]);
37 |
38 | $this->assertCount(2, $transaction->getItems());
39 | $this->assertEquals('bar', $transaction->getItem(0)->foo);
40 | $this->assertEquals('qux', $transaction->getItem(1)->baz);
41 | }
42 |
43 | public function testCallsOrderMethodAsItems()
44 | {
45 | $transaction = new WebpayMallTransaction([
46 | 'items' => [
47 | ['foo' => 'bar'],
48 | ['baz' => 'qux']
49 | ]
50 | ]);
51 |
52 | $transaction->addOrder([
53 | 'quux' => 'quuz'
54 | ]);
55 |
56 | $this->assertCount(3, $transaction->getOrders());
57 | $this->assertEquals('bar', $transaction->getOrder(0)->foo);
58 | $this->assertEquals('qux', $transaction->getOrder(1)->baz);
59 | $this->assertEquals('quuz', $transaction->getOrder(2)->quux);
60 | }
61 |
62 | public function testExceptionOnCallingInvalidMethod()
63 | {
64 | $this->expectException(BadMethodCallException::class);
65 |
66 | $transaction = new WebpayMallTransaction([
67 | 'items' => [
68 | ['foo' => 'bar'],
69 | ['baz' => 'qux']
70 | ]
71 | ]);
72 |
73 | $transaction->anything();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/Transactions/WebpayTransaction.php:
--------------------------------------------------------------------------------
1 | type) {
17 | case 'plus.normal':
18 | case 'plus.defer':
19 | $defaults = $this->filterDefaults(
20 | 'plus', ['plusReturnUrl', 'plusFinalUrl'], $defaults
21 | );
22 | break;
23 | case 'plus.mall.normal':
24 | case 'plus.mall.defer':
25 | $defaults = $this->filterDefaults(
26 | 'plusMall', ['plusMallReturnUrl', 'plusMallFinalUrl'], $defaults
27 | );
28 | break;
29 | case 'oneclick.register':
30 | $defaults = $this->filterDefaults(
31 | 'oneclick', ['oneclickResponseURL'], $defaults
32 | );
33 | break;
34 | default:
35 | $defaults = [];
36 | break;
37 | }
38 |
39 | parent::setDefaults($defaults);
40 | }
41 |
42 | /**
43 | * Filter the defaults for the Transaction type
44 | *
45 | * @param string $service
46 | * @param array $only
47 | * @param array $defaults
48 | * @return array
49 | */
50 | protected function filterDefaults(string $service, array $only, array $defaults)
51 | {
52 | foreach (Helpers::arrayOnly($defaults, $only) as $name => $default) {
53 | $result[lcfirst(str_replace($service, '', $name))] = $default;
54 | }
55 | return $result ?? [];
56 | }
57 |
58 | /**
59 | * Fills Empty Attributes
60 | */
61 | protected function fillEmptyAttributes()
62 | {
63 | // Create the BuyOder with the required timestamp only when this
64 | // transaction is a Webpay Oneclick Charge.
65 | if ($this->type === 'oneclick.charge' && strlen((string)$this->buyOrder) < 14) {
66 | $this->buyOrder = date('YmdHis') . (substr((string)$this->buyOrder, -3) ?? '000');
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/src/Helpers/Helpers.php:
--------------------------------------------------------------------------------
1 | getShortName();
21 | } catch (ReflectionException $e) {
22 | return null;
23 | }
24 | }
25 |
26 | /**
27 | * Return the directory contents without dots directories.
28 | *
29 | * @param string $directory
30 | * @return array|null
31 | */
32 | public static function dirContents(string $directory)
33 | {
34 | try {
35 | return array_values(array_diff(scandir($directory), array('.', '..')));
36 | } catch (Throwable $throwable) {
37 | return null;
38 | }
39 | }
40 |
41 | /**
42 | * Returns if the array is an untouched numeric index
43 | *
44 | * @param array $array
45 | * @return bool
46 | */
47 | public static function isNumericArray(array $array)
48 | {
49 | return array_keys($array) === range(0, count($array) - 1);
50 | }
51 |
52 | /**
53 | * Filter an array by the given array keys
54 | *
55 | * @param array $array
56 | * @param string|array $keys
57 | * @return array
58 | */
59 | public static function arrayOnly(array $array, $keys)
60 | {
61 | return array_intersect_key($array, array_flip((array)$keys));
62 | }
63 |
64 | /**
65 | * Returns the $array without
66 | *
67 | * @param array $array
68 | * @param $excluded
69 | * @return array
70 | */
71 | public static function arrayExcept(array $array, $excluded)
72 | {
73 | return array_diff_key($array, array_flip($excluded));
74 | }
75 |
76 | /**
77 | * Returns the first item in the array.
78 | *
79 | * @param array $array
80 | * @param mixed $default
81 | * @return mixed
82 | */
83 | public static function arrayFirst(array $array, $default = null)
84 | {
85 | foreach ($array as $item) {
86 | return $item;
87 | }
88 |
89 | return $default;
90 | }
91 | }
--------------------------------------------------------------------------------
/src/Concerns/HasCredentialOperations.php:
--------------------------------------------------------------------------------
1 | transbankConfig->getCredentials(
24 | lcfirst(Helpers::classBasename(static::class))
25 | );
26 | }
27 |
28 | /**
29 | * Returns the credentials directory for the active environment
30 | *
31 | * @return string
32 | */
33 | public function environmentCredentialsDirectory()
34 | {
35 | return $this->credentialsDirectory() . '/' . $this->transbankConfig->getEnvironment() . '/';
36 | }
37 |
38 | /**
39 | * Set the correct credentials in the adapter.
40 | *
41 | * Whe using `integration` environments, Credentials may depend on the
42 | * transaction type being used, so the type is passed to the method.
43 | * After that, these are overridden by any of the user credentials.
44 | *
45 | * @param string|null $type
46 | */
47 | protected function setAdapterCredentials(string $type = null)
48 | {
49 | $this->adapter->setCredentials(
50 | new Fluid(
51 | array_merge(
52 | $this->isProduction()
53 | ? $this->getProductionCredentials()
54 | : $this->getIntegrationCredentials($type),
55 | (array)$this->credentials ?? []
56 | )
57 | )
58 | );
59 | }
60 |
61 | /**
62 | * Get the Service Credentials for the Production Environment
63 | *
64 | * @return array
65 | */
66 | abstract protected function getProductionCredentials();
67 |
68 | /**
69 | * Get the Service Credentials for the Integration Environment
70 | *
71 | * @param string $type
72 | * @return array
73 | */
74 | abstract protected function getIntegrationCredentials(string $type = null);
75 | }
--------------------------------------------------------------------------------
/src/Clients/Webpay/PlusNullify.php:
--------------------------------------------------------------------------------
1 | $transaction->authorizationCode,
39 | // Authorized Transaction amount to null (substract), or full Capture Amount
40 | 'authorizedAmount' => $transaction->authorizedAmount,
41 | 'buyOrder' => $transaction->buyOrder,
42 | 'commerceId' => $transaction->commerceCode ?? $this->credentials->commerceCode,
43 | 'nullifyAmount' => $transaction->nullifyAmount
44 | ];
45 |
46 | try {
47 | // Perform the capture with the data, and return if validates
48 | $response = $this->performNullify($transaction);
49 | } catch (Exception $e) {
50 | throw new ErrorResponseException($e->getMessage(), $e->getCode(), $e);
51 | }
52 |
53 | if ($this->validate()) {
54 | return $response;
55 | }
56 |
57 | throw new InvalidSignatureException();
58 |
59 | }
60 |
61 | /**
62 | * Performs the Nullify on Webpay
63 | *
64 | * @param $transaction
65 | * @return mixed
66 | */
67 | protected function performNullify($transaction)
68 | {
69 | return (array)($this->connector->nullify([
70 | 'nullificationInput' => $transaction
71 | ]))->return;
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/Contracts/ServiceInterface.php:
--------------------------------------------------------------------------------
1 | 'Resultado exitoso.',
5 | 'CANCELLED_BY_USER' => 'Transacción abortada o no pagada por el usuario.',
6 | 'COMMERCE_NOT_FOUND' => 'El comercio no existe.',
7 | 'ILCAT_ERROR' => 'Error desconocido de Onepay en Transbank.',
8 | 'ILCAT_RESPONSE_ERROR' => 'Error durante la respuesta de Transbank.',
9 | 'ILCAT_SERVICE_ERROR' => 'Error interno del Onepay en Transbank.',
10 | 'INVALID_APP_KEY' => 'App Key (código del lenguage de la librería) inválido.',
11 | 'INVALID_NULLIFY_AMOUNT' => 'El monto a anular no coincide con el de la transacción.',
12 | 'INVALID_PARAMS' => 'Los parámetros de la transacción son incorrectos.',
13 | 'INVALID_PLUGIN_VERSION' => 'Versión inválida, antigua, o no-existente, del plugin.',
14 | 'INVALID_TRANSACTION' => 'El Carro de Compra posee montos o cantidades inválidos, o la transacción no está autorizada y no se puede anular o confirmar.',
15 | 'INVALID_TRANSACTION_SIGN' => 'La firma (signature) de la transacción es inválida.',
16 | 'INVALID_TRANSACTION_STATUS' => 'El estado de la transacción no es válida o autorizada y no se puede confirmar.',
17 | 'INVALID_USER' => 'El usuario o cliente de Onepay es inválido.',
18 | 'ERROR' => 'Error desconocido de Transbank.',
19 | 'FAILED_REVERSE_NULLIFY' => 'La reversa de la transacción falló.',
20 | 'NONEXISTENT_TRANSACTION' => 'La transacción no fue encontrada.',
21 | 'NONEXISTENT_USER' => 'El usuario o cliente de Onepay no existe.',
22 | 'NOT_ACTIVE_COMMERCE' => 'El comercio para esta transacción no está activa.',
23 | 'NULLIFICATION_PERIOD_HAS_EXPIRED' => 'El período para anular la transacción expiró.',
24 | 'ONE_PAY_NOT_INSTALLED' => 'La aplicación de Onepay no está instalado.',
25 | 'REJECTED' => 'Transacción rechazada por el medio de pago o autorizador.',
26 | 'REVERSE_NOT_COMPLETE' => 'La reversa falló por razones desconocidas.',
27 | 'REVERSED' => 'Transacción reversada internamente ante la ausencia de confirmación.',
28 | 'REVERSED_NULLIFY' => 'La reversa de la anulación de la transacción ya fue hecha.',
29 | 'SIGN_VALIDATION_ERROR' => 'La validación de la firma (signature) es inválida.',
30 | 'TRANSACTION_ALREADY_EXISTS' => 'El "externalUniqueNumber" ya fue usado previamente.',
31 | ];
--------------------------------------------------------------------------------
/tests/Unit/Services/OnepayTest.php:
--------------------------------------------------------------------------------
1 | mockTransbank = \Mockery::mock(Transbank::class);
33 |
34 | $this->mockTransbank->shouldReceive('getDefaults') ->once()
35 | ->andReturn([ 'foo' => 'bar' ]);
36 |
37 | $this->mockTransbank->shouldReceive('getCredentials') ->once()
38 | ->andReturn([ 'baz' => 'qux' ]);
39 |
40 | $this->mockAdapter = \Mockery::mock(OnepayAdapter::class);
41 |
42 | $this->mockAdapter->shouldReceive('setCredentials')
43 | ->andReturn(['foo' => 'bar']);
44 |
45 | $this->mockLogger = \Mockery::mock(LoggerInterface::class);
46 |
47 | $this->onepay = new Onepay($this->mockTransbank, $this->mockLogger);
48 |
49 | $this->onepay->setAdapter($this->mockAdapter);
50 | }
51 |
52 | public function testGetTransaction()
53 | {
54 | $this->mockTransbank->shouldReceive('isProduction')->once()
55 | ->andReturnTrue();
56 |
57 | $this->mockAdapter->shouldReceive('retrieveAndConfirm')
58 | ->andReturn(['foo' => 'bar']);
59 |
60 | $this->mockLogger->shouldReceive('info')
61 | ->with(\Mockery::type('string'))
62 | ->andReturnNull();
63 |
64 | $transaction = $this->onepay->getTransaction(['mock.transaction']);
65 |
66 | $this->assertInstanceOf(OnepayResponse::class, $transaction);
67 | $this->assertEquals('bar', $transaction->foo);
68 |
69 | $this->mockTransbank->shouldReceive('isProduction')->once()
70 | ->andReturnFalse();
71 |
72 | $transaction = $this->onepay->getTransaction(['mock.transaction']);
73 |
74 | $this->assertInstanceOf(OnepayResponse::class, $transaction);
75 | $this->assertEquals('bar', $transaction->foo);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/tests/Unit/Adapters/OnepayAdapterTest.php:
--------------------------------------------------------------------------------
1 | adapter = new OnepayAdapter();
29 |
30 | $this->client = \Mockery::mock(AbstractClient::class, [
31 | true, new Fluid(['foo' => 'bar'])
32 | ]);
33 |
34 | $this->adapter->setClient($this->client);
35 | }
36 |
37 | public function testCommit()
38 | {
39 | $this->client->allows([
40 | 'commit' => true,
41 | 'refund' => true,
42 | ]);
43 |
44 | $transaction = new OnepayTransaction([ 'foo' => 'bar' ]);
45 | $transaction->setType('onepay.cart');
46 | $response = $this->adapter->commit($transaction);
47 | $this->assertTrue($response);
48 |
49 | $transaction = new OnepayNullifyTransaction([ 'foo' => 'bar' ]);
50 | $transaction->setType('onepay.nullify');
51 | $response = $this->adapter->commit($transaction);
52 | $this->assertTrue($response);
53 | }
54 |
55 | public function testDoesntInstancesClientAgain()
56 | {
57 | $client = \Mockery::mock('overload:' . OnepayClient::class);
58 |
59 | $client->expects('boot');
60 | $client->shouldReceive('commit')->andReturnTrue();
61 |
62 | $this->adapter->setClient(null);
63 |
64 | $transaction = new OnepayTransaction([ 'foo' => 'bar' ]);
65 | $transaction->setType('onepay.cart');
66 | $response = $this->adapter->commit($transaction);
67 | $this->assertTrue($response);
68 | }
69 |
70 | public function testNullOnCommitUnavailable()
71 | {
72 | $transaction = new OnepayTransaction([ 'foo' => 'bar' ]);
73 | $transaction->setType('anthing');
74 | $response = $this->adapter->commit($transaction);
75 | $this->assertNull($response);
76 | }
77 |
78 | public function testRetrieveAndConfirm()
79 | {
80 | $this->client->allows([
81 | 'confirm' => true,
82 | ]);
83 |
84 | $response = $this->adapter->retrieveAndConfirm(['transaction']);
85 | $this->assertTrue($response);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/TransactionFactories/OnepayTransactionFactory.php:
--------------------------------------------------------------------------------
1 | prepareTransaction($type, new OnepayNullifyTransaction($attributes));
24 | case 'onepay.cart':
25 | default:
26 | return $this->prepareTransaction($type, new OnepayTransaction($attributes));
27 | }
28 | }
29 |
30 | /**
31 | * Makes a Onepay Transaction, optionally with Items inside it
32 | *
33 | * @param array $attributes
34 | * @return \DarkGhostHunter\TransbankApi\Transactions\AbstractTransaction
35 | * @return OnepayTransaction
36 | * @throws \Exception
37 | */
38 | public function makeCart(array $attributes = [])
39 | {
40 | return $this->makeTransaction('onepay.cart', $attributes);
41 | }
42 |
43 | /**
44 | * Creates a Onepay Transaction and immediately sends it to Transbank
45 | *
46 | * @param array $attributes
47 | * @return \DarkGhostHunter\TransbankApi\Responses\AbstractResponse
48 | * @return OnepayTransaction
49 | * @throws \Exception
50 | */
51 | public function createCart(array $attributes)
52 | {
53 | return $this->makeCart($attributes)->commit();
54 | }
55 |
56 | /**
57 | * Creates a new Onepay Nullify transaction
58 | *
59 | * @param array $attributes
60 | * @return \DarkGhostHunter\TransbankApi\Transactions\AbstractTransaction&OnepayNullifyTransaction
61 | * @return OnepayTransaction
62 | * @throws \Exception
63 | */
64 | public function makeNullify(array $attributes)
65 | {
66 | return $this->makeTransaction('onepay.nullify', $attributes);
67 | }
68 |
69 | /**
70 | * Creates a Onepay Nullify transaction and immediately sends it to Transbank
71 | *
72 | * @param array $attributes
73 | * @return \DarkGhostHunter\TransbankApi\Responses\AbstractResponse
74 | * @return \DarkGhostHunter\TransbankApi\Responses\OnepayResponse
75 | * @throws \Exception
76 | */
77 | public function createNullify(array $attributes)
78 | {
79 | return $this->makeNullify($attributes)->commit();
80 | }
81 |
82 | }
--------------------------------------------------------------------------------
/tests/Unit/Transactions/AbstractTransactionTest.php:
--------------------------------------------------------------------------------
1 | mockService = \Mockery::mock(AbstractService::class);
21 |
22 | $this->transaction = new class extends AbstractTransaction {};
23 | }
24 |
25 | public function testGetAndSetService()
26 | {
27 | $this->transaction->setService($this->mockService);
28 |
29 | $this->assertInstanceOf(AbstractService::class, $this->transaction->getService());
30 | }
31 |
32 | public function testGetAndSetType()
33 | {
34 | $this->transaction->setType('test-type');
35 |
36 | $this->assertEquals('test-type', $this->transaction->getType());
37 | }
38 |
39 | public function testCommit()
40 | {
41 | $this->mockService->shouldReceive('commit')->once()
42 | ->with($this->transaction)
43 | ->andReturn($array = ['foo' => 'bar']);
44 |
45 | $this->transaction->setService($this->mockService);
46 |
47 | $response = $this->transaction->commit();
48 |
49 | $this->assertEquals($array, $response);
50 | }
51 |
52 | public function testSingleCommit()
53 | {
54 | $this->mockService->shouldReceive('commit')->once()
55 | ->with($this->transaction)
56 | ->andReturn($array = ['foo' => 'bar']);
57 |
58 | $this->transaction->setService($this->mockService);
59 |
60 | $this->transaction->commit();
61 |
62 | $response = $this->transaction->commit();
63 |
64 | $this->assertEquals($array, $response);
65 | }
66 |
67 | public function testForceCommit()
68 | {
69 | $this->mockService->shouldReceive('commit')->twice()
70 | ->with($this->transaction)
71 | ->andReturn($array = ['foo' => 'bar']);
72 |
73 | $this->transaction->setService($this->mockService);
74 |
75 | $response = $this->transaction->commit();
76 |
77 | $forcedResponse = $this->transaction->forceCommit();
78 |
79 | $this->assertEquals($array, $response);
80 | $this->assertEquals($array, $forcedResponse);
81 | }
82 |
83 | public function testSetDefaults()
84 | {
85 | $this->transaction->baz = 'qux';
86 | $this->transaction->quux = 'quuz';
87 |
88 | $this->transaction->setDefaults([
89 | 'foo' => 'bar',
90 | 'quux' => 'notQuuz'
91 | ]);
92 |
93 | $this->assertEquals('bar', $this->transaction->foo);
94 | $this->assertEquals('qux', $this->transaction->baz);
95 | $this->assertEquals('quuz', $this->transaction->quux);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/Concerns/HasServiceGettersAndSetters.php:
--------------------------------------------------------------------------------
1 | transbankConfig->isProduction();
26 | }
27 |
28 | /**
29 | * Returns if the service is using an Integration environment
30 | *
31 | * @return bool
32 | */
33 | public function isIntegration()
34 | {
35 | return $this->transbankConfig->isIntegration();
36 | }
37 |
38 | /**
39 | * Retrieves the default options for the service Transactions
40 | *
41 | * @return array|null
42 | */
43 | protected function getDefaults()
44 | {
45 | return $this->transbankConfig->getDefaults(
46 | lcfirst(Helpers::classBasename(static::class))
47 | ) ?? [];
48 | }
49 |
50 | /**
51 | * Get the Adapter
52 | *
53 | * @return AdapterInterface
54 | */
55 | public function getAdapter()
56 | {
57 | return $this->adapter;
58 | }
59 |
60 | /**
61 | * Set the Adapter
62 | *
63 | * @param AdapterInterface $adapter
64 | */
65 | public function setAdapter(AdapterInterface $adapter)
66 | {
67 | $this->adapter = $adapter;
68 | }
69 |
70 | /**
71 | * Get the Transaction Factory
72 | *
73 | * @return string
74 | */
75 | public function getTransactionFactory()
76 | {
77 | return $this->transactionFactory;
78 | }
79 |
80 | /**
81 | * Set the Transaction Factory
82 | *
83 | * @param AbstractTransactionFactory $transactionFactory
84 | */
85 | public function setTransactionFactory(AbstractTransactionFactory $transactionFactory)
86 | {
87 | $this->transactionFactory = $transactionFactory;
88 | }
89 |
90 | /**
91 | * Get the Response Factory
92 | *
93 | * @return string
94 | */
95 | public function getResponseFactory()
96 | {
97 | return $this->responseFactory;
98 | }
99 |
100 | /**
101 | * Set the Response Factory
102 | *
103 | * @param AbstractResponseFactory $responseFactory
104 | */
105 | public function setResponseFactory(AbstractResponseFactory $responseFactory)
106 | {
107 | $this->responseFactory = $responseFactory;
108 | }
109 | }
--------------------------------------------------------------------------------
/tests/Unit/Transactions/WebpayTransactionTest.php:
--------------------------------------------------------------------------------
1 | 'http://app.com/webpay/return',
16 | 'plusFinalUrl' => 'http://app.com/webpay/final',
17 | 'plusMallReturnUrl' => 'http://app.com/webpay/mall/return',
18 | 'plusMallFinalUrl' => 'http://app.com/webpay/mall/final',
19 | 'oneclickResponseURL' => 'http://app.com/webpay/response',
20 | ];
21 |
22 | protected function setUp() : void
23 | {
24 | $this->transaction = new WebpayTransaction();
25 | }
26 |
27 | public function testSetsDefaultsForPlusNormal()
28 | {
29 | $this->transaction->setType('plus.normal');
30 |
31 | $this->transaction->setDefaults($this->defaults);
32 |
33 | $this->assertEquals('http://app.com/webpay/return', $this->transaction->returnUrl);
34 | $this->assertEquals('http://app.com/webpay/final', $this->transaction->finalUrl);
35 | $this->assertCount(2, $this->transaction->getAttributes());
36 | }
37 |
38 | public function testSetsDefaultsForPlusDefer()
39 | {
40 | $this->transaction->setType('plus.defer');
41 |
42 | $this->transaction->setDefaults($this->defaults);
43 |
44 | $this->assertEquals('http://app.com/webpay/return', $this->transaction->returnUrl);
45 | $this->assertEquals('http://app.com/webpay/final', $this->transaction->finalUrl);
46 | $this->assertCount(2, $this->transaction->getAttributes());
47 | }
48 |
49 | public function testSetsDefaultsForPlusMallNormal()
50 | {
51 | $this->transaction->setType('plus.mall.normal');
52 |
53 | $this->transaction->setDefaults($this->defaults);
54 |
55 | $this->assertEquals('http://app.com/webpay/mall/return', $this->transaction->returnUrl);
56 | $this->assertEquals('http://app.com/webpay/mall/final', $this->transaction->finalUrl);
57 | $this->assertCount(2, $this->transaction->getAttributes());
58 | }
59 |
60 | public function testSetsDefaultsForPlusMallDefer()
61 | {
62 | $this->transaction->setType('plus.mall.defer');
63 |
64 | $this->transaction->setDefaults($this->defaults);
65 |
66 | $this->assertEquals('http://app.com/webpay/mall/return', $this->transaction->returnUrl);
67 | $this->assertEquals('http://app.com/webpay/mall/final', $this->transaction->finalUrl);
68 | $this->assertCount(2, $this->transaction->getAttributes());
69 | }
70 |
71 | public function testSetsDefaultsForOneclickRegister()
72 | {
73 | $this->transaction->setType('oneclick.register');
74 |
75 | $this->transaction->setDefaults($this->defaults);
76 |
77 | $this->assertEquals('http://app.com/webpay/response', $this->transaction->responseURL);
78 | $this->assertCount(1, $this->transaction->getAttributes());
79 | }
80 |
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/Adapters/OnepayAdapter.php:
--------------------------------------------------------------------------------
1 | client) {
27 | $this->client = new OnepayClient($this->isProduction, $this->credentials);
28 | $this->client->boot();
29 | }
30 | }
31 |
32 | /**
33 | * Commits a transaction into the Transbank SDK
34 | *
35 | * @param TransactionInterface|\DarkGhostHunter\TransbankApi\Transactions\OnepayTransaction|\DarkGhostHunter\TransbankApi\Transactions\OnepayNullifyTransaction $transaction
36 | * @param mixed|null $options
37 | * @return array
38 | * @throws \Exception
39 | */
40 | public function commit(TransactionInterface $transaction, $options = null)
41 | {
42 | $this->bootClient();
43 |
44 | switch ($transaction->getType()) {
45 | case 'onepay.cart':
46 | return $this->commitCart($transaction);
47 | case 'onepay.nullify':
48 | return $this->commitNullify($transaction);
49 | }
50 | }
51 |
52 | /**
53 | * Commits a Onepay Cart
54 | *
55 | * @param OnepayTransaction $transaction
56 | * @return array
57 | * @throws \DarkGhostHunter\TransbankApi\Exceptions\Onepay\OnepayValidationException
58 | * @throws \DarkGhostHunter\TransbankApi\Exceptions\Onepay\OnepayClientException
59 | * @throws \DarkGhostHunter\TransbankApi\Exceptions\Onepay\OnepayResponseException
60 | */
61 | protected function commitCart(OnepayTransaction $transaction)
62 | {
63 | return $this->client->commit($transaction);
64 | }
65 |
66 | /**
67 | * Commits a Nullify transaction
68 | *
69 | * @param OnepayNullifyTransaction $transaction
70 | * @return array
71 | * @throws \DarkGhostHunter\TransbankApi\Exceptions\Onepay\OnepayClientException
72 | * @throws \DarkGhostHunter\TransbankApi\Exceptions\Onepay\OnepayResponseException
73 | */
74 | protected function commitNullify(OnepayNullifyTransaction $transaction)
75 | {
76 | return $this->client->refund($transaction);
77 | }
78 |
79 | /**
80 | * Retrieves and Acknowledges a transaction into the Transbank SDK
81 | *
82 | * @param $transaction
83 | * @param mixed|null $options
84 | * @return mixed
85 | * @throws \Exception
86 | */
87 | public function retrieveAndConfirm($transaction, $options = null)
88 | {
89 | $this->bootClient();
90 |
91 | return $this->client->confirm(new OnepayTransaction($transaction));
92 | }
93 | }
--------------------------------------------------------------------------------
/tests/Feature/Integration/OnepayIntegrationTransactionsTest.php:
--------------------------------------------------------------------------------
1 | setDefaults('onepay', [
23 | 'channel' => 'mobile',
24 | 'generateOttQrCode' => true,
25 | 'callbackUrl' => 'http://app.com/onepay/result',
26 | 'appScheme' => 'my-app://onepay/result',
27 | ]);
28 |
29 | $this->onepay = Onepay::fromConfig($transbank);
30 | }
31 |
32 | public function testCreatesCartInTransbank()
33 | {
34 | $cart = $this->onepay->createCart([
35 | 'channel' => 'web',
36 | 'items' => [
37 | 'description' => 'Zapatos',
38 | 'quantity' => 1,
39 | 'amount' => 15000
40 | ]
41 | ]);
42 |
43 | $this->assertTrue($cart->isSuccess());
44 | $this->assertNotEmpty($cart->ott);
45 | $this->assertNotEmpty($cart->externalUniqueNumber);
46 | $this->assertNotEmpty($cart->qrCodeAsBase64);
47 | $this->assertNotEmpty($cart->issuedAt);
48 | $this->assertNotEmpty($cart->signature);
49 | }
50 |
51 | public function testExceptionOnChannelAppWithoutScheme()
52 | {
53 | $this->expectException(OnepayResponseException::class);
54 |
55 | $this->onepay->createCart([
56 | 'channel' => 'app',
57 | 'appScheme' => null,
58 | 'items' => [
59 | 'description' => 'Zapatos',
60 | 'quantity' => 1,
61 | 'amount' => 15000
62 | ]
63 | ]);
64 | }
65 |
66 | public function testCreatedCartHidesSignatureOnSerialization()
67 | {
68 | $cart = $this->onepay->createCart([
69 | 'items' => [
70 | 'description' => 'Zapatos',
71 | 'quantity' => 1,
72 | 'amount' => 15000
73 | ]
74 | ]);
75 |
76 | $this->assertFalse(strpos($cart->toJson(), 'signature'));
77 | $this->assertFalse(strpos((string)$cart, 'signature'));
78 | }
79 |
80 | public function testExceptionOnCartWithZeroAmount()
81 | {
82 | $this->expectException(CartNegativeAmountException::class);
83 |
84 | $cart = $this->onepay->createCart([
85 | 'items' => [
86 | 'description' => 'Zapatos',
87 | 'quantity' => 10,
88 | 'amount' => -15000
89 | ]
90 | ]);
91 | }
92 |
93 | public function testExceptionOnEmptyCart()
94 | {
95 | $this->expectException(CartEmptyException::class);
96 |
97 | $cart = $this->onepay->createCart([
98 | 'items' => []
99 | ]);
100 | }
101 | }
--------------------------------------------------------------------------------
/src/Transactions/AbstractTransaction.php:
--------------------------------------------------------------------------------
1 | $method();
50 | }
51 |
52 | // Do any logic before getting the result
53 | if (method_exists($this, $method = 'performPreLogic') && is_callable([$this, $method])) {
54 | $this->$method();
55 | }
56 |
57 | if ($this->response = $this->service->commit($this)) {
58 | $this->performed = true;
59 | }
60 |
61 | return $this->response;
62 | }
63 |
64 | /**
65 | * Set default attributes for the Item
66 | *
67 | * @param array $defaults
68 | */
69 | public function setDefaults(array $defaults)
70 | {
71 | $this->attributes = array_merge($defaults, $this->attributes ?? []);
72 | }
73 |
74 | /**
75 | * Set the Transaction type
76 | *
77 | * @param string $type
78 | */
79 | public function setType(string $type)
80 | {
81 | $this->type = $type;
82 | }
83 |
84 | /**
85 | * Return the Transaction type
86 | *
87 | * @return string
88 | */
89 | public function getType()
90 | {
91 | return $this->type;
92 | }
93 |
94 | /**
95 | * Sets the Service to be used for this Transaction
96 | *
97 | * @param ServiceInterface $service
98 | */
99 | public function setService(ServiceInterface $service)
100 | {
101 | $this->service = $service;
102 | }
103 |
104 | /**
105 | * Returns the Service used by this Transaction
106 | *
107 | * @return ServiceInterface
108 | */
109 | public function getService()
110 | {
111 | return $this->service;
112 | }
113 |
114 | /**
115 | * Commits the transaction to Transbank and return a AbstractResult
116 | *
117 | * @return \DarkGhostHunter\TransbankApi\Responses\AbstractResponse
118 | */
119 | public function commit()
120 | {
121 | return $this->performed ? $this->response : $this->performCommit();
122 | }
123 |
124 | /**
125 | * Forcefully commits the transaction to Transbank
126 | *
127 | * @return \DarkGhostHunter\TransbankApi\Responses\AbstractResponse
128 | */
129 | public function forceCommit()
130 | {
131 | return $this->performCommit();
132 | }
133 | }
--------------------------------------------------------------------------------
/tests/Unit/Clients/Webpay/PlusCaptureTest.php:
--------------------------------------------------------------------------------
1 | client = new PlusCapture(true, new Fluid(['privateKey' => 'foo', 'publicCert' => 'bar']));
32 |
33 | $this->client->boot();
34 |
35 | $this->mockConnector = \Mockery::instanceMock(SoapImplementation::class);
36 |
37 | $this->mockValidator = \Mockery::instanceMock('overload:' . Validation::class)
38 | ->makePartial();
39 |
40 | $this->client->setConnector($this->mockConnector);
41 | }
42 |
43 | public function testCapture()
44 | {
45 | $this->mockValidator->expects('isValid')->andReturnTrue();
46 |
47 | $transaction = new WebpayTransaction([
48 | 'buyOrder' => 'baz',
49 | 'amount' => 'qux',
50 | ]);
51 |
52 | $this->mockConnector
53 | ->expects('capture')
54 | ->with(\Mockery::type('array'))
55 | ->andReturn(
56 | (object)['return' => ['foo' => 'bar']]
57 | );
58 |
59 | $this->mockConnector
60 | ->expects('__getLastResponse')
61 | ->andReturn('foo');
62 |
63 | $response = $this->client->capture($transaction);
64 |
65 | $this->assertEquals('bar', $response['foo']);
66 | }
67 |
68 | public function testExceptionOnCapture()
69 | {
70 | $this->expectException(ErrorResponseException::class);
71 |
72 | $this->mockValidator->expects('isValid')->andReturnTrue();
73 |
74 | $transaction = new WebpayTransaction([
75 | 'buyOrder' => 'baz',
76 | 'amount' => 'qux',
77 | ]);
78 |
79 | $this->mockConnector
80 | ->expects('capture')
81 | ->with(\Mockery::type('array'))
82 | ->andThrow(\Exception::class);
83 |
84 | $this->mockConnector
85 | ->expects('__getLastResponse')
86 | ->andReturn('foo');
87 |
88 | $this->client->capture($transaction);
89 | }
90 |
91 | public function testExceptionOnCaptureNotValid()
92 | {
93 | $this->expectException(InvalidSignatureException::class);
94 |
95 | $this->mockValidator->expects('isValid')->andReturnFalse();
96 |
97 | $transaction = new WebpayTransaction([
98 | 'buyOrder' => 'baz',
99 | 'amount' => 'qux',
100 | ]);
101 |
102 | $this->mockConnector
103 | ->expects('capture')
104 | ->with(\Mockery::type('array'))
105 | ->andReturn(
106 | (object)['return' => ['foo' => 'bar']]
107 | );
108 |
109 | $this->mockConnector
110 | ->expects('__getLastResponse')
111 | ->andReturn('foo');
112 |
113 | $this->client->capture($transaction);
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/tests/Unit/Clients/Webpay/PlusNullifyTest.php:
--------------------------------------------------------------------------------
1 | client = new PlusNullify(true, new Fluid(['privateKey' => 'foo', 'publicCert' => 'bar']));
32 |
33 | $this->client->boot();
34 |
35 | $this->mockConnector = \Mockery::instanceMock(SoapImplementation::class);
36 |
37 | $this->mockValidator = \Mockery::instanceMock('overload:' . Validation::class)
38 | ->makePartial();
39 |
40 | $this->client->setConnector($this->mockConnector);
41 | }
42 |
43 | public function testNullify()
44 | {
45 | $this->mockValidator->expects('isValid')->andReturnTrue();
46 |
47 | $transaction = new WebpayTransaction([
48 | 'buyOrder' => 'baz',
49 | 'amount' => 'qux',
50 | ]);
51 |
52 | $this->mockConnector
53 | ->expects('nullify')
54 | ->with(\Mockery::type('array'))
55 | ->andReturn(
56 | (object)['return' => ['foo' => 'bar']]
57 | );
58 |
59 | $this->mockConnector
60 | ->expects('__getLastResponse')
61 | ->andReturn('foo');
62 |
63 | $response = $this->client->nullify($transaction);
64 |
65 | $this->assertEquals('bar', $response['foo']);
66 | }
67 |
68 | public function testExceptionNullify()
69 | {
70 | $this->expectException(ErrorResponseException::class);
71 |
72 | $this->mockValidator->expects('isValid')->andReturnTrue();
73 |
74 | $transaction = new WebpayTransaction([
75 | 'buyOrder' => 'baz',
76 | 'amount' => 'qux',
77 | ]);
78 |
79 | $this->mockConnector
80 | ->expects('nullify')
81 | ->with(\Mockery::type('array'))
82 | ->andThrow(\Exception::class);
83 |
84 | $this->mockConnector
85 | ->expects('__getLastResponse')
86 | ->andReturn('foo');
87 |
88 | $response = $this->client->nullify($transaction);
89 |
90 | $this->assertEquals('bar', $response['foo']);
91 | }
92 |
93 | public function testExceptionNullifyInvalid()
94 | {
95 | $this->expectException(InvalidSignatureException::class);
96 |
97 | $this->mockValidator->expects('isValid')->andReturnFalse();
98 |
99 | $transaction = new WebpayTransaction([
100 | 'buyOrder' => 'baz',
101 | 'amount' => 'qux',
102 | ]);
103 |
104 | $this->mockConnector
105 | ->expects('nullify')
106 | ->with(\Mockery::type('array'))
107 | ->andReturn(
108 | (object)['return' => ['foo' => 'bar']]
109 | );
110 |
111 | $this->mockConnector
112 | ->expects('__getLastResponse')
113 | ->andReturn('foo');
114 |
115 | $this->client->nullify($transaction);
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/tests/Unit/TransactionFactories/OnepayTransactionFactoryTest.php:
--------------------------------------------------------------------------------
1 | mockTransbank = \Mockery::mock(Transbank::class);
30 | $this->mockTransbank->shouldReceive('getDefaults')->once()
31 | ->andReturn(['foo' => 'bar']);
32 | $this->mockTransbank->shouldReceive('getCredentials')->once()
33 | ->with('onepay')
34 | ->andReturn(new Fluid(['foo' => 'bar']));
35 | $this->mockTransbank->shouldReceive('isProduction')->once()
36 | ->andReturnTrue();
37 | $this->mockTransbank->shouldReceive('getEnvironment')
38 | ->andReturn('production');
39 |
40 | $this->mockAdapter = \Mockery::mock(OnepayAdapter::class);
41 |
42 | $this->onepay = new Onepay($this->mockTransbank, new NullLogger());
43 | $this->onepay->setAdapter($this->mockAdapter);
44 | }
45 |
46 | public function testCreateNullify()
47 | {
48 | $this->mockAdapter->shouldReceive('setCredentials')->once()
49 | ->andReturn(['foo' => 'bar']);
50 | $this->mockAdapter->shouldReceive('commit')->once()
51 | ->andReturnUsing(function ($transaction) {
52 | $this->assertInstanceOf(OnepayNullifyTransaction::class, $transaction);
53 | return $transaction->toArray();
54 | });
55 |
56 | $response = $this->onepay->createNullify([
57 | 'foo' => 'bar',
58 | 'amount' => 1,
59 | 'quantity' => 1,
60 | ]);
61 |
62 | $this->assertInstanceOf(OnepayResponse::class, $response);
63 | $this->assertEquals('bar', $response->foo);
64 | $this->assertEquals(1, $response->amount);
65 | $this->assertEquals(1, $response->quantity);
66 | }
67 |
68 | public function testMakeCart()
69 | {
70 | $cart = $this->onepay->makeCart([
71 | 'foo' => 'bar'
72 | ]);
73 |
74 | $this->assertInstanceOf(OnepayTransaction::class, $cart);
75 | $this->assertEquals('bar', $cart->foo);
76 | }
77 |
78 | public function testCreateCart()
79 | {
80 | $this->mockAdapter->shouldReceive('setCredentials')->once()
81 | ->andReturn(['foo' => 'bar']);
82 | $this->mockAdapter->shouldReceive('commit')->once()
83 | ->andReturnUsing(function ($transaction) {
84 | $this->assertInstanceOf(OnepayTransaction::class, $transaction);
85 | return $transaction->items[0]->toArray();
86 | });
87 |
88 | $response = $this->onepay->createCart([
89 | 'items' => [
90 | 'foo' => 'bar',
91 | 'amount' => 1,
92 | 'quantity' => 1,
93 | ]
94 | ]);
95 |
96 | $this->assertInstanceOf(OnepayResponse::class, $response);
97 | $this->assertEquals('bar', $response->foo);
98 | $this->assertEquals(1, $response->amount);
99 | $this->assertEquals(1, $response->quantity);
100 | }
101 |
102 | public function testMakeNullify()
103 | {
104 | $nullify = $this->onepay->makeNullify([
105 | 'foo' => 'bar'
106 | ]);
107 |
108 | $this->assertInstanceOf(OnepayNullifyTransaction::class, $nullify);
109 | $this->assertEquals('bar', $nullify->foo);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Versión 4.0 Final
2 |
3 | Como leen, esta será la última versión de Transbank API. El nuevo SDK oficial de Transbank usa HTTPS en vez de SOAP (puaj!), así que este SDK ya no es necesario.
4 |
5 | # Ve y usa el [SDK Oficial de Transbank](https://github.com/TransbankDevelopers/transbank-sdk-php)
6 |
7 | 
8 |
9 | [](https://packagist.org/packages/darkghosthunter/transbank-api) [](https://packagist.org/packages/darkghosthunter/transbank-api)
10 |  [](https://github.com/DarkGhostHunter/TransbankApi/actions) [](https://coveralls.io/github/DarkGhostHunter/TransbankApi?branch=master) [](https://codeclimate.com/github/DarkGhostHunter/TransbankApi/maintainability)
11 |
12 |
13 | # Transbank API
14 |
15 | `TransbankApi` es un reemplazo al [Transbank SDK](https://github.com/TransbankDevelopers/transbank-sdk-php) con la finalidad de mejorar la experiencia de integración y uso.
16 |
17 | > Esta versión es incompatible con PHP 5. Para usar este código con PHP 5, usa el packete oficial de [Transbank SDK](https://github.com/TransbankDevelopers/transbank-sdk-php).
18 |
19 | ## Requisitos:
20 |
21 | - PHP 7.4, o PHP 8.0
22 | - Composer
23 |
24 | ## Dependencias
25 |
26 | Este paquete usa [Guzzle HTTP 7.0](http://docs.guzzlephp.org/en/stable/) y la [implementación de SOAP de Luis Urrutia](https://github.com/LuisUrrutia/TransbankSoap).
27 |
28 | A su vez, este paquete necesita las siguientes extensiones de PHP habilitadas:
29 |
30 | * ext-curl
31 | * ext-json
32 | * ext-mbstring
33 | * ext-soap
34 | * ext-dom
35 |
36 | Instalarlas dependerá de tu sistema: en algunos casos sólo necesitarás habilitarlas en tu `php.ini`; en otros, descargarlas usando tu gestor de packetes (como `apt-get` o `apk`) o compilarlas manualmente.
37 |
38 | ### Logger
39 |
40 | Esta librería es compatible con cualquier [logger PSR-3](https://www.php-fig.org/psr/psr-3/). Si quieres que tu proyecto escriba información sobre las transacciones, puedes usar [Monolog](https://github.com/Seldaek/monolog/) o cualquier otro que siga el estándar.
41 |
42 | # Instalación
43 |
44 | Hay tres formas para instalar el paquete: usando Composer, sin composer, y todo de forma (muy) manual.
45 |
46 | ### Instalar con Composer
47 |
48 | Para usar el SDK en tu proyecto usa Composer:
49 |
50 | ```bash
51 | composer require darkghosthunter/transbank-api
52 | ```
53 |
54 | ## Documentación
55 |
56 | La documentación de este paquete está [en la Wiki](https://github.com/DarkGhostHunter/TransbankApi/wiki).
57 |
58 | Sin embargo, la idea de este paquete es que puedas realizar la mayoría de tus transacciones usando sintaxis expresiva:
59 |
60 | La información sobre las variables que necesitas para realizar cada transacción está en [Transbank Developers](https://www.transbankdevelopers.cl). Este paquete no modifica el nombre de las variables.
61 |
62 | ## Ejemplos
63 |
64 | Este paquete incluye una pequeña sección de ejemplos que te permitirán probar (y ver en acción) cómo funciona la interacción con los distintos servicios Transbank en modo `integration`.
65 |
66 | Sólo dirígete al [directorio `examples`](examples) y sigue las instrucciones.
67 |
68 | ## Información para contribuir y desarrollar este Wrapper
69 |
70 | Tirar la talla en buen chileno en los PR. Si usas otro idioma, serás víctima de bullying.
71 |
72 | # Licencia
73 |
74 | Este paquete está licenciado bajo la [Licencia MIT](LICENCIA) [(En inglés)](LICENSE).
75 |
76 | `Redcompra`, `Webpay`, `Onepay`, `Patpass` y `tbk` son marcas registradas de [Transbank S.A.](https://www.transbank.cl/)
77 |
78 | Este paquete no está aprobado, apoyado ni avalado por Transbank S.A. ni ninguna persona natural o jurídica vinculada directa o indirectamente a Transbank S.A.
79 |
--------------------------------------------------------------------------------
/src/Clients/Webpay/PlusNormal.php:
--------------------------------------------------------------------------------
1 | $this->credentials->commerceCode,
37 | 'buyOrder' => $transaction->buyOrder,
38 | 'amount' => $transaction->amount,
39 | ]
40 | ];
41 | // Otherwise, we will change the transaction type to Mall and...
42 | } else {
43 | $commit['wSTransactionType'] = 'TR_MALL_WS';
44 | $commit['commerceId'] = $this->credentials->commerceCode;
45 | }
46 |
47 | // ..for each item (even if its one), transform it as something
48 | // Soap Connector can digest.
49 | foreach ($commit['transactionDetails'] as &$item) {
50 | $item = (object)[
51 | 'commerceCode' => $item['commerceCode'],
52 | 'buyOrder' => $item['buyOrder'],
53 | 'amount' => $item['amount'],
54 | ];
55 | }
56 |
57 | return (object)$commit;
58 | }
59 |
60 | /**
61 | * Commits a Normal or Mall Transaction into Webpay
62 | *
63 | * @param WebpayTransaction $transaction
64 | * @return array
65 | * @throws \DarkGhostHunter\TransbankApi\Exceptions\Webpay\ErrorResponseException
66 | * @throws InvalidSignatureException
67 | */
68 | public function commit(WebpayTransaction $transaction)
69 | {
70 | // Create a normal transaction using the Fluid Helper
71 | $commit = $this->makeCommit([
72 | 'wSTransactionType' => 'TR_NORMAL_WS',
73 | 'sessionId' => $transaction->sessionId,
74 | 'buyOrder' => $transaction->buyOrder,
75 | 'returnURL' => $transaction->returnUrl,
76 | 'finalURL' => $transaction->finalUrl,
77 | 'transactionDetails' => $transaction->items,
78 | ], $transaction);
79 |
80 | try {
81 | // Now that we have the transaction completed, commit it
82 | $response = $this->performCommit($commit);
83 | } catch (Exception $e) {
84 | throw new ErrorResponseException($e->getMessage(), $e->getCode(), $e);
85 | }
86 |
87 | if ($this->validate()) {
88 | return $response;
89 | }
90 |
91 | throw new InvalidSignatureException();
92 | }
93 |
94 | /**
95 | * Obtains the Transaction results from Webpay Soap
96 | *
97 | * @param string $transaction
98 | * @return array
99 | * @throws InvalidSignatureException
100 | */
101 | public function retrieveAndConfirm($transaction)
102 | {
103 | // Retrieve Transaction result
104 | $response = $this->retrieve($transaction);
105 |
106 | // If Validation passes and the Transaction is Confirmed...
107 | if ($this->validate() && $this->confirm($transaction)) {
108 | // Extract the results from the response and return it
109 | return $response;
110 | }
111 |
112 | throw new InvalidSignatureException();
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/Onepay.php:
--------------------------------------------------------------------------------
1 | bootAdapter();
57 | $this->bootTransactionFactory();
58 | }
59 |
60 | /**
61 | * Instantiates (and/or boots) the Adapter for the Service
62 | *
63 | * @return void
64 | */
65 | public function bootAdapter()
66 | {
67 | $this->adapter = new OnepayAdapter();
68 | }
69 |
70 | /**
71 | * Instantiates (and/or boots) the Transaction Factory for the Service
72 | *
73 | * @return void
74 | */
75 | public function bootTransactionFactory()
76 | {
77 | $this->transactionFactory = new OnepayTransactionFactory($this, $this->defaults);
78 | }
79 |
80 | /*
81 | |--------------------------------------------------------------------------
82 | | Credentials
83 | |--------------------------------------------------------------------------
84 | */
85 |
86 | /**
87 | * Get the Service Credentials for the Production Environment
88 | *
89 | * @return array
90 | */
91 | protected function getProductionCredentials()
92 | {
93 | return include __DIR__ . '/' .
94 | trim(self::CREDENTIALS_DIR, '/') . '/' .
95 | trim(self::PRODUCTION_KEYS, '/');
96 | }
97 |
98 | /**
99 | * Get the Service Credentials for the Integration Environment
100 | *
101 | * @param string $type
102 | * @return array
103 | */
104 | protected function getIntegrationCredentials(string $type = null)
105 | {
106 | return include __DIR__ . '/' .
107 | trim(self::CREDENTIALS_DIR, '/') . '/' .
108 | trim(self::INTEGRATION_KEYS, '/');
109 | }
110 |
111 | /*
112 | |--------------------------------------------------------------------------
113 | | Operations
114 | |--------------------------------------------------------------------------
115 | */
116 |
117 | /**
118 | * Gets and Acknowledges a Transaction in Transbank
119 | *
120 | * @param $transaction
121 | * @param $options
122 | * @return Contracts\ResponseInterface
123 | */
124 | public function getTransaction($transaction, $options = null)
125 | {
126 | // Add the `issuedAt` timestamp for getting the transaction
127 | return parent::getTransaction($transaction + ['issuedAt' => time()], 'onepay.cart');
128 | }
129 |
130 | /*
131 | |--------------------------------------------------------------------------
132 | | Parsers
133 | |--------------------------------------------------------------------------
134 | */
135 |
136 | /**
137 | * Transform the adapter raw answer of a transaction commitment to a
138 | * more friendly Onepay Response
139 | *
140 | * @param array $result
141 | * @param mixed $options
142 | * @return Contracts\ResponseInterface
143 | */
144 | protected function parseResponse(array $result, $options = null)
145 | {
146 | $response = new OnepayResponse($result);
147 |
148 | // Set the type of the Transaction where this response belongs
149 | $response->setType($options);
150 |
151 | // Set the status of the Response
152 | $response->dynamicallySetSuccessStatus();
153 |
154 | return $response;
155 | }
156 | }
--------------------------------------------------------------------------------
/src/Responses/AbstractResponse.php:
--------------------------------------------------------------------------------
1 | tokenName;
114 | }
115 |
116 | /**
117 | * Sets the Token Name for redirection
118 | *
119 | * @param string $tokenName
120 | */
121 | public function setTokenName(string $tokenName)
122 | {
123 | $this->tokenName = $tokenName;
124 | }
125 |
126 | /**
127 | * Gets the Transaction Type for the Response (if available)
128 | *
129 | * @return string
130 | */
131 | public function getType()
132 | {
133 | return $this->type;
134 | }
135 |
136 | /**
137 | * Sets the Transaction Type for the Response (if available)
138 | *
139 | * @param string $type
140 | */
141 | public function setType(string $type)
142 | {
143 | $this->type = $type;
144 | }
145 |
146 | /*
147 | |--------------------------------------------------------------------------
148 | | Success indicator
149 | |--------------------------------------------------------------------------
150 | */
151 |
152 | /**
153 | * Return if the Response is a success
154 | *
155 | * @return bool
156 | */
157 | public function isSuccess()
158 | {
159 | return $this->isSuccess;
160 | }
161 |
162 | /**
163 | * Returns if the Response was a failure
164 | *
165 | * @return bool
166 | */
167 | public function isFailed()
168 | {
169 | return !$this->isSuccess();
170 | }
171 |
172 | /*
173 | |--------------------------------------------------------------------------
174 | | Error Handling
175 | |--------------------------------------------------------------------------
176 | */
177 |
178 | /**
179 | * Returns the loaded array of Error translations (or loads it)
180 | *
181 | * @return array|bool|string
182 | */
183 | protected static function getLoadedErrorList()
184 | {
185 | return self::$translationList
186 | ? self::$translationList
187 | : self::$translationList = include_once(self::TRANSLATION_LIST_FILE);
188 | }
189 |
190 | /**
191 | * Returns the Error Code if the transaction was a failure
192 | *
193 | * @return string
194 | */
195 | public function getErrorCode()
196 | {
197 | return $this->errorCode;
198 | }
199 |
200 | /**
201 | * Returns the error as an understandable text string
202 | *
203 | * @return mixed
204 | */
205 | public function getErrorForHumans()
206 | {
207 | return self::getLoadedErrorList()[$this->listKey][$this->errorCode] ?? null;
208 | }
209 |
210 | }
--------------------------------------------------------------------------------
/src/ResponseFactories/WebpayResponseFactory.php:
--------------------------------------------------------------------------------
1 | service->getTransaction($transaction, 'plus.normal');
23 | }
24 |
25 | /**
26 | * Retrieves a Webpay Plus Normal Transaction
27 | *
28 | * @param string $transaction
29 | * @return \DarkGhostHunter\TransbankApi\Responses\WebpayPlusResponse
30 | */
31 | public function retrieveNormal(string $transaction)
32 | {
33 | return $this->service->retrieveTransaction($transaction, 'plus.normal');
34 | }
35 |
36 | /**
37 | * Confirms a Webpay Plus Normal Transaction
38 | *
39 | * @param string $transaction
40 | * @return \DarkGhostHunter\TransbankApi\Responses\WebpayPlusResponse
41 | */
42 | public function confirmNormal(string $transaction)
43 | {
44 | return $this->service->confirmTransaction($transaction, 'plus.normal');
45 | }
46 |
47 | /*
48 | |--------------------------------------------------------------------------
49 | | Webpay Plus Mall Normal
50 | |--------------------------------------------------------------------------
51 | */
52 |
53 | /**
54 | * Retrieves and Confirms a Webpay Plus Mall Normal Transaction
55 | *
56 | * @param string $transaction
57 | * @return \DarkGhostHunter\TransbankApi\Contracts\ResponseInterface|\DarkGhostHunter\TransbankApi\Responses\WebpayPlusMallResponse
58 | * @throws \DarkGhostHunter\TransbankApi\Exceptions\Webpay\TransactionTypeNullException
59 | */
60 | public function getMallNormal(string $transaction)
61 | {
62 | return $this->service->getTransaction($transaction, 'plus.mall.normal');
63 | }
64 |
65 | /**
66 | * Retrieves a Webpay Plus Mall Normal Transaction
67 | *
68 | * @param string $transaction
69 | * @return \DarkGhostHunter\TransbankApi\Contracts\ResponseInterface|\DarkGhostHunter\TransbankApi\Responses\WebpayPlusMallResponse
70 | */
71 | public function retrieveMallNormal(string $transaction)
72 | {
73 | return $this->service->retrieveTransaction($transaction, 'plus.mall.normal');
74 | }
75 |
76 | /**
77 | * Confirms a Webpay Plus Mall Normal Transaction
78 | *
79 | * @param string $transaction
80 | * @return \DarkGhostHunter\TransbankApi\Responses\WebpayPlusResponse
81 | */
82 | public function confirmMallNormal(string $transaction)
83 | {
84 | return $this->service->confirmTransaction($transaction, 'plus.mall.normal');
85 | }
86 |
87 | /*
88 | |--------------------------------------------------------------------------
89 | | Webpay Plus Deferred
90 | |--------------------------------------------------------------------------
91 | */
92 |
93 | /**
94 | * Retrieves and Confirms a Webpay Plus Deferred Transaction
95 | *
96 | * @param string $transaction
97 | * @return \DarkGhostHunter\TransbankApi\Responses\WebpayPlusMallResponse|\DarkGhostHunter\TransbankApi\Responses\WebpayPlusResponse
98 | * @throws \DarkGhostHunter\TransbankApi\Exceptions\Webpay\TransactionTypeNullException
99 | */
100 | public function getDefer(string $transaction)
101 | {
102 | return $this->service->getTransaction($transaction, 'plus.defer');
103 | }
104 |
105 | /**
106 | * Retrieves a Webpay Plus Deferred Transaction
107 | *
108 | * @param string $transaction
109 | * @return \DarkGhostHunter\TransbankApi\Responses\WebpayPlusMallResponse|\DarkGhostHunter\TransbankApi\Responses\WebpayPlusResponse
110 | */
111 | public function retrieveDefer(string $transaction)
112 | {
113 | return $this->service->retrieveTransaction($transaction, 'plus.defer');
114 | }
115 |
116 | /**
117 | * Confirms a Webpay Plus Deferred Transaction
118 | *
119 | * @param string $transaction
120 | * @return \DarkGhostHunter\TransbankApi\Responses\WebpayPlusResponse
121 | */
122 | public function confirmDefer(string $transaction)
123 | {
124 | return $this->service->confirmTransaction($transaction, 'plus.defer');
125 | }
126 |
127 | /*
128 | |--------------------------------------------------------------------------
129 | | Webpay Oneclick Registration
130 | |--------------------------------------------------------------------------
131 | */
132 |
133 | /**
134 | * Confirms the Webpay Oneclick Registration
135 | *
136 | * @param string $transaction
137 | * @return \DarkGhostHunter\TransbankApi\Responses\WebpayPlusResponse
138 | */
139 | public function getRegistration(string $transaction)
140 | {
141 | return $this->service->confirmTransaction($transaction, 'oneclick.confirm');
142 | }
143 |
144 | /**
145 | * Alias for getRegistration()
146 | *
147 | * @param string $transaction
148 | * @return \DarkGhostHunter\TransbankApi\Responses\WebpayPlusResponse
149 | */
150 | public function confirmRegistration(string $transaction)
151 | {
152 | return $this->getRegistration($transaction);
153 | }
154 |
155 | }
--------------------------------------------------------------------------------
/src/Clients/Webpay/WebpayClient.php:
--------------------------------------------------------------------------------
1 | [
20 | 'integration' => 'https://webpay3gint.transbank.cl/WSWebpayTransaction/cxf/WSWebpayService?wsdl',
21 | 'production' => 'https://webpay3g.transbank.cl/WSWebpayTransaction/cxf/WSWebpayService?wsdl',
22 | ],
23 | 'commerce' => [
24 | 'integration' => 'https://webpay3gint.transbank.cl/WSWebpayTransaction/cxf/WSCommerceIntegrationService?wsdl',
25 | 'production' => 'https://webpay3g.transbank.cl/WSWebpayTransaction/cxf/WSCommerceIntegrationService?wsdl',
26 | ],
27 | 'complete' => [
28 | 'integration' => 'https://webpay3gint.transbank.cl/WSWebpayTransaction/cxf/WSCompleteWebpayService?wsdl',
29 | 'production' => 'https://webpay3g.transbank.cl/WSWebpayTransaction/cxf/WSCompleteWebpayService?wsdl',
30 | ],
31 | 'oneclick' => [
32 | 'integration' => 'https://webpay3gint.transbank.cl/webpayserver/wswebpay/OneClickPaymentService?wsdl',
33 | 'production' => 'https://webpay3g.transbank.cl/webpayserver/wswebpay/OneClickPaymentService?wsdl',
34 | ],
35 | ];
36 |
37 | /**
38 | * Endpoint type to use
39 | *
40 | * @var string
41 | */
42 | protected $endpointType;
43 |
44 | /**
45 | * Class map for SOAP
46 | *
47 | * @var array
48 | */
49 | protected $classMap;
50 |
51 | /**
52 | * Soap Connector
53 | *
54 | * @var SoapImplementation|SoapClient
55 | */
56 | protected $connector;
57 |
58 | /*
59 | |--------------------------------------------------------------------------
60 | | Getters and Setters
61 | |--------------------------------------------------------------------------
62 | */
63 |
64 | /**
65 | * Get the Soap Connector
66 | *
67 | * @return SoapImplementation
68 | */
69 | public function getConnector()
70 | {
71 | return $this->connector;
72 | }
73 |
74 | /**
75 | * Set the Soap Connector
76 | *
77 | * @param SoapImplementation|SoapClient $connector
78 | */
79 | public function setConnector(SoapClient $connector)
80 | {
81 | $this->connector = $connector;
82 | }
83 |
84 | /**
85 | * Get the Endpoint Type
86 | *
87 | * @return string
88 | */
89 | public function getEndpointType()
90 | {
91 | return $this->endpointType;
92 | }
93 |
94 | /**
95 | * Set the Endpoint Type
96 | *
97 | * @param string $endpointType
98 | */
99 | public function setEndpointType(string $endpointType)
100 | {
101 | $this->endpointType = $endpointType;
102 | }
103 |
104 | /*
105 | |--------------------------------------------------------------------------
106 | | Initialization
107 | |--------------------------------------------------------------------------
108 | */
109 |
110 | /**
111 | * Boot the connector
112 | *
113 | * @return void
114 | * @throws \DarkGhostHunter\TransbankApi\Exceptions\TransbankUnavailableException
115 | */
116 | public function boot()
117 | {
118 | $this->bootEndpoint();
119 |
120 | $this->bootClassMap();
121 |
122 | $this->bootSoapClient();
123 | }
124 |
125 | /**
126 | * Creates a new instance of the Soap Client using the Configuration as base
127 | *
128 | * @return void
129 | * @throws \DarkGhostHunter\TransbankApi\Exceptions\TransbankUnavailableException
130 | */
131 | protected function bootSoapClient()
132 | {
133 | try {
134 | $this->connector = new SoapImplementation(
135 | $this->endpoint,
136 | $this->credentials->privateKey,
137 | $this->credentials->publicCert,
138 | [
139 | 'classmap' => $this->classMap,
140 | 'trace' => true,
141 | 'exceptions' => true
142 | ]
143 | );
144 | } catch (SoapFault $exception) {
145 | throw new TransbankUnavailableException(null, null, $exception);
146 | }
147 | }
148 |
149 | /**
150 | * Initializes the Class Map to give to the Soap Client
151 | *
152 | * @return void
153 | */
154 | protected function bootClassMap()
155 | {
156 | $this->classMap = include __DIR__ . '/classmaps.php';
157 | }
158 |
159 | /**
160 | * Sets the Endpoint to use depending on the environment type
161 | *
162 | * @return void
163 | */
164 | protected function bootEndpoint()
165 | {
166 | $this->endpoint = self::$endpoints[$this->endpointType][$this->isProduction ? 'production' : 'integration'];
167 | }
168 |
169 | /*
170 | |--------------------------------------------------------------------------
171 | | Common functions for all Transactions
172 | |--------------------------------------------------------------------------
173 | */
174 |
175 | /**
176 | * Validates the last response from the SoapClient
177 | *
178 | * @return bool
179 | */
180 | protected function validate()
181 | {
182 | return (new Validation(
183 | $this->connector->__getLastResponse(),
184 | $this->credentials->webpayCert
185 | ))->isValid();
186 | }
187 |
188 | }
189 |
--------------------------------------------------------------------------------
/src/Transactions/Concerns/HasItems.php:
--------------------------------------------------------------------------------
1 | 1 && !Helpers::isNumericArray($items)) {
28 | $items = [$items];
29 | }
30 |
31 | $this->addItems($items);
32 | }
33 |
34 | /**
35 | * Parse the Item we are getting
36 | *
37 | * @param $item
38 | * @return null
39 | */
40 | protected function parseItem($item)
41 | {
42 | // First, let's try to decode this Item
43 | if (is_string($item) && $array = json_decode($item, true)) {
44 | $item = $array;
45 | }
46 |
47 | // If it was decoded, then return the Item
48 | if (is_array($item)) {
49 | return new Item(array_merge($item, $this->itemDefaults ?? []));
50 | }
51 |
52 | // We did nothing, so we return nothing
53 | return null;
54 | }
55 |
56 | /**
57 | * Add an Item, or multiple Items
58 | *
59 | * @param array $items
60 | */
61 | public function addItem(...$items)
62 | {
63 | foreach ($items as $item) {
64 | // Add the Item only if we can parse it
65 | if ($item = $this->parseItem($item)) {
66 | $this->items[] = $item;
67 | }
68 | }
69 | }
70 |
71 | /**
72 | * Add multiple items.
73 | *
74 | * @param array $items
75 | */
76 | public function addItems(array $items)
77 | {
78 | $this->addItem(...$items);
79 | }
80 |
81 | /**
82 | * Return all the Items in the OnepayTransaction
83 | *
84 | * @return array
85 | */
86 | public function getItems()
87 | {
88 | return $this->items;
89 | }
90 |
91 | /**
92 | * Dynamically gets the Items
93 | *
94 | * @return array
95 | */
96 | public function getItemsAttribute()
97 | {
98 | return $this->getItems();
99 | }
100 |
101 | /**
102 | * Gets a particular Item from the OnepayTransaction by its Key
103 | *
104 | * @param int $key
105 | * @return mixed|null
106 | */
107 | public function getItem(int $key)
108 | {
109 | return $this->items[$key] ?? null;
110 | }
111 |
112 | /**
113 | * Get an Item by its exact description
114 | *
115 | * @param string $description
116 | * @return mixed|null
117 | */
118 | public function getItemByDescription(string $description)
119 | {
120 | foreach ($this->items as $item) {
121 | if ($item->description === $description) {
122 | return $item;
123 | }
124 | }
125 | return null;
126 | }
127 |
128 | /**
129 | * Get an Item Key by its Description
130 | *
131 | * @param string $description
132 | * @return int|null|string
133 | */
134 | public function getItemKeyByDescription(string $description)
135 | {
136 | foreach ($this->items as $key => $item) {
137 | if ($item->description === $description) {
138 | return $key;
139 | }
140 | }
141 | return null;
142 | }
143 |
144 | /**
145 | * Deletes an Item by its Key
146 | *
147 | * @param int $key
148 | * @return bool
149 | */
150 | public function deleteItem(int $key)
151 | {
152 | if (isset($this->items[$key])) {
153 | unset($this->items[$key]);
154 | return true;
155 | }
156 | return false;
157 | }
158 |
159 | /**
160 | * Deletes an Item by its Description
161 | *
162 | * @param string $description
163 | * @return bool
164 | */
165 | public function deleteItemByDescription(string $description)
166 | {
167 | if ($key = $this->getItemKeyByDescription($description)) {
168 | return $this->deleteItem($key);
169 | }
170 | return false;
171 | }
172 |
173 | /**
174 | * Updates an Item attributes, replacing or adding them, and return the result
175 | *
176 | * @param int $key
177 | * @param array $attributes
178 | * @return object|bool
179 | */
180 | public function updateItem(int $key, array $attributes)
181 | {
182 | if (isset($this->items[$key])) {
183 |
184 | $this->items[$key]->setAttributes(
185 | array_merge($this->items[$key]->getAttributes(), $attributes)
186 | );
187 |
188 | return $this->items[$key];
189 | }
190 | return false;
191 | }
192 |
193 | /**
194 | * Replaces completely an Item with another
195 | *
196 | * @param int $key
197 | * @param $item
198 | * @return bool
199 | */
200 | public function replaceItem(int $key, $item)
201 | {
202 | if (isset($this->items[$key])) {
203 | return !!($this->items[$key] = $this->parseItem($item));
204 | }
205 | return false;
206 | }
207 |
208 | /**
209 | * Count all Items in the OnepayTransaction
210 | *
211 | * @return int
212 | */
213 | public function countItems()
214 | {
215 | return count($this->items);
216 | }
217 |
218 |
219 | /**
220 | * Clears the Items array
221 | *
222 | * @return void
223 | */
224 | public function clearItems()
225 | {
226 | $this->items = [];
227 | }
228 |
229 | /**
230 | * Reindex the Items array
231 | *
232 | * @return void
233 | */
234 | public function reindexItems()
235 | {
236 | $this->items = array_values($this->items);
237 | }
238 | }
--------------------------------------------------------------------------------
/src/Responses/WebpayPlusMallResponse.php:
--------------------------------------------------------------------------------
1 | detailOutput) {
30 | $this->detailOutput = is_array($this->detailOutput)
31 | ? $this->detailOutput
32 | : [$this->detailOutput];
33 | }
34 |
35 | }
36 |
37 | /*
38 | |--------------------------------------------------------------------------
39 | | Status
40 | |--------------------------------------------------------------------------
41 | */
42 |
43 | /**
44 | * Detect if the Result was successful or not
45 | *
46 | * @return void
47 | */
48 | public function dynamicallySetSuccessStatus()
49 | {
50 | if ($this->token) {
51 | $this->isSuccess = true;
52 | return;
53 | }
54 |
55 | if ($this->detailOutput) {
56 | $this->isSuccess = $this->allItemsAreOk($this->detailOutput);
57 | }
58 | }
59 |
60 | /**
61 | * Detect if all the items returned in the response are successful
62 | *
63 | * @param array|null $items
64 | * @return bool
65 | */
66 | protected function allItemsAreOk(array $items)
67 | {
68 | foreach ($items as $item) {
69 | if ($item->responseCode !== 0) {
70 | return false;
71 | }
72 | }
73 |
74 | return true;
75 | }
76 |
77 | /*
78 | |--------------------------------------------------------------------------
79 | | Error Management
80 | |--------------------------------------------------------------------------
81 | */
82 |
83 | /**
84 | * Returns the Order Error for Humans
85 | *
86 | * @param int $key
87 | * @return string|null
88 | */
89 | public function getOrderErrorForHumans(int $key)
90 | {
91 | // First let's see if the item index exists
92 | $item = $this->detailOutput[$key] ?? null;
93 |
94 | // If the item exists and the errorCode also exists, return the translated
95 | // error code only if you can find it. Otherwise the script will proceed
96 | // and eventually return null since it did not exists from the get go.
97 | if ($item && $item->errorCode) {
98 | return self::getLoadedErrorList()[$this->listKey][$item->errorCode] ?? null;
99 | }
100 | return null;
101 | }
102 |
103 | /**
104 | * Alias for getOrderErrorForHumans()
105 | *
106 | * @param int $key
107 | * @return string|null
108 | */
109 | public function getItemErrorForHumans(int $key)
110 | {
111 | return $this->getOrderErrorForHumans($key);
112 | }
113 |
114 | /*
115 | |--------------------------------------------------------------------------
116 | | Order (Item) management
117 | |--------------------------------------------------------------------------
118 | */
119 |
120 | /**
121 | * Return all the orders
122 | *
123 | * @return array
124 | */
125 | public function getOrders()
126 | {
127 | return $this->detailOutput;
128 | }
129 |
130 | /**
131 | * Alias for getOrders()
132 | *
133 | * @return mixed
134 | */
135 | public function getItems()
136 | {
137 | return $this->getOrders();
138 | }
139 |
140 | /**
141 | * Return only successful orders
142 | *
143 | * @return array
144 | */
145 | public function getSuccessfulOrders()
146 | {
147 | $successful = [];
148 |
149 | foreach ($this->getItems() as $item) {
150 | if ($item->responseCode === 0) {
151 | $successful[] = $item;
152 | }
153 | }
154 |
155 | return $successful;
156 | }
157 |
158 | /**
159 | * Alias for getSuccessfulOrders()
160 | *
161 | * @return array
162 | */
163 | public function getSuccessfulItems()
164 | {
165 | return $this->getSuccessfulOrders();
166 | }
167 |
168 | /**
169 | * Return all failed Orders
170 | *
171 | * @return array
172 | */
173 | public function getFailedOrders()
174 | {
175 | $successful = [];
176 |
177 | foreach ($this->getItems() as $item) {
178 | if ($item->responseCode !== 0) {
179 | $successful[] = $item;
180 | }
181 | }
182 |
183 | return $successful;
184 | }
185 |
186 | /**
187 | * Alias for getFailedOrders()
188 | *
189 | * @return array
190 | */
191 | public function getFailedItems()
192 | {
193 | return $this->getFailedOrders();
194 | }
195 |
196 |
197 | /**
198 | * Return the total amount of the whole transaction
199 | *
200 | * @return int
201 | */
202 | public function getTotal()
203 | {
204 | $total = 0;
205 |
206 | foreach ($this->getItems() as $item) {
207 | $total += $item->amount;
208 | }
209 |
210 | return $total;
211 | }
212 |
213 | /**
214 | * Return only the total amount from successful items
215 | *
216 | * @return int
217 | */
218 | public function getSuccessfulTotal()
219 | {
220 | $total = 0;
221 |
222 | foreach ($this->getSuccessfulItems() as $item) {
223 | $total += $item->amount;
224 | }
225 |
226 | return $total;
227 | }
228 |
229 | /**
230 | * Return only the total amount from failed items
231 | *
232 | * @return int
233 | */
234 | public function getFailedTotal()
235 | {
236 | $total = 0;
237 |
238 | foreach ($this->getFailedItems() as $item) {
239 | $total += $item->amount;
240 | }
241 |
242 | return $total;
243 | }
244 | }
--------------------------------------------------------------------------------
/tests/Unit/Responses/WebpayPlusMallResponseTest.php:
--------------------------------------------------------------------------------
1 | 'test-token'
15 | ]);
16 |
17 | $response->dynamicallySetSuccessStatus();
18 |
19 | $this->assertTrue($response->isSuccess());
20 |
21 | $response = new WebpayPlusMallResponse([]);
22 |
23 | $response->dynamicallySetSuccessStatus();
24 |
25 | $this->assertFalse($response->isSuccess());
26 | }
27 |
28 | public function testDynamicallySetSuccessStatusWithItems()
29 | {
30 | $response = new WebpayPlusMallResponse([
31 | 'detailOutput' => [
32 | (object)['responseCode' => 0],
33 | (object)['responseCode' => 0],
34 | (object)['responseCode' => 0],
35 | ]
36 | ]);
37 |
38 | $response->dynamicallySetSuccessStatus();
39 |
40 | $this->assertTrue($response->isSuccess());
41 |
42 | $response = new WebpayPlusMallResponse([
43 | 'detailOutput' => [
44 | (object)['responseCode' => 0],
45 | (object)['responseCode' => 1],
46 | (object)['responseCode' => 0],
47 | ]
48 | ]);
49 |
50 | $response->dynamicallySetSuccessStatus();
51 |
52 | $this->assertFalse($response->isSuccess());
53 |
54 | $response = new WebpayPlusMallResponse([
55 | 'detailOutput' => (object)['responseCode' => 0]
56 | ]);
57 |
58 | $response->dynamicallySetSuccessStatus();
59 |
60 | $this->assertTrue($response->isSuccess());
61 |
62 | $response = new WebpayPlusMallResponse([
63 | 'detailOutput' => (object)['responseCode' => 999]
64 | ]);
65 |
66 | $response->dynamicallySetSuccessStatus();
67 |
68 | $this->assertFalse($response->isSuccess());
69 | }
70 |
71 | public function testGetSuccessfulTotal()
72 | {
73 | $response = new WebpayPlusMallResponse([
74 | 'detailOutput' => [
75 | (object)['responseCode' => 0, 'amount' => 4990],
76 | (object)['responseCode' => 1, 'amount' => 4990],
77 | (object)['responseCode' => 0, 'amount' => 4990],
78 | ]
79 | ]);
80 |
81 | $this->assertEquals(4990 * 2, $response->getSuccessfulTotal());
82 | }
83 |
84 | public function testGetSuccessfulOrdersOrGetSuccessfulItems()
85 | {
86 | $response = new WebpayPlusMallResponse([
87 | 'detailOutput' => [
88 | (object)['responseCode' => 0, 'amount' => 4990],
89 | (object)['responseCode' => 1, 'amount' => 4990],
90 | (object)['responseCode' => 0, 'amount' => 4990],
91 | ]
92 | ]);
93 |
94 | $this->assertCount(2, $response->getSuccessfulOrders());
95 | $this->assertCount(2, $response->getSuccessfulItems());
96 | }
97 |
98 | public function testGetTotal()
99 | {
100 | $response = new WebpayPlusMallResponse([
101 | 'detailOutput' => [
102 | (object)['responseCode' => 0, 'amount' => 4990],
103 | (object)['responseCode' => 1, 'amount' => 4990],
104 | (object)['responseCode' => 0, 'amount' => 4990],
105 | ]
106 | ]);
107 |
108 | $this->assertEquals(4990 * 3, $response->getTotal());
109 | }
110 |
111 | public function testGetOrdersOrGetItems()
112 | {
113 | $response = new WebpayPlusMallResponse([
114 | 'detailOutput' => $array = [
115 | (object)['responseCode' => 0, 'amount' => 4990],
116 | (object)['responseCode' => 1, 'amount' => 4990],
117 | (object)['responseCode' => 0, 'amount' => 4990],
118 | ]
119 | ]);
120 |
121 | $this->assertEquals($array, $response->getOrders());
122 | $this->assertEquals($array, $response->getItems());
123 | }
124 |
125 | public function testGetOrderErrorForHumansOrGetItemErrorForHumans()
126 | {
127 | $response = new WebpayPlusMallResponse([
128 | 'detailOutput' => [
129 | (object)['responseCode' => 0, 'amount' => 4990],
130 | (object)['responseCode' => 1, 'errorCode' => 18, 'amount' => 4990],
131 | (object)['responseCode' => 0, 'amount' => 4990],
132 | (object)['responseCode' => 1, 'errorCode' => 99999, 'amount' => 4990],
133 | ]
134 | ]);
135 |
136 | $this->assertEquals('ERR_SERVIDOR_COMERCIO', $response->getOrderErrorForHumans(1));
137 | $this->assertEquals('ERR_SERVIDOR_COMERCIO', $response->getItemErrorForHumans(1));
138 | $this->assertNull($response->getOrderErrorForHumans(3));
139 | $this->assertNull($response->getOrderErrorForHumans(5));
140 | }
141 |
142 | public function testGetFailedOrdersOrGetFailedItems()
143 | {
144 | $failed = [
145 | (object)['responseCode' => 1, 'errorCode' => 18, 'amount' => 4990],
146 | (object)['responseCode' => 1, 'errorCode' => 1, 'amount' => 4990],
147 | ];
148 |
149 | $response = new WebpayPlusMallResponse([
150 | 'detailOutput' => [
151 | (object)['responseCode' => 0, 'amount' => 4990],
152 | (object)['responseCode' => 1, 'errorCode' => 18, 'amount' => 4990],
153 | (object)['responseCode' => 0, 'amount' => 4990],
154 | (object)['responseCode' => 1, 'errorCode' => 1, 'amount' => 4990],
155 | ]
156 | ]);
157 |
158 | $this->assertEquals($failed, $response->getFailedOrders());
159 | $this->assertEquals($failed, $response->getFailedItems());
160 | }
161 |
162 | public function testGetFailedTotal()
163 | {
164 | $response = new WebpayPlusMallResponse([
165 | 'detailOutput' => [
166 | (object)['responseCode' => 0, 'amount' => 4990],
167 | (object)['responseCode' => 1, 'errorCode' => 18, 'amount' => 1990],
168 | (object)['responseCode' => 0, 'amount' => 4990],
169 | (object)['responseCode' => 1, 'errorCode' => 1, 'amount' => 1990],
170 | ]
171 | ]);
172 |
173 | $this->assertEquals(1990 * 2, $response->getFailedTotal());
174 | }
175 | }
176 |
--------------------------------------------------------------------------------