Projeto de transações monetárias entre usuários e lojistas
-
Instale a última versão do
docker
edocker-compose
. -
Clone este repositório.
-
Suba o ambiente executando o comando:
make up
-
Acesse
http://localhost:8080/healthcheck
e deverá retornar uma resposta como:{ "msg":"ok", "datetime":"2020-06-21T01:49:25Z", "timestamp":"1592704165" }
Há dois tipos de usuários os comuns
e os lojistas
, para efetuar transações entre eles é necessário criar um usuário e obter uma hash chamada secret
para obter autorização na transação
A propriedade type
pode ser default
e storekeeper
:
Ao efetuar a seguinte request
curl --location --request POST 'http://localhost/users' \
--header 'Content-Type: application/json' \
--data-raw '{
"cpf_cnpj": "144.579.940-57",
"full_name": "Foo Bar",
"email": "foo@bar.com",
"wallet_amount": 99,
"type": "default"
}'
Obterá uma resposta como:
{
"secret": "JGFyZ29uMmkkdj0xOSRtPTY1NTM2LHQ9NCxwPTEkZVUwNVJsaDJhVE56YUVwT2FXZ3plZyQzRXFrYnUyMVo5SlU5dkhPdGFCVmFzRHpvQ2RwOS9BZk9EemRtY2x0VFow"
}
curl --location --request POST 'http://localhost/transaction' \
--header 'X-User-Secret: JGFyZ29uMmkkdj0xOSRtPTY1NTM2LHQ9NCxwPTEkZVUwNVJsaDJhVE56YUVwT2FXZ3plZyQzRXFrYnUyMVo5SlU5dkhPdGFCVmFzRHpvQ2RwOS9BZk9EemRtY2x0VFow' \
--header 'Content-Type: application/json' \
--data-raw '{
"payee": "580b70fe-6955-453e-bde7-41280a465427",
"payer": "4485d8e1-9803-49fc-97ae-2f0a8bbd5506",
"value": 100.0
}'
Desenvolvido com conceitos como S.O.L.I.D., TDD (Test Driven Development) e DDD (Domain Driven Design), o projeto foi modularizado de forma que facilitem e incorporem esses conceitos. Além
Foi utilizado a seguinte stack:
- PHP 7.4
- MySQL
- Symfony Framework
- Doctrine & Doctrine Migrations
- PHPStan/Psalm/PHPUnit
O Symfony é um framework maduro e com alta reputação, conhecido pela comunidade PHP através dos seus componentes reutilizáveis e que compõem projetos como Magento/Drupal. Possui uma organização e recursos que facilitam a escrita de código limpo através de padrões de projeto, injeção de dependência e testes integrados.
O componente Symfony Messenger
provê uma série de mecanismos para a manipulação de mensagens/eventos de forma assíncrona e implementação do pattern Command através do Bus. Ele foi utilizado para manipular o recurso de envio de notificação para o usuário ao receber uma transação.
Para consumir as mensagens assíncronas através do messenger, é necessário executar, dentro do container php, o comando:
composer worker:queue:consumer
Haverá o processamento:
/app # composer worker:queue:consumer
> console messenger:consume async --limit=20 -vvv --no-interaction
[OK] Consuming messages from transports "async".
// The worker will automatically exit once it has processed 20 messages or received a stop signal via the
// messenger:stop-workers command.
// Quit the worker with CONTROL-C.
20:14:28 INFO [messenger] Received message MiniPay\Core\Transaction\Application\Async\SendTransactionReceivedNotification
[
"message" => MiniPay\Core\Transaction\Application\Async\SendTransactionReceivedNotification^ {
+userId: "580b70fe-6955-453e-bde7-41280a465427"
+amount: 1.0
},
"class" => "MiniPay\Core\Transaction\Application\Async\SendTransactionReceivedNotification"
]
20:14:29 INFO [messenger] Message MiniPay\Core\Transaction\Application\Async\SendTransactionReceivedNotification handled by MiniPay\Core\Transaction\Application\Async\SendTransactionReceivedNotificationHandler::__invoke
[
"message" => MiniPay\Core\Transaction\Application\Async\SendTransactionReceivedNotification^ {
+userId: "580b70fe-6955-453e-bde7-41280a465427"
+amount: 1.0
},
"class" => "MiniPay\Core\Transaction\Application\Async\SendTransactionReceivedNotification",
"handler" => "MiniPay\Core\Transaction\Application\Async\SendTransactionReceivedNotificationHandler::__invoke"
]
20:14:29 INFO [messenger] MiniPay\Core\Transaction\Application\Async\SendTransactionReceivedNotification was handled successfully (acknowledging to transport).
[
"message" => MiniPay\Core\Transaction\Application\Async\SendTransactionReceivedNotification^ {
+userId: "580b70fe-6955-453e-bde7-41280a465427"
+amount: 1.0
},
"class" => "MiniPay\Core\Transaction\Application\Async\SendTransactionReceivedNotification"
]
As ferramentas PHPStan/Psalm/PHPUnit foram introduzidas para garantir o teste de aplicação assim como a análise estática do código para capturar possíveis bugs com tipagem e smell codes;
Ao executar o comando composer test
uma sequência de comandos avalia o projeto:
/app # composer test
> phpcs
> phpstan analyse --memory-limit=-1
Note: Using configuration file /app/phpstan.neon.
96/96 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
[OK] No errors
> psalm
Scanning files...
Analyzing files...
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 60 / 95 (63%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
------------------------------
No errors found!
------------------------------
29 other issues found.
You can display them with --show-info=true
------------------------------
Psalm can automatically fix 1 of these issues.
Run Psalm again with
--alter --issues=MissingClosureReturnType --dry-run
to see what it can fix.
------------------------------
Checks took 5.32 seconds and used 297.696MB of memory
Psalm was able to infer types for 98.9369% of the codebase
> phpunit
PHPUnit 9.5.0 by Sebastian Bergmann and contributors.
Warning: Your XML configuration validates against a deprecated schema.
Suggestion: Migrate your XML configuration using "--migrate-configuration"!
............................................................... 63 / 131 ( 48%)
............................................................... 126 / 131 ( 96%)
..... 131 / 131 (100%)
Time: 00:07.433, Memory: 40.00 MB
OK (131 tests, 256 assertions)
- O uso de mensageria pode ser útil para processamentos assíncronos, diminuindo o tempo de resposta das operações e podendo ter garantias de reprocessamento de informação através de fallbacks.
- Junto da mensageria, pode ser possível também implementar o Pattern
Event Sourcing
onde as alterações são baseadas em eventos e mantendo um histórico dessas alterações