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; } }