diff --git a/app/Domains/Integration/Services/TelepagosWebhookService.php b/app/Domains/Integration/Services/TelepagosWebhookService.php index 421af1c..ac0a2b6 100644 --- a/app/Domains/Integration/Services/TelepagosWebhookService.php +++ b/app/Domains/Integration/Services/TelepagosWebhookService.php @@ -54,7 +54,7 @@ class TelepagosWebhookService $dni = substr($cuit, 2, -1); $compra = Purchase::where('tenant_codigo', $tenantCodigo) - ->whereRaw("REPLACE(dni, '.', '') = ?", [$dni]) + ->where('payer_dni', $dni) ->whereIn('status', [Purchase::STATUS_CREATED, Purchase::STATUS_PENDING_PAYMENT]) ->where('payment_method', 'transfer') ->where('total', $amount) diff --git a/app/Domains/Purchase/Controllers/PurchaseController.php b/app/Domains/Purchase/Controllers/PurchaseController.php index 499536e..1557dcc 100644 --- a/app/Domains/Purchase/Controllers/PurchaseController.php +++ b/app/Domains/Purchase/Controllers/PurchaseController.php @@ -68,10 +68,16 @@ class PurchaseController extends Controller $method = $request->validated('method'); $totalAmount = $compra->calculateCurrentTotalAmount(); - $compra->update([ + $purchaseUpdate = [ 'payment_method' => $method, 'total' => $totalAmount, - ]); + ]; + + if ($method === 'transfer') { + $purchaseUpdate['payer_dni'] = preg_replace('/\D+/', '', (string) $request->validated('payer_dni')); + } + + $compra->update($purchaseUpdate); if ($method === 'transfer') { $telepagosService = new TelepagosIntegrationService; diff --git a/app/Domains/Purchase/Models/Purchase.php b/app/Domains/Purchase/Models/Purchase.php index 2d39e7a..c1cd132 100644 --- a/app/Domains/Purchase/Models/Purchase.php +++ b/app/Domains/Purchase/Models/Purchase.php @@ -20,6 +20,7 @@ use Illuminate\Database\Eloquent\Relations\HasOne; 'payment_method', 'total', 'dni', + 'payer_dni', 'telefono', 'nombre_apellido', 'email', diff --git a/app/Domains/Purchase/Requests/PaymentIntentRequest.php b/app/Domains/Purchase/Requests/PaymentIntentRequest.php index cfb7b65..095f4b9 100644 --- a/app/Domains/Purchase/Requests/PaymentIntentRequest.php +++ b/app/Domains/Purchase/Requests/PaymentIntentRequest.php @@ -19,6 +19,11 @@ class PaymentIntentRequest extends FormRequest { return [ 'method' => ['required', 'string', Rule::in(['qr', 'transfer'])], + 'payer_dni' => [ + Rule::requiredIf(fn (): bool => $this->input('method') === 'transfer'), + 'string', + 'regex:/^\d{7,8}$/', + ], ]; } } diff --git a/app/Domains/Purchase/Resources/PurchaseResource.php b/app/Domains/Purchase/Resources/PurchaseResource.php index b955849..8fdc774 100644 --- a/app/Domains/Purchase/Resources/PurchaseResource.php +++ b/app/Domains/Purchase/Resources/PurchaseResource.php @@ -44,6 +44,7 @@ class PurchaseResource extends JsonResource 'status' => $this->status, 'payment_method' => $this->payment_method, 'dni' => $this->dni, + 'payer_dni' => $this->payer_dni, 'telefono' => $this->telefono, 'nombre_apellido' => $this->nombre_apellido, 'email' => $this->email, diff --git a/database/migrations/2026_07_12_000000_add_payer_dni_to_compras_table.php b/database/migrations/2026_07_12_000000_add_payer_dni_to_compras_table.php new file mode 100644 index 0000000..298b385 --- /dev/null +++ b/database/migrations/2026_07_12_000000_add_payer_dni_to_compras_table.php @@ -0,0 +1,22 @@ +string('payer_dni', 8)->nullable()->after('dni'); + }); + } + + public function down(): void + { + Schema::table('compras', function (Blueprint $table) { + $table->dropColumn('payer_dni'); + }); + } +}; diff --git a/tests/Feature/Integration/TelepagosWebhookTest.php b/tests/Feature/Integration/TelepagosWebhookTest.php index db8ec16..99eafef 100644 --- a/tests/Feature/Integration/TelepagosWebhookTest.php +++ b/tests/Feature/Integration/TelepagosWebhookTest.php @@ -33,6 +33,68 @@ class TelepagosWebhookTest extends TestCase Cache::flush(); } + public function test_transfer_payment_intent_requires_a_valid_payer_dni(): void + { + $tenant = $this->createTenant('sonder', 'Sonder', 'sonder.com.ar'); + $user = User::factory()->create(); + $variant = $this->createVariantForTenant('sonder', 10, '50.00'); + $purchase = $this->createPendingTransferPurchase($tenant, $user->id, $variant->id, 1, '12345678'); + + $this->actingAs($user, 'sanctum') + ->postJson("/api/tenants/sonder/compras/{$purchase->id}/payment-intent", [ + 'method' => 'transfer', + ]) + ->assertUnprocessable() + ->assertJsonValidationErrors(['payer_dni']); + + $this->actingAs($user, 'sanctum') + ->postJson("/api/tenants/sonder/compras/{$purchase->id}/payment-intent", [ + 'method' => 'transfer', + 'payer_dni' => '12.345.678', + ]) + ->assertUnprocessable() + ->assertJsonValidationErrors(['payer_dni']); + } + + public function test_transfer_payment_intent_persists_payer_dni_without_replacing_customer_dni(): void + { + $tenant = $this->createTenant('sonder', 'Sonder', 'sonder.com.ar'); + $this->configureTelepagosIntegration($tenant); + $user = User::factory()->create(); + $variant = $this->createVariantForTenant('sonder', 10, '50.00'); + $purchase = $this->createPendingTransferPurchase($tenant, $user->id, $variant->id, 1, '12345678'); + + Http::fake([ + 'https://api.telepagos.com.ar/v2/auth/token' => Http::response([ + 'status' => 'ok', + 'token' => 'test-token', + 'expires_at' => now()->addHour()->toIso8601String(), + ]), + 'https://api.telepagos.com.ar/v2/account/info' => Http::response([ + 'status' => 'ok', + 'holder' => 'Telepagos Test', + 'cvu' => '0000003100000000000001', + 'alias' => 'telepagos.test', + 'entity' => 'Telepagos S.A.', + ]), + ]); + + $this->actingAs($user, 'sanctum') + ->postJson("/api/tenants/sonder/compras/{$purchase->id}/payment-intent", [ + 'method' => 'transfer', + 'payer_dni' => '23456789', + ]) + ->assertOk() + ->assertJsonPath('transfer_data.alias', 'telepagos.test'); + + $this->assertDatabaseHas('compras', [ + 'id' => $purchase->id, + 'dni' => '87654321', + 'payer_dni' => '23456789', + 'payment_method' => 'transfer', + ]); + } + public function test_transfer_webhook_matches_pending_purchase_by_dni_and_total_amount(): void { $tenant = $this->createTenant('sonder', 'Sonder', 'sonder.com.ar'); @@ -209,7 +271,7 @@ class TelepagosWebhookTest extends TestCase $purchase = $checkoutService->startCheckout($tenant, $userId, [ 'cart_id' => $cart->id, - 'dni' => $dni, + 'dni' => '87654321', 'telefono' => '+54 9 341 555-4321', 'nombre_apellido' => 'Juan Perez', 'email' => 'juan.perez@example.com', @@ -217,6 +279,7 @@ class TelepagosWebhookTest extends TestCase $purchase->update([ 'payment_method' => 'transfer', + 'payer_dni' => $dni, ]); $checkoutService->completePurchase($purchase);