PaymentService.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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 = PaymentModel::STATUS_PENDING;
  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, ?string $paymentFlag = null): 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. $paymentFlag ?? ''
  31. );
  32. return [
  33. 'payment_id' => $paymentId,
  34. 'payment_code' => $pixCode,
  35. 'payment_external_id' => $externalId,
  36. ];
  37. }
  38. private function resolveAuthenticatedUserId(): int
  39. {
  40. $userId = $GLOBALS['api_user_id'] ?? null;
  41. if (!is_numeric($userId) || (int)$userId <= 0) {
  42. throw new \RuntimeException('Authenticated user context not available for payment creation');
  43. }
  44. return (int)$userId;
  45. }
  46. private function generateExternalId(): string
  47. {
  48. return 'PAY_' . bin2hex(random_bytes(8));
  49. }
  50. private function resolveWooviCliPath(): string
  51. {
  52. if (!empty($_ENV['WOOVI_CLI_PATH'])) {
  53. return $_ENV['WOOVI_CLI_PATH'];
  54. }
  55. return dirname(__DIR__, 2) . '/cli-woovi/woovi';
  56. }
  57. private function runWooviCommand(int $value, int $expires, string $externalId): string
  58. {
  59. $cliPath = $this->wooviCliPath;
  60. if (!is_file($cliPath)) {
  61. throw new \RuntimeException('Woovi CLI executable not found at ' . $cliPath);
  62. }
  63. if (!is_executable($cliPath)) {
  64. throw new \RuntimeException('Woovi CLI executable is not executable at ' . $cliPath);
  65. }
  66. $command = sprintf(
  67. '%s -value=%d -expires=%d -correlation=%s',
  68. escapeshellarg($cliPath),
  69. $value,
  70. $expires,
  71. escapeshellarg($externalId)
  72. );
  73. $result = BashExecutor::run($command, 60);
  74. if (($result['exitCode'] ?? 1) !== 0) {
  75. $message = $result['error'] ?: $result['output'] ?: 'Unknown Woovi CLI error';
  76. throw new \RuntimeException('Woovi CLI failed: ' . $message);
  77. }
  78. $output = trim((string)($result['output'] ?? ''));
  79. if ($output === '') {
  80. $error = trim((string)($result['error'] ?? ''));
  81. $combined = $error !== '' ? $error : 'empty response';
  82. throw new \RuntimeException('Woovi CLI did not return a payment code: ' . $combined);
  83. }
  84. return $output;
  85. }
  86. }