Skip to content

Commit

Permalink
Release 0.3.1 (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
shoman4eg authored May 29, 2022
1 parent 9c6c89f commit 5e1c694
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 37 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
All notable changes to this project will be documented in this file.
<!--- END HEADER -->

## [0.3.1](https://github.com/shoman4eg/moy-nalog/compare/v0.3.0...v0.3.1) (2022-05-29)
### Features
* Add throw `UnauthorizedException` if server respond 401 status #19

### Documentation
* Update README with exception
* Add donation link
---

## [0.3.0](https://github.com/shoman4eg/moy-nalog/compare/v0.2.3...v0.3.0) (2022-05-15)
### Features
* Add new method for income with multiple items #14
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
[![Total Downloads](https://img.shields.io/packagist/dt/shoman4eg/moy-nalog.svg?style=flat-square)](https://packagist.org/packages/shoman4eg/moy-nalog)
[![Scrutinizer code quality](https://img.shields.io/scrutinizer/quality/g/shoman4eg/moy-nalog/master?style=flat-square)](https://scrutinizer-ci.com/g/shoman4eg/moy-nalog/?branch=master)
[![Packagist License](https://img.shields.io/packagist/l/shoman4eg/moy-nalog?style=flat-square)](LICENSE)
[![Donate](https://img.shields.io/badge/Donate-Tinkoff-yellow?style=flat-square)](https://www.tinkoff.ru/cf/7rZnC7N4bOO)

An unofficial wrapper client for [lknpd.nalog.ru](https://lknpd.nalog.ru/) API

Expand All @@ -16,6 +17,10 @@ Via Composer
$ composer require shoman4eg/moy-nalog
```

Also you need one of packages suggests `psr/http-client-implementation`

Recommends `symfony/http-client` or `guzzlehttp/guzzle`

## Usage

### Settings
Expand All @@ -32,7 +37,11 @@ use Shoman4eg\Nalog\ApiClient;
$apiClient = ApiClient::create();

// If known accessToken skip this step
$accessToken = $apiClient->createNewAccessToken($username, $password);
try {
$accessToken = $apiClient->createNewAccessToken($username, $password);
} catch (\Shoman4eg\Nalog\Exception\Domain\UnauthorizedException $e) {
var_dump($e->getMessage());
}

// Access token MUST contains all json response from method createNewAccessToken()
$accessToken = '...';
Expand Down Expand Up @@ -126,5 +135,10 @@ JS lib [alexstep/moy-nalog](https://github.com/alexstep/moy-nalog)
## Changelog
[Changelog](CHANGELOG.md): A complete changelog

## Donation
If this project help you reduce time to develop, you can give me a cup of coffee :)

[Link to donate](https://www.tinkoff.ru/cf/7rZnC7N4bOO)

## License
The MIT License (MIT). Please see [License File](LICENSE) for more information.
13 changes: 11 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "shoman4eg/moy-nalog",
"description": "An unofficial wrapper client for lknpd.nalog.ru API",
"license": "MIT",
"version": "0.3.0",
"version": "0.3.1",
"keywords": [
"api",
"nalog.ru"
Expand All @@ -13,6 +13,12 @@
"email": "artem@dubinin.me"
}
],
"funding": [
{
"type": "other",
"url": "https://www.tinkoff.ru/cf/7rZnC7N4bOO"
}
],
"require": {
"php": ">=7.4 || ^8.0",
"ext-json": "*",
Expand All @@ -25,14 +31,17 @@
"webmozart/assert": "^1.4"
},
"require-dev": {
"guzzlehttp/guzzle": "^7.0",
"guzzlehttp/guzzle": "^7.4.3",
"nyholm/nsa": "^1.3",
"php-http/curl-client": "^2.0",
"php-http/message": "^1.0",
"php-http/message-factory": "^1.0",
"phpunit/phpunit": "^9.5",
"roave/security-advisories": "dev-latest"
},
"suggest": {
"psr/http-client-implementation": "Required for using this package"
},
"autoload": {
"psr-4": {
"Shoman4eg\\Nalog\\": "src/"
Expand Down
23 changes: 5 additions & 18 deletions src/Api/BaseHttpApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use Http\Client\HttpClient;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Message\ResponseInterface;
use Shoman4eg\Nalog\Exception\Domain as DomainExceptions;
use Shoman4eg\Nalog\ErrorHandler;
use Shoman4eg\Nalog\Exception\DomainException;
use Shoman4eg\Nalog\RequestBuilder;
use Shoman4eg\Nalog\Util\JSON;
Expand Down Expand Up @@ -134,28 +134,15 @@ protected function httpDelete(string $path, array $params = [], array $requestHe
* Handle HTTP errors.
*
* Call is controlled by the specific API methods.
* Use ErrorHandler::handle instead of this
*
* @throws DomainException
*
* @deprecated
*/
protected function handleErrors(ResponseInterface $response): void
{
$body = (string)$response->getBody();
switch ($response->getStatusCode()) {
case 400:
throw new DomainExceptions\ValidationException($body);
case 401:
throw new DomainExceptions\UnauthorizedException();
case 403:
throw new DomainExceptions\ForbiddenException();
case 404:
throw new DomainExceptions\NotFoundException();
case 406:
throw new DomainExceptions\ClientException('Wrong Accept headers');
case 500:
throw new DomainExceptions\ServerException();
default:
throw new DomainExceptions\UnknownErrorException();
}
(new ErrorHandler())->handleResponse($response);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/ApiClient.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<?php

declare(strict_types=1);

namespace Shoman4eg\Nalog;
Expand Down Expand Up @@ -69,6 +68,7 @@ public static function createWithCustomClient(ClientInterface $client): self
*
* @throws ClientExceptionInterface
* @throws JsonException
* @throws Exception\DomainException
*/
public function createNewAccessToken(string $username, string $password): ?string
{
Expand Down
43 changes: 43 additions & 0 deletions src/ErrorHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);

namespace Shoman4eg\Nalog;

use Psr\Http\Message\ResponseInterface;
use Shoman4eg\Nalog\Exception\Domain as DomainExceptions;
use Shoman4eg\Nalog\Exception\DomainException;

/**
* @author Artem Dubinin <artem@dubinin.me>
*/
final class ErrorHandler
{
/**
* Handle HTTP errors.
*
* Call is controlled by the specific API methods.
*
* @throws DomainException
*/
public function handleResponse(ResponseInterface $response): void
{
$body = (string)$response->getBody();

switch ($response->getStatusCode()) {
case 400:
throw new DomainExceptions\ValidationException($body);
case 401:
throw new DomainExceptions\UnauthorizedException($body);
case 403:
throw new DomainExceptions\ForbiddenException();
case 404:
throw new DomainExceptions\NotFoundException();
case 406:
throw new DomainExceptions\ClientException('Wrong Accept headers');
case 500:
throw new DomainExceptions\ServerException();
default:
throw new DomainExceptions\UnknownErrorException();
}
}
}
5 changes: 5 additions & 0 deletions src/Exception/Domain/UnauthorizedException.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@
*/
final class UnauthorizedException extends ClientException
{
public function __construct($message = '')
{
$decodedMessage = json_decode($message, true);
parent::__construct($decodedMessage['message'] ?? '');
}
}
7 changes: 5 additions & 2 deletions src/Http/Authenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use Http\Client\HttpClient;
use Psr\Http\Client\ClientExceptionInterface;
use Shoman4eg\Nalog\DTO\DeviceInfo;
use Shoman4eg\Nalog\ErrorHandler;
use Shoman4eg\Nalog\Exception\DomainException;
use Shoman4eg\Nalog\RequestBuilder;
use Shoman4eg\Nalog\Util\JSON;

Expand Down Expand Up @@ -33,6 +35,7 @@ public function __construct(RequestBuilder $requestBuilder, HttpClient $httpClie
/**
* @throws ClientExceptionInterface
* @throws \JsonException
* @throws DomainException
*/
public function createAccessToken(string $username, string $password): ?string
{
Expand All @@ -47,8 +50,8 @@ public function createAccessToken(string $username, string $password): ?string

$response = $this->httpClient->sendRequest($request);

if ($response->getStatusCode() !== 200) {
return null;
if ($response->getStatusCode() >= 400) {
(new ErrorHandler())->handleResponse($response);
}

$this->accessToken = (string)$response->getBody();
Expand Down
23 changes: 10 additions & 13 deletions tests/ApiClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@

namespace Shoman4eg\Nalog\Tests;

use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use Shoman4eg\Nalog\ApiClient;
use Shoman4eg\Nalog\Exception\Domain\UnauthorizedException;

/**
* @author Artem Dubinin <artem@dubinin.me>
Expand All @@ -20,23 +17,23 @@ class ApiClientTest extends ApiTestCase
/**
* @throws \Psr\Http\Client\ClientExceptionInterface
* @throws \JsonException
* @throws \Shoman4eg\Nalog\Exception\DomainException
*/
public function testCreateNewAccessToken(): void
{
$mock = new MockHandler([
$this->mock->append(
new Response(200, [], self::getAccessToken()),
new Response(400, []),
]);
$client = ApiClient::createWithCustomClient(new Client(['handler' => HandlerStack::create($mock)]));
new Response(401, [], json_encode(['message' => 'Указанный Вами ИНН некорректен'])),
);

self::assertJson($client->createNewAccessToken('validUserName', 'validPassword'));
self::assertNull($client->createNewAccessToken('invalidUserName', 'invalidPassword'));
self::assertJson($this->client->createNewAccessToken('validUserName', 'validPassword'));
$this->expectException(UnauthorizedException::class);
$this->client->createNewAccessToken('invalidUserName', 'invalidPassword');
}

public function testGetAccessToken(): void
{
$client = ApiClient::create();
$client->authenticate(self::getAccessToken());
self::assertJson($client->getAccessToken());
$this->client->authenticate(self::getAccessToken());
self::assertJson($this->client->getAccessToken());
}
}

0 comments on commit 5e1c694

Please sign in to comment.