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.
87 lines
2.8 KiB
87 lines
2.8 KiB
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
use App\Models\Activity;
|
|
use App\Models\VerifyPortalCredential;
|
|
use Illuminate\Support\Facades\Crypt;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Hash;
|
|
|
|
final class ActivityVerifyPortalPin
|
|
{
|
|
/** verify_portal_credentials 中占位用户名,核销登录仅校验 6 位数字密码并按活动发卡 */
|
|
public const CRED_USERNAME = '__pin__';
|
|
|
|
/** 随机 6 位数字口令,与场馆抢票口令一起全库唯一(含软删活动占用) */
|
|
public static function generateUnique(): string
|
|
{
|
|
return PortalSixDigitPin::generateUnique();
|
|
}
|
|
|
|
public static function syncPinCredential(Activity $activity): VerifyPortalCredential
|
|
{
|
|
$pin = trim((string) ($activity->verify_portal_pin ?? ''));
|
|
if ($pin === '' || ! preg_match('/^\d{6}$/', $pin)) {
|
|
throw new \InvalidArgumentException('活动核销口令无效');
|
|
}
|
|
|
|
/** @var VerifyPortalCredential|null $cred */
|
|
$cred = VerifyPortalCredential::query()
|
|
->where('portal_kind', VerifyPortalCredential::KIND_ACTIVITY)
|
|
->where('portal_id', $activity->id)
|
|
->where('username', self::CRED_USERNAME)
|
|
->first();
|
|
|
|
$attributes = [
|
|
'venue_id' => (int) $activity->venue_id,
|
|
'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_ACTIVITY,
|
|
'portal_id' => (int) $activity->id,
|
|
'username' => self::CRED_USERNAME,
|
|
], $attributes));
|
|
}
|
|
|
|
/** 补齐 activities.verify_portal_pin 占位凭证行 */
|
|
public static function ensure(Activity $activity): string
|
|
{
|
|
$activity->refresh();
|
|
|
|
$pinOut = trim((string) ($activity->verify_portal_pin ?? ''));
|
|
if ($pinOut !== '' && preg_match('/^\d{6}$/', $pinOut)) {
|
|
self::syncPinCredential($activity);
|
|
|
|
return $pinOut;
|
|
}
|
|
|
|
DB::transaction(function () use ($activity): void {
|
|
$fresh = Activity::query()->whereKey($activity->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' => self::generateUnique()])->saveQuietly();
|
|
});
|
|
|
|
$activity->refresh();
|
|
$pinOut = trim((string) ($activity->verify_portal_pin ?? ''));
|
|
self::syncPinCredential($activity);
|
|
|
|
return $pinOut;
|
|
}
|
|
}
|