openid) throw new InvalidArgumentException('请重新进入小程序后再试'); $id = DB::table('content_security_checks')->insertGetId([ 'user_id' => $user->id, 'upload_id' => $upload->id, 'url' => $upload->url, 'status' => 'pending', 'created_at' => now(), 'updated_at' => now(), ]); try { // The SDK convenience method uses v1; explicitly send all v2 parameters. $result = miniProgramApp()->content_security->httpPostJson('wxa/media_check_async', [ 'media_url' => $upload->url, 'media_type' => 2, 'version' => 2, 'scene' => 1, 'openid' => $user->openid, ]); if ((int) ($result['errcode'] ?? -1) !== 0 || empty($result['trace_id'])) throw new \RuntimeException('WeChat media check submission failed'); DB::table('content_security_checks')->where('id', $id)->update(['trace_id' => $result['trace_id'], 'updated_at' => now()]); } catch (\Throwable $e) { DB::table('content_security_checks')->where('id', $id)->update(['status' => 'error', 'updated_at' => now()]); Log::warning('Avatar check submission failed', ['check_id' => $id, 'exception' => get_class($e)]); throw new InvalidArgumentException('内容检测暂不可用,请稍后重新上传'); } return ['check_id' => $id, 'status' => 'pending']; } public function result(int $userId, int $id): array { $row = DB::table('content_security_checks')->where('id', $id)->where('user_id', $userId)->first(); if (!$row) throw new InvalidArgumentException('检测记录不存在'); $status = $row->status; if ($status === 'pending' && strtotime($row->created_at) < time() - 600) $status = 'error'; return ['check_id' => $row->id, 'status' => $status, 'url' => $status === 'pass' ? $row->url : null]; } public function receive(array $message): void { if (($message['Event'] ?? '') !== 'wxa_media_check') return; $trace = $message['trace_id'] ?? ''; if (!$trace) return; if (!DB::table('content_security_checks')->where('trace_id', $trace)->exists()) { // A callback may arrive before the submission response is stored; request a retry. throw new \RuntimeException('Unknown media check trace'); } $suggest = $message['result']['suggest'] ?? ''; $error = (int) ($message['errcode'] ?? -1); $status = $error !== 0 ? 'error' : ($suggest === 'pass' ? 'pass' : 'reject'); // Only a signed callback can reach here. Duplicates cannot overwrite a final decision. DB::table('content_security_checks')->where('trace_id', $trace)->where('status', 'pending') ->update(['status' => $status, 'suggest' => $suggest, 'error_code' => $error, 'updated_at' => now()]); } public function assertApproved(int $userId, string $url): void { $approved = DB::table('content_security_checks')->where('user_id', $userId)->where('url', $url) ->where('status', 'pass')->exists(); if (!$approved) throw new InvalidArgumentException('头像尚未通过内容检测,请重新上传并等待检测通过'); } }