PaymentService.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <?php
  2. namespace Services;
  3. use Libs\BashExecutor;
  4. use Models\PaymentModel;
  5. class PaymentService
  6. {
  7. private const DEFAULT_EXPIRES = 1800;
  8. private const DEFAULT_STATUS_ID = 0;
  9. private PaymentModel $paymentModel;
  10. private string $wooviCliPath;
  11. public function __construct(?string $wooviCliPath = null)
  12. {
  13. $this->paymentModel = new PaymentModel();
  14. $this->wooviCliPath = $wooviCliPath ?? $this->resolveWooviCliPath();
  15. }
  16. public function initiatePayment(int $value): array
  17. {
  18. if ($value <= 0) {
  19. throw new \InvalidArgumentException('Payment value must be greater than zero');
  20. }
  21. $userId = $this->resolveAuthenticatedUserId();
  22. $externalId = $this->generateExternalId();
  23. $pixCode = $this->runWooviCommand($value, self::DEFAULT_EXPIRES, $externalId);
  24. $paymentId = $this->paymentModel->create(
  25. $externalId,
  26. self::DEFAULT_STATUS_ID,
  27. $userId,
  28. null,
  29. '',
  30. ''
  31. );
  32. return [
  33. 'payment_id' => $paymentId,
  34. 'payment_code' => $pixCode,
  35. ];
  36. }
  37. private function resolveAuthenticatedUserId(): int
  38. {
  39. $userId = $GLOBALS['api_user_id'] ?? null;
  40. if (!is_numeric($userId) || (int)$userId <= 0) {
  41. throw new \RuntimeException('Authenticated user context not available for payment creation');
  42. }
  43. return (int)$userId;
  44. }
  45. private function generateExternalId(): string
  46. {
  47. return 'PAY_' . bin2hex(random_bytes(8));
  48. }
  49. private function resolveWooviCliPath(): string
  50. {
  51. if (!empty($_ENV['WOOVI_CLI_PATH'])) {
  52. return $_ENV['WOOVI_CLI_PATH'];
  53. }
  54. return dirname(__DIR__, 2) . '/cli-woovi/woovi';
  55. }
  56. private function runWooviCommand(int $value, int $expires, string $externalId): string
  57. {
  58. $cliPath = $this->wooviCliPath;
  59. if (!is_file($cliPath)) {
  60. throw new \RuntimeException('Woovi CLI executable not found at ' . $cliPath);
  61. }
  62. if (!is_executable($cliPath)) {
  63. throw new \RuntimeException('Woovi CLI executable is not executable at ' . $cliPath);
  64. }
  65. $command = sprintf(
  66. '%s -value=%d -expires=%d -correlation=%s',
  67. escapeshellarg($cliPath),
  68. $value,
  69. $expires,
  70. escapeshellarg($externalId)
  71. );
  72. $result = BashExecutor::run($command, 60);
  73. if (($result['exitCode'] ?? 1) !== 0) {
  74. $message = $result['error'] ?: $result['output'] ?: 'Unknown Woovi CLI error';
  75. throw new \RuntimeException('Woovi CLI failed: ' . $message);
  76. }
  77. $output = trim((string)($result['output'] ?? ''));
  78. if ($output === '') {
  79. $error = trim((string)($result['error'] ?? ''));
  80. $combined = $error !== '' ? $error : 'empty response';
  81. throw new \RuntimeException('Woovi CLI did not return a payment code: ' . $combined);
  82. }
  83. return $output;
  84. }
  85. }