PaymentConfirmController.php 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. <?php
  2. namespace Controllers;
  3. use Libs\ResponseLib;
  4. use Models\CprModel;
  5. use Models\PaymentModel;
  6. use Psr\Http\Message\ServerRequestInterface;
  7. use Services\B3CprService;
  8. class PaymentConfirmController
  9. {
  10. private PaymentModel $paymentModel;
  11. private CprModel $cprModel;
  12. private B3CprService $b3Service;
  13. public function __construct()
  14. {
  15. $this->paymentModel = new PaymentModel();
  16. $this->cprModel = new CprModel();
  17. $this->b3Service = new B3CprService();
  18. }
  19. public function __invoke(ServerRequestInterface $request)
  20. {
  21. $body = json_decode((string)$request->getBody(), true) ?? [];
  22. $paymentId = isset($body['payment_id']) ? (int)$body['payment_id'] : 0;
  23. if ($paymentId <= 0) {
  24. return ResponseLib::sendFail('payment_id inválido', [], 'E_VALIDATE')->withStatus(400);
  25. }
  26. $payment = $this->paymentModel->findById($paymentId);
  27. if (!$payment) {
  28. return ResponseLib::sendFail('Pagamento não encontrado', [], 'E_NOT_FOUND')->withStatus(404);
  29. }
  30. $statusId = (int)($payment['status_id'] ?? 0);
  31. if ($statusId === 0) {
  32. return ResponseLib::sendFail('Pagamento ainda não confirmado', ['payment_id' => $paymentId], 'E_PAYMENT_PENDING')->withStatus(409);
  33. }
  34. if ($statusId !== 1) {
  35. return ResponseLib::sendFail('Pagamento em status inválido', ['status_id' => $statusId], 'E_PAYMENT_STATUS')->withStatus(409);
  36. }
  37. $cpr = $this->cprModel->findByPaymentId($paymentId);
  38. if (!$cpr) {
  39. return ResponseLib::sendFail('Nenhuma CPR vinculada ao pagamento', [], 'E_CPR_NOT_FOUND')->withStatus(404);
  40. }
  41. try {
  42. $payload = $this->b3Service->mapToB3($cpr);
  43. $token = $this->resolveB3Token($request, $body);
  44. $result = $this->b3Service->postCpr($token, $payload);
  45. } catch (\Throwable $e) {
  46. return ResponseLib::sendFail('Falha ao enviar CPR à B3: ' . $e->getMessage(), [], 'E_EXTERNAL')->withStatus(502);
  47. }
  48. if (isset($result['error'])) {
  49. return ResponseLib::sendFail('cURL error during B3 CPR request', ['error' => $result['error']], 'E_EXTERNAL')->withStatus(502);
  50. }
  51. return ResponseLib::sendOk([
  52. 'message' => 'CPR gerada com sucesso',
  53. 'payment_id' => $paymentId,
  54. 'b3_response' => $result['json'] ?? ($result['raw'] ?? null),
  55. ], 'S_CPR_SENT');
  56. }
  57. private function resolveB3Token(ServerRequestInterface $request, array $body): string
  58. {
  59. $token = $body['b3_access_token'] ?? ($body['access_token'] ?? null);
  60. if (!$token) {
  61. $b3Auth = $request->getHeaderLine('X-B3-Authorization') ?: '';
  62. if (stripos($b3Auth, 'Bearer ') === 0) {
  63. $token = trim(substr($b3Auth, 7));
  64. }
  65. }
  66. if (!$token) {
  67. $token = $request->getHeaderLine('X-B3-Access-Token') ?: null;
  68. }
  69. if (!$token) {
  70. $token = $this->b3Service->getAccessToken();
  71. }
  72. return $token;
  73. }
  74. }