├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
├── phpunit.xml.dist
├── src
├── AccessToken.php
├── Entities
│ ├── AbstractEntity.php
│ ├── BankAccount.php
│ ├── Payment.php
│ ├── PaymentRequest.php
│ ├── Platform.php
│ └── User.php
├── Environment.php
├── Exceptions
│ ├── AccessTokenException.php
│ ├── PHPTikkieException.php
│ ├── RequestException.php
│ └── ResponseException.php
├── PHPTikkie.php
├── Requests
│ ├── AbstractRequest.php
│ ├── CreatePaymentRequestRequest.php
│ ├── CreatePlatformRequest.php
│ ├── CreateUserRequest.php
│ ├── FetchPaymentRequestRequest.php
│ ├── FetchPaymentRequestsRequest.php
│ ├── FetchPlatformsRequest.php
│ └── FetchUsersRequest.php
└── Response.php
└── tests
├── CreatePaymentRequestTest.php
├── CreatePlatformTest.php
├── CreateUserTest.php
├── EnvironmentTest.php
├── FetchPaymentRequestTest.php
├── FetchPaymentRequestsTest.php
├── FetchPlatformsTest.php
├── FetchUsersTest.php
├── Mock
├── AccessToken.txt
├── CreatePaymentRequestSuccess.txt
├── CreatePlatformSuccess.txt
├── CreateUserSuccess.txt
├── FetchPaymentRequestSuccess.txt
├── FetchPaymentRequestsSuccess.txt
├── FetchPlatformsSuccess.txt
├── FetchUsersSuccess.txt
├── InvalidApiKey.txt
├── ValidationError.txt
├── private_rsa.pem
└── public_rsa.pem
└── TestCase.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | composer.lock
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 7.1
5 | - 7.2
6 | - 7.3
7 |
8 | ## Cache composer
9 | cache:
10 | directories:
11 | - $HOME/.composer/cache
12 |
13 | install:
14 | - travis_retry composer install --prefer-dist --no-interaction
15 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6 |
7 | ## [Unreleased]
8 |
9 | ## [0.2.4] - 2019-11-15
10 | ### Fixed
11 | - `externalId` of payment requests is now documented as mandatory. ([#6](https://github.com/jarnovanleeuwen/php-tikkie/pull/6))
12 |
13 | ### Deprecated
14 | - `Platform::USAGE_TYPE_OTHERS` is deprecated because it is no longer mentioned in the official documentation.
15 |
16 | ## [0.2.3] - 2019-04-24
17 | ### Fixed
18 | - Due to a bug at Tikkie, dates may be returned as a epoch timestamp with milliseconds instead of an ISO-8601 formatted string. This has been reported to Tikkie, and while we wait support for those timestamps has been added to the library.
19 |
20 | ## [0.2.2] - 2018-10-31
21 | ### Changed
22 | - All Guzzle-related exceptions are now turned into a `RequestException`.
23 |
24 | ## [0.2.1] - 2018-09-27
25 | ### Changed
26 | - Trace ID of requests is now included in exception messages. ([#3](https://github.com/jarnovanleeuwen/php-tikkie/pull/3))
27 |
28 | ## [0.2.0] - 2018-06-20
29 | ### Added
30 | - Added a test suite.
31 |
32 | ### Changed
33 | - PHPTikkie now requires PHP 7.1+
34 |
35 | ## [0.1.2] - 2018-06-19
36 | ### Fixed
37 | - Cast `from` and `to` dates to UTC time zone. ([#1](https://github.com/jarnovanleeuwen/php-tikkie/pull/1))
38 |
39 | ## [0.1.1] - 2018-03-05
40 | ### Fixed
41 | - Check if responses are valid JSON.
42 | - Fix the class name of `ResponseException`.
43 |
44 | ## [0.1.0] - 2017-12-12
45 | ### Added
46 | - Initial implementation of the Tikkie API.
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Jarno van Leeuwen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | #
4 |
5 | [](https://travis-ci.com/jarnovanleeuwen/php-tikkie)
6 |
7 | ⚠️ Tikkie has announced that on **01-01-2021** it will stop supporting the Tikkie Payment Request API (the API that this library implements) in favor of the new Tikkie API. See https://medium.com/abn-amro-developer/abn-amro-introduces-the-new-tikkie-api-87c8bb54720a for more information, including a roadmap.
8 |
9 | Currently, I am not planning to update this library. This might change in the future, but meanwhile PRs are welcome.
10 |
11 | ---
12 |
13 | #### Easily create payment requests through [Tikkie](https://tikkie.me/).
14 |
15 | Unofficial PHP implementation of the [Tikkie Payment Request API](https://developer.abnamro.com/content/tikkie-payment-request) (deprecated, available until 01-01-2021).
16 |
17 | # Installation
18 |
19 | *PHPTikkie requires PHP 7.1+*
20 |
21 | Add this package to your project using [Composer](https://getcomposer.org/):
22 |
23 | `composer require jarnovanleeuwen/php-tikkie`
24 |
25 | # Usage
26 |
27 | ### Initialise PHPTikkie
28 | ```php
29 | use PHPTikkie\Environment;
30 | use PHPTikkie\PHPTikkie;
31 |
32 | $apiKey = "abc123";
33 | $testMode = true;
34 |
35 | $environment = new Environment($apiKey, $testMode);
36 | $environment->loadPrivateKey('private_rsa.pem');
37 |
38 | $tikkie = new PHPTikkie($environment);
39 | ```
40 |
41 | ### Create platform
42 | ```php
43 | use PHPTikkie\Entities\Platform;
44 |
45 | $platform = $tikkie->newPlatform([
46 | // Mandatory attributes
47 | 'name' => 'YourPlatform',
48 | 'phoneNumber' => '06123456789',
49 | 'platformUsage' => Platform::USAGE_TYPE_MYSELF,
50 |
51 | // Optional attributes
52 | 'email' => 'tikkie@yourcompany.com',
53 | 'notificationUrl' => ''
54 | ])->save();
55 |
56 | $platformToken = $platform->platformToken;
57 | ```
58 |
59 | ### Create user
60 | ```php
61 | $user = $tikkie->newUser($platformToken, [
62 | 'name' => 'ExamplePlatform',
63 | 'phoneNumber' => '06123456789',
64 | 'iban' => 'NL00BANK123456789',
65 | 'bankAccountLabel' => 'YourLabel'
66 | ])->save();
67 |
68 | $userToken = $user->userToken;
69 | $bankAccountToken = $user->bankAccounts[0]->bankAccountToken;
70 | ```
71 |
72 | ### Create payment request
73 | ```php
74 | $paymentRequest = $tikkie->newPaymentRequest($platformToken, $userToken, $bankAccountToken, [
75 | // Mandatory attributes
76 | 'amountInCents' => '1250',
77 | 'currency' => 'EUR',
78 | 'description' => 'Thank you',
79 | 'externalId' => 'Order 1234'
80 | ])->save();
81 |
82 | $tikkieUrl = $paymentRequest->paymentRequestUrl;
83 | $paymentRequestToken = $paymentRequest->paymentRequestToken;
84 | ```
85 |
86 | ### Get payment request
87 | ```php
88 | function paymentRequest(string $platformToken, string $userToken, string $paymentRequestToken): PaymentRequest
89 | ```
90 |
91 | ### List platforms
92 | ```php
93 | function platforms(): Platform[]
94 | ```
95 |
96 | ### List users
97 | ```php
98 | function users(string $platformToken): User[]
99 | ```
100 |
101 | ### List payment requests
102 | ```php
103 | function paymentRequests(string $platformToken, string $userToken, int $offset, int $limit, DateTimeInterface $fromDate = null, DateTimeInterface $toDate = null): PaymentRequest[]
104 | ```
105 |
106 | ### Process payments
107 | ```php
108 | $paymentRequest = $tikkie->paymentRequest($platformToken, $userToken, $paymentRequestToken);
109 |
110 | foreach ($paymentRequest->payments as $payment) {
111 | if ($payment->isPaid()) {
112 | // Payment successful
113 | }
114 | }
115 | ```
116 |
117 | ### Exception handling
118 | All methods may return a `PHPTikkieException` containing an error code and description.
119 |
120 | ```php
121 | use PHPTikkie\Exceptions\PHPTikkieException;
122 |
123 | try {
124 | var_dump($tikkie->platforms());
125 | } catch (PHPTikkieException $exception) {
126 | print $exception->getMessage(); // [ERR_2005_002] The API Key is invalid for the requested resource | traceId: 6fda2ce8-225d-4ca2-920a-b687c7aeb2f3 | (see https://developer.abnamro.com/get-started#obtaining-an-api-key)
127 | }
128 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jarnovanleeuwen/php-tikkie",
3 | "type": "library",
4 | "description": "Implementation of the Tikkie API interface.",
5 | "keywords": [
6 | "tikkie",
7 | "payment",
8 | "pay",
9 | "api",
10 | "abnamro"
11 | ],
12 | "homepage": "https://github.com/jarnovanleeuwen/php-tikkie",
13 | "license": "MIT",
14 | "authors": [
15 | {
16 | "name": "Jarno van Leeuwen",
17 | "email": "vanleeuwen.jarno@gmail.com"
18 | }
19 | ],
20 | "autoload": {
21 | "psr-4": {
22 | "PHPTikkie\\": "src/"
23 | }
24 | },
25 | "autoload-dev": {
26 | "psr-4": {
27 | "PHPTikkie\\Tests\\": "tests/"
28 | }
29 | },
30 | "require": {
31 | "php": ">=7.1.0",
32 | "guzzlehttp/guzzle": "~6.0",
33 | "firebase/php-jwt": "~5.0"
34 | },
35 | "require-dev": {
36 | "phpunit/phpunit": "^6"
37 | },
38 | "abandoned": true
39 | }
40 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 | ./tests/
15 |
16 |
17 |
18 |
19 | ./src
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/AccessToken.php:
--------------------------------------------------------------------------------
1 | token = $token;
26 | $this->lifetime = $lifetime;
27 | $this->expiryTime = time() + $lifetime;
28 | }
29 |
30 | public function getLifetime(): int
31 | {
32 | return $this->lifetime;
33 | }
34 |
35 | public function getToken(): string
36 | {
37 | return $this->token;
38 | }
39 |
40 | public function isValid(): bool
41 | {
42 | return time() < $this->expiryTime;
43 | }
44 |
45 | public function __toString(): string
46 | {
47 | return $this->token;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Entities/AbstractEntity.php:
--------------------------------------------------------------------------------
1 | tikkie = $tikkie;
22 | }
23 |
24 | protected function getTikkie(): PHPTikkie
25 | {
26 | return $this->tikkie;
27 | }
28 |
29 | public function setAttributes(array $attributes)
30 | {
31 | foreach ($attributes as $key => $value) {
32 | if (in_array($key, $this->fillableAttributes)) {
33 | $this->{$key} = $value;
34 | }
35 | }
36 | }
37 |
38 | /**
39 | * Convert an ISO-8601 formatted string to DateTimeImmutable.
40 | */
41 | protected function toDateTime(string $representation): DateTimeImmutable
42 | {
43 | // Due to a Tikkie bug, the API may return epoch timestamps with milliseconds instead of a ISO-8601 formatted string.
44 | // I reported this on 24-04-2019.
45 | if (is_numeric($representation)) {
46 | // Remove milliseconds and prepend with @ to mark as timestamp.
47 | $representation = '@'.substr($representation, 0, 10);
48 | }
49 |
50 | return new DateTimeImmutable($representation);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Entities/BankAccount.php:
--------------------------------------------------------------------------------
1 | onlinePaymentStatus === static::STATUS_PAID;
56 | }
57 |
58 | public function setAttributes(array $attributes)
59 | {
60 | parent::setAttributes($attributes);
61 |
62 | if (isset($attributes['created'])) {
63 | $this->created = $this->toDateTime($attributes['created']);
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Entities/PaymentRequest.php:
--------------------------------------------------------------------------------
1 | {$dateAttribute} = $this->toDateTime($attributes[$dateAttribute]);
97 | }
98 | }
99 |
100 | $this->payments = [];
101 |
102 | if ($payments = $attributes['payments'] ?? null) {
103 | foreach ($payments as $paymentData) {
104 | $payment = new Payment($this->getTikkie());
105 |
106 | $payment->setAttributes($paymentData);
107 |
108 | $this->payments[] = $payment;
109 | }
110 | }
111 | }
112 |
113 | public function save(): self
114 | {
115 | $this->getTikkie()->persistPaymentRequest($this);
116 |
117 | return $this;
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/Entities/Platform.php:
--------------------------------------------------------------------------------
1 | status === static::STATUS_ACTIVE;
59 | }
60 |
61 | public function save(): self
62 | {
63 | $this->getTikkie()->persistPlatform($this);
64 |
65 | return $this;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Entities/User.php:
--------------------------------------------------------------------------------
1 | status === static::STATUS_ACTIVE;
59 | }
60 |
61 | public function setAttributes(array $attributes)
62 | {
63 | parent::setAttributes($attributes);
64 |
65 | $this->bankAccounts = [];
66 |
67 | if ($bankAccounts = $attributes['bankAccounts'] ?? null) {
68 | foreach ($bankAccounts as $bankAccountData) {
69 | $bankAccount = new BankAccount($this->getTikkie());
70 |
71 | $bankAccount->setAttributes($bankAccountData);
72 |
73 | $this->bankAccounts[] = $bankAccount;
74 | }
75 | }
76 | }
77 |
78 | public function save(): self
79 | {
80 | $this->getTikkie()->persistUser($this);
81 |
82 | return $this;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/Environment.php:
--------------------------------------------------------------------------------
1 | apiKey = $apiKey;
54 | $this->testMode = $testMode;
55 |
56 | $this->httpClient = new HttpClient(array_merge([
57 | 'base_uri' => $testMode ? static::SANDBOX_API_URL : static::PRODUCTION_API_URL,
58 | 'http_errors' => false,
59 | 'headers' => ['User-Agent' => 'PHPTikkie/'.static::VERSION]
60 | ], $requestOptions));
61 | }
62 |
63 | public function loadPrivateKey(string $path, string $hashAlgorithm = self::DEFAULT_HASH_ALGORITHM)
64 | {
65 | return $this->loadPrivateKeyFromString(file_get_contents($path), $hashAlgorithm);
66 | }
67 |
68 | public function loadPrivateKeyFromString(string $privateKey, string $hashAlgorithm = self::DEFAULT_HASH_ALGORITHM)
69 | {
70 | $this->privateKey = $privateKey;
71 | $this->hashAlgorithm = $hashAlgorithm;
72 | }
73 |
74 | protected function getAccessToken(): AccessToken
75 | {
76 | if ($this->accessToken && $this->accessToken->isValid()) {
77 | return $this->accessToken;
78 | }
79 |
80 | return $this->accessToken = $this->requestAccessToken();
81 | }
82 |
83 | protected function getJsonWebToken(): string
84 | {
85 | if (empty($this->privateKey)) {
86 | throw new AccessTokenException("Cannot create JSON Web Token because no Private Key has been set.");
87 | }
88 |
89 | $now = time();
90 |
91 | return JWT::encode([
92 | 'exp' => $now + 60, // Expires after one minute
93 | 'nbf' => $now - 60,
94 | 'iss' => 'PHPTikkie',
95 | 'sub' => $this->apiKey,
96 | 'aud' => $this->testMode ? static::SANDBOX_TOKEN_URL : static::PRODUCTION_TOKEN_URL
97 | ], $this->privateKey, $this->hashAlgorithm);
98 | }
99 |
100 | /**
101 | * @throws AccessTokenException
102 | */
103 | protected function requestAccessToken(): AccessToken
104 | {
105 | try {
106 | $response = $this->httpClient->request('POST', '/v1/oauth/token', [
107 | 'headers' => [
108 | 'API-Key' => $this->apiKey
109 | ],
110 | 'form_params' => [
111 | 'client_assertion' => $this->getJsonWebToken(),
112 | 'client_assertion_type' => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
113 | 'grant_type' => 'client_credentials',
114 | 'scope' => 'tikkie'
115 | ]
116 | ]);
117 |
118 | if ($response->getStatusCode() == 200 && is_object($responseData = json_decode($response->getBody()))) {
119 | return new AccessToken($responseData->access_token, (int) $responseData->expires_in);
120 | }
121 |
122 | throw new AccessTokenException($response->getBody());
123 | } catch (GuzzleException $exception) {
124 | throw new AccessTokenException($exception->getMessage());
125 | }
126 | }
127 |
128 | protected function getRequestOptions(AbstractRequest $request): array
129 | {
130 | $options = [
131 | RequestOptions::HEADERS => [
132 | 'API-Key' => $this->apiKey,
133 | 'Authorization' => "Bearer {$this->getAccessToken()}",
134 | 'Accept' => 'application/json'
135 | ]
136 | ];
137 |
138 | if ($parameters = $request->getParameters()) {
139 | $options[RequestOptions::QUERY] = $parameters;
140 | }
141 |
142 | if ($payload = $request->getPayload()) {
143 | $options[RequestOptions::JSON] = $payload;
144 | }
145 |
146 | return array_merge_recursive($options, $request->getRequestOptions());
147 | }
148 |
149 | /**
150 | * @throws RequestException
151 | */
152 | public function send(AbstractRequest $request): Response
153 | {
154 | try {
155 | $response = $this->httpClient->request(
156 | $request->getMethod(),
157 | $request->getUri(),
158 | $this->getRequestOptions($request)
159 | );
160 |
161 | if (in_array($response->getStatusCode(), [200, 201])) {
162 | return new Response($response);
163 | }
164 |
165 | throw new RequestException($response->getBody());
166 | } catch (GuzzleException $exception) {
167 | throw new RequestException($exception->getMessage());
168 | }
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/src/Exceptions/AccessTokenException.php:
--------------------------------------------------------------------------------
1 | errors = $response->errors ?? [];
21 |
22 | if (count($this->errors) > 0) {
23 | $error = $this->errors[0];
24 |
25 | $message = "[{$error->code}] {$error->message} "
26 | . "| traceId: {$error->traceId} | "
27 | . "(see {$error->reference})";
28 | }
29 | }
30 |
31 | parent::__construct($message, $code, $previous);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Exceptions/RequestException.php:
--------------------------------------------------------------------------------
1 | environment = $environment;
26 | }
27 |
28 | public function getEnvironment(): Environment
29 | {
30 | return $this->environment;
31 | }
32 |
33 | public function newPaymentRequest(string $platformToken, string $userToken, string $bankAccountToken, array $attributes = []): PaymentRequest
34 | {
35 | $paymentRequest = new PaymentRequest($this);
36 |
37 | $paymentRequest->platformToken = $platformToken;
38 | $paymentRequest->userToken = $userToken;
39 | $paymentRequest->bankAccountToken = $bankAccountToken;
40 |
41 | $paymentRequest->setAttributes($attributes);
42 |
43 | return $paymentRequest;
44 | }
45 |
46 | public function persistPaymentRequest(PaymentRequest $paymentRequest)
47 | {
48 | $response = $this->environment->send(new CreatePaymentRequestRequest($paymentRequest));
49 |
50 | $paymentRequest->setAttributes($response->getData());
51 | }
52 |
53 | public function paymentRequest(string $platformToken, string $userToken, string $paymentRequestToken): PaymentRequest
54 | {
55 | $response = $this->environment->send(new FetchPaymentRequestRequest($platformToken, $userToken, $paymentRequestToken));
56 |
57 | $paymentRequest = new PaymentRequest($this);
58 |
59 | $paymentRequest->setAttributes($response->getData());
60 |
61 | return $paymentRequest;
62 | }
63 |
64 | /**
65 | * @return PaymentRequest[]
66 | */
67 | public function paymentRequests(string $platformToken, string $userToken, int $offset, int $limit, DateTimeInterface $fromDate = null, DateTimeInterface $toDate = null): array
68 | {
69 | $response = $this->environment->send(new FetchPaymentRequestsRequest($platformToken, $userToken, $offset, $limit, $fromDate, $toDate));
70 |
71 | $paymentRequests = [];
72 | foreach ($response->getData()['paymentRequests'] as $paymentRequestData) {
73 | $paymentRequest = new PaymentRequest($this);
74 |
75 | $paymentRequest->setAttributes($paymentRequestData);
76 |
77 | $paymentRequests[] = $paymentRequest;
78 | }
79 |
80 | return $paymentRequests;
81 | }
82 |
83 | public function newPlatform(array $attributes = []): Platform
84 | {
85 | $platform = new Platform($this);
86 |
87 | $platform->setAttributes($attributes);
88 |
89 | return $platform;
90 | }
91 |
92 | public function persistPlatform(Platform $platform)
93 | {
94 | $response = $this->environment->send(new CreatePlatformRequest($platform));
95 |
96 | $platform->setAttributes($response->getData());
97 | }
98 |
99 | /**
100 | * @return Platform[]
101 | */
102 | public function platforms(): array
103 | {
104 | $response = $this->environment->send(new FetchPlatformsRequest);
105 |
106 | $platforms = [];
107 | foreach ($response->getData() as $platformData) {
108 | $platform = new Platform($this);
109 |
110 | $platform->setAttributes($platformData);
111 |
112 | $platforms[] = $platform;
113 | }
114 |
115 | return $platforms;
116 | }
117 |
118 | public function newUser(string $platformToken, array $attributes = []): User
119 | {
120 | $user = new User($this);
121 |
122 | $user->platformToken = $platformToken;
123 |
124 | $user->setAttributes($attributes);
125 |
126 | return $user;
127 | }
128 |
129 | public function persistUser(User $user)
130 | {
131 | $response = $this->environment->send(new CreateUserRequest($user));
132 |
133 | $user->setAttributes($response->getData());
134 | }
135 |
136 | /**
137 | * @return User[]
138 | */
139 | public function users(string $platformToken): array
140 | {
141 | $response = $this->environment->send(new FetchUsersRequest($platformToken));
142 |
143 | $users = [];
144 | foreach ($response->getData() as $userData) {
145 | $user = new User($this);
146 |
147 | $user->setAttributes($userData);
148 |
149 | $users[] = $user;
150 | }
151 |
152 | return $users;
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/src/Requests/AbstractRequest.php:
--------------------------------------------------------------------------------
1 | parameters;
26 | }
27 |
28 | public function getPayload(): ?array
29 | {
30 | return $this->payload;
31 | }
32 |
33 | public function getRequestOptions(): ?array
34 | {
35 | return [];
36 | }
37 |
38 | abstract public function getMethod(): string;
39 | abstract public function getUri(): string;
40 | }
41 |
--------------------------------------------------------------------------------
/src/Requests/CreatePaymentRequestRequest.php:
--------------------------------------------------------------------------------
1 | paymentRequest = $paymentRequest;
16 | }
17 |
18 | public function getMethod(): string
19 | {
20 | return 'POST';
21 | }
22 |
23 | public function getUri(): string
24 | {
25 | return "v1/tikkie/platforms/{$this->paymentRequest->platformToken}/users/{$this->paymentRequest->userToken}/bankaccounts/{$this->paymentRequest->bankAccountToken}/paymentrequests";
26 | }
27 |
28 | public function getPayload(): ?array
29 | {
30 | $paymentRequest = $this->paymentRequest;
31 |
32 | return [
33 | 'amountInCents' => $paymentRequest->amountInCents,
34 | 'currency' => $paymentRequest->currency,
35 | 'description' => $paymentRequest->description,
36 | 'externalId' => $paymentRequest->externalId
37 | ];
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Requests/CreatePlatformRequest.php:
--------------------------------------------------------------------------------
1 | platform = $platform;
16 | }
17 |
18 | public function getMethod(): string
19 | {
20 | return 'POST';
21 | }
22 |
23 | public function getUri(): string
24 | {
25 | return 'v1/tikkie/platforms';
26 | }
27 |
28 | public function getPayload(): ?array
29 | {
30 | $platform = $this->platform;
31 |
32 | return [
33 | 'email' => $platform->email,
34 | 'name' => $platform->name,
35 | 'notificationUrl' => $platform->notificationUrl,
36 | 'phoneNumber' => $platform->phoneNumber,
37 | 'platformUsage' => $platform->platformUsage
38 | ];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Requests/CreateUserRequest.php:
--------------------------------------------------------------------------------
1 | user = $user;
16 | }
17 |
18 | public function getMethod(): string
19 | {
20 | return 'POST';
21 | }
22 |
23 | public function getUri(): string
24 | {
25 | return "v1/tikkie/platforms/{$this->user->platformToken}/users";
26 | }
27 |
28 | public function getPayload(): ?array
29 | {
30 | $user = $this->user;
31 |
32 | return [
33 | 'name' => $user->name,
34 | 'phoneNumber' => $user->phoneNumber,
35 | 'iban' => $user->iban,
36 | 'bankAccountLabel' => $user->bankAccountLabel
37 | ];
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Requests/FetchPaymentRequestRequest.php:
--------------------------------------------------------------------------------
1 | platformToken = $platformToken;
24 | $this->userToken = $userToken;
25 | $this->paymentRequestToken = $paymentRequestToken;
26 | }
27 |
28 | public function getMethod(): string
29 | {
30 | return 'GET';
31 | }
32 |
33 | public function getUri(): string
34 | {
35 | return "v1/tikkie/platforms/{$this->platformToken}/users/{$this->userToken}/paymentrequests/{$this->paymentRequestToken}";
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Requests/FetchPaymentRequestsRequest.php:
--------------------------------------------------------------------------------
1 | platformToken = $platformToken;
23 | $this->userToken = $userToken;
24 |
25 | $params = compact('offset', 'limit');
26 |
27 | if ($fromDate) {
28 | $params['fromDate'] = $this->formatDateTime($fromDate);
29 | }
30 |
31 | if ($toDate) {
32 | $params['toDate'] = $this->formatDateTime($toDate);
33 | }
34 |
35 | $this->parameters = $params;
36 | }
37 |
38 | public function getMethod(): string
39 | {
40 | return 'GET';
41 | }
42 |
43 | public function getUri(): string
44 | {
45 | return "v1/tikkie/platforms/{$this->platformToken}/users/{$this->userToken}/paymentrequests";
46 | }
47 |
48 | /**
49 | * Use UTC time zone and return ISO-8601 format.
50 | */
51 | protected function formatDateTime(DateTimeInterface $date): string
52 | {
53 | return (new DateTime)
54 | ->setTimestamp($date->getTimestamp())
55 | ->setTimezone(new DateTimeZone('UTC'))
56 | ->format('Y-m-d\TH:i:s\Z');
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Requests/FetchPlatformsRequest.php:
--------------------------------------------------------------------------------
1 | platformToken = $platformToken;
14 | }
15 |
16 | public function getMethod(): string
17 | {
18 | return 'GET';
19 | }
20 |
21 | public function getUri(): string
22 | {
23 | return "v1/tikkie/platforms/{$this->platformToken}/users";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Response.php:
--------------------------------------------------------------------------------
1 | hasHeader(static::TRACE_ID_HEADER)) {
27 | throw new ResponseException("Trace ID header missing");
28 | }
29 |
30 | $this->traceId = $response->getHeader(static::TRACE_ID_HEADER);
31 |
32 | if (($this->data = json_decode($response->getBody(), true)) === null) {
33 | throw new ResponseException("Could not decode response");
34 | }
35 | }
36 |
37 | public function getData(): array
38 | {
39 | return $this->data;
40 | }
41 |
42 | public function getTraceId(): string
43 | {
44 | return $this->traceId;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/tests/CreatePaymentRequestTest.php:
--------------------------------------------------------------------------------
1 | setMockHttpResponse(['AccessToken.txt', 'CreatePaymentRequestSuccess.txt']);
13 |
14 | $paymentRequest = $this->newPaymentRequest()->save();
15 |
16 | $this->assertEquals('https://pay.here.com/123', $paymentRequest->paymentRequestUrl);
17 | $this->assertEquals('paymentrequesttoken1', $paymentRequest->paymentRequestToken);
18 | $this->assertEquals('Invoice: 4567', $paymentRequest->externalId);
19 |
20 | $request = $this->history[1]['request'];
21 |
22 | $this->assertEquals('POST', $request->getMethod());
23 | $this->assertEquals('https://api.abnamro.com/v1/tikkie/platforms/platformtoken1/users/usertoken1/bankaccounts/bankaccounttoken1/paymentrequests', $request->getUri());
24 | $this->assertEquals('{"amountInCents":"1250","currency":"EUR","description":"Thank you","externalId":"Order 1234"}', $request->getBody());
25 | }
26 |
27 | public function testCreatePaymentRequestFailed()
28 | {
29 | $this->setMockHttpResponse(['AccessToken.txt', 'ValidationError.txt']);
30 |
31 | $this->expectException(RequestException::class);
32 | $this->expectExceptionMessage("[ERR_1100_004] Field validation error | traceId: 3cbf4bc9-108c-4e02-ad6e-937c79d875e3 | (see https://developer.abnamro.com/api/tikkie/technical-details)");
33 |
34 | $this->newPaymentRequest()->save();
35 | }
36 |
37 | protected function newPaymentRequest(): PaymentRequest
38 | {
39 | return $this->tikkie->newPaymentRequest('platformtoken1', 'usertoken1', 'bankaccounttoken1', [
40 | 'amountInCents' => '1250',
41 | 'currency' => 'EUR',
42 | 'description' => 'Thank you',
43 | 'externalId' => 'Order 1234'
44 | ]);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/tests/CreatePlatformTest.php:
--------------------------------------------------------------------------------
1 | setMockHttpResponse(['AccessToken.txt', 'CreatePlatformSuccess.txt']);
13 |
14 | $platform = $this->newPlatform()->save();
15 |
16 | $this->assertEquals('platformtoken1', $platform->platformToken);
17 | $this->assertEquals('x@yz.com', $platform->email);
18 | $this->assertEquals('NewPlatform', $platform->name);
19 | $this->assertEquals('0601234567', $platform->phoneNumber);
20 | $this->assertEquals(Platform::USAGE_TYPE_MYSELF, $platform->platformUsage);
21 | $this->assertNull($platform->notificationUrl);
22 | $this->assertTrue($platform->isActive());
23 |
24 | $request = $this->history[1]['request'];
25 |
26 | $this->assertEquals('POST', $request->getMethod());
27 | $this->assertEquals('https://api.abnamro.com/v1/tikkie/platforms', $request->getUri());
28 | $this->assertEquals('{"email":"tikkie@example.com","name":"MyPlatform","notificationUrl":"","phoneNumber":"0612345678","platformUsage":"PAYMENT_REQUEST_FOR_MYSELF"}', $request->getBody());
29 | }
30 |
31 | public function testCreatePlatformFailed()
32 | {
33 | $this->setMockHttpResponse(['AccessToken.txt', 'ValidationError.txt']);
34 |
35 | $this->expectException(RequestException::class);
36 | $this->expectExceptionMessage("[ERR_1100_004] Field validation error | traceId: 3cbf4bc9-108c-4e02-ad6e-937c79d875e3 | (see https://developer.abnamro.com/api/tikkie/technical-details)");
37 |
38 | $this->newPlatform()->save();
39 | }
40 |
41 | protected function newPlatform(): Platform
42 | {
43 | return $this->tikkie->newPlatform([
44 | 'name' => 'MyPlatform',
45 | 'phoneNumber' => '0612345678',
46 | 'platformUsage' => Platform::USAGE_TYPE_MYSELF,
47 | 'email' => 'tikkie@example.com',
48 | 'notificationUrl' => ''
49 | ]);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/tests/CreateUserTest.php:
--------------------------------------------------------------------------------
1 | setMockHttpResponse(['AccessToken.txt', 'CreateUserSuccess.txt']);
14 |
15 | $user = $this->newUser()->save();
16 |
17 | $this->assertEquals('YourLabel', $user->bankAccountLabel);
18 | $this->assertEquals('NL00BANK123456789', $user->iban);
19 | $this->assertEquals('NewUser', $user->name);
20 | $this->assertEquals('06123456789', $user->phoneNumber);
21 | $this->assertEquals('platformtoken1', $user->platformToken);
22 | $this->assertEquals(User::STATUS_ACTIVE, $user->status);
23 | $this->assertEquals('usertoken1', $user->userToken);
24 | $this->assertTrue($user->isActive());
25 | $this->assertCount(1, $user->bankAccounts);
26 |
27 | $bankAccount = $user->bankAccounts[0];
28 |
29 | $this->assertInstanceOf(BankAccount::class, $bankAccount);
30 | $this->assertEquals('Personal account', $bankAccount->bankAccountLabel);
31 | $this->assertEquals('bankaccounttoken1', $bankAccount->bankAccountToken);
32 | $this->assertEquals('NL02ABNA0123456789', $bankAccount->iban);
33 |
34 | $request = $this->history[1]['request'];
35 |
36 | $this->assertEquals('POST', $request->getMethod());
37 | $this->assertEquals('https://api.abnamro.com/v1/tikkie/platforms/platformtoken1/users', $request->getUri());
38 | $this->assertEquals('{"name":"ExamplePlatform","phoneNumber":"06123456789","iban":"NL00BANK123456789","bankAccountLabel":"YourLabel"}', $request->getBody());
39 | }
40 |
41 | public function testCreateUserFailed()
42 | {
43 | $this->setMockHttpResponse(['AccessToken.txt', 'ValidationError.txt']);
44 |
45 | $this->expectException(RequestException::class);
46 | $this->expectExceptionMessage("[ERR_1100_004] Field validation error | traceId: 3cbf4bc9-108c-4e02-ad6e-937c79d875e3 | (see https://developer.abnamro.com/api/tikkie/technical-details)");
47 |
48 | $this->newUser()->save();
49 | }
50 |
51 | protected function newUser(): User
52 | {
53 | return $this->tikkie->newUser('platformtoken1', [
54 | 'name' => 'ExamplePlatform',
55 | 'phoneNumber' => '06123456789',
56 | 'iban' => 'NL00BANK123456789',
57 | 'bankAccountLabel' => 'YourLabel'
58 | ]);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/tests/EnvironmentTest.php:
--------------------------------------------------------------------------------
1 | expectException(AccessTokenException::class);
12 |
13 | $this->tikkie->getEnvironment()->loadPrivateKeyFromString('');
14 |
15 | $this->tikkie->newPlatform()->save();
16 | }
17 |
18 | public function testInvalidApiKeyHandling()
19 | {
20 | $this->setMockHttpResponse('InvalidApiKey.txt');
21 |
22 | $this->expectException(AccessTokenException::class);
23 | $this->expectExceptionMessage("[ERR_2005_001] The API Key is invalid | traceId: 98de8459-377d-4834-a0a2-079f94f0f43d | (see https://developer.abnamro.com/get-started#obtaining-an-api-key)");
24 |
25 | $this->tikkie->newPlatform()->save();
26 | }
27 |
28 | public function testHeadersOnApiRequest()
29 | {
30 | $this->setMockHttpResponse(['AccessToken.txt', 'CreatePlatformSuccess.txt']);
31 |
32 | $this->tikkie->newPlatform()->save();
33 |
34 | // AccessTokenRequest
35 | $request = $this->history[0]['request'];
36 | $this->assertEquals(static::API_KEY, $request->getHeader('API-Key')[0]);
37 |
38 | // CreatePlatformRequest
39 | $request = $this->history[1]['request'];
40 | $this->assertEquals(static::API_KEY, $request->getHeader('API-Key')[0]);
41 | $this->assertTrue($request->hasHeader('Authorization'));
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/FetchPaymentRequestTest.php:
--------------------------------------------------------------------------------
1 | setMockHttpResponse(['AccessToken.txt', 'FetchPaymentRequestSuccess.txt']);
15 |
16 | $paymentRequest = $this->tikkie->paymentRequest('platformtoken1', 'usertoken1', 'paymentrequesttoken1');
17 |
18 | $this->assertEquals('123', $paymentRequest->amountInCents);
19 | $this->assertFalse($paymentRequest->bankAccountYieldedTooFast);
20 | $this->assertEquals('1465495200', $paymentRequest->created->getTimestamp());
21 | $this->assertEquals('EUR', $paymentRequest->currency);
22 | $this->assertEquals('Last night\'s dinner', $paymentRequest->description);
23 | $this->assertNull($paymentRequest->expired);
24 | $this->assertEquals('paymentrequesttoken1', $paymentRequest->paymentRequestToken);
25 | $this->assertEquals('Invoice: 4567', $paymentRequest->externalId);
26 | $this->assertEquals(PaymentRequest::STATUS_OPEN, $paymentRequest->status);
27 | $this->assertCount(1, $paymentRequest->payments);
28 |
29 | $payment = $paymentRequest->payments[0];
30 |
31 | $this->assertInstanceOf(Payment::class, $payment);
32 | $this->assertEquals('EUR', $payment->amountCurrency);
33 | $this->assertEquals('123', $payment->amountInCents);
34 | $this->assertEquals('E. Xample', $payment->counterPartyName);
35 | $this->assertEquals('Payment for tikkie', $payment->description);
36 | $this->assertEquals(Payment::STATUS_PAID, $payment->onlinePaymentStatus);
37 | $this->assertEquals('paymenttoken1', $payment->paymentToken);
38 | $this->assertEquals('1465495200', $payment->created->getTimestamp());
39 | $this->assertTrue($payment->isPaid());
40 |
41 | $request = $this->history[1]['request'];
42 |
43 | $this->assertEquals('GET', $request->getMethod());
44 | $this->assertEquals('https://api.abnamro.com/v1/tikkie/platforms/platformtoken1/users/usertoken1/paymentrequests/paymentrequesttoken1', $request->getUri());
45 | }
46 |
47 | public function testFetchPaymentRequestFailed()
48 | {
49 | $this->setMockHttpResponse(['AccessToken.txt', 'ValidationError.txt']);
50 |
51 | $this->expectException(RequestException::class);
52 | $this->expectExceptionMessage("[ERR_1100_004] Field validation error | traceId: 3cbf4bc9-108c-4e02-ad6e-937c79d875e3 | (see https://developer.abnamro.com/api/tikkie/technical-details)");
53 |
54 | $this->tikkie->paymentRequest('platformtoken1', 'usertoken1', 'paymentrequesttoken1');
55 | }
56 |
57 | // Due to a Tikkie bug, the API may return epoch timestamps with milliseconds instead of a ISO-8601 formatted string.
58 | // I reported this on 24-04-2019.
59 | public function testCreatedDateCanBeTimestampWithMilliseconds()
60 | {
61 | $payment = new Payment($this->tikkie);
62 | $payment->setAttributes(['created' => '1554957274674']);
63 |
64 | $this->assertInstanceOf(DateTimeImmutable::class, $payment->created);
65 | $this->assertEquals('1554957274', $payment->created->getTimestamp());
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/tests/FetchPaymentRequestsTest.php:
--------------------------------------------------------------------------------
1 | setMockHttpResponse(['AccessToken.txt', 'FetchPaymentRequestsSuccess.txt']);
16 |
17 | $timezone = new DateTimeZone('Europe/Amsterdam');
18 |
19 | $from = new DateTime('2018-06-01 13:00', $timezone);
20 | $to = new DateTime('2018-06-05 01:00', $timezone);
21 |
22 | $paymentRequests = $this->tikkie->paymentRequests('platformtoken1', 'usertoken1', 0, 10, $from, $to);
23 | $paymentRequest = $paymentRequests[0];
24 |
25 | $this->assertCount(1, $paymentRequests);
26 | $this->assertInstanceOf(PaymentRequest::class, $paymentRequest);
27 | $this->assertEquals('123', $paymentRequest->amountInCents);
28 | $this->assertFalse($paymentRequest->bankAccountYieldedTooFast);
29 | $this->assertEquals('1465495200', $paymentRequest->created->getTimestamp());
30 | $this->assertEquals('EUR', $paymentRequest->currency);
31 | $this->assertEquals('Last night\'s dinner', $paymentRequest->description);
32 | $this->assertNull($paymentRequest->expired);
33 | $this->assertEquals('paymentrequesttoken1', $paymentRequest->paymentRequestToken);
34 | $this->assertEquals('Invoice: 4567', $paymentRequest->externalId);
35 | $this->assertEquals(PaymentRequest::STATUS_OPEN, $paymentRequest->status);
36 | $this->assertCount(1, $paymentRequest->payments);
37 |
38 | $payment = $paymentRequest->payments[0];
39 |
40 | $this->assertInstanceOf(Payment::class, $payment);
41 | $this->assertEquals('EUR', $payment->amountCurrency);
42 | $this->assertEquals('123', $payment->amountInCents);
43 | $this->assertEquals('E. Xample', $payment->counterPartyName);
44 | $this->assertEquals('Payment for tikkie', $payment->description);
45 | $this->assertEquals(Payment::STATUS_NEW, $payment->onlinePaymentStatus);
46 | $this->assertEquals('paymenttoken1', $payment->paymentToken);
47 | $this->assertEquals('1465495200', $payment->created->getTimestamp());
48 | $this->assertFalse($payment->isPaid());
49 |
50 | $request = $this->history[1]['request'];
51 |
52 | $this->assertEquals('GET', $request->getMethod());
53 | $this->assertEquals('https://api.abnamro.com/v1/tikkie/platforms/platformtoken1/users/usertoken1/paymentrequests?offset=0&limit=10&fromDate=2018-06-01T11%3A00%3A00Z&toDate=2018-06-04T23%3A00%3A00Z', $request->getUri());
54 | }
55 |
56 | public function testFetchPaymentRequestsFailed()
57 | {
58 | $this->setMockHttpResponse(['AccessToken.txt', 'ValidationError.txt']);
59 |
60 | $this->expectException(RequestException::class);
61 | $this->expectExceptionMessage("[ERR_1100_004] Field validation error | traceId: 3cbf4bc9-108c-4e02-ad6e-937c79d875e3 | (see https://developer.abnamro.com/api/tikkie/technical-details)");
62 |
63 | $this->tikkie->paymentRequests('platformtoken1', 'usertoken1', 0, 10);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/tests/FetchPlatformsTest.php:
--------------------------------------------------------------------------------
1 | setMockHttpResponse(['AccessToken.txt', 'FetchPlatformsSuccess.txt']);
13 |
14 | $platforms = $this->tikkie->platforms();
15 | $platform = $platforms[0];
16 |
17 | $this->assertCount(1, $platforms);
18 | $this->assertInstanceOf(Platform::class, $platform);
19 | $this->assertEquals('platformtoken1', $platform->platformToken);
20 | $this->assertEquals('x@yz.com', $platform->email);
21 | $this->assertEquals('NewPlatform', $platform->name);
22 | $this->assertEquals('0601234567', $platform->phoneNumber);
23 | $this->assertEquals(Platform::USAGE_TYPE_MYSELF, $platform->platformUsage);
24 | $this->assertNull($platform->notificationUrl);
25 | $this->assertTrue($platform->isActive());
26 |
27 | $request = $this->history[1]['request'];
28 |
29 | $this->assertEquals('GET', $request->getMethod());
30 | $this->assertEquals('https://api.abnamro.com/v1/tikkie/platforms', $request->getUri());
31 | $this->assertEmpty($request->getUri()->getQuery());
32 | }
33 |
34 | public function testFetchUsersFailed()
35 | {
36 | $this->setMockHttpResponse(['AccessToken.txt', 'ValidationError.txt']);
37 |
38 | $this->expectException(RequestException::class);
39 | $this->expectExceptionMessage("[ERR_1100_004] Field validation error | traceId: 3cbf4bc9-108c-4e02-ad6e-937c79d875e3 | (see https://developer.abnamro.com/api/tikkie/technical-details)");
40 |
41 | $this->tikkie->platforms();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/FetchUsersTest.php:
--------------------------------------------------------------------------------
1 | setMockHttpResponse(['AccessToken.txt', 'FetchUsersSuccess.txt']);
14 |
15 | $users = $this->tikkie->users('platformtoken1');
16 | $user = $users[0];
17 |
18 | $this->assertCount(1, $users);
19 | $this->assertInstanceOf(User::class, $user);
20 | $this->assertEquals('NewUser', $user->name);
21 | $this->assertEquals(User::STATUS_ACTIVE, $user->status);
22 | $this->assertEquals('usertoken1', $user->userToken);
23 | $this->assertTrue($user->isActive());
24 | $this->assertCount(1, $user->bankAccounts);
25 |
26 | $bankAccount = $user->bankAccounts[0];
27 |
28 | $this->assertInstanceOf(BankAccount::class, $bankAccount);
29 | $this->assertEquals('Personal account', $bankAccount->bankAccountLabel);
30 | $this->assertEquals('bankaccounttoken1', $bankAccount->bankAccountToken);
31 | $this->assertEquals('NL02ABNA0123456789', $bankAccount->iban);
32 |
33 | $request = $this->history[1]['request'];
34 |
35 | $this->assertEquals('GET', $request->getMethod());
36 | $this->assertEquals('https://api.abnamro.com/v1/tikkie/platforms/platformtoken1/users', $request->getUri());
37 | $this->assertEmpty($request->getUri()->getQuery());
38 | }
39 |
40 | public function testFetchUsersFailed()
41 | {
42 | $this->setMockHttpResponse(['AccessToken.txt', 'ValidationError.txt']);
43 |
44 | $this->expectException(RequestException::class);
45 | $this->expectExceptionMessage("[ERR_1100_004] Field validation error | traceId: 3cbf4bc9-108c-4e02-ad6e-937c79d875e3 | (see https://developer.abnamro.com/api/tikkie/technical-details)");
46 |
47 | $this->tikkie->users('platformtoken1');
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/Mock/AccessToken.txt:
--------------------------------------------------------------------------------
1 | HTTP/1.1 200 OK
2 | Date: Tue, 19 Jun 2018 09:20:42 GMT
3 | Content-Type: application/json
4 | Connection: keep-alive
5 | Trace-Id: 98de8459-377d-4834-a0a2-079f94f0f43d
6 |
7 | {
8 | "access_token": "accesstoken1",
9 | "expires_in": "60",
10 | "scope": "tikkie",
11 | "token_type": "Bearer"
12 | }
--------------------------------------------------------------------------------
/tests/Mock/CreatePaymentRequestSuccess.txt:
--------------------------------------------------------------------------------
1 | HTTP/1.1 201 Created
2 | Date: Tue, 19 Jun 2018 09:20:42 GMT
3 | Content-Type: application/json
4 | Connection: keep-alive
5 | Trace-Id: 98de8459-377d-4834-a0a2-079f94f0f43d
6 |
7 | {
8 | "paymentRequestUrl": "https://pay.here.com/123",
9 | "paymentRequestToken": "paymentrequesttoken1",
10 | "externalId": "Invoice: 4567"
11 | }
--------------------------------------------------------------------------------
/tests/Mock/CreatePlatformSuccess.txt:
--------------------------------------------------------------------------------
1 | HTTP/1.1 201 Created
2 | Date: Tue, 19 Jun 2018 09:20:42 GMT
3 | Content-Type: application/json
4 | Connection: keep-alive
5 | Trace-Id: 98de8459-377d-4834-a0a2-079f94f0f43d
6 |
7 | {
8 | "name": "NewPlatform",
9 | "platformToken": "platformtoken1",
10 | "phoneNumber": "0601234567",
11 | "email": "x@yz.com",
12 | "notificationUrl": null,
13 | "status": "ACTIVE",
14 | "platformUsage": "PAYMENT_REQUEST_FOR_MYSELF"
15 | }
--------------------------------------------------------------------------------
/tests/Mock/CreateUserSuccess.txt:
--------------------------------------------------------------------------------
1 | HTTP/1.1 201 Created
2 | Date: Tue, 19 Jun 2018 09:20:42 GMT
3 | Content-Type: application/json
4 | Connection: keep-alive
5 | Trace-Id: 98de8459-377d-4834-a0a2-079f94f0f43d
6 |
7 | {
8 | "userToken": "usertoken1",
9 | "name": "NewUser",
10 | "status": "ACTIVE",
11 | "bankAccounts": [
12 | {
13 | "bankAccountToken": "bankaccounttoken1",
14 | "iban": "NL02ABNA0123456789",
15 | "bankAccountLabel": "Personal account"
16 | }
17 | ]
18 | }
--------------------------------------------------------------------------------
/tests/Mock/FetchPaymentRequestSuccess.txt:
--------------------------------------------------------------------------------
1 | HTTP/1.1 200 OK
2 | Date: Tue, 19 Jun 2018 09:20:42 GMT
3 | Content-Type: application/json
4 | Connection: keep-alive
5 | Trace-Id: 98de8459-377d-4834-a0a2-079f94f0f43d
6 |
7 | {
8 | "paymentRequestToken": "paymentrequesttoken1",
9 | "amountInCents": "123",
10 | "currency": "EUR",
11 | "description": "Last night's dinner",
12 | "created": "2016-06-09T18:00:00.000Z",
13 | "expired": null,
14 | "status": "OPEN",
15 | "bankAccountYieldedTooFast": false,
16 | "externalId": "Invoice: 4567",
17 | "payments": [
18 | {
19 | "paymentToken": "paymenttoken1",
20 | "counterPartyName": "E. Xample",
21 | "amountInCents": "123",
22 | "amountCurrency": "EUR",
23 | "description": "Payment for tikkie",
24 | "created": "2016-06-09T18:00:00.000Z",
25 | "onlinePaymentStatus": "PAID"
26 | }
27 | ]
28 | }
--------------------------------------------------------------------------------
/tests/Mock/FetchPaymentRequestsSuccess.txt:
--------------------------------------------------------------------------------
1 | HTTP/1.1 200 OK
2 | Date: Tue, 19 Jun 2018 09:20:42 GMT
3 | Content-Type: application/json
4 | Connection: keep-alive
5 | Trace-Id: 98de8459-377d-4834-a0a2-079f94f0f43d
6 |
7 | {
8 | "paymentRequests": [
9 | {
10 | "paymentRequestToken": "paymentrequesttoken1",
11 | "amountInCents": "123",
12 | "currency": "EUR",
13 | "description": "Last night's dinner",
14 | "created": "2016-06-09T18:00:00.000Z",
15 | "expired": null,
16 | "status": "OPEN",
17 | "bankAccountYieldedTooFast": false,
18 | "externalId": "Invoice: 4567",
19 | "payments": [
20 | {
21 | "paymentToken": "paymenttoken1",
22 | "counterPartyName": "E. Xample",
23 | "amountInCents": "123",
24 | "amountCurrency": "EUR",
25 | "description": "Payment for tikkie",
26 | "created": "2016-06-09T18:00:00.000Z",
27 | "onlinePaymentStatus": "NEW"
28 | }
29 | ]
30 | }
31 | ],
32 | "totalElements": 1
33 | }
--------------------------------------------------------------------------------
/tests/Mock/FetchPlatformsSuccess.txt:
--------------------------------------------------------------------------------
1 | HTTP/1.1 200 OK
2 | Date: Tue, 19 Jun 2018 09:20:42 GMT
3 | Content-Type: application/json
4 | Connection: keep-alive
5 | Trace-Id: 98de8459-377d-4834-a0a2-079f94f0f43d
6 |
7 | [
8 | {
9 | "name": "NewPlatform",
10 | "platformToken": "platformtoken1",
11 | "phoneNumber": "0601234567",
12 | "email": "x@yz.com",
13 | "notificationUrl": null,
14 | "status": "ACTIVE",
15 | "platformUsage": "PAYMENT_REQUEST_FOR_MYSELF"
16 | }
17 | ]
--------------------------------------------------------------------------------
/tests/Mock/FetchUsersSuccess.txt:
--------------------------------------------------------------------------------
1 | HTTP/1.1 200 OK
2 | Date: Tue, 19 Jun 2018 09:20:42 GMT
3 | Content-Type: application/json
4 | Connection: keep-alive
5 | Trace-Id: 98de8459-377d-4834-a0a2-079f94f0f43d
6 |
7 | [
8 | {
9 | "userToken": "usertoken1",
10 | "name": "NewUser",
11 | "status": "ACTIVE",
12 | "bankAccounts": [
13 | {
14 | "bankAccountToken": "bankaccounttoken1",
15 | "iban": "NL02ABNA0123456789",
16 | "bankAccountLabel": "Personal account"
17 | }
18 | ]
19 | }
20 | ]
--------------------------------------------------------------------------------
/tests/Mock/InvalidApiKey.txt:
--------------------------------------------------------------------------------
1 | HTTP/1.1 401 Unauthorized
2 | Date: Tue, 19 Jun 2018 09:20:42 GMT
3 | Content-Type: application/json
4 | Connection: keep-alive
5 | Trace-Id: 98de8459-377d-4834-a0a2-079f94f0f43d
6 |
7 | {
8 | "errors": [
9 | {
10 | "code": "ERR_2005_001",
11 | "message": "The API Key is invalid",
12 | "reference": "https://developer.abnamro.com/get-started#obtaining-an-api-key",
13 | "traceId": "98de8459-377d-4834-a0a2-079f94f0f43d",
14 | "status": 401,
15 | "category":"INVALID_API_KEY"
16 | }
17 | ]
18 | }
--------------------------------------------------------------------------------
/tests/Mock/ValidationError.txt:
--------------------------------------------------------------------------------
1 | HTTP/1.1 400 Bad Request
2 | Date: Tue, 19 Jun 2018 10:24:12 GMT
3 | Content-Type: application/json
4 | Transfer-Encoding: chunked
5 | Connection: keep-alive
6 | Server: Apache-Coyote/1.1
7 | Trace-Id: 3cbf4bc9-108c-4e02-ad6e-937c79d875e3
8 | X-Application-Context: application
9 | X-Content-Type-Options: nosniff
10 | X-Frame-Options: sameorigin
11 | X-XSS-Protection: 1; mode=block
12 |
13 | {
14 | "errors": [
15 | {
16 | "code": "ERR_1100_004",
17 | "message": "Field validation error",
18 | "reference": "https://developer.abnamro.com/api/tikkie/technical-details",
19 | "traceId": "3cbf4bc9-108c-4e02-ad6e-937c79d875e3",
20 | "status": 400,
21 | "category": "BAD_REQUEST"
22 | }
23 | ]
24 | }
--------------------------------------------------------------------------------
/tests/Mock/private_rsa.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEAuLGN/Wcdr4s7b9rKJiWpi0PHa4kOsEBbAh1oS78ETzpgzVl6
3 | K0pQ96tZQpx90VqnhCh2eyycCmSKBtd9SKVswsHO21mw/Xh5S0mEd0g9Fl5f8XVr
4 | +GGSL5wxUhgJcP1ZOtsh3yUt14hQZk0/CF5yf0Y8M3u92Tq/LC6OVwUQC5qAPcOo
5 | tJv4yhqHCCe0RK+QxYZ1Rk7A0zbhW9n/eatf0qSN3pRKIPFUmAIgiJ1i9i362PJ6
6 | /Ri6nyeeXtwuqzxZ6ryA+L1WXNUswOoU3HXBWiRVsEGt0o68btQan1T680qfuevP
7 | usAd6jkQkHwehYbMAjWGRUGxgeEDUgGN2KndOwIDAQABAoIBAAGZD6hslvYo1zfN
8 | hcg0tTXOPVBx3B2sQN1Q0dEt8uSYlbPRHVx4hSDPa7NG1VPVW/OpwfSo2yS/3+3V
9 | OXFCdSFuOdLuALkArNP469t4VYb3BA97u5ZnibM9v7N9H7/JgVcgBDgBA1eFB2UL
10 | MAtrfcQaIHU1kdvqRTMlp/eaxJvFE6m7W1fKqNtfjWvsG8eOPK09tIkreQ8RES4p
11 | SUjVLMpwfDBEysjE0m+QtOrtBzENZ8AK/Jj3kYlgjJLorcUkwStG/QzDaKthPxXO
12 | pDC8rU28B4unAidPYpSzFVpgWek4+wNu0bp1H7CFOm9/fFV4p2a9nElIwiI5H2JG
13 | TvmNFIkCgYEA2trtt2wL1Grsx0OmoV/BFWBT3p2L2WP1JzyVOzYV5gttyDgK123e
14 | jrbqJhTJzWR9/r5ZmlzlWTgOe5OUsSENQgceDl24aF+c3xCjqhvEvaNgHkyie7wV
15 | GxOZbtouoxAV9aBN2tr6TKmpZeI4wjwefAxpnxXWWSbcuFd1NcvM9mUCgYEA2ApV
16 | O0Mk2A25Wt5zqdi7zyiGN3MHbbzbk6RADObRsfAtAc+hzhm9zHoWZ+GQtZbV//cM
17 | LAwItk8hSPb16frSZRTC3xPQXEAUbNFbo3iC8XfbkWGQ1daSD3vjggZMl0oyTOeT
18 | f8+V5GA0CEO+shdL7OdX2wrT5303CciSGc6H+x8CgYEAwg6D4DM23hgdcabD1q1w
19 | KMMsOuWZfp5KX4sxi7ouerfBlVpUCqeKQyNfxXqDYdLsgXhJPT2Hw6+X7+1xWApF
20 | ljl3Ziel/y5gi85WQNy0e66k6Njs7ihc0pBzaT6fQclen1iQEDJA5L8/zG5mA5yJ
21 | L1dWRFB5qr1x0ycBcD0QtZ0CgYBMIpgW4nrBiVShKXQpjy/gua9TKz6a9cuMJH5O
22 | DaoowzOZR8sGDxxMS1pKEbwlwpp4MmAfxb3sQcbBKAdSBgrPhJmIdDshx5NrJfzd
23 | h0LeRhcjDPc15QBkZIyw7fdf+c3wPExG5qk0apLrtrQlnwAq5PyZPR+gnQggcobK
24 | gXZ6kQKBgQC7IW0jrjjW+fx262yGMDa+VZRXN/xctupj+n/GWtLA0Pq/fy3/2CqY
25 | MMHsYlidjcurMvmX9HX9ft2RqdPBV/sEr4pR2Vietxje7xFZPNiy0z45UHYQ1zfn
26 | /iJkEoPKzaKqDBXGRi9E+GhG5KxClY5dZniPhu6GHUWdyq7uFDxLUw==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/tests/Mock/public_rsa.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuLGN/Wcdr4s7b9rKJiWp
3 | i0PHa4kOsEBbAh1oS78ETzpgzVl6K0pQ96tZQpx90VqnhCh2eyycCmSKBtd9SKVs
4 | wsHO21mw/Xh5S0mEd0g9Fl5f8XVr+GGSL5wxUhgJcP1ZOtsh3yUt14hQZk0/CF5y
5 | f0Y8M3u92Tq/LC6OVwUQC5qAPcOotJv4yhqHCCe0RK+QxYZ1Rk7A0zbhW9n/eatf
6 | 0qSN3pRKIPFUmAIgiJ1i9i362PJ6/Ri6nyeeXtwuqzxZ6ryA+L1WXNUswOoU3HXB
7 | WiRVsEGt0o68btQan1T680qfuevPusAd6jkQkHwehYbMAjWGRUGxgeEDUgGN2Knd
8 | OwIDAQAB
9 | -----END PUBLIC KEY-----
10 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | history = [];
32 | $this->tikkie = $this->createPHPTikkie();
33 | }
34 |
35 | protected function createPHPTikkie(array $options = []): PHPTikkie
36 | {
37 | $environment = new Environment(static::API_KEY, false, $options);
38 | $environment->loadPrivateKey(static::MOCK_PATH.'/private_rsa.pem');
39 |
40 | return new PHPTikkie($environment);
41 | }
42 |
43 | protected function getMockHttpResponse(string $path): ResponseInterface
44 | {
45 | return \GuzzleHttp\Psr7\parse_response(file_get_contents(static::MOCK_PATH.'/'.$path));
46 | }
47 |
48 | /**
49 | * @param string|array $paths
50 | */
51 | protected function setMockHttpResponse($paths): void
52 | {
53 | $history = Middleware::history($this->history);
54 |
55 | $responses = [];
56 | foreach ((array) $paths as $path) {
57 | $responses[] = $this->getMockHttpResponse($path);
58 | }
59 |
60 | $mock = new MockHandler($responses);
61 |
62 | $stack = HandlerStack::create($mock);
63 | $stack->push($history);
64 |
65 | $this->tikkie = $this->createPHPTikkie([
66 | 'handler' => $stack
67 | ]);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------