diff --git a/src/Api/Blik/BlikApi.php b/src/Api/Blik/BlikApi.php new file mode 100644 index 0000000..ae4e6b2 --- /dev/null +++ b/src/Api/Blik/BlikApi.php @@ -0,0 +1,39 @@ +run(static::POST, '/blik/alias', $fields, new CreateAlias()); + } + + /** + * @param string $aliasValue + * @param string $aliasType + */ + public function getAlias($aliasValue, $aliasType) + { + $requestUrl = $this->addQueryFields( + sprintf('/blik/alias/%s', $aliasValue), + ['aliasType' => $aliasType] + ); + + return $this->run(static::GET, $requestUrl); + } + + /** + * @param string $aliasValue + * @param array $fields + */ + public function deleteAlias($aliasValue, $fields) + { + return $this->run(static::DELETE, sprintf('/blik/alias/%s', $aliasValue), $fields, new DeleteAlias()); + } +} diff --git a/src/Api/TpayApi.php b/src/Api/TpayApi.php index 66ca600..0518459 100644 --- a/src/Api/TpayApi.php +++ b/src/Api/TpayApi.php @@ -5,6 +5,7 @@ use RuntimeException; use Tpay\OpenApi\Api\Accounts\AccountsApi; use Tpay\OpenApi\Api\Authorization\AuthorizationApi; +use Tpay\OpenApi\Api\Blik\BlikApi; use Tpay\OpenApi\Api\Collect\CollectApi; use Tpay\OpenApi\Api\Refunds\RefundsApi; use Tpay\OpenApi\Api\Reports\ReportsApi; @@ -15,6 +16,9 @@ class TpayApi { + /** @var null|BlikApi */ + private $blik; + /** @var null|AccountsApi */ private $accounts; @@ -93,6 +97,22 @@ public function getToken() return $this->token; } + /** @return BlikApi */ + public function blik() + { + $this->authorize(); + if (null === $this->blik) { + $this->blik = (new BlikApi($this->token, $this->productionMode)) + ->overrideApiUrl($this->apiUrl); + + if ($this->clientName) { + $this->blik->setClientName($this->clientName); + } + } + + return $this->blik; + } + /** @return AccountsApi */ public function accounts() { diff --git a/src/Curl/Curl.php b/src/Curl/Curl.php index 2a1a8dc..8bcd9b8 100644 --- a/src/Curl/Curl.php +++ b/src/Curl/Curl.php @@ -193,7 +193,7 @@ private function setCurlMethod($curl) case 'POST': curl_setopt($curl, CURLOPT_POST, 1); if (!empty($this->postData)) { - $json = json_encode($this->postData); + $json = json_encode($this->postData, JSON_PRESERVE_ZERO_FRACTION); curl_setopt($curl, CURLOPT_POSTFIELDS, $json); } break; @@ -203,7 +203,9 @@ private function setCurlMethod($curl) case 'DELETE': curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE'); if (!empty($this->postData)) { - curl_setopt($curl, CURLOPT_POSTFIELDS, $this->postData); + $json = json_encode($this->postData, JSON_PRESERVE_ZERO_FRACTION); + curl_setopt($curl, CURLOPT_POSTFIELDS, $json); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE'); } break; case 'GET': diff --git a/src/Dictionary/HttpCodesDictionary.php b/src/Dictionary/HttpCodesDictionary.php index 6ee8b77..8c3ee48 100644 --- a/src/Dictionary/HttpCodesDictionary.php +++ b/src/Dictionary/HttpCodesDictionary.php @@ -9,6 +9,7 @@ class HttpCodesDictionary 200 => 'OK - default successful outcome of the request', 201 => 'Created - successfully created a new object', 202 => 'Accepted - successfully created a new object, but requires further action', + 204 => 'No Content - successful outcome of the request, but no content to return', ]; const HTTP_ERROR_CODES = [ diff --git a/src/Model/Fields/Alias/RecommendedAuthLevel.php b/src/Model/Fields/Alias/RecommendedAuthLevel.php new file mode 100644 index 0000000..ecb8f5b --- /dev/null +++ b/src/Model/Fields/Alias/RecommendedAuthLevel.php @@ -0,0 +1,17 @@ + BlikPaymentData::class, + ]; + + /** @var BlikPaymentData */ + public $blikPaymentData; + + public function getRequiredFields() + { + return [ + $this->blikPaymentData, + ]; + } +} diff --git a/src/Model/Objects/RequestBody/CreateAlias.php b/src/Model/Objects/RequestBody/CreateAlias.php new file mode 100644 index 0000000..7f6d82c --- /dev/null +++ b/src/Model/Objects/RequestBody/CreateAlias.php @@ -0,0 +1,34 @@ + Description::class, + 'lang' => Lang::class, + 'pay' => CreateAliasPay::class, + ]; + + /** @var Description */ + public $description; + + /** @var Lang */ + public $lang; + + /** @var CreateAliasPay */ + public $pay; + + public function getRequiredFields() + { + return [ + $this->description, + $this->pay, + ]; + } +} diff --git a/src/Model/Objects/RequestBody/DeleteAlias.php b/src/Model/Objects/RequestBody/DeleteAlias.php new file mode 100644 index 0000000..7a3553a --- /dev/null +++ b/src/Model/Objects/RequestBody/DeleteAlias.php @@ -0,0 +1,23 @@ + Type::class, + ]; + + /** @var Type */ + public $aliasType; + + public function getRequiredFields() + { + return [ + $this->aliasType, + ]; + } +} diff --git a/src/Model/Objects/Transactions/Alias.php b/src/Model/Objects/Transactions/Alias.php index b23bc46..0f95e8e 100644 --- a/src/Model/Objects/Transactions/Alias.php +++ b/src/Model/Objects/Transactions/Alias.php @@ -4,6 +4,7 @@ use Tpay\OpenApi\Model\Fields\Alias\Key; use Tpay\OpenApi\Model\Fields\Alias\Label; +use Tpay\OpenApi\Model\Fields\Alias\RecommendedAuthLevel; use Tpay\OpenApi\Model\Fields\Alias\Type; use Tpay\OpenApi\Model\Fields\Alias\Value; use Tpay\OpenApi\Model\Fields\Boolean; @@ -17,6 +18,7 @@ class Alias extends Objects 'type' => Type::class, 'label' => Label::class, 'key' => Key::class, + 'recommendedAuthLevel' => RecommendedAuthLevel::class, 'autopayment' => Autopayment::class, 'noDelay' => Boolean::class, ]; @@ -33,6 +35,9 @@ class Alias extends Objects /** @var Key */ public $key; + /** @var RecommendedAuthLevel */ + public $recommendedAuthLevel; + /** @var Autopayment */ public $autopayment; diff --git a/tests/Api/Blik/BlikApiTest.php b/tests/Api/Blik/BlikApiTest.php new file mode 100644 index 0000000..f8557d9 --- /dev/null +++ b/tests/Api/Blik/BlikApiTest.php @@ -0,0 +1,98 @@ +createBlikApiWithCurlMock('"ok"'); + + $result = $blikApi->createAlias($fields); + + self::assertSame('ok', $result); + } + + public function testGetAlias() + { + $blikApi = $this->createBlikApiWithCurlMock('"ok"'); + + $result = $blikApi->getAlias('some-alias-value', 'PAYID'); + + self::assertSame('ok', $result); + } + + public function testDeleteAlias() + { + $blikApi = $this->createBlikApiWithCurlMock('"ok"'); + + $result = $blikApi->deleteAlias('some-alias-value', ['aliasType' => 'PAYID']); + + self::assertSame('ok', $result); + } + + public static function dataCreateAlias() + { + $fields = [ + 'description' => 'YourGroceryShop payments', + 'pay' => [ + 'blikPaymentData' => [ + 'blikToken' => '123456', + 'type' => 0, + ], + ], + ]; + + yield 'without lang' => [$fields]; + + $fields['lang'] = 'pl'; + + yield 'with lang' => [$fields]; + + $fields['pay']['blikPaymentData']['aliases'] = [ + 'value' => 'TPAY_ALIAS_1', + 'type' => 'PAYID', + 'label' => 'YourGroceryShop, the best shop for your grocery needs', + 'autopayment' => [ + 'model' => 'A', + 'frequency' => '17D', + 'singleLimitAmount' => 100, + 'totalLimitAmount' => 1000, + 'currency' => 'PLN', + 'initDate' => '2025-01-01T00:00:00+00:00', + 'expirationDate' => '2028-01-01T00:00:00+00:00', + ], + ]; + + yield 'with aliases and autopayment' => [$fields]; + + $fields['pay']['blikPaymentData']['type'] = 2; + unset($fields['pay']['blikPaymentData']['blikToken']); + + yield 'autopayment type 2 without blikToken' => [$fields]; + } + + private function createBlikApiWithCurlMock($response) + { + $accessToken = $this->createMock(AccessToken::class); + + $token = $this->createMock(Token::class); + $token->access_token = $accessToken; + + $blikApi = new BlikApi($token, false); + + CurlMock::setConsecutiveReturnedTransfers($response); + + return $blikApi; + } +}