You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.6 KiB
82 lines
2.6 KiB
|
4 days ago
|
<?php
|
||
|
|
|
||
|
|
namespace App\Support;
|
||
|
|
|
||
|
|
use App\Models\Venue;
|
||
|
|
use App\Models\VerifyPortalCredential;
|
||
|
|
use Illuminate\Support\Facades\Crypt;
|
||
|
|
use Illuminate\Support\Facades\DB;
|
||
|
|
use Illuminate\Support\Facades\Hash;
|
||
|
|
|
||
|
|
/** 抢票核销:场馆维度 6 位口令(与活动共用同一核销入口页);凭证 kind = ticket_grab_venue */
|
||
|
|
final class VenueVerifyPortalPin
|
||
|
|
{
|
||
|
|
public const CRED_USERNAME = '__tg_pin__';
|
||
|
|
|
||
|
|
public static function syncPinCredential(Venue $venue): VerifyPortalCredential
|
||
|
|
{
|
||
|
|
$pin = trim((string) ($venue->verify_portal_pin ?? ''));
|
||
|
|
if ($pin === '' || ! preg_match('/^\d{6}$/', $pin)) {
|
||
|
|
throw new \InvalidArgumentException('场馆抢票核销口令无效');
|
||
|
|
}
|
||
|
|
|
||
|
|
$vid = (int) $venue->id;
|
||
|
|
|
||
|
|
/** @var VerifyPortalCredential|null $cred */
|
||
|
|
$cred = VerifyPortalCredential::query()
|
||
|
|
->where('portal_kind', VerifyPortalCredential::KIND_TICKET_GRAB_VENUE)
|
||
|
|
->where('portal_id', $vid)
|
||
|
|
->where('username', self::CRED_USERNAME)
|
||
|
|
->first();
|
||
|
|
|
||
|
|
$attributes = [
|
||
|
|
'venue_id' => $vid,
|
||
|
|
'password' => Hash::make($pin),
|
||
|
|
'password_plain_enc' => Crypt::encryptString($pin),
|
||
|
|
'note' => null,
|
||
|
|
];
|
||
|
|
|
||
|
|
if ($cred !== null) {
|
||
|
|
$cred->forceFill($attributes)->save();
|
||
|
|
|
||
|
|
return $cred;
|
||
|
|
}
|
||
|
|
|
||
|
|
return VerifyPortalCredential::query()->create(array_merge([
|
||
|
|
'portal_kind' => VerifyPortalCredential::KIND_TICKET_GRAB_VENUE,
|
||
|
|
'portal_id' => $vid,
|
||
|
|
'username' => self::CRED_USERNAME,
|
||
|
|
], $attributes));
|
||
|
|
}
|
||
|
|
|
||
|
|
public static function ensure(Venue $venue): string
|
||
|
|
{
|
||
|
|
$venue->refresh();
|
||
|
|
|
||
|
|
$pinOut = trim((string) ($venue->verify_portal_pin ?? ''));
|
||
|
|
if ($pinOut !== '' && preg_match('/^\d{6}$/', $pinOut)) {
|
||
|
|
self::syncPinCredential($venue);
|
||
|
|
|
||
|
|
return $pinOut;
|
||
|
|
}
|
||
|
|
|
||
|
|
DB::transaction(function () use ($venue): void {
|
||
|
|
$fresh = Venue::query()->whereKey($venue->id)->lockForUpdate()->first();
|
||
|
|
if ($fresh === null) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
$p = trim((string) ($fresh->verify_portal_pin ?? ''));
|
||
|
|
if ($p !== '' && preg_match('/^\d{6}$/', $p)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
$fresh->forceFill(['verify_portal_pin' => PortalSixDigitPin::generateUnique()])->saveQuietly();
|
||
|
|
});
|
||
|
|
|
||
|
|
$venue->refresh();
|
||
|
|
$pinOut = trim((string) ($venue->verify_portal_pin ?? ''));
|
||
|
|
self::syncPinCredential($venue);
|
||
|
|
|
||
|
|
return $pinOut;
|
||
|
|
}
|
||
|
|
}
|