mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-04 07:06:36 +08:00
压缩历史至 95081aff
This commit is contained in:
@@ -0,0 +1,589 @@
|
||||
import { type PolicySection } from "./types"
|
||||
import { CodeBlock } from "@/components/ui/code-block"
|
||||
import {
|
||||
DocsTable,
|
||||
DocsTableHeader,
|
||||
DocsTableBody,
|
||||
DocsTableHead,
|
||||
DocsTableRow,
|
||||
DocsTableCell,
|
||||
} from "@/components/ui/docs-table"
|
||||
|
||||
export const DOCS_LAST_UPDATED = "2026-04-20"
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------
|
||||
* API 文档
|
||||
* ------------------------------------------------------------------
|
||||
*/
|
||||
export const apiSections: PolicySection[] = [
|
||||
{
|
||||
value: "official-service",
|
||||
title: "1. 官方 LDC 接口",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<div className="bg-muted/50 border border-border/50 rounded-lg px-3 py-2 mb-6">
|
||||
<p className="text-muted-foreground m-0">官方原生接口,使用 Ed25519 签名算法,安全性更高</p>
|
||||
</div>
|
||||
|
||||
<h3 id="1-1-overview" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">1.1 概览</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li><strong>协议:</strong>官方 LDC 支付协议</li>
|
||||
<li><strong>服务类型:</strong>支持 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">type=ldcpay</code></li>
|
||||
<li><strong>网关基址:</strong><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">https://credit.linux.do/epay</code></li>
|
||||
<li><strong>签名方式:</strong>Ed25519 非对称加密</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="1-2-flow" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">1.2 对接流程</h3>
|
||||
<ol className="list-decimal pl-4 md:pl-5 space-y-2">
|
||||
<li>控制台创建应用,配置 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">client_id</code> 并在应用设置中上传商户 Ed25519 公钥</li>
|
||||
<li>根据“签名算法”及商户私钥生成 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">sign</code></li>
|
||||
<li>调用 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">/pay/submit</code> 发起积分流转请求</li>
|
||||
<li>认证完成后,通过异步回调或轮询接口同步状态</li>
|
||||
</ol>
|
||||
|
||||
<h3 id="1-3-auth-sign" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">1.3 鉴权与签名</h3>
|
||||
<h4 className="font-medium text-foreground mt-3 md:mt-4 mb-2">1.3.1 签名算法</h4>
|
||||
<div className="space-y-4">
|
||||
<ol className="list-decimal pl-4 md:pl-5 space-y-2">
|
||||
<li>取除 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">sign</code> 以外的所有非空请求参数</li>
|
||||
<li>将参数按参数名 ASCII 码从到大排序(字典序)</li>
|
||||
<li>使用 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">k1=v1&k2=v2...</code> 格式拼接成字符串</li>
|
||||
<li>将 <strong>应用密钥 (Client Secret)</strong> 直接追加到字符串末尾</li>
|
||||
<li>使用商户私钥对最终字符串进行 <strong>Ed25519</strong> 签名</li>
|
||||
<li>将签名结果转换成 Base64 编码作为 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">sign</code> 参数</li>
|
||||
</ol>
|
||||
<CodeBlock
|
||||
code={`// 示例:client_id=1&money=10.00&order_name=Test&out_trade_no=M1&type=ldcpay{SECRET}
|
||||
data = "client_id=1&money=10.00&order_name=Test&out_trade_no=M1&type=ldcpay" + client_secret
|
||||
signature = ed25519.Sign(privateKey, []byte(data))
|
||||
signBase64 = base64.StdEncoding.EncodeToString(signature)`}
|
||||
language="javascript"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h3 id="1-4-submit" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">1.4 积分流转服务</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2 mb-6">
|
||||
<li><strong>方法:</strong>POST <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">/epay/pay/submit.php</code></li>
|
||||
<li><strong>编码:</strong><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">application/json</code> 或 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">application/x-www-form-urlencoded</code></li>
|
||||
</ul>
|
||||
|
||||
<DocsTable>
|
||||
<DocsTableHeader>
|
||||
<DocsTableRow>
|
||||
<DocsTableHead className="w-[100px] whitespace-nowrap">参数</DocsTableHead>
|
||||
<DocsTableHead className="w-[80px] whitespace-nowrap">必填</DocsTableHead>
|
||||
<DocsTableHead>说明</DocsTableHead>
|
||||
</DocsTableRow>
|
||||
</DocsTableHeader>
|
||||
<DocsTableBody>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">client_id</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>应用客户端 ID</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">type</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>固定 <code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">ldcpay</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">out_trade_no</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>业务单号</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">money</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>积分数量,必须保留两位小数(比如,10.00)</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">order_name</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>商品名称</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">notify_url</DocsTableCell>
|
||||
<DocsTableCell>否</DocsTableCell>
|
||||
<DocsTableCell>会参与签名;可选订单级异步通知地址。长度不超过 100,需为合法 URL。传入后支付成功优先回调该地址,未传则使用应用 notify_url</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">return_url</DocsTableCell>
|
||||
<DocsTableCell>否</DocsTableCell>
|
||||
<DocsTableCell>会参与签名;可选订单级回跳地址。长度不超过 100,需为合法 URL。传入后支付成功页面优先跳转该地址,未传则使用应用 redirect_uri</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">sign</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>按“签名算法”生成的 Base64 签名串</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
</DocsTableBody>
|
||||
</DocsTable>
|
||||
|
||||
<h3 id="1-5-others" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">1.5 其他接口</h3>
|
||||
<p className="text-muted-foreground mb-4">其他接口定义请参考 <a href="#3-common-services" className="text-primary underline underline-offset-4">3. 其他接口</a>。</p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li><strong>订单查询:</strong>详见 <a href="#3-1-order" className="text-primary underline underline-offset-4">3.1 订单查询</a></li>
|
||||
<li><strong>订单退款:</strong>详见 <a href="#3-2-refund" className="text-primary underline underline-offset-4">3.2 订单退款</a></li>
|
||||
<li><strong>异步通知:</strong>详见 <a href="#3-3-notify" className="text-primary underline underline-offset-4">3.3 异步通知</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
),
|
||||
children: [
|
||||
{ value: "1-1-overview", title: "1.1 概览" },
|
||||
{ value: "1-2-flow", title: "1.2 对接流程" },
|
||||
{ value: "1-3-auth-sign", title: "1.3 鉴权与签名" },
|
||||
{ value: "1-4-submit", title: "1.4 积分流转服务" },
|
||||
{ value: "1-5-others", title: "1.5 其他接口" },
|
||||
]
|
||||
},
|
||||
{
|
||||
value: "epay-compatibility",
|
||||
title: "2. 易支付兼容接口",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<div className="bg-muted/50 border border-border/50 rounded-lg px-3 py-2 mb-6">
|
||||
<p className="text-muted-foreground m-0">兼容易支付、CodePay、VPay 等支付协议</p>
|
||||
</div>
|
||||
|
||||
<h3 id="2-1-overview" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">2.1 概览</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li><strong>协议:</strong>EasyPay / CodePay / VPay 兼容协议</li>
|
||||
<li><strong>服务类型:</strong>仅支持 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">type=epay</code></li>
|
||||
<li><strong>网关基址:</strong><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">https://credit.linux.do/epay</code></li>
|
||||
<li><strong>订单有效期:</strong>取系统配置 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">merchant_order_expire_minutes</code>(平台端设置)</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="2-2-common-errors" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">2.2 常见错误</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">不支持的请求类型</code>:<code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">type</code> 仅允许 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">epay</code></li>
|
||||
<li><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">签名验证失败</code>:参与签名字段与请求体需一致,密钥直接拼接</li>
|
||||
<li><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">金额必须大于0</code> / <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">积分小数位数不能超过2位</code></li>
|
||||
<li><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">订单已过期</code>:超出系统配置有效期</li>
|
||||
<li><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">订单不存在或已完成</code>:订单号错误、已退回或已完成</li>
|
||||
<li><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">余额不足</code>:余额退回时用户积分不足</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="2-3-flow" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">2.3 对接流程</h3>
|
||||
<ol className="list-decimal pl-4 md:pl-5 space-y-2">
|
||||
<li>控制台创建 API Key,记录 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">pid</code>、<code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">key</code>,配置回调地址</li>
|
||||
<li>按“签名算法”生成 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">sign</code>,调用 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">/epay/pay/submit.php</code> 创建积分流转服务并跳转认证界面</li>
|
||||
<li>可通过 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">/epay/api.php</code> 轮询结果,或等待异步回调</li>
|
||||
<li>退回服务时,携带同一 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">trade_no</code> 和原积分数量,调用积分退回接口</li>
|
||||
<li>回调验签通过后返回 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">success</code> 完成闭环</li>
|
||||
</ol>
|
||||
|
||||
<h3 id="2-4-auth-sign" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">2.4 鉴权与签名</h3>
|
||||
<h4 className="font-medium text-foreground mt-3 md:mt-4 mb-2">2.4.1 API Key</h4>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2 mb-4">
|
||||
<li><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">pid</code>:Client ID</li>
|
||||
<li><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">key</code>:Client Secret(妥善保管)</li>
|
||||
<li><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">notify_url</code> / <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">return_url</code>:应用级默认回调地址(兜底);创建订单时可在请求中传同名字段作为订单级覆盖,未传时回退应用配置。</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="font-medium text-foreground mt-3 md:mt-4 mb-2">2.4.2 签名算法</h4>
|
||||
<div className="space-y-4">
|
||||
<ol className="list-decimal pl-4 md:pl-5 space-y-2">
|
||||
<li>取所有非空字段(排除 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">sign</code>、<code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">sign_type</code> 字段)</li>
|
||||
<li>将上述字段按 ASCII 升序,依次拼成 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">k1=v1&k2=v2</code></li>
|
||||
<li>在末尾追加应用密钥:<code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">k1=v1&k2=v2{"{secret}"}</code></li>
|
||||
<li>整体进行 MD5,取小写十六进制作为 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">sign</code></li>
|
||||
</ol>
|
||||
<CodeBlock
|
||||
code={`payload="money=10&name=Test&out_trade_no=M20250101&pid=001&type=epay"
|
||||
sign=$(echo -n "\${payload}\${SECRET}" | md5) # 输出小写`}
|
||||
language="bash"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h3 id="2-5-submit" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">2.5 积分流转服务</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2 mb-6">
|
||||
<li><strong>方法:</strong>POST <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">/epay/pay/submit.php</code></li>
|
||||
<li><strong>编码:</strong><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">application/json</code> 或 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">application/x-www-form-urlencoded</code></li>
|
||||
<li><strong>成功:</strong>验签通过后,平台自动创建积分流转服务,并跳转到认证界面(Location=<code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">https://credit.linux.do/paying?order_no=...</code>)</li>
|
||||
<li><strong>失败:</strong>返回 JSON <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">{`{"error_msg":"...", "data":null}`}</code></li>
|
||||
</ul>
|
||||
|
||||
<DocsTable>
|
||||
<DocsTableHeader>
|
||||
<DocsTableRow>
|
||||
<DocsTableHead className="w-[100px] whitespace-nowrap">参数</DocsTableHead>
|
||||
<DocsTableHead className="w-[80px] whitespace-nowrap">必填</DocsTableHead>
|
||||
<DocsTableHead>说明</DocsTableHead>
|
||||
</DocsTableRow>
|
||||
</DocsTableHeader>
|
||||
<DocsTableBody>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">pid</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>Client ID</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">type</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>固定 <code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">epay</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">out_trade_no</DocsTableCell>
|
||||
<DocsTableCell>否</DocsTableCell>
|
||||
<DocsTableCell>业务单号,建议全局唯一</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">name</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>标题,最多 64 字符</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">money</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>积分数量,最多 2 位小数</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">notify_url</DocsTableCell>
|
||||
<DocsTableCell>否</DocsTableCell>
|
||||
<DocsTableCell>会参与签名;可选订单级异步通知地址。长度不超过 100,需为合法 URL。传入后支付成功优先回调该地址,未传则使用应用 notify_url</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">return_url</DocsTableCell>
|
||||
<DocsTableCell>否</DocsTableCell>
|
||||
<DocsTableCell>会参与签名;可选订单级回跳地址。长度不超过 100,需为合法 URL。传入后支付成功页面优先跳转该地址,未传则使用应用 redirect_uri</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">device</DocsTableCell>
|
||||
<DocsTableCell>否</DocsTableCell>
|
||||
<DocsTableCell>终端标识,可选</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">sign</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>按“签名算法”生成</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">sign_type</DocsTableCell>
|
||||
<DocsTableCell>否</DocsTableCell>
|
||||
<DocsTableCell>固定 <code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">MD5</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
</DocsTableBody>
|
||||
</DocsTable>
|
||||
|
||||
<p className="text-muted-foreground mb-2">请求示例:</p>
|
||||
<CodeBlock
|
||||
code={`curl -X POST https://credit.linux.do/epay/pay/submit.php \\
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \\
|
||||
-d "pid=001" \\
|
||||
-d "type=epay" \\
|
||||
-d "out_trade_no=M20250101" \\
|
||||
-d "name=Test" \\
|
||||
-d "money=10" \\
|
||||
-d "sign=\${SIGN}" \\
|
||||
-d "sign_type=MD5"`}
|
||||
language="bash"
|
||||
/>
|
||||
|
||||
<h3 id="2-6-others" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">2.6 其他接口</h3>
|
||||
<p className="text-muted-foreground mb-4">其他接口定义请参考 <a href="#3-common-services" className="text-primary underline underline-offset-4">3. 其他接口</a>。</p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li><strong>订单查询:</strong>详见 <a href="#3-1-order" className="text-primary underline underline-offset-4">3.1 订单查询</a></li>
|
||||
<li><strong>订单退款:</strong>详见 <a href="#3-2-refund" className="text-primary underline underline-offset-4">3.2 订单退款</a></li>
|
||||
<li><strong>异步通知:</strong>详见 <a href="#3-3-notify" className="text-primary underline underline-offset-4">3.3 异步通知</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
),
|
||||
children: [
|
||||
{ value: "2-1-overview", title: "2.1 概览" },
|
||||
{ value: "2-2-common-errors", title: "2.2 常见错误" },
|
||||
{ value: "2-3-flow", title: "2.3 对接流程" },
|
||||
{ value: "2-4-auth-sign", title: "2.4 鉴权与签名" },
|
||||
{ value: "2-5-submit", title: "2.5 积分流转服务" },
|
||||
{ value: "2-6-others", title: "2.6 其他接口" },
|
||||
]
|
||||
},
|
||||
{
|
||||
value: "common-services",
|
||||
title: "3. 其他接口",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<div className="bg-muted/50 border border-border/50 rounded-lg px-3 py-2 mb-6">
|
||||
<p className="text-muted-foreground m-0">官方接口与易支付兼容接口公用接口。</p>
|
||||
</div>
|
||||
|
||||
<h3 id="3-1-order" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">3.1 订单查询</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2 mb-6">
|
||||
<li><strong>方法:</strong>GET <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">/epay/api.php</code></li>
|
||||
<li><strong>认证:</strong><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">pid</code> + <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">key</code></li>
|
||||
<li><strong>说明:</strong><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">out_trade_no</code> 必填;<code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">act</code> 可传 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">order</code>,后端不强校验。</li>
|
||||
</ul>
|
||||
|
||||
<DocsTable>
|
||||
<DocsTableHeader>
|
||||
<DocsTableRow>
|
||||
<DocsTableHead className="w-[100px] whitespace-nowrap">参数</DocsTableHead>
|
||||
<DocsTableHead className="w-[80px] whitespace-nowrap">必填</DocsTableHead>
|
||||
<DocsTableHead>说明</DocsTableHead>
|
||||
</DocsTableRow>
|
||||
</DocsTableHeader>
|
||||
<DocsTableBody>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">act</DocsTableCell>
|
||||
<DocsTableCell>否</DocsTableCell>
|
||||
<DocsTableCell>可选字段,建议 <code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">order</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">pid</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>Client ID</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">key</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>Client Secret</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">out_trade_no</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>业务单号</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
</DocsTableBody>
|
||||
</DocsTable>
|
||||
|
||||
<p className="text-muted-foreground mb-2">成功响应:</p>
|
||||
<CodeBlock
|
||||
code={`{
|
||||
"code": 1,
|
||||
"msg": "查询订单号成功!",
|
||||
"trade_no": "M20250101",
|
||||
"out_trade_no": "M20250101",
|
||||
"type": "epay",
|
||||
"pid": "001",
|
||||
"addtime": "2025-01-01 12:00:00",
|
||||
"endtime": "2025-01-01 12:01:30",
|
||||
"name": "Test",
|
||||
"money": "10",
|
||||
"status": 1
|
||||
}`}
|
||||
language="json"
|
||||
/>
|
||||
<p className="text-muted-foreground text-xs"><strong className="text-foreground">补充:</strong><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">status</code> 1=成功,0=失败/处理中;不存在会返回 HTTP 404 且 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">{`{"code":-1,"msg":"服务不存在或已完成"}`}</code>。</p>
|
||||
|
||||
<h3 id="3-2-refund" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">3.2 订单退款</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2 mb-6">
|
||||
<li><strong>方法:</strong>POST <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">/epay/api.php</code></li>
|
||||
<li><strong>编码:</strong><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">application/json</code> 或 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">application/x-www-form-urlencoded</code></li>
|
||||
<li><strong>限制:</strong>仅支持对已成功的积分流转服务进行积分的全额退回</li>
|
||||
</ul>
|
||||
|
||||
<div>
|
||||
<DocsTable>
|
||||
<DocsTableHeader>
|
||||
<DocsTableRow>
|
||||
<DocsTableHead className="w-[100px] whitespace-nowrap">参数</DocsTableHead>
|
||||
<DocsTableHead className="w-[80px] whitespace-nowrap">必填</DocsTableHead>
|
||||
<DocsTableHead>说明</DocsTableHead>
|
||||
</DocsTableRow>
|
||||
</DocsTableHeader>
|
||||
<DocsTableBody>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">pid</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>Client ID</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">key</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>Client Secret</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">trade_no</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>编号</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">money</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>必须等于原积分流转服务的积分数量</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">out_trade_no</DocsTableCell>
|
||||
<DocsTableCell>否</DocsTableCell>
|
||||
<DocsTableCell>业务单号(兼容)</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
</DocsTableBody>
|
||||
</DocsTable>
|
||||
</div>
|
||||
|
||||
<p className="text-muted-foreground mb-2">响应:</p>
|
||||
<CodeBlock code={`{ "code": 1, "msg": "退款成功" }`} language="json" />
|
||||
<p className="text-muted-foreground text-xs"><strong className="text-foreground">常见失败:</strong>服务不存在/未认证、金额不合法(<=0 或小数超过 2 位)。</p>
|
||||
|
||||
|
||||
<h3 id="3-3-notify" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">3.3 异步通知</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2 mb-6">
|
||||
<li><strong>触发:</strong>认证成功后;失败自动重试,最多 5 次(单次 30s 超时)</li>
|
||||
<li><strong>目标:</strong>订单级 notify_url(如有)优先,否则回退到创建应用时设置的 notify_url</li>
|
||||
<li><strong>方式:</strong>HTTP GET</li>
|
||||
</ul>
|
||||
|
||||
<div>
|
||||
<DocsTable>
|
||||
<DocsTableHeader>
|
||||
<DocsTableRow>
|
||||
<DocsTableHead className="w-[100px] whitespace-nowrap">参数</DocsTableHead>
|
||||
<DocsTableHead>说明</DocsTableHead>
|
||||
</DocsTableRow>
|
||||
</DocsTableHeader>
|
||||
<DocsTableBody>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">pid</DocsTableCell>
|
||||
<DocsTableCell>Client ID</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">trade_no</DocsTableCell>
|
||||
<DocsTableCell>编号</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">out_trade_no</DocsTableCell>
|
||||
<DocsTableCell>业务单号</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">type</DocsTableCell>
|
||||
<DocsTableCell>固定 <code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">epay</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">name</DocsTableCell>
|
||||
<DocsTableCell>标题</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">money</DocsTableCell>
|
||||
<DocsTableCell>积分数量,最多 2 位小数</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">trade_status</DocsTableCell>
|
||||
<DocsTableCell>固定 <code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">TRADE_SUCCESS</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">sign</DocsTableCell>
|
||||
<DocsTableCell>按“签名算法”生成</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
</DocsTableBody>
|
||||
</DocsTable>
|
||||
</div>
|
||||
<p className="text-muted-foreground text-xs">应用需返回 HTTP 200 且响应体为 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">success</code>(大小写不敏感),否则视为失败并继续重试。</p>
|
||||
|
||||
<h3 id="3-4-distribute" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">3.4 商户分发接口</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2 mb-6">
|
||||
<li><strong>方法:</strong>POST <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">/lpay/distribute</code></li>
|
||||
<li><strong>编码:</strong><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">application/json</code></li>
|
||||
<li><strong>认证:</strong>Basic Auth (使用 <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">client_id:client_secret</code> 进行 Base64 编码)</li>
|
||||
</ul>
|
||||
|
||||
<DocsTable>
|
||||
<DocsTableHeader>
|
||||
<DocsTableRow>
|
||||
<DocsTableHead className="w-[100px] whitespace-nowrap">参数</DocsTableHead>
|
||||
<DocsTableHead className="w-[80px] whitespace-nowrap">必填</DocsTableHead>
|
||||
<DocsTableHead>说明</DocsTableHead>
|
||||
</DocsTableRow>
|
||||
</DocsTableHeader>
|
||||
<DocsTableBody>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">user_id</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>收款人用户 ID (数字)</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">username</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>收款人用户名 (用于二次校验)</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">amount</DocsTableCell>
|
||||
<DocsTableCell>是</DocsTableCell>
|
||||
<DocsTableCell>分发积分数量,最多 2 位小数</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">out_trade_no</DocsTableCell>
|
||||
<DocsTableCell>否</DocsTableCell>
|
||||
<DocsTableCell>商户自定义单号</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">remark</DocsTableCell>
|
||||
<DocsTableCell>否</DocsTableCell>
|
||||
<DocsTableCell>分发备注</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
</DocsTableBody>
|
||||
</DocsTable>
|
||||
<p className="text-muted-foreground text-xs"><strong className="text-foreground">成功响应:</strong><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">{`{"code":1, "data":{"trade_no":"...", "out_trade_no":"..."}}`}</code></p>
|
||||
|
||||
<h3 id="3-5-user-balance" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">3.5 用户余额统计</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2 mb-6">
|
||||
<li><strong>方法:</strong>GET <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">/api/v1/dashboard/stats/user-balance</code></li>
|
||||
<li><strong>认证:</strong>无需鉴权(公开接口)</li>
|
||||
<li><strong>说明:</strong>获取平台所有用户可用余额的统计数据,结果有缓存,TTL 由系统配置决定</li>
|
||||
</ul>
|
||||
|
||||
<p className="text-muted-foreground mb-2">成功响应:</p>
|
||||
<CodeBlock
|
||||
code={`{
|
||||
"error_msg": "",
|
||||
"data": {
|
||||
"total_count": 1234,
|
||||
"total_amount": "98765.00",
|
||||
"avg_amount": "80.03",
|
||||
"median_amount": "50.00",
|
||||
"min_amount": "0.00",
|
||||
"max_amount": "9999.00",
|
||||
"std_dev": "123.45"
|
||||
}
|
||||
}`}
|
||||
language="json"
|
||||
/>
|
||||
|
||||
<DocsTable>
|
||||
<DocsTableHeader>
|
||||
<DocsTableRow>
|
||||
<DocsTableHead className="w-[120px] whitespace-nowrap">字段</DocsTableHead>
|
||||
<DocsTableHead>说明</DocsTableHead>
|
||||
</DocsTableRow>
|
||||
</DocsTableHeader>
|
||||
<DocsTableBody>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">total_count</DocsTableCell>
|
||||
<DocsTableCell>统计用户总数</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">total_amount</DocsTableCell>
|
||||
<DocsTableCell>所有用户可用余额之和</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">avg_amount</DocsTableCell>
|
||||
<DocsTableCell>平均余额</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">median_amount</DocsTableCell>
|
||||
<DocsTableCell>余额中位数</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">min_amount</DocsTableCell>
|
||||
<DocsTableCell>最小余额</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">max_amount</DocsTableCell>
|
||||
<DocsTableCell>最大余额</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell className="font-mono text-xs">std_dev</DocsTableCell>
|
||||
<DocsTableCell>余额标准差</DocsTableCell>
|
||||
</DocsTableRow>
|
||||
</DocsTableBody>
|
||||
</DocsTable>
|
||||
</div>
|
||||
),
|
||||
children: [
|
||||
{ value: "3-1-order", title: "3.1 订单查询" },
|
||||
{ value: "3-2-refund", title: "3.2 订单退款" },
|
||||
{ value: "3-3-notify", title: "3.3 异步通知" },
|
||||
{ value: "3-4-distribute", title: "3.4 商户分发接口" },
|
||||
{ value: "3-5-user-balance", title: "3.5 用户余额统计" },
|
||||
]
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,329 @@
|
||||
import { type PolicySection } from "./types"
|
||||
import { CodeBlock } from "@/components/ui/code-block"
|
||||
import {
|
||||
DocsTable,
|
||||
DocsTableHeader,
|
||||
DocsTableBody,
|
||||
DocsTableHead,
|
||||
DocsTableRow,
|
||||
DocsTableCell,
|
||||
} from "@/components/ui/docs-table"
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------
|
||||
* 使用指南 (How To Use)
|
||||
* ------------------------------------------------------------------
|
||||
*/
|
||||
export const howToUseSections: PolicySection[] = [
|
||||
{
|
||||
value: "quick-start",
|
||||
title: "1. 快速开始",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<div className="bg-muted/50 border border-border/50 rounded-lg px-3 py-2 mb-6">
|
||||
<p className="text-muted-foreground m-0">为社区开发者与用户提供完整的平台使用说明</p>
|
||||
</div>
|
||||
<ul className="list-disc pl-5 space-y-2">
|
||||
<li><strong>身份认证:</strong>基于 LINUX DO Connect (OAuth)</li>
|
||||
<li><strong>认证方式:</strong>账户积分消耗认证</li>
|
||||
<li><strong>手续费:</strong>动态费率,由服务方承担</li>
|
||||
<li><strong>争议处理:</strong>支持服务方与消费方的双方争议处理</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
value: "roles",
|
||||
title: "2. 角色说明",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<ul className="list-disc pl-5 space-y-2">
|
||||
<li><strong>服务方:</strong>最终积分流转的转入方</li>
|
||||
<li><strong>消费方:</strong>最终积分流转的转出方</li>
|
||||
<li><strong>认证平台:</strong>LINUX DO Credit 系统本身</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
value: "integration",
|
||||
title: "3. 接入积分服务",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<h3 id="3-1-api" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">3.1 使用 API 接口</h3>
|
||||
<ol className="list-decimal pl-4 md:pl-5 space-y-2">
|
||||
<li>
|
||||
<strong>创建应用</strong>
|
||||
<ul className="list-disc pl-4 md:pl-5 mt-2 space-y-1 text-muted-foreground">
|
||||
<li>前往 <a href="/merchant" className="text-primary hover:underline">集市中心</a></li>
|
||||
<li>点击顶部右侧 <strong>创建应用</strong> 按钮</li>
|
||||
<li>填写必要信息:应用名称、应用主页、回调地址、通知地址</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<strong>获取 API 凭证</strong>
|
||||
<ul className="list-disc pl-4 md:pl-5 mt-2 space-y-1 text-muted-foreground">
|
||||
<li>在集市中心顶部右侧选择器中选择您的应用</li>
|
||||
<li>在 <strong>API 配置</strong> 面板中获取:
|
||||
<ul className="list-[circle] pl-4 md:pl-5 mt-1">
|
||||
<li><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">Client ID</code>:客户端ID,用于标识您的身份</li>
|
||||
<li><code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono before:content-none after:content-none">Client Secret</code>:客户端密钥,用于签名验证(<strong>请妥善保管,切勿泄露</strong>)</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<strong>使用 API 接口</strong>
|
||||
<ul className="list-disc pl-4 md:pl-5 mt-2 space-y-1 text-muted-foreground">
|
||||
<li>使用 API 接口创建积分流转服务</li>
|
||||
<li>参考文档:<a href="/docs/api" className="text-primary hover:underline">API 接口文档</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h3 id="3-2-online" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">3.2 使用在线服务</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2 mb-4">
|
||||
<li><strong>适用场景:</strong>无代码开发基础,或只用于简单的积分服务。</li>
|
||||
<li><strong>操作步骤:</strong>
|
||||
<ol className="list-decimal pl-4 md:pl-5 mt-2 space-y-1 text-muted-foreground">
|
||||
<li>前往 <a href="/merchant" className="text-primary hover:underline">集市中心</a> 创建应用,获取 API 凭证</li>
|
||||
<li>选择应用,点击 <strong>在线收款</strong> 功能</li>
|
||||
<li>创建在线积分服务</li>
|
||||
<li>获取唯一积分服务链接</li>
|
||||
<li>发送给您所服务的客户使用</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="3-3-new-api" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">3.3 快速集成 New API</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2 mb-4">
|
||||
<li><strong>适用场景:</strong>New API 站点,LINUX DO Credit 兼容 EasyPay 协议,公益站站长可直接集成。</li>
|
||||
<li><strong>操作步骤:</strong>
|
||||
<ol className="list-decimal pl-4 md:pl-5 mt-2 space-y-2 text-muted-foreground">
|
||||
<li>
|
||||
前往 <a href="/merchant" className="text-primary hover:underline">集市中心</a>,点击 <strong>创建应用</strong>,填写 New API 站点信息:
|
||||
<div className="my-4">
|
||||
<DocsTable>
|
||||
<DocsTableHeader>
|
||||
<DocsTableRow>
|
||||
<DocsTableHead>字段</DocsTableHead>
|
||||
<DocsTableHead>值</DocsTableHead>
|
||||
</DocsTableRow>
|
||||
</DocsTableHeader>
|
||||
<DocsTableBody>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell>应用名称</DocsTableCell>
|
||||
<DocsTableCell><code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">您的应用名称</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell>应用主页</DocsTableCell>
|
||||
<DocsTableCell><code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">https://{"{您的 New API 域名}"}</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell>回调地址</DocsTableCell>
|
||||
<DocsTableCell><code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">https://{"{您的 New API 域名}"}/console/log</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell>通知地址</DocsTableCell>
|
||||
<DocsTableCell><code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">https://{"{您的 New API 域名}"}/api/user/epay/notify</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
</DocsTableBody>
|
||||
</DocsTable>
|
||||
</div>
|
||||
</li>
|
||||
<li>前往 New API 站点的系统设置,找到 <strong>支付设置</strong>。</li>
|
||||
<li>
|
||||
配置 LINUX DO Credit 平台参数:
|
||||
<div className="my-4">
|
||||
<DocsTable>
|
||||
<DocsTableHeader>
|
||||
<DocsTableRow>
|
||||
<DocsTableHead>参数</DocsTableHead>
|
||||
<DocsTableHead>值</DocsTableHead>
|
||||
</DocsTableRow>
|
||||
</DocsTableHeader>
|
||||
<DocsTableBody>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell>支付地址</DocsTableCell>
|
||||
<DocsTableCell><code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">https://credit.linux.do/epay/pay</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell>易支付商户ID</DocsTableCell>
|
||||
<DocsTableCell>您的 <code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">Client ID</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell>易支付商户密钥</DocsTableCell>
|
||||
<DocsTableCell>您的 <code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">Client Secret</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
<DocsTableRow>
|
||||
<DocsTableCell>回调地址</DocsTableCell>
|
||||
<DocsTableCell><code className="bg-muted px-1 rounded text-xs before:content-none after:content-none">https://{"{您的 New API 域名}"}</code></DocsTableCell>
|
||||
</DocsTableRow>
|
||||
</DocsTableBody>
|
||||
</DocsTable>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
配置充值方式(JSON 格式):
|
||||
<div className="my-4">
|
||||
<CodeBlock
|
||||
code={`[
|
||||
{"color":"rgba(var(--semi-blue-5), 1)","name":"支付宝","type":"alipay"},
|
||||
{"color":"rgba(var(--semi-green-5), 1)","name":"微信","type":"wxpay"},
|
||||
{"color":"black","name":"Linux Do Credit","type":"epay"}
|
||||
]`}
|
||||
language="json"
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
),
|
||||
children: [
|
||||
{ value: "3-1-api", title: "3.1 使用 API 接口" },
|
||||
{ value: "3-2-online", title: "3.2 使用在线服务" },
|
||||
{ value: "3-3-new-api", title: "3.3 快速集成 New API" },
|
||||
]
|
||||
},
|
||||
{
|
||||
value: "usage",
|
||||
title: "4. 使用 LINUX DO Credit 积分",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p>您可以在任意支持 LINUX DO Credit 的平台下使用积分。在其他平台点击使用 LINUX DO Credit 积分时,会自动跳转到 LINUX DO Credit 的积分流转服务页面,您只需要确认积分流转信息无误,并选择使用 LINUX DO Credit 进行账户认证,即可完成整个交易服务。</p>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
value: "fees",
|
||||
title: "5. 服务(手续)费",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<h3 id="5-1-rules" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">5.1 规则说明</h3>
|
||||
<p>为了更好的维持 LINUX DO Credit 平台的积分服务机制,保证社区积分的生态可持续发展,我们会按照规范进行不同程度的服务(手续)费用收取。</p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li><strong>承担方:</strong>服务(手续)费默认<strong>由服务方承担</strong></li>
|
||||
<li><strong>消费方使用:</strong>不会产生额外费用</li>
|
||||
<li><strong>服务方实收:</strong>订单金额 - 服务(手续)费</li>
|
||||
</ul>
|
||||
<div className="mt-4">
|
||||
<p className="font-mono text-xs mb-2 text-muted-foreground">计算公式:</p>
|
||||
<CodeBlock
|
||||
code={`手续费 = 订单金额 × 当前费率
|
||||
商家实际到账 = 订单金额 - 手续费`}
|
||||
language="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h3 id="5-2-dynamic" className="text-base md:text-lg font-semibold text-foreground mt-6 md:mt-8 mb-3 md:mb-4">5.2 动态费率</h3>
|
||||
<p>费率并非固定不变,会根据以下因素动态调整:</p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-1">
|
||||
<li>服务方平台等级</li>
|
||||
<li>服务方平台积分</li>
|
||||
<li>LINUX DO Credit 平台活动</li>
|
||||
</ul>
|
||||
</div>
|
||||
),
|
||||
children: [
|
||||
{ value: "5-1-rules", title: "5.1 规则说明" },
|
||||
{ value: "5-2-dynamic", title: "5.2 动态费率" },
|
||||
]
|
||||
},
|
||||
{
|
||||
value: "dispute",
|
||||
title: "6. 争议处理",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p>为了保障服务方与消费方的合法权益,当积分服务出现纠纷时,可使用争议功能。</p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li>作为服务方,您需要及时响应消费方的争议请求:
|
||||
<ol className="list-decimal pl-4 md:pl-5 mt-1 text-muted-foreground">
|
||||
<li>在集市中心或通知中查看到 <strong>待处理的争议</strong></li>
|
||||
<li>查看消费方理由,选择操作:
|
||||
<ul className="list-[circle] pl-5 mt-1">
|
||||
<li><strong>同意:</strong>认可消费方诉求,积分原路退回给消费方</li>
|
||||
<li><strong>拒绝:</strong>如果您认为已履约,请提交相关证据</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="bg-yellow-500/10 border border-yellow-500/20 text-yellow-600 dark:text-yellow-400 px-3 py-2 rounded-lg mt-4">
|
||||
<p className="m-0 text-sm">
|
||||
<strong>重要:</strong>建议服务方与消费方优先沟通解决。长时间未处理的争议会由 LINUX DO Credit 平台介入仲裁,这可能会影响您的服务方信誉。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
value: "community-balance",
|
||||
title: "7. 社区积分",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p>您的 LINUX DO Credit 平台基础积分主要由 <strong>社区积分 (Community Balance)</strong> 划转而来。</p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li><strong>基本获取方式:</strong>通过在 LINUX DO 社区的活跃行为获得:
|
||||
<ul className="list-[circle] pl-4 md:pl-5 mt-1 text-muted-foreground">
|
||||
<li>获赞、解决问题等社区贡献</li>
|
||||
<li>详情可见 <a href="https://linux.do/t/topic/1409175" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">LINUX DO 社区</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>划转规则:</strong>
|
||||
<ul className="list-[circle] pl-4 md:pl-5 mt-1 text-muted-foreground">
|
||||
<li>划转时间:社区积分每日凌晨 <strong>00:00</strong> 自动划转至可用余额</li>
|
||||
<li>限制说明:划转前不可用于任何积分服务</li>
|
||||
<li>服务费用:目前不收取任何划转 <strong>服务费</strong></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
value: "settings",
|
||||
title: "8. 账户设置",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p>您可以在 <strong>设置 (Settings)</strong> 页面管理您的账户信息。</p>
|
||||
<h3 className="text-base md:text-lg font-semibold text-foreground mt-4 mb-2">功能列表</h3>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-1">
|
||||
<li><strong>个人资料:</strong>查看当前的账户信息和会员等级</li>
|
||||
<li><strong>安全设置:</strong>修改认证密码</li>
|
||||
<li><strong>外观设置:</strong>切换页面主题、界面外观</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
value: "scripts",
|
||||
title: "9. 辅助脚本",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p>为了方便用户随时查看当前的实时积分收入,我们提供了开源的 Userscript 脚本。</p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li><strong>功能:</strong>在 LINUX DO 显示实时积分收入,支持拖拽,不影响界面。</li>
|
||||
<li><strong>获取:</strong>仅需安装 Tampermonkey 插件即可使用。</li>
|
||||
<li><strong>安装:</strong>
|
||||
<a
|
||||
href="https://linux.do/t/topic/1365853"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline inline-flex items-center gap-1"
|
||||
>
|
||||
「LINUX DO Credit」实时积分收入脚本
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-external-link"><path d="M15 3h6v6" /><path d="M10 14 21 3" /><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" /></svg>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="bg-muted/50 border border-border/50 rounded-lg px-3 py-2 mt-2">
|
||||
<p className="text-xs text-muted-foreground m-0">
|
||||
注:脚本完全开源且安全,仅通过官方 API 获取公开数据,不涉及任何敏感权限。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,416 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import Link from "next/link"
|
||||
import { ArrowLeft, Calendar, Check, Copy, FileText } from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { motion, useScroll, useSpring } from "motion/react"
|
||||
import type { PolicySection } from "./types"
|
||||
|
||||
interface LegalPageLayoutProps {
|
||||
title: string
|
||||
lastUpdated: string
|
||||
sections: PolicySection[]
|
||||
description?: React.ReactNode
|
||||
}
|
||||
|
||||
export function LegalPageLayout({
|
||||
title,
|
||||
lastUpdated,
|
||||
sections,
|
||||
description,
|
||||
}: LegalPageLayoutProps) {
|
||||
const [activeSection, setActiveSection] = React.useState<string>(sections[0]?.value || "")
|
||||
const [hasCopied, setHasCopied] = React.useState(false)
|
||||
const { scrollYProgress } = useScroll()
|
||||
const contentRef = React.useRef<HTMLDivElement | null>(null)
|
||||
const scaleX = useSpring(scrollYProgress, {
|
||||
stiffness: 100,
|
||||
damping: 30,
|
||||
restDelta: 0.001
|
||||
})
|
||||
|
||||
const allSectionIds = React.useMemo(() => {
|
||||
return sections.flatMap(section => [
|
||||
section.value,
|
||||
...(section.children?.map(child => child.value) || [])
|
||||
])
|
||||
}, [sections])
|
||||
|
||||
React.useEffect(() => {
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
setActiveSection(entry.target.id)
|
||||
}
|
||||
})
|
||||
},
|
||||
{ rootMargin: "-20% 0px -35% 0px" }
|
||||
)
|
||||
|
||||
allSectionIds.forEach((id) => {
|
||||
const element = document.getElementById(id)
|
||||
if (element) observer.observe(element)
|
||||
})
|
||||
|
||||
return () => observer.disconnect()
|
||||
}, [sections, allSectionIds])
|
||||
|
||||
const convertInlineNodes = (nodes: ChildNode[]): string => {
|
||||
return nodes.map((node) => {
|
||||
if (node.nodeType === Node.TEXT_NODE) {
|
||||
return node.textContent || ""
|
||||
}
|
||||
if (node.nodeType !== Node.ELEMENT_NODE) {
|
||||
return ""
|
||||
}
|
||||
const element = node as HTMLElement
|
||||
const tagName = element.tagName.toLowerCase()
|
||||
if (tagName === "code") {
|
||||
return `\`${element.textContent?.trim() || ""}\``
|
||||
}
|
||||
if (tagName === "strong" || tagName === "b") {
|
||||
return `**${convertInlineNodes(Array.from(element.childNodes))}**`
|
||||
}
|
||||
if (tagName === "em" || tagName === "i") {
|
||||
return `*${convertInlineNodes(Array.from(element.childNodes))}*`
|
||||
}
|
||||
if (tagName === "a") {
|
||||
const text = convertInlineNodes(Array.from(element.childNodes)) || element.textContent || ""
|
||||
const href = element.getAttribute("href") || ""
|
||||
return href ? `[${text}](${href})` : text
|
||||
}
|
||||
if (tagName === "br") {
|
||||
return "\n"
|
||||
}
|
||||
return convertInlineNodes(Array.from(element.childNodes))
|
||||
}).join("")
|
||||
}
|
||||
|
||||
const convertList = (
|
||||
list: HTMLOListElement | HTMLUListElement,
|
||||
indentLevel: number
|
||||
): string => {
|
||||
const isOrdered = list.tagName.toLowerCase() === "ol"
|
||||
const items = Array.from(list.children).filter((child) => child.tagName.toLowerCase() === "li")
|
||||
return items.map((item, index) => {
|
||||
const prefix = isOrdered ? `${index + 1}. ` : "- "
|
||||
const indent = " ".repeat(indentLevel)
|
||||
const parts: string[] = []
|
||||
const itemElement = item as HTMLElement
|
||||
const childNodes = Array.from(itemElement.childNodes)
|
||||
const nestedLists: HTMLElement[] = []
|
||||
|
||||
childNodes.forEach((child) => {
|
||||
if (child.nodeType === Node.ELEMENT_NODE) {
|
||||
const childElement = child as HTMLElement
|
||||
if (childElement.tagName.toLowerCase() === "ul" || childElement.tagName.toLowerCase() === "ol") {
|
||||
nestedLists.push(childElement)
|
||||
return
|
||||
}
|
||||
}
|
||||
parts.push(convertInlineNodes([child]).trim())
|
||||
})
|
||||
|
||||
const baseLine = `${indent}${prefix}${parts.join("").trim()}`
|
||||
const nestedMarkdown = nestedLists.map((nested) => convertList(nested as HTMLOListElement | HTMLUListElement, indentLevel + 1))
|
||||
return [baseLine, ...nestedMarkdown].filter(Boolean).join("\n")
|
||||
}).join("\n")
|
||||
}
|
||||
|
||||
const convertTable = (table: HTMLTableElement): string => {
|
||||
const rows = Array.from(table.querySelectorAll("tr")).map((row) =>
|
||||
Array.from(row.querySelectorAll("th,td")).map((cell) => (cell.textContent || "").trim())
|
||||
)
|
||||
if (!rows.length) return ""
|
||||
const header = rows[0]
|
||||
const body = rows.slice(1)
|
||||
const headerLine = `| ${header.join(" | ")} |`
|
||||
const separatorLine = `| ${header.map(() => "---").join(" | ")} |`
|
||||
const bodyLines = body.map((row) => `| ${row.join(" | ")} |`)
|
||||
return [headerLine, separatorLine, ...bodyLines].join("\n")
|
||||
}
|
||||
|
||||
const convertBlockNode = (node: HTMLElement, indentLevel: number): string => {
|
||||
const tagName = node.tagName.toLowerCase()
|
||||
if (tagName === "h3") return `### ${node.textContent?.trim() || ""}`
|
||||
if (tagName === "h4") return `#### ${node.textContent?.trim() || ""}`
|
||||
if (tagName === "p") return convertInlineNodes(Array.from(node.childNodes)).trim()
|
||||
if (tagName === "ul" || tagName === "ol") return convertList(node as HTMLOListElement | HTMLUListElement, indentLevel)
|
||||
if (tagName === "pre") {
|
||||
const code = node.textContent || ""
|
||||
return `\`\`\`\n${code.trim()}\n\`\`\``
|
||||
}
|
||||
if (tagName === "table") return convertTable(node as HTMLTableElement)
|
||||
if (tagName === "div") {
|
||||
const hasTable = node.querySelector("table")
|
||||
const hasList = node.querySelector("ul,ol")
|
||||
const hasPre = node.querySelector("pre")
|
||||
if (hasTable || hasList || hasPre) {
|
||||
return Array.from(node.children)
|
||||
.map((child) => convertBlockNode(child as HTMLElement, indentLevel))
|
||||
.filter(Boolean)
|
||||
.join("\n\n")
|
||||
}
|
||||
const text = convertInlineNodes(Array.from(node.childNodes)).trim()
|
||||
return text
|
||||
}
|
||||
return convertInlineNodes(Array.from(node.childNodes)).trim()
|
||||
}
|
||||
|
||||
const buildMarkdown = (): string => {
|
||||
const contentRoot = contentRef.current
|
||||
if (!contentRoot) return ""
|
||||
const lines: string[] = []
|
||||
lines.push(`# ${title}`)
|
||||
lines.push("")
|
||||
lines.push(`最后更新:${lastUpdated}`)
|
||||
if (description) {
|
||||
const descriptionElement = contentRoot.querySelector("[data-docs-description]")
|
||||
if (descriptionElement) {
|
||||
const descriptionText = convertInlineNodes(Array.from(descriptionElement.childNodes)).trim()
|
||||
if (descriptionText) {
|
||||
lines.push("")
|
||||
lines.push(descriptionText)
|
||||
}
|
||||
}
|
||||
}
|
||||
lines.push("")
|
||||
|
||||
const sectionNodes = Array.from(contentRoot.querySelectorAll("[data-docs-section]")) as HTMLElement[]
|
||||
sectionNodes.forEach((section) => {
|
||||
const heading = section.querySelector("h2")
|
||||
if (heading?.textContent) {
|
||||
lines.push(`## ${heading.textContent.trim()}`)
|
||||
lines.push("")
|
||||
}
|
||||
const prose = section.querySelector("[data-docs-content]")
|
||||
if (prose) {
|
||||
const blocks = Array.from(prose.children)
|
||||
.map((child) => convertBlockNode(child as HTMLElement, 0))
|
||||
.filter(Boolean)
|
||||
if (blocks.length) {
|
||||
lines.push(blocks.join("\n\n"))
|
||||
lines.push("")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim() + "\n"
|
||||
}
|
||||
|
||||
const handleCopyMarkdown = async () => {
|
||||
const markdown = buildMarkdown()
|
||||
if (!markdown) return
|
||||
try {
|
||||
await navigator.clipboard.writeText(markdown)
|
||||
setHasCopied(true)
|
||||
setTimeout(() => setHasCopied(false), 2000)
|
||||
} catch {
|
||||
const textArea = document.createElement("textarea")
|
||||
textArea.value = markdown
|
||||
textArea.style.position = "fixed"
|
||||
textArea.style.opacity = "0"
|
||||
document.body.appendChild(textArea)
|
||||
textArea.focus()
|
||||
textArea.select()
|
||||
document.execCommand("copy")
|
||||
document.body.removeChild(textArea)
|
||||
setHasCopied(true)
|
||||
setTimeout(() => setHasCopied(false), 2000)
|
||||
}
|
||||
}
|
||||
|
||||
const scrollToSection = (e: React.MouseEvent<HTMLAnchorElement>, id: string) => {
|
||||
e.preventDefault()
|
||||
const element = document.getElementById(id)
|
||||
if (element) {
|
||||
const offset = 80
|
||||
const bodyRect = document.body.getBoundingClientRect().top
|
||||
const elementRect = element.getBoundingClientRect().top
|
||||
const elementPosition = elementRect - bodyRect
|
||||
const offsetPosition = elementPosition - offset
|
||||
|
||||
window.scrollTo({
|
||||
top: offsetPosition,
|
||||
behavior: "smooth"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background relative selection:bg-primary/20">
|
||||
<motion.div
|
||||
className="fixed top-0 left-0 right-0 h-1 bg-primary origin-left z-50"
|
||||
style={{ scaleX }}
|
||||
/>
|
||||
|
||||
<div className="fixed inset-0 pointer-events-none">
|
||||
<div className="absolute top-0 left-1/4 w-[500px] h-[500px] bg-primary/5 rounded-full blur-[120px] -translate-y-1/2" />
|
||||
<div className="absolute bottom-0 right-1/4 w-[500px] h-[500px] bg-blue-500/5 rounded-full blur-[120px] translate-y-1/2" />
|
||||
</div>
|
||||
|
||||
<div ref={contentRef} className="container relative z-10 max-w-7xl mx-auto px-4 md:px-6 py-8 lg:py-16">
|
||||
<header className="mb-8 md:mb-12">
|
||||
<Link href="/" className="inline-block mb-8">
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="gap-2 pl-0 text-muted-foreground hover:text-foreground hover:bg-transparent -ml-2"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4" />
|
||||
返回首页
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
<h1 className="text-2xl md:text-3xl lg:text-5xl font-bold tracking-tight text-foreground mb-6">
|
||||
{title}
|
||||
</h1>
|
||||
<div className="flex flex-wrap items-center gap-4 text-xs text-muted-foreground mb-8">
|
||||
<span className="flex items-center gap-1.5 bg-muted/50 px-3 py-1 rounded-full border border-border/50">
|
||||
<FileText className="w-3.5 h-3.5" />
|
||||
{sections.length} 个内容
|
||||
</span>
|
||||
<span className="flex items-center gap-1.5 bg-muted/50 px-3 py-1 rounded-full border border-border/50">
|
||||
<Calendar className="w-3.5 h-3.5" />
|
||||
最后更新:{lastUpdated}
|
||||
</span>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleCopyMarkdown}
|
||||
className="h-8 gap-2 text-xs"
|
||||
>
|
||||
{hasCopied ? <Check className="w-3.5 h-3.5" /> : <Copy className="w-3.5 h-3.5" />}
|
||||
{hasCopied ? "已复制" : "复制 Markdown"}
|
||||
</Button>
|
||||
</div>
|
||||
{description && (
|
||||
<div className="w-full p-4 md:p-6 rounded-2xl bg-muted/30 border border-border/50 backdrop-blur-sm overflow-hidden">
|
||||
<div data-docs-description className="text-sm md:text-base text-muted-foreground leading-relaxed m-0 break-all">
|
||||
{description}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</motion.div>
|
||||
</header>
|
||||
|
||||
<div className="grid lg:grid-cols-12 gap-8 lg:gap-12 relative">
|
||||
<aside className="hidden lg:block lg:col-span-3">
|
||||
<div className="sticky top-24">
|
||||
<div className="space-y-2 max-h-[calc(100vh-8rem)] overflow-y-auto pr-4 scrollbar-thin">
|
||||
<div className="text-sm font-semibold text-foreground mb-4 pl-3">目录</div>
|
||||
<nav className="space-y-1">
|
||||
{sections.map((section) => (
|
||||
<div key={section.value} className="space-y-1">
|
||||
<a
|
||||
href={`#${ section.value }`}
|
||||
onClick={(e) => scrollToSection(e, section.value)}
|
||||
className={cn(
|
||||
"group flex items-center justify-between py-2 px-3 text-sm rounded-lg transition-all duration-200",
|
||||
activeSection === section.value
|
||||
? "bg-primary/10 text-primary font-medium"
|
||||
: "text-muted-foreground hover:text-foreground hover:bg-muted/50"
|
||||
)}
|
||||
>
|
||||
<span className="truncate">{section.title}</span>
|
||||
{activeSection === section.value && (
|
||||
<motion.div
|
||||
layoutId="active-dot"
|
||||
className="w-1.5 h-1.5 rounded-full bg-primary"
|
||||
/>
|
||||
)}
|
||||
</a>
|
||||
{section.children && (
|
||||
<div className="pl-4 space-y-1">
|
||||
{section.children.map((child) => (
|
||||
<a
|
||||
key={child.value}
|
||||
href={`#${ child.value }`}
|
||||
onClick={(e) => scrollToSection(e, child.value)}
|
||||
className={cn(
|
||||
"block py-1.5 px-3 text-xs rounded-lg transition-all duration-200 truncate",
|
||||
activeSection === child.value
|
||||
? "text-primary font-medium bg-primary/5"
|
||||
: "text-muted-foreground/80 hover:text-foreground hover:bg-muted/30"
|
||||
)}
|
||||
>
|
||||
{child.title}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main className="lg:col-span-9 lg:col-start-4 space-y-8 md:space-y-16 pb-20">
|
||||
{sections.map((section, index) => (
|
||||
<motion.section
|
||||
key={section.value}
|
||||
id={section.value}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "100px" }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="scroll-mt-24 group"
|
||||
data-docs-section
|
||||
>
|
||||
<div className="sticky top-0 z-20 flex items-center gap-4 py-6 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 mb-2 -mx-4 px-4 md:-mx-0 md:px-0">
|
||||
<span className="flex items-center justify-center w-8 h-8 rounded-lg bg-primary/10 text-primary text-sm font-bold opacity-50 group-hover:opacity-100 transition-opacity flex-shrink-0">
|
||||
{index + 1}
|
||||
</span>
|
||||
<h2 className="text-xl md:text-2xl font-semibold tracking-tight text-foreground group-hover:text-primary transition-colors duration-300">
|
||||
{section.title.replace(/^\d+\.\s*/, '')}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div
|
||||
data-docs-content
|
||||
className={cn(
|
||||
"prose prose-sm md:prose-base prose-neutral dark:prose-invert max-w-none",
|
||||
"prose-p:text-muted-foreground prose-p:leading-7",
|
||||
"prose-li:text-muted-foreground",
|
||||
"prose-strong:text-foreground",
|
||||
"pl-4 md:pl-12 border-l border-border/30 group-hover:border-primary/20 transition-colors duration-500"
|
||||
)}>
|
||||
{section.content}
|
||||
</div>
|
||||
</motion.section>
|
||||
))}
|
||||
|
||||
<div className="pt-16 border-t border-border mt-20">
|
||||
<div className="bg-muted/30 rounded-2xl p-8 text-center">
|
||||
<p className="text-muted-foreground text-sm mb-4">
|
||||
对这些内容有疑问?
|
||||
</p>
|
||||
<div className="flex justify-center gap-4">
|
||||
<Link href="https://github.com/linux-do/credit/issues" target="_blank">
|
||||
<Button variant="outline" className="h-9 text-xs">
|
||||
联系支持
|
||||
</Button>
|
||||
</Link>
|
||||
<Link href="https://linux.do" target="_blank">
|
||||
<Button variant="outline" className="h-9 text-xs">
|
||||
访问社区
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div >
|
||||
</div >
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
import { type PolicySection } from "./types"
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------
|
||||
* 隐私政策 (PRIVACY POLICY)
|
||||
* ------------------------------------------------------------------
|
||||
*/
|
||||
export const privacySections: PolicySection[] = [
|
||||
{
|
||||
value: "collection-details",
|
||||
title: "1. 详细信息收集说明",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p>我们仅遵循合法、正当、必要的原则,收集为您提供服务所必需的信息。我们的数据收集范围严格限制如下:</p>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<span className="font-semibold text-foreground">1.1 身份鉴权信息:</span>
|
||||
<p className="mt-1 text-muted-foreground">当您通过 LINUX DO Connect 登录时,我们会获取您的社区 OpenID(唯一标识符)、加密后的用户名及头像 URL。<strong>我们不收集您的手机号、真实姓名或身份证件信息。</strong></p>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-semibold text-foreground">1.2 服务日志信息:</span>
|
||||
<p className="mt-1 text-muted-foreground">为保障系统运行安全及满足法律合规要求,我们会自动收集您的操作日志,包括 IP 地址、访问日期和时间、API 调用记录、User-Agent(浏览器/设备类型)。</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-semibold text-foreground">1.3 交易与资产信息:</span>
|
||||
<p className="mt-1 text-muted-foreground">若您使用支付功能,我们将记录您的商户订单号、交易金额、交易时间、交易状态摘要。这些信息是账务核对的必要依据。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "storage-security",
|
||||
title: "2. 数据存储与安全保护",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p>我们深知数据安全的重要性,并采取业界领先的技术措施保护您的数据:</p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li><strong>存储地点:</strong>依照法规要求,我们收集和产生的用户个人信息,<strong>存储在独立</strong>的服务器上。我们不会将您的数据传输至境外管辖区。</li>
|
||||
<li><strong>加密技术:</strong>敏感数据(如 支付密码)在数据库中均采用高强度加密算法存储。数据传输全链路采用 SSL/TLS 1.3 协议进行加密,防止网络嗅探。</li>
|
||||
<li><strong>隔离机制:</strong>本平台数据与外部网络物理隔离,且独立于 LINUX DO 社区论坛主数据库,确保单一系统故障不会波及全局数据安全。</li>
|
||||
<li><strong>访问控制:</strong>我们实行严格的最小权限原则(Least Privilege),仅有核心运维人员经授权后方可访问必要的维护数据,且所有操作均有审计日志留存。</li>
|
||||
</ul>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "usage-rules",
|
||||
title: "3. 信息使用规范",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p>我们收集的信息将仅用于以下目的:</p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-1">
|
||||
<li><strong>身份识别:</strong>用于确认您的社区身份,展示您的个人中心数据。</li>
|
||||
<li><strong>业务功能:</strong>处理您的支付指令、API 请求、回调通知及账单生成。</li>
|
||||
<li><strong>安全风控:</strong>利用 IP 及行为日志进行反作弊、反欺诈分析,识别恶意攻击行为,保护平台及其他用户的安全。</li>
|
||||
<li><strong>客户支持:</strong>在您发起工单或申诉时,查询相关日志以协助您解决问题。</li>
|
||||
</ul>
|
||||
<p><strong>禁止用途:</strong>我们承诺<strong>绝不</strong>利用您的数据进行用户画像分析、个性化广告推送或商业营销。</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "sharing-disclosure",
|
||||
title: "4. 信息共享与对外披露",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p><strong>4.1 共享原则:</strong>我们坚持<strong>数据零共享</strong>策略。除以下极端情况外,我们不会向任何第三方(包括且不限于关联公司、支付宝、微信、银行、广告商)共享您的个人信息:</p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-1 text-muted-foreground">
|
||||
<li>事先获得您的明确授权或同意;</li>
|
||||
<li>根据适用的法律法规、法律程序的要求、强制性的行政或司法要求所必须的情况下进行提供。</li>
|
||||
</ul>
|
||||
<p><strong>4.2 转让与公开披露:</strong>我们不会将您的个人信息转让给任何公司、组织和个人。我们仅在法律法规强制要求,或为了保护平台及用户与公众的人身财产安全免受侵害时,才会公开披露您的信息。</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "user-rights",
|
||||
title: "5. 您的权利与数据管理",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p>依照《中华人民共和国个人信息保护法》,您对您的个人信息享有完整的控制权:</p>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<span className="font-semibold text-foreground">5.1 查阅与复制权:</span>
|
||||
<p className="mt-1 text-muted-foreground">您可以随时登录开发者后台,查阅您的概览信息、API Key 状态及历史交易账单。您可以通过“导出账单”功能获取您的数据副本。</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-semibold text-foreground">5.2 删除与遗忘权:</span>
|
||||
<p className="mt-1 text-muted-foreground">若您决定停止使用本服务,在结清所有应付费用及余额后,您可以申请<strong>注销账户</strong>。注销后,我们将立即删除您的所有敏感信息或进行匿名化处理,法律法规规定需保留的日志除外。</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-semibold text-foreground">5.3 纠正与更正权:</span>
|
||||
<p className="mt-1 text-muted-foreground">若您发现您的信息有误,您有权要求我们更正或补充。您可以在设置页面直接修改您的信息,或通过客服提交工单。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "policy-update",
|
||||
title: "6. 政策更新与通知",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p>随着业务的发展或法律法规的变动,我们可能会适时修订本《隐私政策》。</p>
|
||||
<p>当条款发生重大变更时(例如收集范围扩大、使用目的改变),我们会通过站内信、公告或弹窗等显著方式通知您。若您在政策更新后继续使用本服务,即表示您同意接受更新后的隐私政策约束。</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,115 @@
|
||||
import { type PolicySection } from "./types"
|
||||
|
||||
export const TERMS_LAST_UPDATED = "2025-12-22"
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------
|
||||
* 服务条款 (TERMS OF SERVICE)
|
||||
* ------------------------------------------------------------------
|
||||
*/
|
||||
export const termsSections: PolicySection[] = [
|
||||
{
|
||||
value: "contract-establishment",
|
||||
title: "1. 缔约申明与服务综述",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p><strong>1.1 缔约主体:</strong>本《服务协议》(以下简称“本协议”)是您(以下亦称“社区用户”、“开发者”、“消费方”或“服务方”)与 LINUX DO Credit 平台运营团队(以下简称“平台”、“我们”)之间关于使用平台服务所订立的具有法律约束力的契约。</p>
|
||||
<p><strong>1.2 审慎阅读:</strong>请您务必审慎阅读、充分理解各条款内容,特别是<strong>免除或者限制责任的条款、争议解决和法律适用条款</strong>。各免责或限责条款将以粗体标识,您应重点阅读。如您不同意本协议的任何内容,请立即停止注册或使用本服务。</p>
|
||||
<p><strong>1.3 协议构成:</strong>本协议内容包括协议正文及所有我们已经发布或将来可能发布的各类规则、声明、说明。所有规则为本协议不可分割的组成部分,与协议正文具有同等法律效力。</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "service-definition",
|
||||
title: "2. 服务定义与性质界定",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p><strong>2.1 社区技术服务:</strong>LINUX DO Credit 是基于 LINUX DO 社区生态构建的独立价值交换协议与技术系统。我们仅提供 API 接口调用、数据路由、账单管理等<strong>纯技术服务</strong>。</p>
|
||||
<p><strong>2.2 非金融机构申明:</strong></p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li><strong>非银行机构:</strong>我们不是商业银行、持牌支付机构(如支付宝、微信支付、银联)或清算机构。</li>
|
||||
<li><strong>不提供资金沉淀:</strong>平台不设立资金池,不提供真实法币存取款、转账汇款或支付结算服务。所有涉及资金流转的行为均发生于社区用户与社区支付渠道之间,不涉及真实货币。</li>
|
||||
<li><strong>不提供金融服务:</strong>平台不提供任何金融服务,包括但不限于贷款、融资、投资、理财、保险等金融服务。</li>
|
||||
<li><strong>不提供积分兑现:</strong>平台不提供任何积分兑换服务,包括但不限于积分兑换为真实货币、积分兑换为实物商品、积分兑换为服务等。</li>
|
||||
<li><strong>不提供真实货币交易:</strong>平台不提供任何真实货币交易服务,包括但不限于真实货币交易为积分、真实货币交易为虚拟资产、真实货币交易为服务等。</li>
|
||||
</ul>
|
||||
<p><strong>2.3 服务限定:</strong>本平台建议用于仅支持虚拟商品、软件授权、技术咨询、会员订阅等<strong>无实物交付</strong>的场景。关于实物电商、物流发货或涉及线下履约的商业场景造成的任何后果我们概不负责,请妥善保管好自己的个人财产,谨防上当受骗。</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "account-specifications",
|
||||
title: "3. 账号注册与使用规范",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p><strong>3.1 账号体系:</strong>本平台采用 LINUX DO Connect (OAuth) 授权登录体系。您必须拥有合法、有效的 LINUX DO 社区账号方可使用本服务。您的平台账号权益(包括但不限于信誉分、等级)与社区账号严格绑定。</p>
|
||||
<p><strong>3.2 匿名性与真实性:</strong></p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2">
|
||||
<li><strong>无需实名:</strong>我们尊重您的隐私,不强制要求您提供居民身份证、护照或营业执照进行实名认证。</li>
|
||||
<li><strong>操作真实性:</strong>您承诺注册和使用的账号是您本人操作。严禁恶意注册、挂机脚本、自动化程序注册等破坏平台公平性的行为。</li>
|
||||
</ul>
|
||||
<p><strong>3.3 账号安全责任:</strong>您应妥善保管您账号的支付密码、Client ID 和 Client Secret。<strong>因您保管不善可能导致账号被他人非法使用、资金损失或数据泄露的责任,由您自行承担。</strong>如发现账号异常,请立即通知我们进行冻结。</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "user-conduct",
|
||||
title: "4. 用户行为准则(负面清单)",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p>您在使用本服务时,必须严格遵守《中华人民共和国网络安全法》、《计算机信息网络国际联网安全保护管理办法》等法律法规。<strong>严禁利用本平台从事以下活动(“红线条款”):</strong></p>
|
||||
<div className="bg-red-500/5 border border-red-500/20 rounded-lg p-3 md:p-4 space-y-3">
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-2 text-red-600 dark:text-red-400 font-medium">
|
||||
<li><strong>危害国家安全:</strong>反对宪法所确定的基本原则、危害国家安全、泄露国家秘密、颠覆国家政权、破坏国家统一的;</li>
|
||||
<li><strong>非法信息服务:</strong>黑客攻击工具、DDoS 攻击服务、服务器爆破等其他非法信息服务平台;</li>
|
||||
<li><strong>黄赌毒关联:</strong>制作、复制、发布、传播淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;</li>
|
||||
<li><strong>侵犯知识产权:</strong>销售盗版软件、盗版影视资源、非法游戏外挂、私服、黑号、社工库数据等;</li>
|
||||
<li><strong>欺诈与虚假:</strong>进行电信诈骗、金融诈骗、传销、虚假广告虚假交易等;</li>
|
||||
<li><strong>其他违法信息:</strong>涉及散布谣言、宣扬邪教/封建迷信、侮辱/诽谤他人、侵害他人合法权益的。</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p><strong>违约处理:</strong>一旦发现您违反上述规定,平台有权不经通知<strong>立即永久封禁您的账号、拦截所有 API 请求、冻结账户内所有关联价值,并依法向公安机关、网安部门移交相关线索。</strong></p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "virtual-assets",
|
||||
title: "5. 虚拟资产与交易规则",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p><strong>5.1 资产性质:</strong>平台内流转的“余额”、“积分”等均为<strong>社区虚拟积分</strong>,仅代表您在社区生态内的活跃度或贡献值。它们<strong>不具有任何货币属性</strong>,严禁兑换为法定货币,也不可用于任何非平台许可的商业交易。</p>
|
||||
<p><strong>5.2 交易不可逆:</strong>鉴于网络技术的实时性,<strong>一旦积分消耗或划转指令被执行,该操作即不可撤销。</strong>请您在确认相关积分活动前,务必仔细核对服务方信息。</p>
|
||||
<p><strong>5.3 规则说明:</strong>为营造良好的社区积分环境,平台有权收取一定的服务费(以积分为结算单位)进行调控,具体规则以控制台公示为准。平台保留根据社区运营状况调整积分规则的权利。</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "liability-limitation",
|
||||
title: "6. 免责声明与不可抗力",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p><strong>6.1 基础免责:</strong>本平台服务按“现状”(As-Is)及“现有”(As-Available)状态提供。我们不保证服务一定能满足您的要求,也不保证服务不会中断,对服务的及时性、安全性、准确性都不作担保。</p>
|
||||
<p><strong>6.2 不可抗力:</strong>对于因以下原因导致的服务中断、数据丢失或账号损失,平台不承担赔偿责任:</p>
|
||||
<ul className="list-disc pl-4 md:pl-5 space-y-1 text-muted-foreground">
|
||||
<li>自然灾害(台风、地震、海啸、洪水等);</li>
|
||||
<li>政府行为、法律法规或政策调整、行政命令;</li>
|
||||
<li>电信部门技术调整、通讯线路中断、海底光缆故障;</li>
|
||||
<li>黑客攻击、计算机病毒侵入或发作、技术性故障;</li>
|
||||
<li>社区维护、系统升级(我们将尽可能提前公告)。</li>
|
||||
</ul>
|
||||
<p><strong>6.3 责任上限:</strong>在任何情况下,平台对您所承担的违约赔偿责任总额不超过您在违约行为发生前 1 个月内向平台支付的费用总额。</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "governing-law",
|
||||
title: "7. 法律适用与争议解决",
|
||||
content: (
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<p><strong>7.1 法律适用:</strong>本协议的订立、执行、解释及争议的解决均适用<strong>中华人民共和国法律</strong>(不包括港澳台地区法律及冲突法)。</p>
|
||||
<p><strong>7.2 争议解决:</strong>若您和平台发生任何争议或纠纷,首先应友好协商解决;协商不成的,您同意将纠纷或争议提交至<strong>平台运营团队所在地有管辖权的人民法院</strong>管辖。</p>
|
||||
<p><strong>7.3 协议变更:</strong>我们有权根据法律法规变化或业务发展需要修改本协议。变更后的协议将在平台公示,自公示之日起生效。若您继续使用服务,视为您已接受修订后的协议。</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
import { type ReactNode } from "react"
|
||||
|
||||
export type PolicySection = {
|
||||
value: string
|
||||
title: string
|
||||
content: ReactNode
|
||||
children?: {
|
||||
value: string
|
||||
title: string
|
||||
}[]
|
||||
}
|
||||
Reference in New Issue
Block a user