Compare commits
2 Commits
1af5b1d7ed
...
403caf77f5
| Author | SHA1 | Date | |
|---|---|---|---|
| 403caf77f5 | |||
| 04b2bb0b2a |
@@ -5,6 +5,7 @@ namespace App\Domains\Integration\Services;
|
|||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
|
||||||
class TelepagosIntegrationService extends BaseIntegrationService
|
class TelepagosIntegrationService extends BaseIntegrationService
|
||||||
@@ -84,12 +85,12 @@ class TelepagosIntegrationService extends BaseIntegrationService
|
|||||||
'password' => $password,
|
'password' => $password,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($response->failed() || $response->json('status') !== 'ok') {
|
$data = $this->handleResponse($response, 'authentication', [
|
||||||
throw new Exception("Telepagos authentication failed: " . ($response->json('message') ?? $response->body()));
|
'username' => $username,
|
||||||
}
|
]);
|
||||||
|
|
||||||
$token = $response->json('token');
|
$token = $data['token'] ?? null;
|
||||||
$expiresAtStr = $response->json('expires_at');
|
$expiresAtStr = $data['expires_at'] ?? null;
|
||||||
|
|
||||||
if (!$token || !$expiresAtStr) {
|
if (!$token || !$expiresAtStr) {
|
||||||
throw new Exception("Telepagos authentication response is missing token or expires_at.");
|
throw new Exception("Telepagos authentication response is missing token or expires_at.");
|
||||||
@@ -105,6 +106,70 @@ class TelepagosIntegrationService extends BaseIntegrationService
|
|||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a QR code for cash-in.
|
||||||
|
*
|
||||||
|
* @param float $amount
|
||||||
|
* @param string $concept
|
||||||
|
* @param string $description
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function generateQr(float $amount, string $concept, string $description): array
|
||||||
|
{
|
||||||
|
$response = $this->client()->post('/v2/payment/cashin/qr/generate', [
|
||||||
|
'amount' => $amount,
|
||||||
|
'concept' => $concept,
|
||||||
|
'description' => $description,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->handleResponse($response, 'QR generation', [
|
||||||
|
'amount' => $amount,
|
||||||
|
'concept' => $concept,
|
||||||
|
'description' => $description,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the details of a cash-in payment.
|
||||||
|
*
|
||||||
|
* @param int $cashinId
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function getCashinDetails(int $cashinId): array
|
||||||
|
{
|
||||||
|
$response = $this->client()->get("/v2/payment/cashin/{$cashinId}");
|
||||||
|
|
||||||
|
return $this->handleResponse($response, 'get cash-in details', [
|
||||||
|
'cashin_id' => $cashinId,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the Telepagos API response, logging any failures and throwing Exceptions.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Client\Response $response
|
||||||
|
* @param string $actionDescription
|
||||||
|
* @param array $context
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function handleResponse(\Illuminate\Http\Client\Response $response, string $actionDescription, array $context = []): array
|
||||||
|
{
|
||||||
|
if ($response->failed() || $response->json('status') !== 'ok') {
|
||||||
|
$errorMessage = $response->json('message') ?? $response->body();
|
||||||
|
Log::error("Telepagos {$actionDescription} failed: {$errorMessage}", array_merge([
|
||||||
|
'response_status' => $response->status(),
|
||||||
|
'response_body' => $response->json() ?? $response->body(),
|
||||||
|
], $context));
|
||||||
|
|
||||||
|
throw new Exception("Telepagos {$actionDescription} failed: {$errorMessage}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response->json() ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the cached token.
|
* Clear the cached token.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -239,6 +239,14 @@ class IntegrationServiceTest extends TestCase
|
|||||||
], 401)
|
], 401)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
\Illuminate\Support\Facades\Log::shouldReceive('error')
|
||||||
|
->once()
|
||||||
|
->with('Telepagos authentication failed: Invalid credentials', \Mockery::on(function ($context) {
|
||||||
|
return $context['username'] === 'tele_user'
|
||||||
|
&& $context['response_status'] === 401
|
||||||
|
&& $context['response_body'] === ['status' => 'error', 'message' => 'Invalid credentials'];
|
||||||
|
}));
|
||||||
|
|
||||||
$service = new TelepagosIntegrationService('telepagos');
|
$service = new TelepagosIntegrationService('telepagos');
|
||||||
$service->forTenant($this->tenant->codigo);
|
$service->forTenant($this->tenant->codigo);
|
||||||
|
|
||||||
@@ -299,4 +307,219 @@ class IntegrationServiceTest extends TestCase
|
|||||||
&& $request->url() === 'https://api.telepagos.com.ar/v1/payments';
|
&& $request->url() === 'https://api.telepagos.com.ar/v1/payments';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_it_generates_qr_code(): void
|
||||||
|
{
|
||||||
|
Integration::create([
|
||||||
|
'integration_code' => 'telepagos_homo',
|
||||||
|
'name' => 'Telepagos',
|
||||||
|
'url' => 'https://api.telepagos.com.ar',
|
||||||
|
'integration_data_schema' => [
|
||||||
|
'username' => 'required|string',
|
||||||
|
'password' => 'required|string',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
TenantIntegration::create([
|
||||||
|
'tenant_code' => $this->tenant->codigo,
|
||||||
|
'integration_code' => 'telepagos_homo',
|
||||||
|
'integration_data' => [
|
||||||
|
'username' => 'tele_user',
|
||||||
|
'password' => 'tele_pass',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
Http::fake([
|
||||||
|
'https://api.telepagos.com.ar/v2/auth/token' => Http::response([
|
||||||
|
'status' => 'ok',
|
||||||
|
'token' => 'mock-jwt-token-123',
|
||||||
|
'expires_at' => now()->addHour()->toDateTimeString()
|
||||||
|
], 200),
|
||||||
|
'https://api.telepagos.com.ar/v2/payment/cashin/qr/generate' => Http::response([
|
||||||
|
'status' => 'ok',
|
||||||
|
'qr_code' => 'mock-qr-code-data',
|
||||||
|
'qr_order_id' => 6353
|
||||||
|
], 200)
|
||||||
|
]);
|
||||||
|
|
||||||
|
$service = new TelepagosIntegrationService('telepagos');
|
||||||
|
$service->forTenant($this->tenant->codigo);
|
||||||
|
|
||||||
|
$result = $service->generateQr(1200.00, 'Test Concept', 'Test Description');
|
||||||
|
|
||||||
|
$this->assertEquals('ok', $result['status']);
|
||||||
|
$this->assertEquals('mock-qr-code-data', $result['qr_code']);
|
||||||
|
$this->assertEquals(6353, $result['qr_order_id']);
|
||||||
|
|
||||||
|
Http::assertSent(function ($request) {
|
||||||
|
return $request->hasHeader('Authorization', 'Bearer mock-jwt-token-123')
|
||||||
|
&& $request->url() === 'https://api.telepagos.com.ar/v2/payment/cashin/qr/generate'
|
||||||
|
&& $request['amount'] === 1200.00
|
||||||
|
&& $request['concept'] === 'Test Concept'
|
||||||
|
&& $request['description'] === 'Test Description';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_it_logs_and_throws_exception_on_generate_qr_error(): void
|
||||||
|
{
|
||||||
|
Integration::create([
|
||||||
|
'integration_code' => 'telepagos_homo',
|
||||||
|
'name' => 'Telepagos',
|
||||||
|
'url' => 'https://api.telepagos.com.ar',
|
||||||
|
'integration_data_schema' => [
|
||||||
|
'username' => 'required|string',
|
||||||
|
'password' => 'required|string',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
TenantIntegration::create([
|
||||||
|
'tenant_code' => $this->tenant->codigo,
|
||||||
|
'integration_code' => 'telepagos_homo',
|
||||||
|
'integration_data' => [
|
||||||
|
'username' => 'tele_user',
|
||||||
|
'password' => 'tele_pass',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
Http::fake([
|
||||||
|
'https://api.telepagos.com.ar/v2/auth/token' => Http::response([
|
||||||
|
'status' => 'ok',
|
||||||
|
'token' => 'mock-jwt-token-123',
|
||||||
|
'expires_at' => now()->addHour()->toDateTimeString()
|
||||||
|
], 200),
|
||||||
|
'https://api.telepagos.com.ar/v2/payment/cashin/qr/generate' => Http::response([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Importe inválido'
|
||||||
|
], 422)
|
||||||
|
]);
|
||||||
|
|
||||||
|
\Illuminate\Support\Facades\Log::shouldReceive('error')
|
||||||
|
->once()
|
||||||
|
->with('Telepagos QR generation failed: Importe inválido', \Mockery::on(function ($context) {
|
||||||
|
return $context['amount'] === 1200.00
|
||||||
|
&& $context['concept'] === 'Test Concept'
|
||||||
|
&& $context['description'] === 'Test Description'
|
||||||
|
&& $context['response_status'] === 422
|
||||||
|
&& $context['response_body'] === ['status' => 'error', 'message' => 'Importe inválido'];
|
||||||
|
}));
|
||||||
|
|
||||||
|
$service = new TelepagosIntegrationService('telepagos');
|
||||||
|
$service->forTenant($this->tenant->codigo);
|
||||||
|
|
||||||
|
$this->expectException(Exception::class);
|
||||||
|
$this->expectExceptionMessage("Telepagos QR generation failed: Importe inválido");
|
||||||
|
|
||||||
|
$service->generateQr(1200.00, 'Test Concept', 'Test Description');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_it_gets_cashin_details(): void
|
||||||
|
{
|
||||||
|
Integration::create([
|
||||||
|
'integration_code' => 'telepagos_homo',
|
||||||
|
'name' => 'Telepagos',
|
||||||
|
'url' => 'https://api.telepagos.com.ar',
|
||||||
|
'integration_data_schema' => [
|
||||||
|
'username' => 'required|string',
|
||||||
|
'password' => 'required|string',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
TenantIntegration::create([
|
||||||
|
'tenant_code' => $this->tenant->codigo,
|
||||||
|
'integration_code' => 'telepagos_homo',
|
||||||
|
'integration_data' => [
|
||||||
|
'username' => 'tele_user',
|
||||||
|
'password' => 'tele_pass',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
Http::fake([
|
||||||
|
'https://api.telepagos.com.ar/v2/auth/token' => Http::response([
|
||||||
|
'status' => 'ok',
|
||||||
|
'token' => 'mock-jwt-token-123',
|
||||||
|
'expires_at' => now()->addHour()->toDateTimeString()
|
||||||
|
], 200),
|
||||||
|
'https://api.telepagos.com.ar/v2/payment/cashin/6351' => Http::response([
|
||||||
|
'status' => 'ok',
|
||||||
|
'buyer' => [
|
||||||
|
'cuit' => '20416561398',
|
||||||
|
'cvu' => '0000124900000000011974'
|
||||||
|
],
|
||||||
|
'amount' => 1200,
|
||||||
|
'concept' => 'VAR',
|
||||||
|
'operation' => 'QR Telepagos',
|
||||||
|
'operation_id' => 37,
|
||||||
|
'description' => 'Pago prueba',
|
||||||
|
'transaction_id' => '2026070364',
|
||||||
|
'qr_order_id' => 6351,
|
||||||
|
'link_id' => null
|
||||||
|
], 200)
|
||||||
|
]);
|
||||||
|
|
||||||
|
$service = new TelepagosIntegrationService('telepagos');
|
||||||
|
$service->forTenant($this->tenant->codigo);
|
||||||
|
|
||||||
|
$result = $service->getCashinDetails(6351);
|
||||||
|
|
||||||
|
$this->assertEquals('ok', $result['status']);
|
||||||
|
$this->assertEquals(1200, $result['amount']);
|
||||||
|
$this->assertEquals('VAR', $result['concept']);
|
||||||
|
$this->assertEquals(6351, $result['qr_order_id']);
|
||||||
|
|
||||||
|
Http::assertSent(function ($request) {
|
||||||
|
return $request->hasHeader('Authorization', 'Bearer mock-jwt-token-123')
|
||||||
|
&& $request->url() === 'https://api.telepagos.com.ar/v2/payment/cashin/6351'
|
||||||
|
&& $request->method() === 'GET';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_it_logs_and_throws_exception_on_get_cashin_details_error(): void
|
||||||
|
{
|
||||||
|
Integration::create([
|
||||||
|
'integration_code' => 'telepagos_homo',
|
||||||
|
'name' => 'Telepagos',
|
||||||
|
'url' => 'https://api.telepagos.com.ar',
|
||||||
|
'integration_data_schema' => [
|
||||||
|
'username' => 'required|string',
|
||||||
|
'password' => 'required|string',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
TenantIntegration::create([
|
||||||
|
'tenant_code' => $this->tenant->codigo,
|
||||||
|
'integration_code' => 'telepagos_homo',
|
||||||
|
'integration_data' => [
|
||||||
|
'username' => 'tele_user',
|
||||||
|
'password' => 'tele_pass',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
Http::fake([
|
||||||
|
'https://api.telepagos.com.ar/v2/auth/token' => Http::response([
|
||||||
|
'status' => 'ok',
|
||||||
|
'token' => 'mock-jwt-token-123',
|
||||||
|
'expires_at' => now()->addHour()->toDateTimeString()
|
||||||
|
], 200),
|
||||||
|
'https://api.telepagos.com.ar/v2/payment/cashin/6351' => Http::response([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Cashin no encontrado'
|
||||||
|
], 404)
|
||||||
|
]);
|
||||||
|
|
||||||
|
\Illuminate\Support\Facades\Log::shouldReceive('error')
|
||||||
|
->once()
|
||||||
|
->with('Telepagos get cash-in details failed: Cashin no encontrado', \Mockery::on(function ($context) {
|
||||||
|
return $context['cashin_id'] === 6351
|
||||||
|
&& $context['response_status'] === 404
|
||||||
|
&& $context['response_body'] === ['status' => 'error', 'message' => 'Cashin no encontrado'];
|
||||||
|
}));
|
||||||
|
|
||||||
|
$service = new TelepagosIntegrationService('telepagos');
|
||||||
|
$service->forTenant($this->tenant->codigo);
|
||||||
|
|
||||||
|
$this->expectException(Exception::class);
|
||||||
|
$this->expectExceptionMessage("Telepagos get cash-in details failed: Cashin no encontrado");
|
||||||
|
|
||||||
|
$service->getCashinDetails(6351);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user