refactor: 调整返点字段为百分比格式并新增集成指南路由

- 将 rebate_limit 和 default_player_rebate 的校验范围从 0-1 改为 0-100
- 在服务层进行百分比与小数的转换(输入除以100,输出乘以100)
- 更新相关测试用例以匹配新的百分比格式
- 新增 admin/docs/integration-guide 路由用于集成文档展示
This commit is contained in:
2026-06-11 09:23:16 +08:00
parent 1d13d19b65
commit 4d1c2b3d63
5 changed files with 457 additions and 11 deletions

View File

@@ -13,8 +13,8 @@ trait AgentProfileFieldRules
'total_share_rate' => ['sometimes', 'numeric', 'min:0', 'max:100'],
'relative_share_rate' => ['sometimes', 'numeric', 'min:0', 'max:100'],
'credit_limit' => ['sometimes', 'integer', 'min:0'],
'rebate_limit' => ['sometimes', 'numeric', 'min:0', 'max:1'],
'default_player_rebate' => ['sometimes', 'numeric', 'min:0', 'max:1'],
'rebate_limit' => ['sometimes', 'numeric', 'min:0', 'max:100'],
'default_player_rebate' => ['sometimes', 'numeric', 'min:0', 'max:100'],
'settlement_cycle' => ['sometimes', 'string', 'in:'.implode(',', AgentSettlementCycle::VALUES)],
'can_grant_extra_rebate' => ['sometimes', 'boolean'],
'can_create_child_agent' => ['sometimes', 'boolean'],

View File

@@ -29,8 +29,8 @@ final class AgentProfileService
$totalShare = (float) ($payload['total_share_rate'] ?? 0);
$creditLimit = (int) ($payload['credit_limit'] ?? 0);
$rebateLimit = (float) ($payload['rebate_limit'] ?? 0);
$defaultRebate = (float) ($payload['default_player_rebate'] ?? 0);
$rebateLimit = (float) ($payload['rebate_limit'] ?? 0) / 100;
$defaultRebate = (float) ($payload['default_player_rebate'] ?? 0) / 100;
$useRelative = $parent !== null && array_key_exists('relative_share_rate', $payload);
@@ -124,8 +124,8 @@ final class AgentProfileService
'allocated_credit' => (int) $profile->allocated_credit,
'used_credit' => (int) $profile->used_credit,
'available_credit' => $available,
'rebate_limit' => (float) $profile->rebate_limit,
'default_player_rebate' => (float) $profile->default_player_rebate,
'rebate_limit' => round((float) $profile->rebate_limit * 100, 4),
'default_player_rebate' => round((float) $profile->default_player_rebate * 100, 4),
'settlement_cycle' => AgentSettlementCycle::normalize($profile->settlement_cycle),
'can_grant_extra_rebate' => (bool) $profile->can_grant_extra_rebate,
'can_create_child_agent' => (bool) $profile->can_create_child_agent,
@@ -157,7 +157,7 @@ final class AgentProfileService
return [
'agent_node_id' => (int) $parent->id,
'total_share_rate' => (float) $profile->total_share_rate,
'rebate_limit' => (float) $profile->rebate_limit,
'rebate_limit' => round((float) $profile->rebate_limit * 100, 4),
'available_credit' => max(0, (int) $profile->credit_limit - (int) $profile->allocated_credit),
];
}

View File

@@ -0,0 +1,441 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>彩票代理接入文档</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="min-h-screen bg-slate-950 text-slate-100 antialiased">
@php
$sections = [
[
'id' => 'overview',
'title' => '1. 文档概览',
'summary' => '说明接入目标、适用对象与总体范围。',
],
[
'id' => 'architecture',
'title' => '2. 接入架构',
'summary' => '描述主站、彩票端与钱包系统之间的数据流向。',
],
[
'id' => 'prerequisites',
'title' => '3. 对接前准备',
'summary' => '列出域名、密钥、接口地址和测试账号等准备项。',
],
[
'id' => 'sso',
'title' => '4. SSO 单点登录',
'summary' => '说明客户如何生成 token 并跳转进入彩票端。',
],
[
'id' => 'wallet',
'title' => '5. 钱包接口',
'summary' => '说明余额、扣款、加款三个接口的职责与约束。',
],
[
'id' => 'signature',
'title' => '6. 签名与安全',
'summary' => '说明签名算法、密钥保护与重放防护。',
],
[
'id' => 'errors',
'title' => '7. 错误码与幂等',
'summary' => '统一交易状态和重复请求处理方式。',
],
[
'id' => 'testing',
'title' => '8. 联调与验收',
'summary' => '提供联调流程、测试清单和上线前核对项。',
],
[
'id' => 'appendix',
'title' => '9. 附录',
'summary' => '给出标准报文示例和字段规范。',
],
];
@endphp
<div class="mx-auto flex max-w-7xl gap-8 px-4 py-8 sm:px-6 lg:px-8">
<aside class="sticky top-6 hidden h-[calc(100vh-3rem)] w-72 shrink-0 overflow-y-auto rounded-3xl border border-white/10 bg-slate-900/70 p-5 shadow-2xl backdrop-blur lg:block">
<div class="mb-6">
<p class="text-xs font-semibold uppercase tracking-[0.28em] text-cyan-300">Admin Docs</p>
<h1 class="mt-3 text-2xl font-semibold text-white">彩票代理接入文档</h1>
<p class="mt-3 text-sm leading-6 text-slate-400">面向客户技术团队的接入说明页,覆盖 SSO、钱包、联调和上线约束。</p>
</div>
<nav class="space-y-2 text-sm">
@foreach ($sections as $section)
<a
href="#{{ $section['id'] }}"
class="block rounded-2xl border border-transparent px-3 py-3 transition hover:border-cyan-400/30 hover:bg-cyan-400/10"
>
<div class="font-medium text-slate-100">{{ $section['title'] }}</div>
<div class="mt-1 text-xs leading-5 text-slate-400">{{ $section['summary'] }}</div>
</a>
@endforeach
</nav>
</aside>
<main class="min-w-0 flex-1">
<section class="overflow-hidden rounded-[2rem] border border-white/10 bg-linear-to-br from-slate-900 via-slate-900 to-cyan-950/70 shadow-2xl">
<div class="border-b border-white/10 px-6 py-8 sm:px-10 lg:px-12">
<div class="flex flex-col gap-6 lg:flex-row lg:items-end lg:justify-between">
<div class="max-w-3xl">
<p class="text-sm font-medium text-cyan-300">LOTTERY INTEGRATION GUIDE</p>
<h1 class="mt-3 text-3xl font-semibold tracking-tight text-white sm:text-4xl">彩票代理接入技术文档</h1>
<p class="mt-4 text-base leading-7 text-slate-300 sm:text-lg">
本页面用于给客户技术团队直接阅读和联调,按文档页方式展示接入说明,包含目录、数据流、接口约束、联调步骤和上线前检查项。
</p>
</div>
<div class="grid gap-3 rounded-3xl border border-cyan-400/20 bg-slate-950/40 p-4 text-sm text-slate-300 sm:grid-cols-3 lg:min-w-[360px]">
<div>
<div class="text-xs uppercase tracking-[0.2em] text-slate-500">接入方式</div>
<div class="mt-2 font-medium text-white">SSO + 钱包接口</div>
</div>
<div>
<div class="text-xs uppercase tracking-[0.2em] text-slate-500">适用对象</div>
<div class="mt-2 font-medium text-white">客户技术团队</div>
</div>
<div>
<div class="text-xs uppercase tracking-[0.2em] text-slate-500">文档形态</div>
<div class="mt-2 font-medium text-white">后台独立页面</div>
</div>
</div>
</div>
</div>
<div class="px-6 py-8 sm:px-10 lg:px-12 lg:hidden">
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-5">
<div class="text-sm font-semibold text-white">目录</div>
<div class="mt-4 grid gap-3">
@foreach ($sections as $section)
<a href="#{{ $section['id'] }}" class="rounded-2xl border border-white/10 px-4 py-3 text-sm text-slate-200 transition hover:border-cyan-400/40 hover:bg-cyan-400/10">
{{ $section['title'] }}
</a>
@endforeach
</div>
</div>
</div>
<div class="space-y-12 px-6 py-8 sm:px-10 lg:px-12 lg:py-12">
<section id="overview" class="scroll-mt-8 space-y-6 rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div>
<h2 class="text-2xl font-semibold text-white">1. 文档概览</h2>
<p class="mt-3 leading-7 text-slate-300">
本文档用于指导客户将自有主站接入我方彩票端,形成完整的登录、跳转、余额、投注扣款与派奖加款链路。
</p>
</div>
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
<div class="rounded-2xl border border-white/10 bg-white/5 p-4">
<div class="text-sm font-medium text-white">登录接入</div>
<div class="mt-2 text-sm leading-6 text-slate-400">客户主站登录后,通过 SSO 进入彩票端,无需再次认证。</div>
</div>
<div class="rounded-2xl border border-white/10 bg-white/5 p-4">
<div class="text-sm font-medium text-white">钱包接入</div>
<div class="mt-2 text-sm leading-6 text-slate-400">投注与派奖资金动作由我方调用客户钱包接口完成。</div>
</div>
<div class="rounded-2xl border border-white/10 bg-white/5 p-4">
<div class="text-sm font-medium text-white">联调验收</div>
<div class="mt-2 text-sm leading-6 text-slate-400">客户、我方技术与测试按照同一套流程完成联调和上线验收。</div>
</div>
<div class="rounded-2xl border border-white/10 bg-white/5 p-4">
<div class="text-sm font-medium text-white">适用范围</div>
<div class="mt-2 text-sm leading-6 text-slate-400">适用于 H5、Web、App 内嵌 WebView 等进入彩票端的接入方式。</div>
</div>
</div>
</section>
<section id="architecture" class="scroll-mt-8 space-y-6">
<div>
<h2 class="text-2xl font-semibold text-white">2. 接入架构</h2>
<p class="mt-3 leading-7 text-slate-300">客户系统与彩票端的职责边界如下,登录由主站发起,资金由主站钱包记账,彩票端负责业务过程编排。</p>
</div>
<div class="grid gap-4 xl:grid-cols-4">
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-5">
<div class="text-sm font-semibold text-cyan-300">01 客户主站</div>
<div class="mt-3 text-base font-medium text-white">用户登录与身份来源</div>
<div class="mt-2 text-sm leading-6 text-slate-400">客户负责维护会员账号、登录态和唯一用户标识。</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-5">
<div class="text-sm font-semibold text-cyan-300">02 SSO 网关</div>
<div class="mt-3 text-base font-medium text-white">生成短期 token</div>
<div class="mt-2 text-sm leading-6 text-slate-400">客户服务端生成签名凭证,浏览器携带后进入彩票端。</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-5">
<div class="text-sm font-semibold text-cyan-300">03 彩票端</div>
<div class="mt-3 text-base font-medium text-white">验签并建立会话</div>
<div class="mt-2 text-sm leading-6 text-slate-400">我方校验 token 后创建会话,承接投注、撤单、派奖等业务流程。</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-5">
<div class="text-sm font-semibold text-cyan-300">04 客户钱包</div>
<div class="mt-3 text-base font-medium text-white">余额与账务真理源</div>
<div class="mt-2 text-sm leading-6 text-slate-400">余额查询、扣款、加款由客户钱包接口统一响应并负责幂等记账。</div>
</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/60 p-6">
<div class="text-sm font-semibold text-white">端到端链路</div>
<ol class="mt-4 space-y-3 text-sm leading-6 text-slate-300">
<li>1. 用户在客户主站完成登录。</li>
<li>2. 客户服务端生成 SSO token。</li>
<li>3. 浏览器跳转到彩票端入口地址。</li>
<li>4. 彩票端校验 token 并建立用户会话。</li>
<li>5. 用户查询余额、进行投注或等待派奖。</li>
<li>6. 彩票端按业务场景调用客户钱包接口。</li>
<li>7. 钱包返回处理结果,彩票端落业务状态并反馈前端。</li>
</ol>
</div>
</section>
<section id="prerequisites" class="scroll-mt-8 space-y-6">
<div>
<h2 class="text-2xl font-semibold text-white">3. 对接前准备</h2>
<p class="mt-3 leading-7 text-slate-300">双方开始联调前,需要先完成以下准备项,避免联调阶段反复返工。</p>
</div>
<div class="grid gap-4 lg:grid-cols-2">
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">客户需提供</div>
<ul class="mt-4 space-y-3 text-sm leading-6 text-slate-300">
<li> 站点名称、站点编码、测试环境与生产环境标识。</li>
<li> 技术联系人、测试联系人、上线当天紧急联系人。</li>
<li> 客户主站域名、钱包接口域名、可嵌入来源域名。</li>
<li> 测试账号、测试余额和可重复联调的测试场景说明。</li>
</ul>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">双方需共同确认</div>
<ul class="mt-4 space-y-3 text-sm leading-6 text-slate-300">
<li> SSO 密钥或 JWT 验签密钥。</li>
<li> 钱包 API 鉴权方式、签名算法、请求头规范。</li>
<li> 钱包三类接口地址:余额、扣款、加款。</li>
<li> 请求超时、重试策略、幂等键和错误码表。</li>
</ul>
</div>
</div>
</section>
<section id="sso" class="scroll-mt-8 space-y-6">
<div>
<h2 class="text-2xl font-semibold text-white">4. SSO 单点登录</h2>
<p class="mt-3 leading-7 text-slate-300">客户用户在主站登录后,通过服务端签发的短期 token 进入彩票端,我方校验通过后自动建立会话。</p>
</div>
<div class="grid gap-4 lg:grid-cols-[1.1fr_0.9fr]">
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">推荐接入流程</div>
<ol class="mt-4 space-y-3 text-sm leading-6 text-slate-300">
<li>1. 客户主站用户完成登录。</li>
<li>2. 客户服务端按约定字段组装 SSO 负载。</li>
<li>3. 使用共享密钥签发 token并设置短期过期时间。</li>
<li>4. 浏览器跳转我方彩票端地址,携带 token 参数。</li>
<li>5. 我方校验签名、时间戳、站点编码和用户标识后建立彩票端登录态。</li>
</ol>
</div>
<div class="rounded-3xl border border-cyan-400/20 bg-cyan-400/10 p-6">
<div class="text-base font-medium text-white">SSO 关键约束</div>
<ul class="mt-4 space-y-3 text-sm leading-6 text-slate-200">
<li> token 必须是短时有效,建议 60 300 秒。</li>
<li> `user_id` 在客户站点内必须稳定且唯一。</li>
<li> `site_code` 必须与约定站点保持一致。</li>
<li> 生产密钥与测试密钥必须隔离。</li>
<li> 不可把签名密钥暴露在前端代码里。</li>
</ul>
</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/60 p-6">
<div class="text-base font-medium text-white">SSO 负载示例</div>
<div class="mt-4 overflow-x-auto rounded-2xl border border-white/10 bg-slate-950 p-4 text-sm text-slate-200">
<pre class="whitespace-pre-wrap break-words">{
"user_id": "100001",
"username": "demo_user",
"site_code": "demo",
"timestamp": 1718000000,
"nonce": "N8F2X9Q1",
"currency": "CNY",
"device": "h5"
}</pre>
</div>
</div>
</section>
<section id="wallet" class="scroll-mt-8 space-y-6">
<div>
<h2 class="text-2xl font-semibold text-white">5. 钱包接口</h2>
<p class="mt-3 leading-7 text-slate-300">我方会调用客户钱包完成账务动作。客户至少需要实现余额查询、扣款、加款三类能力。</p>
</div>
<div class="grid gap-4 xl:grid-cols-3">
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">余额查询</div>
<div class="mt-2 text-sm leading-6 text-slate-400">用于进入彩票端、下注前或关键账务时机同步可用余额。</div>
<div class="mt-4 rounded-2xl border border-white/10 bg-slate-950 p-4 text-xs text-slate-300">POST /wallet/balance</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">扣款接口</div>
<div class="mt-2 text-sm leading-6 text-slate-400">用于用户下注成功后的资金扣减,必须以交易号作为唯一幂等键。</div>
<div class="mt-4 rounded-2xl border border-white/10 bg-slate-950 p-4 text-xs text-slate-300">POST /wallet/debit</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">加款接口</div>
<div class="mt-2 text-sm leading-6 text-slate-400">用于派奖、退款或撤单返还资金,重复请求不得重复记账。</div>
<div class="mt-4 rounded-2xl border border-white/10 bg-slate-950 p-4 text-xs text-slate-300">POST /wallet/credit</div>
</div>
</div>
<div class="grid gap-4 lg:grid-cols-2">
<div class="rounded-3xl border border-white/10 bg-slate-950/60 p-6">
<div class="text-base font-medium text-white">扣款报文示例</div>
<div class="mt-4 overflow-x-auto rounded-2xl border border-white/10 bg-slate-950 p-4 text-sm text-slate-200">
<pre class="whitespace-pre-wrap break-words">{
"site_code": "demo",
"user_id": "100001",
"transaction_id": "BET202606100001",
"order_id": "TICKET202606100001",
"amount": "20.00",
"timestamp": 1718000001,
"sign": "xxxxxx"
}</pre>
</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/60 p-6">
<div class="text-base font-medium text-white">成功返回示例</div>
<div class="mt-4 overflow-x-auto rounded-2xl border border-white/10 bg-slate-950 p-4 text-sm text-slate-200">
<pre class="whitespace-pre-wrap break-words">{
"code": 0,
"message": "success",
"data": {
"transaction_id": "BET202606100001",
"balance": "980.00"
}
}</pre>
</div>
</div>
</div>
</section>
<section id="signature" class="scroll-mt-8 space-y-6">
<div>
<h2 class="text-2xl font-semibold text-white">6. 签名与安全</h2>
<p class="mt-3 leading-7 text-slate-300">签名规则和密钥保护是接入稳定性的基础。推荐统一采用服务端签名并在所有敏感请求中校验。</p>
</div>
<div class="grid gap-4 lg:grid-cols-2">
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">推荐签名规则</div>
<ol class="mt-4 space-y-3 text-sm leading-6 text-slate-300">
<li>1. 请求字段按字段名升序排序。</li>
<li>2. `key=value` 形式拼接原始串。</li>
<li>3. 原始串尾部追加共享密钥。</li>
<li>4. 使用 `HMAC-SHA256` 计算签名。</li>
<li>5. 结果输出为十六进制小写字符串。</li>
</ol>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">安全要求</div>
<ul class="mt-4 space-y-3 text-sm leading-6 text-slate-300">
<li> 所有请求必须使用 HTTPS。</li>
<li> token 和钱包请求必须校验时间戳与签名。</li>
<li> 建议增加 nonce request_id 防止重放。</li>
<li> 测试环境与生产环境密钥不得共用。</li>
<li> 密钥轮换时必须预留并行切换窗口。</li>
</ul>
</div>
</div>
</section>
<section id="errors" class="scroll-mt-8 space-y-6">
<div>
<h2 class="text-2xl font-semibold text-white">7. 错误码与幂等</h2>
<p class="mt-3 leading-7 text-slate-300">为了保证交易可重试、可审计,客户钱包接口必须统一错误码并支持强幂等。</p>
</div>
<div class="grid gap-4 lg:grid-cols-[0.95fr_1.05fr]">
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">建议错误码</div>
<ul class="mt-4 space-y-3 text-sm leading-6 text-slate-300">
<li> `0`:成功</li>
<li> `1001`:参数错误</li>
<li> `1002`:签名错误</li>
<li> `1003`:用户不存在</li>
<li> `1004`:余额不足</li>
<li> `1006`:重复交易</li>
<li> `1099`:系统异常</li>
</ul>
</div>
<div class="rounded-3xl border border-cyan-400/20 bg-cyan-400/10 p-6">
<div class="text-base font-medium text-white">幂等处理要求</div>
<ul class="mt-4 space-y-3 text-sm leading-6 text-slate-200">
<li> 扣款和加款必须使用 `transaction_id` 作为唯一交易键。</li>
<li> 同一 `transaction_id` 的重复请求,不得重复扣款或重复加款。</li>
<li> 已成功处理的交易,重复请求必须返回首次处理结果。</li>
<li> 钱包超时或网络抖动时,我方可能发起重试,因此客户必须按幂等方式落账。</li>
</ul>
</div>
</div>
</section>
<section id="testing" class="scroll-mt-8 space-y-6">
<div>
<h2 class="text-2xl font-semibold text-white">8. 联调与验收</h2>
<p class="mt-3 leading-7 text-slate-300">建议双方按固定节奏联调,先通登录链路,再通钱包链路,最后做异常回归和上线核验。</p>
</div>
<div class="grid gap-4 lg:grid-cols-2">
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">联调顺序</div>
<ol class="mt-4 space-y-3 text-sm leading-6 text-slate-300">
<li>1. 域名连通与证书校验。</li>
<li>2. SSO token 生成与跳转验证。</li>
<li>3. 余额查询接口联调。</li>
<li>4. 扣款和加款接口联调。</li>
<li>5. 超时、重复请求和余额不足场景回归。</li>
</ol>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">上线前检查清单</div>
<ul class="mt-4 space-y-3 text-sm leading-6 text-slate-300">
<li> 正式域名、正式密钥和正式白名单均已配置。</li>
<li> 测试环境和生产环境参数已分离。</li>
<li> 核心错误码、日志和告警已对齐。</li>
<li> 关键交易链路已通过验收回归。</li>
<li> 上线当天应急联系人与回滚预案已确认。</li>
</ul>
</div>
</div>
</section>
<section id="appendix" class="scroll-mt-8 space-y-6">
<div>
<h2 class="text-2xl font-semibold text-white">9. 附录</h2>
<p class="mt-3 leading-7 text-slate-300">为了减少不同系统之间的解析差异,建议双方统一基础字段格式。</p>
</div>
<div class="grid gap-4 lg:grid-cols-3">
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">金额字段</div>
<div class="mt-3 text-sm leading-6 text-slate-400">统一使用字符串传输,例如 `1000.00`,避免浮点精度误差。</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">时间字段</div>
<div class="mt-3 text-sm leading-6 text-slate-400">建议使用 Unix 时间戳秒级,双方也可统一为 ISO8601。</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<div class="text-base font-medium text-white">报文格式</div>
<div class="mt-3 text-sm leading-6 text-slate-400">字符编码统一 UTF-8,请求内容类型统一 `application/json`</div>
</div>
</div>
</section>
</div>
</section>
</main>
</div>
</body>
</html>

View File

@@ -5,3 +5,8 @@ use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
Route::prefix('admin/docs')->group(function (): void {
Route::view('integration-guide', 'admin.integration-guide')
->name('admin.docs.integration-guide');
});

View File

@@ -42,8 +42,8 @@ test('super admin can update agent profile with capability flags', function ():
->putJson('/api/v1/admin/agent-nodes/'.$child->id.'/profile', [
'total_share_rate' => 12,
'credit_limit' => 1200,
'rebate_limit' => 0.01,
'default_player_rebate' => 0.005,
'rebate_limit' => 1,
'default_player_rebate' => 0.5,
'settlement_cycle' => 'weekly',
'can_grant_extra_rebate' => false,
'can_create_child_agent' => true,
@@ -224,8 +224,8 @@ test('agent profile update rejects default rebate above limit', function (): voi
$this->withHeader('Authorization', 'Bearer '.$token)
->putJson('/api/v1/admin/agent-nodes/'.$child->id.'/profile', [
'rebate_limit' => 0.005,
'default_player_rebate' => 0.01,
'rebate_limit' => 0.5,
'default_player_rebate' => 1,
])
->assertStatus(422)
->assertJsonPath('code', ErrorCode::ValidationFailed->value);