Files
clinicpro/migrations/Version20260628153625.php
T
hamedandClaude Opus 4.8 7fa4b55d3f fix(security): unique payment reference_id, reject replayed callbacks (H3)
reference_id (the gateway's settled-transaction ref) was not unique, so the
same successful callback — or a RefNum replayed onto another order — could
credit twice. Add a unique index (NULL until success, so pending/failed rows
don't collide) and an application-level pre-check in the callback that fails the
payment if the reference already belongs to another order. The unique index is
the hard backstop behind the check.

Regression: PaymentCallbackAmountTest::testReplayedGatewayReferenceIsRejected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 19:08:26 +03:30

32 lines
882 B
PHP

<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20260628153625 extends AbstractMigration
{
public function getDescription(): string
{
return 'Unique index on payments.reference_id — one settled transaction per gateway reference';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE UNIQUE INDEX UNIQ_65D29B321645DEA9 ON payments (reference_id)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP INDEX UNIQ_65D29B321645DEA9 ON payments');
}
}