mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-08 16:46:37 +08:00
裁剪
swagger 移除 merchant swagger 改造首页内容为通用后台管理系统定位 - 修改首页标题从 'LINUX DO Credit' 改为 'Modern Platform' - 更新副标题为 '为二次开发而生' - 更新首页描述为通用平台的特点 - 更新首页特性标签为 '开箱即用、高度可扩展、工业级基建' - 修改展示卡片为技术栈和二次开发相关 - 更新开发者示例代码为通用的注册和 API Key 获取示例 - 更新页脚品牌名为 'Modern Platform' - 调整页脚导航链接为通用平台相关内容 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> 去除遗留 裁剪 移除 /api/v1/user/pay-key 相关代码 - 删除后端 UpdatePayKey 处理器函数和 UpdatePayKeyRequest 结构体 - 删除 User 模型中的 PayKey 字段 - 删除 User.VerifyPayKey 方法 - 删除 EncryptPayKeyFailed 错误常量 - 删除 /api/v1/user/pay-key PUT 路由 - 删除 OAuth 返回中的 IsPayKey 字段 - 删除前端 UserService.updatePayKey 方法 - 删除前端所有支付密钥 UI 和逻辑 - 更新相关的导出和注释 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> 去除遗留 api 修正 系统配置 前端裁剪 后端裁剪 init
This commit is contained in:
@@ -3,9 +3,6 @@ import type {
|
||||
SystemConfig,
|
||||
CreateSystemConfigRequest,
|
||||
UpdateSystemConfigRequest,
|
||||
UserPayConfig,
|
||||
CreateUserPayConfigRequest,
|
||||
UpdateUserPayConfigRequest,
|
||||
TaskMeta,
|
||||
TaskTypeResponse,
|
||||
DispatchTaskRequest,
|
||||
@@ -63,8 +60,9 @@ export class AdminService extends BaseService {
|
||||
* console.log('系统配置数量:', configs.length);
|
||||
* ```
|
||||
*/
|
||||
static async listSystemConfigs(): Promise<SystemConfig[]> {
|
||||
return this.get<SystemConfig[]>('/system-configs');
|
||||
static async listSystemConfigs(type?: 'system' | 'business'): Promise<SystemConfig[]> {
|
||||
const query = type ? `?type=${type}` : '';
|
||||
return this.get<SystemConfig[]>(`/system-configs${query}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,121 +125,7 @@ export class AdminService extends BaseService {
|
||||
return this.delete<void>(`/system-configs/${ key }`);
|
||||
}
|
||||
|
||||
// ==================== 用户积分配置管理 ====================
|
||||
|
||||
/**
|
||||
* 创建用户积分配置
|
||||
* @param request - 创建用户积分配置的请求参数
|
||||
* @returns 创建的用户积分配置
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ForbiddenError} 当无管理员权限时
|
||||
* @throws {ValidationError} 当参数验证失败或等级已存在时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const config = await AdminService.createUserPayConfig({
|
||||
* level: PayLevel.Premium,
|
||||
* min_score: 1000,
|
||||
* max_score: null,
|
||||
* daily_limit: 100000,
|
||||
* fee_rate: 0.01
|
||||
* });
|
||||
* console.log('配置ID:', config.id);
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* - min_score 必须 >= 0
|
||||
* - max_score 必须大于 min_score(如果提供)
|
||||
* - fee_rate 必须在 0-1 之间,最多2位小数
|
||||
*/
|
||||
static async createUserPayConfig(
|
||||
request: CreateUserPayConfigRequest,
|
||||
): Promise<UserPayConfig> {
|
||||
return this.post<UserPayConfig>('/user-pay-configs', request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户积分配置列表
|
||||
* @returns 用户积分配置列表(按最低分数升序排序)
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ForbiddenError} 当无管理员权限时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const configs = await AdminService.listUserPayConfigs();
|
||||
* console.log('积分配置数量:', configs.length);
|
||||
* ```
|
||||
*/
|
||||
static async listUserPayConfigs(): Promise<UserPayConfig[]> {
|
||||
return this.get<UserPayConfig[]>('/user-pay-configs');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个用户积分配置
|
||||
* @param id - 配置ID
|
||||
* @returns 用户积分配置信息
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ForbiddenError} 当无管理员权限时
|
||||
* @throws {NotFoundError} 当配置不存在时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const config = await AdminService.getUserPayConfig(123);
|
||||
* console.log('手续费率:', config.fee_rate);
|
||||
* ```
|
||||
*/
|
||||
static async getUserPayConfig(id: string): Promise<UserPayConfig> {
|
||||
return this.get<UserPayConfig>(`/user-pay-configs/${ id }`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户积分配置
|
||||
* @param id - 配置ID
|
||||
* @param request - 更新用户积分配置的请求参数
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ForbiddenError} 当无管理员权限时
|
||||
* @throws {NotFoundError} 当配置不存在时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await AdminService.updateUserPayConfig(123, {
|
||||
* min_score: 500,
|
||||
* max_score: 999,
|
||||
* daily_limit: 50000,
|
||||
* fee_rate: 0.02
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* - min_score 必须 >= 0
|
||||
* - max_score 必须大于 min_score(如果提供)
|
||||
* - fee_rate 必须在 0-1 之间,最多2位小数
|
||||
*/
|
||||
static async updateUserPayConfig(
|
||||
id: string,
|
||||
request: UpdateUserPayConfigRequest,
|
||||
): Promise<void> {
|
||||
return this.put<void>(`/user-pay-configs/${ id }`, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户积分配置
|
||||
* @param id - 配置ID
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ForbiddenError} 当无管理员权限时
|
||||
* @throws {NotFoundError} 当配置不存在时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await AdminService.deleteUserPayConfig(123);
|
||||
* ```
|
||||
*/
|
||||
static async deleteUserPayConfig(id: string): Promise<void> {
|
||||
return this.delete<void>(`/user-pay-configs/${ id }`);
|
||||
}
|
||||
|
||||
// ==================== 任务管理 ====================
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
* 管理员服务模块
|
||||
*
|
||||
* @description
|
||||
* 提供系统配置和用户积分配置管理功能,包括:
|
||||
* 提供系统配置、用户与任务管理功能,包括:
|
||||
* - 系统配置管理(创建、查询、更新、删除)
|
||||
* - 用户积分配置管理(创建、查询、更新、删除)
|
||||
* - 异步任务配置及下发
|
||||
* - 用户账号状态管理
|
||||
*
|
||||
* @remarks
|
||||
* 所有接口都需要管理员权限
|
||||
@@ -15,15 +16,6 @@
|
||||
*
|
||||
* // 获取系统配置列表
|
||||
* const configs = await AdminService.listSystemConfigs();
|
||||
*
|
||||
* // 创建用户积分配置
|
||||
* await AdminService.createUserPayConfig({
|
||||
* level: 1,
|
||||
* min_score: 0,
|
||||
* max_score: 999,
|
||||
* daily_limit: 10000,
|
||||
* fee_rate: 0.01
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
|
||||
@@ -32,9 +24,6 @@ export type {
|
||||
SystemConfig,
|
||||
CreateSystemConfigRequest,
|
||||
UpdateSystemConfigRequest,
|
||||
UserPayConfig,
|
||||
CreateUserPayConfigRequest,
|
||||
UpdateUserPayConfigRequest,
|
||||
TaskMeta,
|
||||
DispatchTaskRequest,
|
||||
AdminUser,
|
||||
@@ -42,4 +31,3 @@ export type {
|
||||
ListUsersResponse,
|
||||
UpdateUserStatusRequest,
|
||||
} from './types';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PayLevel } from '@/lib/services/auth/types';
|
||||
|
||||
|
||||
/**
|
||||
* 系统配置信息
|
||||
@@ -8,6 +8,8 @@ export interface SystemConfig {
|
||||
key: string;
|
||||
/** 配置值 */
|
||||
value: string;
|
||||
/** 配置类型:'system' | 'business' */
|
||||
type: 'system' | 'business';
|
||||
/** 配置描述 */
|
||||
description: string;
|
||||
/** 创建时间 */
|
||||
@@ -24,6 +26,8 @@ export interface CreateSystemConfigRequest {
|
||||
key: string;
|
||||
/** 配置值(最大255字符) */
|
||||
value: string;
|
||||
/** 配置类型:'system' | 'business' */
|
||||
type: 'system' | 'business';
|
||||
/** 配置描述(最大255字符,可选) */
|
||||
description?: string;
|
||||
}
|
||||
@@ -38,69 +42,7 @@ export interface UpdateSystemConfigRequest {
|
||||
description?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户积分配置信息
|
||||
*/
|
||||
export interface UserPayConfig {
|
||||
/** 配置ID */
|
||||
id: string;
|
||||
/** 积分等级 */
|
||||
level: PayLevel;
|
||||
/** 最低分数 */
|
||||
min_score: number;
|
||||
/** 最高分数(可选) */
|
||||
max_score: number | null;
|
||||
/** 每日限额(可选) */
|
||||
daily_limit: number | null;
|
||||
/** 手续费率(0-1之间的小数,最多2位小数) */
|
||||
fee_rate: number | string;
|
||||
/** 积分费率(0-1之间的小数,最多2位小数) */
|
||||
score_rate: number | string;
|
||||
/** 分发费率(0-1之间的小数,最多2位小数) */
|
||||
distribute_rate: number | string;
|
||||
/** 创建时间 */
|
||||
created_at: string;
|
||||
/** 更新时间 */
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建用户积分配置请求参数
|
||||
*/
|
||||
export interface CreateUserPayConfigRequest {
|
||||
/** 积分等级 */
|
||||
level: PayLevel;
|
||||
/** 最低分数(必须 >= 0) */
|
||||
min_score: number;
|
||||
/** 最高分数(可选,必须大于 min_score) */
|
||||
max_score?: number | null;
|
||||
/** 每日限额(可选) */
|
||||
daily_limit?: number | null;
|
||||
/** 手续费率(0-1之间的小数,最多2位小数) */
|
||||
fee_rate: number | string;
|
||||
/** 积分费率(0-1之间的小数,最多2位小数) */
|
||||
score_rate: number | string;
|
||||
/** 分发费率(0-1之间的小数,最多2位小数) */
|
||||
distribute_rate: number | string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户积分配置请求参数
|
||||
*/
|
||||
export interface UpdateUserPayConfigRequest {
|
||||
/** 最低分数(必须 >= 0) */
|
||||
min_score: number;
|
||||
/** 最高分数(可选,必须大于 min_score) */
|
||||
max_score?: number | null;
|
||||
/** 每日限额(可选) */
|
||||
daily_limit?: number | null;
|
||||
/** 手续费率(0-1之间的小数,最多2位小数) */
|
||||
fee_rate: number | string;
|
||||
/** 积分费率(0-1之间的小数,最多2位小数) */
|
||||
score_rate: number | string;
|
||||
/** 分发费率(0-1之间的小数,最多2位小数) */
|
||||
distribute_rate: number | string;
|
||||
}
|
||||
|
||||
// ==================== 任务管理 ====================
|
||||
|
||||
|
||||
@@ -56,8 +56,6 @@ export interface User {
|
||||
pending_balance: string;
|
||||
/** 支付分数 */
|
||||
pay_score: number;
|
||||
/** 是否有支付密钥 */
|
||||
is_pay_key: boolean;
|
||||
/** 是否为管理员 */
|
||||
is_admin: boolean;
|
||||
/** 当日剩余配额 */
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { BaseService } from '../core/base.service';
|
||||
import type { PublicConfigResponse } from './types';
|
||||
import type { UserPayConfig } from '../admin/types';
|
||||
|
||||
/**
|
||||
* 配置服务
|
||||
@@ -16,29 +15,9 @@ export class ConfigService extends BaseService {
|
||||
* @example
|
||||
* ```typescript
|
||||
* const config = await ConfigService.getPublicConfig();
|
||||
* console.log('争议时间窗口:', config.dispute_time_window_hours, '小时');
|
||||
* ```
|
||||
*/
|
||||
static async getPublicConfig(): Promise<PublicConfigResponse> {
|
||||
return this.get<PublicConfigResponse>('/public');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户平台等级配置(公开接口)
|
||||
* 返回所有平台等级的配置信息,用于向用户展示不同等级的权益
|
||||
*
|
||||
* @returns 用户支付配置列表
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const payConfigs = await ConfigService.getUserPayConfigs();
|
||||
* payConfigs.forEach(config => {
|
||||
* console.log(`等级 ${config.level}: 手续费率 ${config.fee_rate}, 每日限额 ${config.daily_limit}`);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
static async getUserPayConfigs(): Promise<UserPayConfig[]> {
|
||||
return this.get<UserPayConfig[]>('/user-pay');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,20 +2,12 @@
|
||||
* 公共配置响应
|
||||
*/
|
||||
export interface PublicConfigResponse {
|
||||
/** 争议时间窗口(小时) */
|
||||
dispute_time_window_hours: number;
|
||||
/** 红包功能是否启用 */
|
||||
red_envelope_enabled: boolean;
|
||||
/** 单个红包的最大积分上限 */
|
||||
red_envelope_max_amount: string;
|
||||
/** 每日发红包的个数限制 */
|
||||
red_envelope_daily_limit: number;
|
||||
/** 红包手续费率(0-1之间的小数) */
|
||||
red_envelope_fee_rate: string;
|
||||
/** 每个红包的最大可领取人数上限 */
|
||||
red_envelope_max_recipients: number;
|
||||
/** 到账最短时间 **/
|
||||
settlement_delay_days_min: number;
|
||||
/** 到账最长时间 **/
|
||||
settlement_delay_days_max: number;
|
||||
/** 允许上传的图片扩展名 */
|
||||
upload_allowed_extensions: string;
|
||||
/** 站点名称 */
|
||||
site_name: string;
|
||||
/** 是否允许注册 */
|
||||
registration_enabled: boolean;
|
||||
/** 每个用户最大 API Key 数量 */
|
||||
max_api_keys_per_user: number;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import axios, { AxiosError, AxiosResponse, CancelTokenSource, InternalAxiosRequestConfig } from 'axios';
|
||||
import { toast } from 'sonner';
|
||||
import { showRiskWarningToast } from '@/components/common/risk/risk-warning-toast';
|
||||
import { apiConfig } from './config';
|
||||
import {
|
||||
ApiErrorBase,
|
||||
@@ -37,108 +36,7 @@ const cancelTokens = new Map<string, CancelTokenSource>();
|
||||
*/
|
||||
const pendingRequests = new Map<string, Promise<AxiosResponse<ApiResponse>>>();
|
||||
|
||||
const RISK_LEVEL_HEADER = 'x-credit-risk-level';
|
||||
const RISK_LABELS_HEADER = 'x-credit-risk-labels';
|
||||
const RISK_ITEMS_HEADER = 'x-credit-risks';
|
||||
const RISK_BLOCKED_CODE = 'RISK_BLOCKED';
|
||||
const RISK_BLOCKED_EVENT = 'credit-risk-blocked';
|
||||
|
||||
interface RiskItem {
|
||||
label: string;
|
||||
value?: string;
|
||||
desc?: string;
|
||||
}
|
||||
|
||||
interface RiskInfo {
|
||||
risk_level: string;
|
||||
risk_labels: string[];
|
||||
risks: RiskItem[];
|
||||
}
|
||||
|
||||
function decodeBase64JSON(value?: string): unknown {
|
||||
if (!value || typeof window === 'undefined') return [];
|
||||
|
||||
try {
|
||||
const binary = window.atob(value);
|
||||
const bytes = Uint8Array.from(binary, char => char.charCodeAt(0));
|
||||
const json = new TextDecoder().decode(bytes);
|
||||
return JSON.parse(json);
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeRiskItems(value: unknown): RiskItem[] {
|
||||
if (!Array.isArray(value)) return [];
|
||||
|
||||
return value.reduce<RiskItem[]>((items, item) => {
|
||||
if (!item || typeof item !== 'object') return items;
|
||||
|
||||
const label = 'label' in item ? (item as { label?: unknown }).label : undefined;
|
||||
if (typeof label !== 'string' || !label.trim()) return items;
|
||||
|
||||
const value = 'value' in item ? (item as { value?: unknown }).value : undefined;
|
||||
const desc = 'desc' in item ? (item as { desc?: unknown }).desc : undefined;
|
||||
items.push({
|
||||
label: label.trim(),
|
||||
value: typeof value === 'string' ? value.trim() : undefined,
|
||||
desc: typeof desc === 'string' ? desc.trim() : undefined,
|
||||
});
|
||||
|
||||
return items;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function normalizeRiskLabels(value: unknown): string[] {
|
||||
return Array.isArray(value) ? value.filter((label): label is string => typeof label === 'string' && !!label.trim()).map(label => label.trim()) : [];
|
||||
}
|
||||
|
||||
function riskLabelsFromItems(items: RiskItem[]): string[] {
|
||||
return items.map(item => item.label).filter(Boolean);
|
||||
}
|
||||
|
||||
function riskInfoFromHeaders(headers: AxiosResponse['headers']): RiskInfo | null {
|
||||
const riskLevel = headers[RISK_LEVEL_HEADER];
|
||||
if (typeof riskLevel !== 'string' || !riskLevel) return null;
|
||||
|
||||
const riskLabelsHeader = headers[RISK_LABELS_HEADER];
|
||||
const riskItemsHeader = headers[RISK_ITEMS_HEADER];
|
||||
const risks = typeof riskItemsHeader === 'string' ? normalizeRiskItems(decodeBase64JSON(riskItemsHeader)) : [];
|
||||
const labels = typeof riskLabelsHeader === 'string' ? normalizeRiskLabels(decodeBase64JSON(riskLabelsHeader)) : riskLabelsFromItems(risks);
|
||||
|
||||
return {
|
||||
risk_level: riskLevel,
|
||||
risk_labels: labels,
|
||||
risks,
|
||||
};
|
||||
}
|
||||
|
||||
function riskInfoFromDetails(details: unknown): RiskInfo | null {
|
||||
if (!details || typeof details !== 'object') return null;
|
||||
|
||||
const riskLevel = 'risk_level' in details ? (details as { risk_level?: unknown }).risk_level : undefined;
|
||||
const riskLabels = 'risk_labels' in details ? (details as { risk_labels?: unknown }).risk_labels : undefined;
|
||||
const riskItems = 'risks' in details ? (details as { risks?: unknown }).risks : undefined;
|
||||
if (typeof riskLevel !== 'string' || !riskLevel) return null;
|
||||
|
||||
const risks = normalizeRiskItems(riskItems);
|
||||
const labels = normalizeRiskLabels(riskLabels);
|
||||
|
||||
return {
|
||||
risk_level: riskLevel,
|
||||
risk_labels: labels.length ? labels : riskLabelsFromItems(risks),
|
||||
risks,
|
||||
};
|
||||
}
|
||||
|
||||
function showRiskWarning(riskInfo: RiskInfo): void {
|
||||
showRiskWarningToast(riskInfo);
|
||||
}
|
||||
|
||||
function showRiskBlockedDialog(riskInfo: RiskInfo): void {
|
||||
if (typeof window === 'undefined') return;
|
||||
window.dispatchEvent(new CustomEvent<RiskInfo>(RISK_BLOCKED_EVENT, { detail: riskInfo }));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成请求的唯一键
|
||||
@@ -204,11 +102,6 @@ apiClient.interceptors.response.use(
|
||||
cancelTokens.delete(requestKey);
|
||||
pendingRequests.delete(requestKey);
|
||||
|
||||
const riskInfo = riskInfoFromHeaders(response.headers);
|
||||
if (riskInfo) {
|
||||
showRiskWarning(riskInfo);
|
||||
}
|
||||
|
||||
return response;
|
||||
},
|
||||
(error: AxiosError<ApiError>) => {
|
||||
@@ -232,17 +125,6 @@ apiClient.interceptors.response.use(
|
||||
|
||||
/* 403 权限不足错误 */
|
||||
if (error.response?.status === 403) {
|
||||
if (error.response.data?.error_code === RISK_BLOCKED_CODE) {
|
||||
const riskInfo = riskInfoFromDetails(error.response.data.details) || riskInfoFromHeaders(error.response.headers);
|
||||
if (riskInfo) {
|
||||
showRiskBlockedDialog(riskInfo);
|
||||
}
|
||||
|
||||
return Promise.reject(
|
||||
new ForbiddenError(error.response.data?.error_msg || '账号存在风险', RISK_BLOCKED_CODE, error.response.data?.details),
|
||||
);
|
||||
}
|
||||
|
||||
return Promise.reject(
|
||||
new ForbiddenError(error.response.data?.error_msg || '权限不足,请过盾后重试', error.response.data?.error_code, error.response.data?.details),
|
||||
);
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
import { BaseService } from '../core/base.service';
|
||||
import type {
|
||||
DailyStatsResponse,
|
||||
TopCustomersResponse,
|
||||
} from './types';
|
||||
|
||||
/**
|
||||
* 仪表板服务
|
||||
* 处理仪表板统计数据相关的 API 请求
|
||||
*/
|
||||
export class DashboardService extends BaseService {
|
||||
protected static readonly basePath = '/api/v1/dashboard';
|
||||
|
||||
/**
|
||||
* 获取每日收支统计
|
||||
* @param days - 查询天数,最大7天,最小1天
|
||||
* @returns 每日统计数据列表
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const stats = await DashboardService.getDailyStats(7);
|
||||
* console.log('每日统计:', stats);
|
||||
* // 输出: [
|
||||
* // { date: '2025-12-22', income: '1000.00', expense: '500.00' },
|
||||
* // { date: '2025-12-21', income: '800.00', expense: '300.00' },
|
||||
* // ...
|
||||
* // ]
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* - days 参数必须在 1-7 之间
|
||||
* - 返回的数据按日期降序排列
|
||||
* - income 和 expense 为字符串格式的金额
|
||||
*/
|
||||
static async getDailyStats(days: number): Promise<DailyStatsResponse> {
|
||||
return this.get<DailyStatsResponse>('/stats/daily', { days });
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Top 客户统计
|
||||
* @param days - 查询天数,最大7天,最小1天
|
||||
* @param limit - 返回数量,最大10条,最小1条
|
||||
* @returns Top 客户列表
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const customers = await DashboardService.getTopCustomers(7, 5);
|
||||
* console.log('Top 5 客户:', customers);
|
||||
* // 输出: [
|
||||
* // { user_id: 123, username: 'user1', total_amount: '5000.00', order_count: 10 },
|
||||
* // { user_id: 456, username: 'user2', total_amount: '3000.00', order_count: 8 },
|
||||
* // ...
|
||||
* // ]
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* - days 参数必须在 1-7 之间
|
||||
* - limit 参数必须在 1-10 之间
|
||||
* - 返回的数据按累计付款金额降序排列
|
||||
* - total_amount 为字符串格式的金额
|
||||
*/
|
||||
static async getTopCustomers(days: number, limit: number): Promise<TopCustomersResponse> {
|
||||
return this.get<TopCustomersResponse>('/stats/top-customers', { days, limit });
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* Dashboard 服务模块
|
||||
*
|
||||
* @description
|
||||
* 提供仪表板统计数据相关的服务,包括:
|
||||
* - 每日收支统计
|
||||
* - Top 客户统计
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { DashboardService } from '@/lib/services/dashboard';
|
||||
*
|
||||
* // 获取最近7天的收支统计
|
||||
* const dailyStats = await DashboardService.getDailyStats(7);
|
||||
*
|
||||
* // 获取 Top 5 客户
|
||||
* const topCustomers = await DashboardService.getTopCustomers(7, 5);
|
||||
* ```
|
||||
*/
|
||||
|
||||
export { DashboardService } from './dashboard.service';
|
||||
export type {
|
||||
DailyStatsItem,
|
||||
DailyStatsResponse,
|
||||
GetDailyStatsRequest,
|
||||
TopCustomer,
|
||||
TopCustomersResponse,
|
||||
GetTopCustomersRequest,
|
||||
} from './types';
|
||||
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* Dashboard 服务类型定义
|
||||
*/
|
||||
|
||||
/**
|
||||
* 每日统计项
|
||||
*/
|
||||
export interface DailyStatsItem {
|
||||
/** 日期,格式: YYYY-MM-DD */
|
||||
date: string;
|
||||
/** 当日收入金额 */
|
||||
income: string;
|
||||
/** 当日支出金额 */
|
||||
expense: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 每日统计响应
|
||||
*/
|
||||
export type DailyStatsResponse = DailyStatsItem[];
|
||||
|
||||
/**
|
||||
* 获取每日统计请求参数
|
||||
*/
|
||||
export interface GetDailyStatsRequest {
|
||||
/** 查询天数,最大7天,最小1天 */
|
||||
days: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Top 客户项
|
||||
*/
|
||||
export interface TopCustomer {
|
||||
/** 客户用户ID */
|
||||
user_id: number;
|
||||
/** 客户用户名 */
|
||||
username: string;
|
||||
/** 累计付款金额 */
|
||||
total_amount: string;
|
||||
/** 订单数量 */
|
||||
order_count: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Top 客户响应
|
||||
*/
|
||||
export type TopCustomersResponse = TopCustomer[];
|
||||
|
||||
/**
|
||||
* 获取 Top 客户请求参数
|
||||
*/
|
||||
export interface GetTopCustomersRequest {
|
||||
/** 查询天数,最大7天,最小1天 */
|
||||
days: number;
|
||||
/** 返回数量,最大10条,最小1条 */
|
||||
limit: number;
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
import { BaseService } from '../core/base.service';
|
||||
import type {
|
||||
ListDisputesRequest,
|
||||
ListDisputesResponse,
|
||||
RefundReviewRequest,
|
||||
CloseDisputeRequest,
|
||||
CreateDisputeRequest,
|
||||
CreateDisputeResponse,
|
||||
} from './types';
|
||||
|
||||
/**
|
||||
* 争议服务
|
||||
* 处理争议相关的 API 请求
|
||||
*/
|
||||
export class DisputeService extends BaseService {
|
||||
protected static readonly basePath = '/api/v1/order';
|
||||
|
||||
/**
|
||||
* 创建争议
|
||||
* @param data - 争议信息
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {NotFoundError} 当订单不存在或不符合争议条件时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await DisputeService.createDispute({
|
||||
* order_id: 123,
|
||||
* reason: '商品质量问题'
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
static async createDispute(data: CreateDisputeRequest): Promise<CreateDisputeResponse> {
|
||||
return this.post<CreateDisputeResponse>('/dispute', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户发起的争议列表
|
||||
* @param params - 查询参数
|
||||
* @returns 争议列表
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const result = await DisputeService.listDisputes({
|
||||
* page: 1,
|
||||
* page_size: 20,
|
||||
* status: 'disputing'
|
||||
* });
|
||||
* console.log('争议数量:', result.total);
|
||||
* ```
|
||||
*/
|
||||
static async listDisputes(
|
||||
params: ListDisputesRequest
|
||||
): Promise<ListDisputesResponse> {
|
||||
return this.post<ListDisputesResponse>('/disputes', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询商户的争议列表
|
||||
* @param params - 查询参数
|
||||
* @returns 争议列表
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const result = await DisputeService.listMerchantDisputes({
|
||||
* page: 1,
|
||||
* page_size: 20
|
||||
* });
|
||||
* console.log('商户争议数量:', result.total);
|
||||
* ```
|
||||
*/
|
||||
static async listMerchantDisputes(
|
||||
params: ListDisputesRequest
|
||||
): Promise<ListDisputesResponse> {
|
||||
return this.post<ListDisputesResponse>('/disputes/merchant', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款审核(商户使用)
|
||||
* @param data - 审核请求
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {NotFoundError} 当争议不存在时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // 同意退款
|
||||
* await DisputeService.refundReview({
|
||||
* dispute_id: 123,
|
||||
* status: 'refund'
|
||||
* });
|
||||
*
|
||||
* // 拒绝退款
|
||||
* await DisputeService.refundReview({
|
||||
* dispute_id: 123,
|
||||
* status: 'closed',
|
||||
* reason: '不符合退款条件'
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
static async refundReview(data: RefundReviewRequest): Promise<void> {
|
||||
return this.post('/refund-review', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭争议(用户主动关闭)
|
||||
* @param data - 关闭争议请求
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {NotFoundError} 当争议不存在时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await DisputeService.closeDispute({
|
||||
* dispute_id: 123
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
static async closeDispute(data: CloseDisputeRequest): Promise<void> {
|
||||
return this.post('/dispute/close', data);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/**
|
||||
* 争议服务模块
|
||||
*
|
||||
* @description
|
||||
* 提供争议处理相关的功能,包括:
|
||||
* - 创建争议
|
||||
* - 查询用户发起的争议列表
|
||||
* - 查询商户的争议列表
|
||||
* - 退款审核(商户)
|
||||
* - 关闭争议(用户)
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { DisputeService } from '@/lib/services';
|
||||
*
|
||||
* // 创建争议
|
||||
* await DisputeService.createDispute({
|
||||
* order_id: 123,
|
||||
* reason: '商品质量问题'
|
||||
* });
|
||||
*
|
||||
* // 查询争议列表
|
||||
* const disputes = await DisputeService.listDisputes({
|
||||
* page: 1,
|
||||
* page_size: 20
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
|
||||
export { DisputeService } from './dispute.service';
|
||||
export type * from './types';
|
||||
@@ -1,105 +0,0 @@
|
||||
/**
|
||||
* 争议状态
|
||||
*/
|
||||
export type DisputeStatus = 'disputing' | 'refund' | 'closed';
|
||||
|
||||
/**
|
||||
* 争议信息
|
||||
*/
|
||||
export interface Dispute {
|
||||
/** 争议 ID */
|
||||
id: string;
|
||||
/** 订单 ID */
|
||||
order_id: string;
|
||||
/** 发起者用户 ID */
|
||||
initiator_user_id: number;
|
||||
/** 争议原因 */
|
||||
reason: string;
|
||||
/** 争议状态 */
|
||||
status: DisputeStatus;
|
||||
/** 处理者用户 ID */
|
||||
handler_user_id?: number;
|
||||
/** 发起者账户 */
|
||||
initiator_username: string;
|
||||
/** 处理者账户 */
|
||||
handler_username: string;
|
||||
/** 创建时间 */
|
||||
created_at: string;
|
||||
/** 更新时间 */
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 争议列表项(包含订单信息)
|
||||
*/
|
||||
export interface DisputeWithOrder extends Dispute {
|
||||
/** 订单名称 */
|
||||
order_name: string;
|
||||
/** 收款方账户 */
|
||||
payee_username: string;
|
||||
/** 订单金额 */
|
||||
amount: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询争议列表请求
|
||||
*/
|
||||
export interface ListDisputesRequest {
|
||||
/** 页码,从 1 开始 */
|
||||
page: number;
|
||||
/** 每页数量,1-100 */
|
||||
page_size: number;
|
||||
/** 状态筛选(可选) */
|
||||
status?: DisputeStatus;
|
||||
/** 争议 ID(可选) */
|
||||
dispute_id?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 争议列表响应
|
||||
*/
|
||||
export interface ListDisputesResponse {
|
||||
/** 总记录数 */
|
||||
total: number;
|
||||
/** 当前页码 */
|
||||
page: number;
|
||||
/** 每页数量 */
|
||||
page_size: number;
|
||||
/** 争议列表 */
|
||||
disputes: DisputeWithOrder[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款审核请求
|
||||
*/
|
||||
export interface RefundReviewRequest {
|
||||
/** 争议 ID */
|
||||
dispute_id: string;
|
||||
/** 审核结果 */
|
||||
status: 'refund' | 'closed';
|
||||
/** 拒绝原因(status 为 closed 时必填,最大 100 字符) */
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭争议请求
|
||||
*/
|
||||
export interface CloseDisputeRequest {
|
||||
/** 争议 ID */
|
||||
dispute_id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建争议请求
|
||||
*/
|
||||
export interface CreateDisputeRequest {
|
||||
/** 订单 ID */
|
||||
order_id: string;
|
||||
/** 争议原因(最大 100 字符) */
|
||||
reason: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建争议响应
|
||||
*/
|
||||
export type CreateDisputeResponse = Dispute;
|
||||
@@ -8,7 +8,7 @@
|
||||
* import services from '@/lib/services';
|
||||
*
|
||||
* const user = await services.auth.getUserInfo();
|
||||
* const transactions = await services.transaction.getTransactions({ page: 1, page_size: 20 });
|
||||
* const systemConfig = await services.admin.listSystemConfigs();
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
@@ -21,15 +21,9 @@
|
||||
*/
|
||||
|
||||
import { AuthService } from './auth';
|
||||
import { TransactionService } from './transaction';
|
||||
import { MerchantService } from './merchant';
|
||||
import { AdminService } from './admin';
|
||||
import { UserService } from './user';
|
||||
import { DisputeService } from './dispute';
|
||||
import { ConfigService } from './config';
|
||||
import { DashboardService } from './dashboard';
|
||||
import { LeaderboardService } from './leaderboard';
|
||||
import { RedEnvelopeService } from './redenvelope';
|
||||
import { UploadService } from './upload';
|
||||
|
||||
/**
|
||||
@@ -42,24 +36,12 @@ import { UploadService } from './upload';
|
||||
const services = {
|
||||
/** 认证服务 */
|
||||
auth: AuthService,
|
||||
/** 交易服务 */
|
||||
transaction: TransactionService,
|
||||
/** 商户服务 */
|
||||
merchant: MerchantService,
|
||||
/** 管理员服务 */
|
||||
admin: AdminService,
|
||||
/** 用户服务 */
|
||||
user: UserService,
|
||||
/** 争议服务 */
|
||||
dispute: DisputeService,
|
||||
/** 配置服务 */
|
||||
config: ConfigService,
|
||||
/** 仪表板服务 */
|
||||
dashboard: DashboardService,
|
||||
/** 排行榜服务 */
|
||||
leaderboard: LeaderboardService,
|
||||
/** 红包服务 */
|
||||
redEnvelope: RedEnvelopeService,
|
||||
/** 上传服务 */
|
||||
upload: UploadService,
|
||||
} as const;
|
||||
@@ -102,62 +84,16 @@ export type {
|
||||
export { AuthService, TrustLevel } from './auth';
|
||||
export type { User, OAuthLoginUrlResponse, OAuthCallbackRequest } from './auth';
|
||||
|
||||
// 交易服务
|
||||
export { TransactionService } from './transaction';
|
||||
export { DEFAULT_ORDER_TYPES } from './transaction';
|
||||
export type {
|
||||
Order,
|
||||
OrderType,
|
||||
OrderStatus,
|
||||
TransferStatus,
|
||||
TransactionQueryParams,
|
||||
TransactionListResponse,
|
||||
} from './transaction';
|
||||
|
||||
// 争议服务
|
||||
export { DisputeService } from './dispute';
|
||||
export type {
|
||||
Dispute,
|
||||
DisputeStatus,
|
||||
DisputeWithOrder,
|
||||
ListDisputesRequest,
|
||||
ListDisputesResponse,
|
||||
RefundReviewRequest,
|
||||
CloseDisputeRequest,
|
||||
CreateDisputeRequest,
|
||||
} from './dispute';
|
||||
|
||||
// 配置服务
|
||||
export { ConfigService } from './config';
|
||||
export type { PublicConfigResponse } from './config';
|
||||
|
||||
// 商户服务
|
||||
export { MerchantService } from './merchant';
|
||||
export type {
|
||||
MerchantAPIKey,
|
||||
CreateAPIKeyRequest,
|
||||
UpdateAPIKeyRequest,
|
||||
PayMerchantOrderRequest,
|
||||
GetMerchantOrderRequest,
|
||||
GetMerchantOrderResponse,
|
||||
PaymentLink,
|
||||
CreatePaymentLinkRequest,
|
||||
QueryMerchantOrderRequest,
|
||||
QueryMerchantOrderResponse,
|
||||
RefundMerchantOrderRequest,
|
||||
RefundMerchantOrderResponse,
|
||||
GetPaymentLinkInfoResponse,
|
||||
} from './merchant';
|
||||
|
||||
// 管理员服务
|
||||
export { AdminService } from './admin';
|
||||
export type {
|
||||
SystemConfig,
|
||||
CreateSystemConfigRequest,
|
||||
UpdateSystemConfigRequest,
|
||||
UserPayConfig,
|
||||
CreateUserPayConfigRequest,
|
||||
UpdateUserPayConfigRequest,
|
||||
TaskMeta,
|
||||
DispatchTaskRequest,
|
||||
AdminUser,
|
||||
@@ -168,44 +104,6 @@ export type {
|
||||
|
||||
// 用户服务
|
||||
export { UserService } from './user';
|
||||
export type { UpdatePayKeyRequest } from './user';
|
||||
|
||||
// 仪表板服务
|
||||
export { DashboardService } from './dashboard';
|
||||
export type {
|
||||
DailyStatsItem,
|
||||
DailyStatsResponse,
|
||||
GetDailyStatsRequest,
|
||||
TopCustomer,
|
||||
TopCustomersResponse,
|
||||
GetTopCustomersRequest,
|
||||
} from './dashboard';
|
||||
|
||||
// 红包服务
|
||||
export { RedEnvelopeService } from './redenvelope';
|
||||
export type {
|
||||
RedEnvelopeType,
|
||||
RedEnvelopeStatus,
|
||||
RedEnvelope,
|
||||
RedEnvelopeClaim,
|
||||
CreateRedEnvelopeRequest,
|
||||
CreateRedEnvelopeResponse,
|
||||
ClaimRedEnvelopeRequest,
|
||||
ClaimRedEnvelopeResponse,
|
||||
RedEnvelopeDetailResponse,
|
||||
RedEnvelopeListParams,
|
||||
RedEnvelopeListResponse,
|
||||
} from './redenvelope';
|
||||
|
||||
// 排行榜服务
|
||||
export { LeaderboardService } from './leaderboard';
|
||||
export type {
|
||||
LeaderboardEntry,
|
||||
LeaderboardListRequest,
|
||||
LeaderboardListResponse,
|
||||
UserRankInfo,
|
||||
UserRankResponse,
|
||||
} from './leaderboard';
|
||||
|
||||
// 上传服务
|
||||
export { UploadService } from './upload';
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Leaderboard 服务模块
|
||||
*
|
||||
* @description
|
||||
* 提供排行榜相关的服务,基于 available_balance 排序
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { LeaderboardService } from '@/lib/services/leaderboard';
|
||||
*
|
||||
* // 获取排行榜
|
||||
* const list = await LeaderboardService.getList({ page: 1, page_size: 20 });
|
||||
*
|
||||
* // 获取当前用户排名
|
||||
* const myRank = await LeaderboardService.getMyRank();
|
||||
* ```
|
||||
*/
|
||||
|
||||
export { LeaderboardService } from "./leaderboard.service";
|
||||
export type {
|
||||
LeaderboardEntry,
|
||||
LeaderboardListRequest,
|
||||
LeaderboardListResponse,
|
||||
UserRankInfo,
|
||||
UserRankResponse,
|
||||
} from "./types";
|
||||
@@ -1,42 +0,0 @@
|
||||
import { BaseService } from "../core/base.service";
|
||||
import type {
|
||||
LeaderboardListRequest,
|
||||
LeaderboardListResponse,
|
||||
UserRankResponse,
|
||||
} from "./types";
|
||||
|
||||
/**
|
||||
* 排行榜服务
|
||||
* 基于 available_balance 排序
|
||||
*/
|
||||
export class LeaderboardService extends BaseService {
|
||||
protected static readonly basePath = "/api/v1/leaderboard";
|
||||
|
||||
/**
|
||||
* 获取排行榜列表
|
||||
* @param params - 分页参数
|
||||
* @returns 排行榜列表响应
|
||||
*/
|
||||
static async getList(
|
||||
params?: LeaderboardListRequest,
|
||||
): Promise<LeaderboardListResponse> {
|
||||
return this.get<LeaderboardListResponse>("", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户排名
|
||||
* @returns 用户排名响应
|
||||
*/
|
||||
static async getMyRank(): Promise<UserRankResponse> {
|
||||
return this.get<UserRankResponse>("/me");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定用户排名
|
||||
* @param userId - 用户 ID
|
||||
* @returns 用户排名响应
|
||||
*/
|
||||
static async getUserRankById(userId: number): Promise<UserRankResponse> {
|
||||
return this.get<UserRankResponse>(`/users/${ userId }`);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/**
|
||||
* Leaderboard 服务类型定义
|
||||
* 使用 available_balance 排序
|
||||
*/
|
||||
|
||||
/**
|
||||
* 排行榜条目
|
||||
*/
|
||||
export interface LeaderboardEntry {
|
||||
/** 用户ID */
|
||||
user_id: number;
|
||||
/** 用户名 */
|
||||
username: string;
|
||||
/** 头像URL */
|
||||
avatar_url: string;
|
||||
/** 可用余额 */
|
||||
available_balance: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 排行榜请求参数
|
||||
*/
|
||||
export interface LeaderboardListRequest {
|
||||
/** 页码 */
|
||||
page: number;
|
||||
/** 每页数量 */
|
||||
page_size: number;
|
||||
/** 索引签名 */
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* 排行榜列表响应
|
||||
*/
|
||||
export interface LeaderboardListResponse {
|
||||
/** 排序字段 */
|
||||
sort_by: string;
|
||||
/** 排序方向 */
|
||||
order: string;
|
||||
/** 当前页码 */
|
||||
page: number;
|
||||
/** 每页数量 */
|
||||
page_size: number;
|
||||
/** 总数 */
|
||||
total: number;
|
||||
/** 排行榜条目列表 */
|
||||
items: LeaderboardEntry[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户排名信息
|
||||
*/
|
||||
export interface UserRankInfo {
|
||||
/** 用户ID */
|
||||
user_id: number;
|
||||
/** 排名 */
|
||||
rank: number;
|
||||
/** 可用余额 */
|
||||
available_balance: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户排名响应
|
||||
*/
|
||||
export interface UserRankResponse {
|
||||
/** 用户排名信息 */
|
||||
user: UserRankInfo;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* 商户服务模块
|
||||
*
|
||||
* @description
|
||||
* 提供商户相关的功能,包括:
|
||||
* - API Key 管理(创建、查询、更新、删除)
|
||||
* - 支付链接管理(创建、列表、删除)
|
||||
* - 商户订单查询和支付
|
||||
* - 商户订单退款
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { MerchantService } from '@/lib/services';
|
||||
*
|
||||
* // 创建 API Key
|
||||
* const apiKey = await MerchantService.createAPIKey({
|
||||
* app_name: '我的应用',
|
||||
* app_homepage_url: 'https://example.com',
|
||||
* redirect_uri: 'https://example.com/callback',
|
||||
* notify_url: 'https://example.com/notify'
|
||||
* });
|
||||
*
|
||||
* // 获取支付链接
|
||||
* const links = await MerchantService.listPaymentLinks(apiKey.id);
|
||||
* ```
|
||||
*/
|
||||
|
||||
export { MerchantService } from './merchant.service';
|
||||
export type {
|
||||
MerchantAPIKey,
|
||||
CreateAPIKeyRequest,
|
||||
UpdateAPIKeyRequest,
|
||||
PayMerchantOrderRequest,
|
||||
GetMerchantOrderRequest,
|
||||
GetMerchantOrderResponse,
|
||||
PaymentLink,
|
||||
CreatePaymentLinkRequest,
|
||||
PayByLinkRequest,
|
||||
GetPaymentLinkInfoResponse,
|
||||
QueryMerchantOrderRequest,
|
||||
QueryMerchantOrderResponse,
|
||||
RefundMerchantOrderRequest,
|
||||
RefundMerchantOrderResponse,
|
||||
} from './types';
|
||||
|
||||
@@ -1,491 +0,0 @@
|
||||
import { AxiosHeaders, type InternalAxiosRequestConfig } from 'axios';
|
||||
import { BaseService } from '../core/base.service';
|
||||
import { encodeBase64 } from '../../utils';
|
||||
import type {
|
||||
MerchantAPIKey,
|
||||
CreateAPIKeyRequest,
|
||||
UpdateAPIKeyRequest,
|
||||
PayMerchantOrderRequest,
|
||||
GetMerchantOrderRequest,
|
||||
GetMerchantOrderResponse,
|
||||
PaymentLink,
|
||||
CreatePaymentLinkRequest,
|
||||
UpdatePaymentLinkRequest,
|
||||
PayByLinkRequest,
|
||||
QueryMerchantOrderRequest,
|
||||
QueryMerchantOrderResponse,
|
||||
RefundMerchantOrderRequest,
|
||||
RefundMerchantOrderResponse,
|
||||
MerchantDistributeRequest,
|
||||
MerchantDistributeResponse,
|
||||
} from './types';
|
||||
|
||||
/**
|
||||
* 商户服务
|
||||
* 处理商户 API Key 管理和支付订单相关的 API 请求
|
||||
*/
|
||||
export class MerchantService extends BaseService {
|
||||
protected static readonly basePath = '/api/v1/merchant';
|
||||
|
||||
// ==================== API Key 管理 ====================
|
||||
|
||||
/**
|
||||
* 创建商户 API Key
|
||||
* @param request - 创建 API Key 的请求参数
|
||||
* @returns 创建的 API Key 信息(包含 client_secret)
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const apiKey = await MerchantService.createAPIKey({
|
||||
* app_name: '我的应用',
|
||||
* app_homepage_url: 'https://example.com',
|
||||
* app_description: '应用描述',
|
||||
* redirect_uri: 'https://example.com/callback'
|
||||
* });
|
||||
* console.log('Client ID:', apiKey.client_id);
|
||||
* console.log('Client Secret:', apiKey.client_secret); // 请保存,之后无法再次获取
|
||||
* ```
|
||||
*/
|
||||
static async createAPIKey(request: CreateAPIKeyRequest): Promise<MerchantAPIKey> {
|
||||
return this.post<MerchantAPIKey>('/api-keys', request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商户 API Key 列表
|
||||
* @returns API Key 列表
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const apiKeys = await MerchantService.listAPIKeys();
|
||||
* console.log('API Keys 数量:', apiKeys.length);
|
||||
* ```
|
||||
*/
|
||||
static async listAPIKeys(): Promise<MerchantAPIKey[]> {
|
||||
return this.get<MerchantAPIKey[]>('/api-keys');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个商户 API Key
|
||||
* @param id - API Key ID
|
||||
* @returns API Key 详细信息
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {NotFoundError} 当 API Key 不存在时
|
||||
* @throws {ForbiddenError} 当无权访问该 API Key 时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const apiKey = await MerchantService.getAPIKey(123);
|
||||
* console.log('应用名称:', apiKey.app_name);
|
||||
* ```
|
||||
*/
|
||||
static async getAPIKey(id: string): Promise<MerchantAPIKey> {
|
||||
return this.get<MerchantAPIKey>(`/api-keys/${ id }`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商户 API Key
|
||||
* @param id - API Key ID
|
||||
* @param request - 更新 API Key 的请求参数
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {NotFoundError} 当 API Key 不存在时
|
||||
* @throws {ForbiddenError} 当无权访问该 API Key 时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await MerchantService.updateAPIKey(123, {
|
||||
* app_name: '新的应用名称',
|
||||
* app_description: '新的描述'
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
static async updateAPIKey(
|
||||
id: string,
|
||||
request: UpdateAPIKeyRequest,
|
||||
): Promise<void> {
|
||||
return this.put<void>(`/api-keys/${ id }`, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除商户 API Key
|
||||
* @param id - API Key ID
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {NotFoundError} 当 API Key 不存在时
|
||||
* @throws {ForbiddenError} 当无权访问该 API Key 时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await MerchantService.deleteAPIKey(123);
|
||||
* ```
|
||||
*/
|
||||
static async deleteAPIKey(id: string): Promise<void> {
|
||||
return this.delete<void>(`/api-keys/${ id }`);
|
||||
}
|
||||
|
||||
// ==================== 支付链接管理 ====================
|
||||
|
||||
/**
|
||||
* 创建支付链接
|
||||
* @param apiKeyId - API Key ID
|
||||
* @param request - 创建支付链接请求参数
|
||||
* @returns 创建的支付链接信息
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {NotFoundError} 当 API Key 不存在时
|
||||
* @throws {ForbiddenError} 当无权访问该 API Key 时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const link = await MerchantService.createPaymentLink(123, {
|
||||
* product_name: '测试商品',
|
||||
* amount: 100,
|
||||
* remark: '备注信息'
|
||||
* });
|
||||
* console.log('支付链接 Token:', link.token);
|
||||
* ```
|
||||
*/
|
||||
static async createPaymentLink(apiKeyId: string, request: CreatePaymentLinkRequest): Promise<PaymentLink> {
|
||||
return this.post<PaymentLink>(`/api-keys/${ apiKeyId }/payment-links`, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支付链接列表
|
||||
* @param apiKeyId - API Key ID
|
||||
* @returns 支付链接列表
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {NotFoundError} 当 API Key 不存在时
|
||||
* @throws {ForbiddenError} 当无权访问该 API Key 时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const links = await MerchantService.listPaymentLinks(123);
|
||||
* console.log('支付链接数量:', links.length);
|
||||
* ```
|
||||
*/
|
||||
static async listPaymentLinks(apiKeyId: string): Promise<PaymentLink[]> {
|
||||
return this.get<PaymentLink[]>(`/api-keys/${ apiKeyId }/payment-links`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除支付链接
|
||||
* @param apiKeyId - API Key ID
|
||||
* @param linkId - 支付链接 ID
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {NotFoundError} 当 API Key 或支付链接不存在时
|
||||
* @throws {ForbiddenError} 当无权访问该 API Key 时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await MerchantService.deletePaymentLink(123, 456);
|
||||
* ```
|
||||
*/
|
||||
static async deletePaymentLink(apiKeyId: string, linkId: string): Promise<void> {
|
||||
return this.delete<void>(`/api-keys/${ apiKeyId }/payment-links/${ linkId }`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新支付链接
|
||||
* @param apiKeyId - API Key ID
|
||||
* @param linkId - 支付链接 ID
|
||||
* @param request - 更新支付链接请求参数
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {NotFoundError} 当 API Key 或支付链接不存在时
|
||||
* @throws {ForbiddenError} 当无权访问该 API Key 时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await MerchantService.updatePaymentLink(123, 456, {
|
||||
* product_name: '更新后的商品',
|
||||
* amount: 200,
|
||||
* remark: '新的备注',
|
||||
* total_limit: 100,
|
||||
* user_limit: 1
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
static async updatePaymentLink(
|
||||
apiKeyId: string,
|
||||
linkId: string,
|
||||
request: UpdatePaymentLinkRequest
|
||||
): Promise<void> {
|
||||
return this.put<void>(`/api-keys/${ apiKeyId }/payment-links/${ linkId }`, request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过 Token 获取支付链接信息
|
||||
*
|
||||
* @description
|
||||
* 公开接口,用于支付页面获取支付链接详情。
|
||||
* 无需登录即可访问。
|
||||
*
|
||||
* @param token - 支付链接 Token
|
||||
* @returns 支付链接信息(包含商品名称、金额等)
|
||||
* @throws {NotFoundError} 当支付链接不存在时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const linkInfo = await MerchantService.getPaymentLinkByToken('abc123');
|
||||
* console.log('商品名称:', linkInfo.payment_link.product_name);
|
||||
* console.log('金额:', linkInfo.payment_link.amount);
|
||||
* ```
|
||||
*/
|
||||
static async getPaymentLinkByToken(token: string): Promise<PaymentLink> {
|
||||
return this.get<PaymentLink>(`/payment-links/${ token }`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过支付链接支付
|
||||
*
|
||||
* @description
|
||||
* 用户使用此接口通过支付链接进行支付。
|
||||
* 需要用户登录,并且用户余额充足。
|
||||
*
|
||||
* @param request - 支付请求参数(token 和 pay_key)
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当用户未登录时
|
||||
* @throws {NotFoundError} 当支付链接不存在时
|
||||
* @throws {ApiErrorBase} 当余额不足、支付密码错误等业务错误时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* try {
|
||||
* await MerchantService.payByLink({
|
||||
* token: 'abc123',
|
||||
* pay_key: '123456',
|
||||
* remark: '备注信息'
|
||||
* });
|
||||
* console.log('支付成功');
|
||||
* } catch (error) {
|
||||
* console.error('支付失败:', error.message);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* - 用户不能支付自己创建的支付链接
|
||||
* - 用户余额必须充足
|
||||
* - 支付成功后会扣除手续费(根据商户的支付等级)
|
||||
*/
|
||||
static async payByLink(request: PayByLinkRequest): Promise<void> {
|
||||
return this.post<void>('/payment-links/pay', request);
|
||||
}
|
||||
|
||||
// ==================== 商户支付订单 ====================
|
||||
|
||||
/**
|
||||
* 查询商户订单信息
|
||||
*
|
||||
* @description
|
||||
* 查询商户创建的订单详细信息,用于支付页面显示订单信息。
|
||||
* 订单必须处于待支付状态。
|
||||
*
|
||||
* @param request - 查询订单请求参数
|
||||
* @returns 订单信息和用户积分配置
|
||||
* @throws {UnauthorizedError} 当用户未登录时
|
||||
* @throws {NotFoundError} 当订单不存在时
|
||||
* @throws {ValidationError} 当订单号格式错误时
|
||||
* @throws {ApiErrorBase} 当订单已过期或已支付等业务错误时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // 从 URL 获取订单号
|
||||
* const params = new URLSearchParams(window.location.search);
|
||||
* const orderNo = params.get('order_no');
|
||||
*
|
||||
* if (orderNo) {
|
||||
* try {
|
||||
* const orderInfo = await MerchantService.getMerchantOrder({ order_no: orderNo });
|
||||
* console.log('订单信息:', orderInfo.order);
|
||||
* console.log('积分配置:', orderInfo.user_pay_config);
|
||||
* } catch (error) {
|
||||
* console.error('查询订单失败:', error.message);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* - 订单必须处于待支付状态
|
||||
* - 返回的用户积分配置包含手续费率等信息
|
||||
*/
|
||||
static async getMerchantOrder(request: GetMerchantOrderRequest): Promise<GetMerchantOrderResponse> {
|
||||
return this.get<GetMerchantOrderResponse>('/payment/order', { order_no: request.order_no });
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付商户订单
|
||||
*
|
||||
* @description
|
||||
* 用户使用此接口支付商户创建的订单。
|
||||
* 需要用户登录,并且用户余额充足。
|
||||
*
|
||||
* @param request - 支付订单请求参数
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当用户未登录时
|
||||
* @throws {NotFoundError} 当订单不存在或已过期时
|
||||
* @throws {ValidationError} 当订单号格式错误时
|
||||
* @throws {ApiErrorBase} 当余额不足、订单已支付等业务错误时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // 从 URL 获取订单号
|
||||
* const params = new URLSearchParams(window.location.search);
|
||||
* const orderNo = params.get('order_no');
|
||||
*
|
||||
* if (orderNo) {
|
||||
* try {
|
||||
* await MerchantService.payMerchantOrder({
|
||||
* order_no: orderNo,
|
||||
* pay_key: '123456' // 用户的支付密码
|
||||
* });
|
||||
* // 支付成功
|
||||
* console.log('支付成功');
|
||||
* } catch (error) {
|
||||
* console.error('支付失败:', error.message);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* - 用户不能支付自己作为商户创建的订单
|
||||
* - 订单必须在有效期内(5分钟)
|
||||
* - 用户余额必须充足
|
||||
* - 支付成功后会扣除手续费(根据用户的积分等级)
|
||||
*/
|
||||
static async payMerchantOrder(request: PayMerchantOrderRequest): Promise<void> {
|
||||
return this.post<void>('/payment', request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户查询订单状态
|
||||
*
|
||||
* @description
|
||||
* 商户使用此接口主动查询订单的支付状态。
|
||||
* 需要提供商户凭证(Client ID 和 Client Secret)。
|
||||
*
|
||||
* @param params - 查询参数
|
||||
* @returns 订单状态信息
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
* @throws {ApiErrorBase} 当商户凭证无效或订单不存在时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const orderStatus = await MerchantService.queryMerchantOrder({
|
||||
* trade_no: 12345,
|
||||
* pid: 'your_client_id',
|
||||
* key: 'your_client_secret'
|
||||
* });
|
||||
*
|
||||
* if (orderStatus.status === 1) {
|
||||
* console.log('订单已支付');
|
||||
* } else {
|
||||
* console.log('订单未支付');
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* - 使用 GET 请求调用 `/api.php` 接口
|
||||
* - 返回的 status 字段:1 表示已支付,0 表示未支付
|
||||
*/
|
||||
static async queryMerchantOrder(
|
||||
params: QueryMerchantOrderRequest
|
||||
): Promise<QueryMerchantOrderResponse> {
|
||||
return this.rawGet<QueryMerchantOrderResponse>('/epay/api.php', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户退款
|
||||
*
|
||||
* @description
|
||||
* 商户使用此接口对已支付的订单进行退款。
|
||||
* 需要提供商户凭证(Client ID 和 Client Secret)。
|
||||
* 退款金额必须与订单金额一致。
|
||||
*
|
||||
* @param params - 退款请求参数
|
||||
* @returns 退款结果
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
* @throws {ApiErrorBase} 当商户凭证无效、订单不存在或退款失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const result = await MerchantService.refundMerchantOrder({
|
||||
* trade_no: 12345,
|
||||
* money: 99.99,
|
||||
* pid: 'your_client_id',
|
||||
* key: 'your_client_secret'
|
||||
* });
|
||||
*
|
||||
* if (result.code === 1) {
|
||||
* console.log('退款成功');
|
||||
* } else {
|
||||
* console.error('退款失败:', result.msg);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* - 使用 POST 请求调用 `/api.php` 接口
|
||||
* - 退款金额必须与订单金额完全一致
|
||||
* - 只能对状态为"成功"的订单进行退款
|
||||
* - 返回的 code 字段:1 表示成功,-1 表示失败
|
||||
*/
|
||||
static async refundMerchantOrder(
|
||||
params: RefundMerchantOrderRequest
|
||||
): Promise<RefundMerchantOrderResponse> {
|
||||
return this.rawPost<RefundMerchantOrderResponse>('/epay/api.php', params);
|
||||
}
|
||||
|
||||
// ==================== 商户分发 ====================
|
||||
|
||||
/**
|
||||
* 商户向用户分发积分
|
||||
*
|
||||
* @description
|
||||
* 商户使用此接口向指定用户分发积分。
|
||||
* 需要商户认证(Basic Auth),分发金额会从商户余额中扣除,
|
||||
* 收款人获得扣除分发费率后的金额。
|
||||
*
|
||||
* @param request - 分发请求参数
|
||||
* @returns 分发结果(包含订单号)
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
* @throws {ApiErrorBase} 当余额不足、用户不存在等业务错误时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const result = await MerchantService.distribute({
|
||||
* user_id: 123,
|
||||
* username: 'alice',
|
||||
* amount: 100,
|
||||
* out_trade_no: 'DIST20251231001',
|
||||
* remark: '新年奖励'
|
||||
* });
|
||||
* console.log('订单号:', result.trade_no);
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* - 使用 POST 请求调用 `/pay/distribute` 接口(前端通过 `/lpay/distribute` 代理)
|
||||
* - 需要通过 Basic Auth 提供商户凭证
|
||||
* - 不能分发给商户自己
|
||||
* - 商户余额必须充足
|
||||
* - 分发会扣除分发费率(根据商户的支付等级)
|
||||
*/
|
||||
static async distribute(
|
||||
request: MerchantDistributeRequest,
|
||||
auth?: { client_id: string; client_secret: string }
|
||||
): Promise<MerchantDistributeResponse> {
|
||||
const config: InternalAxiosRequestConfig | undefined = auth
|
||||
? {
|
||||
headers: new AxiosHeaders({
|
||||
Authorization: `Basic ${encodeBase64(`${auth.client_id}:${auth.client_secret}`)}`,
|
||||
}),
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return this.rawPost<MerchantDistributeResponse>('/lpay/distribute', request, config);
|
||||
}
|
||||
}
|
||||
@@ -1,362 +0,0 @@
|
||||
/**
|
||||
* 商户 API Key 信息
|
||||
*/
|
||||
export interface MerchantAPIKey {
|
||||
/** API Key ID */
|
||||
id: string;
|
||||
/** 用户 ID */
|
||||
user_id: string;
|
||||
/** 客户端 ID */
|
||||
client_id: string;
|
||||
/** 客户端密钥 */
|
||||
client_secret: string;
|
||||
/** 应用名称 */
|
||||
app_name: string;
|
||||
/** 应用主页 URL */
|
||||
app_homepage_url: string;
|
||||
/** 应用描述 */
|
||||
app_description: string;
|
||||
/** 重定向 URI */
|
||||
redirect_uri?: string;
|
||||
/** 通知 URL */
|
||||
notify_url: string;
|
||||
/** 公钥 (Base64) */
|
||||
public_key?: string;
|
||||
/** 测试模式 */
|
||||
test_mode: boolean;
|
||||
/** 创建时间 */
|
||||
created_at: string;
|
||||
/** 更新时间 */
|
||||
updated_at: string;
|
||||
/** 删除时间(软删除) */
|
||||
deleted_at: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建商户 API Key 请求参数
|
||||
*/
|
||||
export interface CreateAPIKeyRequest {
|
||||
/** 应用名称(最大20字符) */
|
||||
app_name: string;
|
||||
/** 应用主页 URL(最大100字符,必须是有效的 URL) */
|
||||
app_homepage_url: string;
|
||||
/** 应用描述(最大100字符,可选) */
|
||||
app_description?: string;
|
||||
/** 重定向 URI(最大100字符,必须是有效的 URL,可选) */
|
||||
redirect_uri?: string;
|
||||
/** 通知 URL(最大100字符,必须是有效的 URL) */
|
||||
notify_url: string;
|
||||
/** 公钥 (Base64 编码,32字节,可选) */
|
||||
public_key?: string;
|
||||
/** 测试模式(可选,默认为 false) */
|
||||
test_mode?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商户 API Key 请求参数
|
||||
*/
|
||||
export interface UpdateAPIKeyRequest {
|
||||
/** 应用名称(最大20字符,可选) */
|
||||
app_name?: string;
|
||||
/** 应用主页 URL(最大100字符,必须是有效的 URL,可选) */
|
||||
app_homepage_url?: string;
|
||||
/** 应用描述(最大100字符,可选) */
|
||||
app_description?: string;
|
||||
/** 重定向 URI(最大100字符,必须是有效的 URL,可选) */
|
||||
redirect_uri?: string;
|
||||
/** 通知 URL(最大100字符,必须是有效的 URL,可选) */
|
||||
notify_url?: string;
|
||||
/** 公钥 (Base64 编码,32字节,可选) */
|
||||
public_key?: string;
|
||||
/** 测试模式(可选) */
|
||||
test_mode?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付商户订单请求参数
|
||||
*/
|
||||
export interface PayMerchantOrderRequest {
|
||||
/** 订单号(加密后的订单ID) */
|
||||
order_no: string;
|
||||
/** 支付密码(6位数字) */
|
||||
pay_key: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询商户订单请求参数
|
||||
*/
|
||||
export interface GetMerchantOrderRequest {
|
||||
/** 订单号(加密后的订单ID) */
|
||||
order_no: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询商户订单响应
|
||||
*/
|
||||
export interface GetMerchantOrderResponse {
|
||||
/** 订单信息 */
|
||||
order: {
|
||||
/** 订单ID */
|
||||
id: string;
|
||||
/** 订单号 */
|
||||
order_no: string;
|
||||
/** 订单名称 */
|
||||
order_name: string;
|
||||
/** 付款方账户 */
|
||||
payer_username: string;
|
||||
/** 收款方账户 */
|
||||
payee_username: string;
|
||||
/** 交易金额 */
|
||||
amount: string;
|
||||
/** 订单状态 */
|
||||
status: string;
|
||||
/** 订单类型 */
|
||||
type: string;
|
||||
/** 支付类型 */
|
||||
payment_type: string;
|
||||
/** 备注 */
|
||||
remark: string;
|
||||
/** 客户端ID */
|
||||
client_id: string;
|
||||
/** 同步跳转URL */
|
||||
return_url: string;
|
||||
/** 异步通知URL */
|
||||
notify_url: string;
|
||||
/** 交易时间 */
|
||||
trade_time: string | null;
|
||||
/** 创建时间 */
|
||||
created_at: string;
|
||||
/** 更新时间 */
|
||||
updated_at: string;
|
||||
};
|
||||
/** 用户积分配置信息 */
|
||||
user_pay_config: {
|
||||
/** 配置ID */
|
||||
id: string;
|
||||
/** 积分等级 */
|
||||
level: number;
|
||||
/** 最低分数 */
|
||||
min_score: number;
|
||||
/** 最高分数 */
|
||||
max_score: number | null;
|
||||
/** 每日限额 */
|
||||
daily_limit: number | null;
|
||||
/** 手续费率 */
|
||||
fee_rate: string;
|
||||
/** 创建时间 */
|
||||
created_at: string;
|
||||
/** 更新时间 */
|
||||
updated_at: string;
|
||||
};
|
||||
/** 商户信息 */
|
||||
merchant: {
|
||||
/** 应用名称 */
|
||||
app_name: string;
|
||||
/** 跳转URI */
|
||||
redirect_uri: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付链接信息
|
||||
*/
|
||||
export interface PaymentLink {
|
||||
/** 链接 ID */
|
||||
id: string;
|
||||
/** 商户 API Key ID */
|
||||
merchant_api_key_id: string;
|
||||
/** 支付链接 Token */
|
||||
token: string;
|
||||
/** 金额 */
|
||||
amount: string;
|
||||
/** 商品名称 */
|
||||
product_name: string;
|
||||
/** 备注 */
|
||||
remark: string;
|
||||
/** 总支付次数限制(可选) */
|
||||
total_limit?: number;
|
||||
/** 单用户支付次数限制(可选) */
|
||||
user_limit?: number;
|
||||
/** 创建时间 */
|
||||
created_at: string;
|
||||
/** 更新时间 */
|
||||
updated_at: string;
|
||||
/** 应用名称 */
|
||||
app_name: string;
|
||||
/** 重定向 URI */
|
||||
redirect_uri: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建支付链接请求参数
|
||||
*/
|
||||
export interface CreatePaymentLinkRequest {
|
||||
/** 金额 */
|
||||
amount: number | string;
|
||||
/** 商品名称 */
|
||||
product_name: string;
|
||||
/** 备注(可选) */
|
||||
remark?: string;
|
||||
/** 总支付次数限制(可选,最小值为1) */
|
||||
total_limit?: number;
|
||||
/** 单用户支付次数限制(可选,最小值为1) */
|
||||
user_limit?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新支付链接请求参数
|
||||
*/
|
||||
export interface UpdatePaymentLinkRequest {
|
||||
/** 金额 */
|
||||
amount: number | string;
|
||||
/** 商品名称 */
|
||||
product_name: string;
|
||||
/** 备注(可选) */
|
||||
remark?: string;
|
||||
/** 总支付次数限制(可选,最小值为1) */
|
||||
total_limit?: number;
|
||||
/** 单用户支付次数限制(可选,最小值为1) */
|
||||
user_limit?: number;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过支付链接支付请求参数
|
||||
*/
|
||||
export interface PayByLinkRequest {
|
||||
/** 支付链接 Token */
|
||||
token: string;
|
||||
/** 支付密码(6位数字) */
|
||||
pay_key: string;
|
||||
/** 备注(可选,最大100字符) */
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支付链接信息响应
|
||||
* 包含支付链接信息和商户信息
|
||||
*/
|
||||
export interface GetPaymentLinkInfoResponse {
|
||||
/** 支付链接信息 */
|
||||
payment_link: PaymentLink;
|
||||
/** 商户信息 */
|
||||
merchant: {
|
||||
/** 应用名称 */
|
||||
app_name: string;
|
||||
/** 跳转URI */
|
||||
redirect_uri: string;
|
||||
};
|
||||
/** 用户积分配置信息 */
|
||||
user_pay_config: {
|
||||
/** 配置ID */
|
||||
id: string;
|
||||
/** 积分等级 */
|
||||
level: number;
|
||||
/** 最低分数 */
|
||||
min_score: number;
|
||||
/** 最高分数 */
|
||||
max_score: number | null;
|
||||
/** 每日限额 */
|
||||
daily_limit: number | null;
|
||||
/** 手续费率 */
|
||||
fee_rate: string;
|
||||
/** 创建时间 */
|
||||
created_at: string;
|
||||
/** 更新时间 */
|
||||
updated_at: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户查询订单请求参数
|
||||
*/
|
||||
export interface QueryMerchantOrderRequest {
|
||||
/** 商户订单号(可选) */
|
||||
out_trade_no?: string;
|
||||
/** 平台订单号 */
|
||||
trade_no: string;
|
||||
/** 客户端 ID */
|
||||
pid: string;
|
||||
/** 客户端密钥 */
|
||||
key: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户查询订单响应
|
||||
*/
|
||||
export interface QueryMerchantOrderResponse {
|
||||
/** 状态码(1表示成功,-1表示失败) */
|
||||
code: number;
|
||||
/** 响应消息 */
|
||||
msg: string;
|
||||
/** 平台订单号 */
|
||||
trade_no: string;
|
||||
/** 商户订单号 */
|
||||
out_trade_no: string;
|
||||
/** 支付类型 */
|
||||
type: string;
|
||||
/** 客户端 ID */
|
||||
pid: string;
|
||||
/** 订单创建时间 */
|
||||
addtime: string;
|
||||
/** 订单完成时间 */
|
||||
endtime: string;
|
||||
/** 订单名称 */
|
||||
name: string;
|
||||
/** 订单金额 */
|
||||
money: string;
|
||||
/** 订单状态(1表示已支付,0表示未支付) */
|
||||
status: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户退款请求参数
|
||||
*/
|
||||
export interface RefundMerchantOrderRequest {
|
||||
/** 客户端 ID */
|
||||
pid: string;
|
||||
/** 客户端密钥 */
|
||||
key: string;
|
||||
/** 商户订单号(可选) */
|
||||
out_trade_no?: string;
|
||||
/** 平台订单号 */
|
||||
trade_no: string;
|
||||
/** 退款金额 */
|
||||
money: number | string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户退款响应
|
||||
*/
|
||||
export interface RefundMerchantOrderResponse {
|
||||
/** 状态码(1表示成功,-1表示失败) */
|
||||
code: number;
|
||||
/** 响应消息 */
|
||||
msg: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户分发请求参数
|
||||
*/
|
||||
export interface MerchantDistributeRequest {
|
||||
/** 接收用户 ID (必填) */
|
||||
user_id: number;
|
||||
/** 接收用户名,用于验证 (必填) */
|
||||
username: string;
|
||||
/** 分发金额 (必填) */
|
||||
amount: number | string;
|
||||
/** 商户订单号 (可选,最大64字符) */
|
||||
out_trade_no?: string;
|
||||
/** 备注 (可选,最大100字符) */
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户分发响应
|
||||
*/
|
||||
export interface MerchantDistributeResponse {
|
||||
/** 平台订单号 */
|
||||
trade_no: string;
|
||||
/** 商户订单号 */
|
||||
out_trade_no: string;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
export { RedEnvelopeService } from './redenvelope.service';
|
||||
export type {
|
||||
RedEnvelopeType,
|
||||
RedEnvelopeStatus,
|
||||
RedEnvelope,
|
||||
RedEnvelopeClaim,
|
||||
CreateRedEnvelopeRequest,
|
||||
CreateRedEnvelopeResponse,
|
||||
ClaimRedEnvelopeRequest,
|
||||
ClaimRedEnvelopeResponse,
|
||||
RedEnvelopeDetailResponse,
|
||||
RedEnvelopeListParams,
|
||||
RedEnvelopeListResponse,
|
||||
} from './types';
|
||||
@@ -1,108 +0,0 @@
|
||||
import { BaseService } from '../core/base.service';
|
||||
import type { UploadImageResponse } from '../upload/types';
|
||||
import type {
|
||||
CreateRedEnvelopeRequest,
|
||||
CreateRedEnvelopeResponse,
|
||||
ClaimRedEnvelopeRequest,
|
||||
ClaimRedEnvelopeResponse,
|
||||
RedEnvelopeDetailResponse,
|
||||
RedEnvelopeListParams,
|
||||
RedEnvelopeListResponse,
|
||||
} from './types';
|
||||
|
||||
/**
|
||||
* 红包服务
|
||||
* 处理红包创建、领取、查询相关的 API 请求
|
||||
*/
|
||||
export class RedEnvelopeService extends BaseService {
|
||||
protected static readonly basePath = '/api/v1/redenvelope';
|
||||
|
||||
/**
|
||||
* 创建红包
|
||||
* @param data - 创建红包请求参数
|
||||
* @returns 红包信息(包含分享链接)
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
* @throws {ApiErrorBase} 当余额不足或支付密码错误时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const result = await RedEnvelopeService.create({
|
||||
* type: 'random',
|
||||
* total_amount: 100,
|
||||
* total_count: 10,
|
||||
* greeting: '恭喜发财',
|
||||
* pay_key: '123456'
|
||||
* });
|
||||
* console.log('分享链接:', result.link);
|
||||
* ```
|
||||
*/
|
||||
static async create(data: CreateRedEnvelopeRequest): Promise<CreateRedEnvelopeResponse> {
|
||||
return this.post<CreateRedEnvelopeResponse>('/create', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取红包
|
||||
* @param data - 领取红包请求参数
|
||||
* @returns 领取结果(包含领取金额)
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {NotFoundError} 当红包不存在时
|
||||
* @throws {ApiErrorBase} 当红包已领完、已过期或已领取过时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const result = await RedEnvelopeService.claim({ id: '123456' });
|
||||
* console.log('领取金额:', result.amount);
|
||||
* ```
|
||||
*/
|
||||
static async claim(data: ClaimRedEnvelopeRequest): Promise<ClaimRedEnvelopeResponse> {
|
||||
return this.post<ClaimRedEnvelopeResponse>('/claim', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取红包详情
|
||||
* @param id - 红包ID
|
||||
* @returns 红包详情(包含领取记录)
|
||||
* @throws {NotFoundError} 当红包不存在时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const detail = await RedEnvelopeService.getDetail('123456');
|
||||
* console.log('红包状态:', detail.red_envelope.status);
|
||||
* console.log('已领取人数:', detail.claims.length);
|
||||
* ```
|
||||
*/
|
||||
static async getDetail(id: string): Promise<RedEnvelopeDetailResponse> {
|
||||
return this.get<RedEnvelopeDetailResponse>(`/${ id }`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取红包列表
|
||||
* @param params - 查询参数
|
||||
* @returns 红包列表
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const result = await RedEnvelopeService.getList({
|
||||
* page: 1,
|
||||
* page_size: 20,
|
||||
* type: 'sent'
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
static async getList(params: RedEnvelopeListParams): Promise<RedEnvelopeListResponse> {
|
||||
return this.post<RedEnvelopeListResponse>('/list', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户历史红包封面
|
||||
* @param type - 封面类型 (cover: 背景封面, heterotypic: 异形装饰)
|
||||
* @returns 历史封面列表
|
||||
*/
|
||||
static async listCovers(
|
||||
type: 'cover' | 'heterotypic'
|
||||
): Promise<UploadImageResponse[]> {
|
||||
return this.get<UploadImageResponse[]>('/covers', { type });
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/**
|
||||
* 红包类型
|
||||
* - fixed: 固定金额,每个红包金额相同
|
||||
* - random: 拼手气,随机分配金额
|
||||
*/
|
||||
export type RedEnvelopeType = 'fixed' | 'random';
|
||||
|
||||
/**
|
||||
* 红包状态
|
||||
* - active: 进行中,可领取
|
||||
* - finished: 已领完
|
||||
* - expired: 已过期
|
||||
*/
|
||||
export type RedEnvelopeStatus = 'active' | 'finished' | 'expired';
|
||||
|
||||
/**
|
||||
* 红包信息
|
||||
*/
|
||||
export interface RedEnvelope {
|
||||
/** 红包 ID */
|
||||
id: string;
|
||||
/** 创建者用户 ID */
|
||||
creator_id: string;
|
||||
/** 创建者用户名 */
|
||||
creator_username: string;
|
||||
/** 创建者头像 URL */
|
||||
creator_avatar_url?: string;
|
||||
/** 红包类型 */
|
||||
type: RedEnvelopeType;
|
||||
/** 总金额 */
|
||||
total_amount: string;
|
||||
/** 剩余金额 */
|
||||
remaining_amount: string;
|
||||
/** 红包总个数 */
|
||||
total_count: number;
|
||||
/** 剩余个数 */
|
||||
remaining_count: number;
|
||||
/** 祝福语 */
|
||||
greeting: string;
|
||||
/** 红包状态 */
|
||||
status: RedEnvelopeStatus;
|
||||
/** 封面上传记录 ID */
|
||||
cover_upload_id?: string;
|
||||
/** 装饰上传记录 ID */
|
||||
heterotypic_upload_id?: string;
|
||||
/** 过期时间 */
|
||||
expires_at: string;
|
||||
/** 创建时间 */
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 红包领取记录
|
||||
*/
|
||||
export interface RedEnvelopeClaim {
|
||||
/** 记录 ID (作为字符串以避免 JS 精度问题) */
|
||||
id: string;
|
||||
/** 红包 ID (作为字符串以避免 JS 精度问题) */
|
||||
red_envelope_id: string;
|
||||
/** 领取者用户 ID (作为字符串以避免 JS 精度问题) */
|
||||
user_id: string;
|
||||
/** 领取者用户名 */
|
||||
username: string;
|
||||
/** 领取者头像 URL */
|
||||
avatar_url?: string;
|
||||
/** 领取金额 */
|
||||
amount: string;
|
||||
/** 领取时间 */
|
||||
claimed_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建红包请求参数
|
||||
*/
|
||||
export interface CreateRedEnvelopeRequest {
|
||||
/** 红包类型(fixed: 固定金额, random: 拼手气) */
|
||||
type: RedEnvelopeType;
|
||||
/** 总金额(必须大于0,最多2位小数) */
|
||||
total_amount: number;
|
||||
/** 红包个数(必须大于0) */
|
||||
total_count: number;
|
||||
/** 祝福语(可选,最大100字符) */
|
||||
greeting?: string;
|
||||
/** 支付密码(6-10位) */
|
||||
pay_key: string;
|
||||
/** 封面上传记录 ID */
|
||||
cover_upload_id?: string;
|
||||
/** 异形装饰上传记录 ID */
|
||||
heterotypic_upload_id?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建红包响应
|
||||
*/
|
||||
export interface CreateRedEnvelopeResponse {
|
||||
/** 红包 ID (作为字符串以避免 JS 精度问题) */
|
||||
id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取红包请求参数
|
||||
*/
|
||||
export interface ClaimRedEnvelopeRequest {
|
||||
/** 红包 ID */
|
||||
id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取红包响应
|
||||
*/
|
||||
export interface ClaimRedEnvelopeResponse {
|
||||
/** 领取到的金额 */
|
||||
amount: string;
|
||||
/** 红包信息 */
|
||||
red_envelope: RedEnvelope;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取红包详情响应
|
||||
*/
|
||||
export interface RedEnvelopeDetailResponse {
|
||||
/** 红包信息 */
|
||||
red_envelope: RedEnvelope;
|
||||
/** 领取记录列表 */
|
||||
claims: RedEnvelopeClaim[];
|
||||
/** 当前用户的领取记录(如果已领取) */
|
||||
user_claimed?: RedEnvelopeClaim;
|
||||
}
|
||||
|
||||
/**
|
||||
* 红包列表查询参数
|
||||
*/
|
||||
export interface RedEnvelopeListParams {
|
||||
/** 页码,从 1 开始 */
|
||||
page: number;
|
||||
/** 每页数量,1-100 */
|
||||
page_size: number;
|
||||
/** 查询类型(sent: 发出的, received: 收到的) */
|
||||
type?: 'sent' | 'received';
|
||||
}
|
||||
|
||||
/**
|
||||
* 红包列表响应
|
||||
*/
|
||||
export interface RedEnvelopeListResponse {
|
||||
/** 总记录数 */
|
||||
total: number;
|
||||
/** 当前页码 */
|
||||
page: number;
|
||||
/** 每页数量 */
|
||||
page_size: number;
|
||||
/** 红包列表 */
|
||||
red_envelopes: RedEnvelope[];
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* 交易服务模块
|
||||
*
|
||||
* @description
|
||||
* 提供交易相关的功能,包括:
|
||||
* - 查询交易记录列表(分页)
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { TransactionService } from '@/lib/services';
|
||||
*
|
||||
* // 查询交易记录
|
||||
* const result = await TransactionService.getTransactions({
|
||||
* page: 1,
|
||||
* page_size: 20,
|
||||
* types: ['receive'],
|
||||
* statuses: ['success'],
|
||||
* payee_transfer_status: 'pending',
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
|
||||
export { TransactionService } from './transaction.service';
|
||||
export { DEFAULT_ORDER_TYPES } from './types';
|
||||
export type {
|
||||
Order,
|
||||
OrderType,
|
||||
OrderStatus,
|
||||
TransferStatus,
|
||||
TransactionQueryParams,
|
||||
TransactionListResponse,
|
||||
} from './types';
|
||||
@@ -1,32 +0,0 @@
|
||||
import { BaseService } from '../core/base.service';
|
||||
import type { TransactionQueryParams, TransactionListResponse } from './types';
|
||||
|
||||
/**
|
||||
* 交易服务
|
||||
* 处理订单和交易记录相关的 API 请求
|
||||
*/
|
||||
export class TransactionService extends BaseService {
|
||||
protected static readonly basePath = '/api/v1/order';
|
||||
|
||||
/**
|
||||
* 获取交易记录列表(分页)
|
||||
* @param params - 查询参数
|
||||
* @returns 交易记录列表
|
||||
* @throws {UnauthorizedError} 当未登录时
|
||||
* @throws {ValidationError} 当参数验证失败时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const result = await TransactionService.getTransactions({
|
||||
* page: 1,
|
||||
* page_size: 20,
|
||||
* types: ['receive'],
|
||||
* statuses: ['success'],
|
||||
* payee_transfer_status: 'pending'
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
static async getTransactions(params: TransactionQueryParams): Promise<TransactionListResponse> {
|
||||
return this.post<TransactionListResponse>('/transactions', params as unknown as Record<string, unknown>);
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/**
|
||||
* 订单类型
|
||||
*/
|
||||
export type OrderType = 'receive' | 'payment' | 'community' | 'online' | 'test' | 'distribute' | 'red_envelope_send' | 'red_envelope_receive' | 'red_envelope_refund';
|
||||
|
||||
/**
|
||||
* 前端默认展示的订单类型
|
||||
* 显式排除已移除的积分转移类型
|
||||
*/
|
||||
export const DEFAULT_ORDER_TYPES: OrderType[] = [
|
||||
'receive',
|
||||
'payment',
|
||||
'community',
|
||||
'online',
|
||||
'test',
|
||||
'distribute',
|
||||
'red_envelope_send',
|
||||
'red_envelope_receive',
|
||||
'red_envelope_refund',
|
||||
];
|
||||
|
||||
/**
|
||||
* 订单状态
|
||||
*/
|
||||
export type OrderStatus = 'success' | 'pending' | 'failed' | 'expired' | 'disputing' | 'refund' | 'refused';
|
||||
|
||||
/**
|
||||
* 到账状态
|
||||
*/
|
||||
export type TransferStatus = 'pending' | 'completed';
|
||||
|
||||
/**
|
||||
* 订单信息
|
||||
*/
|
||||
export interface Order {
|
||||
/** 订单 ID */
|
||||
id: string;
|
||||
/** 订单号(18位字符串) */
|
||||
order_no: string;
|
||||
/** 订单名称 */
|
||||
order_name: string;
|
||||
/** 商户订单号 */
|
||||
merchant_order_no: string;
|
||||
/** 付款方用户ID */
|
||||
payer_user_id: string;
|
||||
/** 收款方用户ID */
|
||||
payee_user_id: string;
|
||||
/** 付款方账户 */
|
||||
payer_username: string;
|
||||
/** 付款方头像 */
|
||||
payer_avatar_url?: string;
|
||||
/** 收款方账户 */
|
||||
payee_username: string;
|
||||
/** 收款方头像 */
|
||||
payee_avatar_url?: string;
|
||||
/** 交易金额(decimal字符串) */
|
||||
amount: string;
|
||||
/** 订单状态 */
|
||||
status: OrderStatus;
|
||||
/** 订单类型 */
|
||||
type: OrderType;
|
||||
/** 备注 */
|
||||
remark: string;
|
||||
/** 客户端ID */
|
||||
client_id: string;
|
||||
/** 交易时间 */
|
||||
trade_time: string;
|
||||
/** 过期时间 */
|
||||
expires_at: string;
|
||||
/** 创建时间 */
|
||||
created_at: string;
|
||||
/** 更新时间 */
|
||||
updated_at: string;
|
||||
/** 应用名称(可选) */
|
||||
app_name?: string;
|
||||
/** 应用主页 URL(可选) */
|
||||
app_homepage_url?: string;
|
||||
/** 应用描述(可选) */
|
||||
app_description?: string;
|
||||
/** 重定向 URI(可选) */
|
||||
redirect_uri?: string;
|
||||
/** 关联的争议 ID(可选) */
|
||||
dispute_id?: string;
|
||||
/** 支付类型 */
|
||||
payment_type: string;
|
||||
/** 是否到账 */
|
||||
payee_transfer_status: TransferStatus;
|
||||
/** 到账时间 */
|
||||
payee_transfer_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 交易查询参数
|
||||
*/
|
||||
export interface TransactionQueryParams {
|
||||
/** 页码,从 1 开始 */
|
||||
page: number;
|
||||
/** 每页数量,1-100 */
|
||||
page_size: number;
|
||||
/** 订单类型列表(可选) */
|
||||
types?: OrderType[];
|
||||
/** 订单状态列表(可选) */
|
||||
statuses?: OrderStatus[];
|
||||
/** 收款方结算状态(可选) */
|
||||
payee_transfer_status?: TransferStatus;
|
||||
/** 客户端 ID(可选) */
|
||||
client_id?: string;
|
||||
/** 开始时间(可选) */
|
||||
startTime?: string;
|
||||
/** 结束时间(可选) */
|
||||
endTime?: string;
|
||||
/** 订单 ID(可选) */
|
||||
id?: string;
|
||||
/** 订单名称,支持前缀模糊查询(可选) */
|
||||
order_name?: string;
|
||||
/** 付款方账户,支持前缀模糊查询(可选) */
|
||||
payer_username?: string;
|
||||
/** 收款方账户,支持前缀模糊查询(可选) */
|
||||
payee_username?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 交易列表响应
|
||||
*/
|
||||
export interface TransactionListResponse {
|
||||
/** 总记录数 */
|
||||
total: number;
|
||||
/** 当前页码 */
|
||||
page: number;
|
||||
/** 每页数量 */
|
||||
page_size: number;
|
||||
/** 订单列表 */
|
||||
orders: Order[];
|
||||
}
|
||||
@@ -2,17 +2,7 @@
|
||||
* 用户服务模块
|
||||
*
|
||||
* @description
|
||||
* 提供用户个人设置相关的功能,包括:
|
||||
* - 更新支付密钥
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { UserService } from '@/lib/services';
|
||||
*
|
||||
* // 更新支付密钥
|
||||
* await UserService.updatePayKey('123456');
|
||||
* ```
|
||||
* 提供用户个人设置相关的功能
|
||||
*/
|
||||
|
||||
export { UserService } from './user.service';
|
||||
export type { UpdatePayKeyRequest } from './types';
|
||||
|
||||
@@ -1,8 +1,2 @@
|
||||
/**
|
||||
* 更新支付密钥请求
|
||||
*/
|
||||
export interface UpdatePayKeyRequest {
|
||||
/** 新的支付密钥(6位数字) */
|
||||
pay_key: string;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,25 +6,5 @@ import { BaseService } from '../core/base.service';
|
||||
*/
|
||||
export class UserService extends BaseService {
|
||||
protected static readonly basePath = '/api/v1/user';
|
||||
|
||||
/**
|
||||
* 更新用户支付密钥
|
||||
* @param payKey - 新的支付密钥
|
||||
* @returns void
|
||||
* @throws {UnauthorizedError} 当用户未登录时
|
||||
* @throws {ValidationError} 当支付密钥格式无效时
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await UserService.updatePayKey('123456');
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* - 支付密钥必须为6位数字
|
||||
* - 只能更新当前登录用户的支付密钥
|
||||
*/
|
||||
static async updatePayKey(payKey: string): Promise<void> {
|
||||
return this.put<void>('/pay-key', { pay_key: payKey });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,10 @@ const match = ((): MatchFunction | null => {
|
||||
return p as MatchFunction;
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return null;
|
||||
})();
|
||||
|
||||
export interface SearchItem {
|
||||
id: string
|
||||
title: string
|
||||
@@ -47,440 +49,88 @@ export const searchData: SearchItem[] = [
|
||||
{
|
||||
id: 'home',
|
||||
title: '首页',
|
||||
description: '返回首页仪表板',
|
||||
description: '返回首页控制台',
|
||||
url: '/home',
|
||||
category: 'page',
|
||||
keywords: ['home', '主页', '首页', 'dashboard'],
|
||||
},
|
||||
{
|
||||
id: 'home-disputes',
|
||||
title: '我的争议',
|
||||
description: '查看和处理我的争议',
|
||||
url: '/home',
|
||||
category: 'feature',
|
||||
keywords: ['dispute', '争议', '纠纷', 'my'],
|
||||
},
|
||||
{
|
||||
id: 'home-pending-disputes',
|
||||
title: '待处理的争议',
|
||||
description: '查看待处理的争议',
|
||||
url: '/home',
|
||||
category: 'feature',
|
||||
keywords: ['dispute', '争议', '待处理', 'pending'],
|
||||
},
|
||||
|
||||
// ==================== 商户中心 ====================
|
||||
{
|
||||
id: 'merchant',
|
||||
title: '集市',
|
||||
description: '管理集市应用及其相关功能',
|
||||
url: '/merchant',
|
||||
category: 'page',
|
||||
keywords: ['merchant', '商户', '集市', '应用', '功能'],
|
||||
},
|
||||
{
|
||||
id: 'merchant-disputes',
|
||||
title: '处理争议',
|
||||
description: '您的争议活动',
|
||||
url: '/merchant',
|
||||
category: 'feature',
|
||||
keywords: ['merchant', '服务方', '争议', 'dispute', '处理'],
|
||||
},
|
||||
{
|
||||
id: 'merchant-orders',
|
||||
title: '查看所有活动',
|
||||
description: '查看您的所有活动',
|
||||
url: '/merchant',
|
||||
category: 'feature',
|
||||
keywords: ['merchant', '商户', '订单', 'order', '查看'],
|
||||
},
|
||||
{
|
||||
id: 'merchant-create-online',
|
||||
title: '创建在线流转',
|
||||
description: '创建在线流转活动',
|
||||
url: '/merchant/online-paying',
|
||||
category: 'feature',
|
||||
keywords: ['merchant', '服务方', '创建', '在线', 'create', 'online'],
|
||||
},
|
||||
{
|
||||
id: 'merchant-create-app',
|
||||
title: '创建集市应用',
|
||||
description: '创建新的集市应用',
|
||||
url: '/merchant',
|
||||
category: 'feature',
|
||||
keywords: ['merchant', '服务方', '创建', '应用', 'create', 'app'],
|
||||
},
|
||||
{
|
||||
id: 'merchant-transactions',
|
||||
title: '查看活动记录',
|
||||
description: '查看您的活动记录',
|
||||
url: '/merchant',
|
||||
category: 'feature',
|
||||
keywords: ['merchant', '服务方', '交易', 'transaction', '记录'],
|
||||
},
|
||||
{
|
||||
id: 'merchant-app-info',
|
||||
title: '查看应用信息',
|
||||
description: '查看集市应用详细信息',
|
||||
url: '/merchant',
|
||||
category: 'feature',
|
||||
keywords: ['merchant', '服务方', '应用', '信息', 'app', 'info'],
|
||||
},
|
||||
{
|
||||
id: 'merchant-app-config',
|
||||
title: '应用配置',
|
||||
description: '查看和编辑应用配置',
|
||||
url: '/merchant',
|
||||
category: 'feature',
|
||||
keywords: ['merchant', '服务方', '配置', 'config', 'app'],
|
||||
},
|
||||
{
|
||||
id: 'merchant-edit-app',
|
||||
title: '编辑应用信息',
|
||||
description: '编辑集市应用信息',
|
||||
url: '/merchant',
|
||||
category: 'feature',
|
||||
keywords: ['merchant', '服务方', '编辑', 'edit', 'app'],
|
||||
},
|
||||
{
|
||||
id: 'merchant-delete-app',
|
||||
title: '删除应用',
|
||||
description: '删除集市应用',
|
||||
url: '/merchant',
|
||||
category: 'feature',
|
||||
keywords: ['merchant', '服务方', '删除', 'delete', 'app'],
|
||||
},
|
||||
{
|
||||
id: 'merchant-client-id',
|
||||
title: '查看 Client ID',
|
||||
description: '查看应用 Client ID',
|
||||
url: '/merchant',
|
||||
category: 'feature',
|
||||
keywords: ['merchant', '服务方', 'client', 'id', '查看'],
|
||||
},
|
||||
{
|
||||
id: 'merchant-client-secret',
|
||||
title: '查看 Client Secret',
|
||||
description: '查看应用密钥',
|
||||
url: '/merchant',
|
||||
category: 'feature',
|
||||
keywords: ['merchant', '商户', 'client', 'secret', '密钥', '查看'],
|
||||
},
|
||||
|
||||
// ==================== 在线收款 ====================
|
||||
{
|
||||
id: 'online-paying',
|
||||
title: '在线流转',
|
||||
description: '管理在线流转活动',
|
||||
url: '/merchant/online-paying',
|
||||
category: 'page',
|
||||
keywords: ['online', '在线', '流转', '活动', 'activity', 'link'],
|
||||
},
|
||||
{
|
||||
id: 'online-products',
|
||||
title: '活动列表',
|
||||
description: '查看所有在线活动',
|
||||
url: '/merchant/online-paying',
|
||||
category: 'feature',
|
||||
keywords: ['online', '在线', '商品', 'product', 'list', '列表'],
|
||||
},
|
||||
{
|
||||
id: 'online-create',
|
||||
title: '创建活动',
|
||||
description: '创建新的在线流转活动',
|
||||
url: '/merchant/online-paying',
|
||||
category: 'feature',
|
||||
keywords: ['online', '在线', '创建', 'create', 'activity'],
|
||||
},
|
||||
{
|
||||
id: 'online-manage',
|
||||
title: '管理活动',
|
||||
description: '管理在线流转活动',
|
||||
url: '/merchant/online-paying',
|
||||
category: 'feature',
|
||||
keywords: ['online', '在线', '管理', 'manage', 'activity'],
|
||||
},
|
||||
{
|
||||
id: 'online-delete',
|
||||
title: '删除活动',
|
||||
description: '删除在线流转活动',
|
||||
url: '/merchant/online-paying',
|
||||
category: 'feature',
|
||||
keywords: ['online', '在线', '删除', 'delete', 'activity'],
|
||||
},
|
||||
{
|
||||
id: 'online-preview',
|
||||
title: '实时预览',
|
||||
description: '预览在线流转页面效果',
|
||||
url: '/merchant/online-paying',
|
||||
category: 'feature',
|
||||
keywords: ['online', '在线', '预览', 'preview', '实时'],
|
||||
},
|
||||
|
||||
// ==================== 余额管理 ====================
|
||||
{
|
||||
id: 'balance',
|
||||
title: '积分',
|
||||
description: '查看和管理您的积分余额',
|
||||
url: '/balance',
|
||||
category: 'page',
|
||||
keywords: ['balance', '余额', '积分', '充值', '提现', 'wallet'],
|
||||
},
|
||||
{
|
||||
id: 'balance-view',
|
||||
title: '查看积分余额',
|
||||
description: '查看您的积分余额',
|
||||
url: '/balance',
|
||||
category: 'feature',
|
||||
keywords: ['balance', '余额', '查看', 'view'],
|
||||
},
|
||||
{
|
||||
id: 'balance-report',
|
||||
title: '查看积分报告',
|
||||
description: '查看积分报告和统计',
|
||||
url: '/balance',
|
||||
category: 'feature',
|
||||
keywords: ['balance', '余额', '报告', 'report', '统计'],
|
||||
},
|
||||
{
|
||||
id: 'balance-activity',
|
||||
title: '查看交易活动',
|
||||
description: '查看积分交易活动',
|
||||
url: '/balance',
|
||||
category: 'feature',
|
||||
keywords: ['balance', '余额', '交易', '活动', 'activity'],
|
||||
},
|
||||
{
|
||||
id: 'balance-received',
|
||||
title: '近期积分收益',
|
||||
description: '查看近期积分收益记录',
|
||||
url: '/balance',
|
||||
category: 'feature',
|
||||
keywords: ['balance', '余额', '收益', 'receive', '近期'],
|
||||
},
|
||||
{
|
||||
id: 'balance-payment',
|
||||
title: '近期积分消耗',
|
||||
description: '查看近期积分消耗记录',
|
||||
url: '/balance',
|
||||
category: 'feature',
|
||||
keywords: ['balance', '余额', '消耗', 'payment', '近期'],
|
||||
},
|
||||
{
|
||||
id: 'balance-community',
|
||||
title: '近期社区积分划转',
|
||||
description: '查看社区积分划转记录',
|
||||
url: '/balance',
|
||||
category: 'feature',
|
||||
keywords: ['balance', '余额', '社区', 'community', '划转', '近期'],
|
||||
},
|
||||
{
|
||||
id: 'balance-all',
|
||||
title: '近期所有活动',
|
||||
description: '查看所有积分活动',
|
||||
url: '/balance',
|
||||
category: 'feature',
|
||||
keywords: ['balance', '积分', '所有', 'all', '活动', '近期'],
|
||||
},
|
||||
|
||||
// ==================== 交易记录 ====================
|
||||
{
|
||||
id: 'trade',
|
||||
title: '活动',
|
||||
description: '查看所有交易历史记录',
|
||||
url: '/trade',
|
||||
category: 'page',
|
||||
keywords: ['trade', '交易', '活动', '记录', '历史', 'transaction'],
|
||||
},
|
||||
{
|
||||
id: 'trade-received',
|
||||
title: '积分收益记录',
|
||||
description: '查看积分收益记录',
|
||||
url: '/trade',
|
||||
category: 'feature',
|
||||
keywords: ['trade', '交易', '收益', 'receive', '记录'],
|
||||
},
|
||||
{
|
||||
id: 'trade-payment',
|
||||
title: '积分消耗记录',
|
||||
description: '查看积分消耗记录',
|
||||
url: '/trade',
|
||||
category: 'feature',
|
||||
keywords: ['trade', '交易', '消耗', 'payment', '记录'],
|
||||
},
|
||||
{
|
||||
id: 'trade-community',
|
||||
title: '社区积分划转记录',
|
||||
description: '查看社区积分划转记录',
|
||||
url: '/trade',
|
||||
category: 'feature',
|
||||
keywords: ['trade', '交易', '社区', 'community', '积分', '划转', '记录'],
|
||||
},
|
||||
{
|
||||
id: 'trade-all',
|
||||
title: '所有积分交易记录',
|
||||
description: '查看所有积分交易记录',
|
||||
url: '/trade',
|
||||
category: 'feature',
|
||||
keywords: ['trade', '交易', '积分', '所有', 'all', '记录'],
|
||||
},
|
||||
{
|
||||
id: 'trade-official-api',
|
||||
title: '接入官方积分服务',
|
||||
description: '集成官方积分服务API',
|
||||
url: '/trade',
|
||||
category: 'feature',
|
||||
keywords: ['trade', '交易', '积分', '接入', 'api', '官方', '服务'],
|
||||
},
|
||||
{
|
||||
id: 'trade-custom-form',
|
||||
title: '在线流转表单',
|
||||
description: '创建自定义在线流转表单',
|
||||
url: '/trade',
|
||||
category: 'feature',
|
||||
keywords: ['trade', '交易', '创建', '自定义', 'form', '表单'],
|
||||
},
|
||||
{
|
||||
id: 'trade-overview',
|
||||
title: '数据概览',
|
||||
description: '查看积分交易数据统计',
|
||||
url: '/trade',
|
||||
category: 'feature',
|
||||
keywords: ['trade', '交易', '积分', '数据', 'data', '概览', 'overview'],
|
||||
},
|
||||
|
||||
// ==================== 文档 ====================
|
||||
// ==================== 文档库 ====================
|
||||
{
|
||||
id: 'docs-api',
|
||||
title: '接口文档',
|
||||
description: '查看 API 接口文档',
|
||||
title: '开发接口文档',
|
||||
description: '查看 RESTful API 接口规格定义',
|
||||
url: '/docs/api',
|
||||
category: 'page',
|
||||
keywords: ['api', 'docs', '文档', '接口', 'documentation'],
|
||||
},
|
||||
{
|
||||
id: 'docs-official-api',
|
||||
title: '官方服务接口',
|
||||
description: '官方服务接口文档',
|
||||
url: '/docs/api',
|
||||
category: 'feature',
|
||||
keywords: ['api', 'docs', '文档', '官方', '支付', 'payment'],
|
||||
},
|
||||
{
|
||||
id: 'docs-epay-api',
|
||||
title: '易支付兼容接口',
|
||||
description: '易支付兼容接口文档',
|
||||
url: '/docs/api',
|
||||
category: 'feature',
|
||||
keywords: ['api', 'docs', '文档', '易支付', 'epay', '兼容'],
|
||||
keywords: ['api', 'docs', '文档', '接口', 'specification'],
|
||||
},
|
||||
{
|
||||
id: 'docs-how-to-use',
|
||||
title: '使用文档',
|
||||
description: '查看使用教程和示例',
|
||||
title: '使用帮助文档',
|
||||
description: '查看新手教程和集成示例',
|
||||
url: '/docs/how-to-use',
|
||||
category: 'page',
|
||||
keywords: ['docs', '文档', '使用', 'how to', 'tutorial', '教程'],
|
||||
keywords: ['docs', '文档', '使用', 'how to', 'tutorial', '教程', 'help'],
|
||||
},
|
||||
|
||||
// ==================== 设置 ====================
|
||||
// ==================== 个人设置 ====================
|
||||
{
|
||||
id: 'settings',
|
||||
title: '设置',
|
||||
description: '应用设置和偏好',
|
||||
title: '全局设置',
|
||||
description: '配置应用个人偏好选项',
|
||||
url: '/settings',
|
||||
category: 'setting',
|
||||
keywords: ['settings', '设置', '偏好', 'preferences'],
|
||||
},
|
||||
{
|
||||
id: 'settings-all',
|
||||
title: '所有设置',
|
||||
description: '查看所有设置选项',
|
||||
url: '/settings',
|
||||
category: 'setting',
|
||||
keywords: ['settings', '设置', '所有', 'all'],
|
||||
},
|
||||
{
|
||||
id: 'settings-profile',
|
||||
title: '我的资料',
|
||||
description: '编辑个人信息和头像',
|
||||
description: '编辑昵称、头像和个人属性',
|
||||
url: '/settings/profile',
|
||||
category: 'setting',
|
||||
keywords: ['profile', '资料', '个人', '我的', '信息', '头像'],
|
||||
},
|
||||
{
|
||||
id: 'settings-profile-level',
|
||||
title: '会员等级',
|
||||
description: '查看会员等级和权益',
|
||||
url: '/settings/profile',
|
||||
category: 'setting',
|
||||
keywords: ['profile', '资料', '会员', 'level', '等级'],
|
||||
},
|
||||
{
|
||||
id: 'settings-profile-basic',
|
||||
title: '基本信息',
|
||||
description: '编辑基本个人信息',
|
||||
url: '/settings/profile',
|
||||
category: 'setting',
|
||||
keywords: ['profile', '资料', '基本', 'basic', '信息'],
|
||||
keywords: ['profile', '资料', '个人', '我的', '信息', 'avatar'],
|
||||
},
|
||||
{
|
||||
id: 'settings-appearance',
|
||||
title: '外观设置',
|
||||
description: '自定义界面主题和显示',
|
||||
description: '配置系统显示主题(亮色/暗色)',
|
||||
url: '/settings/appearance',
|
||||
category: 'setting',
|
||||
keywords: ['appearance', '外观', '主题', 'theme', 'dark', 'light'],
|
||||
},
|
||||
{
|
||||
id: 'settings-theme-switch',
|
||||
title: '主题切换',
|
||||
description: '切换亮色/暗色主题',
|
||||
url: '/settings/appearance',
|
||||
category: 'setting',
|
||||
keywords: ['appearance', '外观', '主题', 'theme', '切换', 'switch'],
|
||||
},
|
||||
{
|
||||
id: 'settings-color-theme',
|
||||
title: '颜色主题',
|
||||
description: '选择颜色主题',
|
||||
url: '/settings/appearance',
|
||||
category: 'setting',
|
||||
keywords: ['appearance', '外观', '颜色', 'color', '主题'],
|
||||
},
|
||||
{
|
||||
id: 'settings-notification',
|
||||
title: '通知设置',
|
||||
description: '管理通知偏好',
|
||||
url: '/settings',
|
||||
category: 'setting',
|
||||
keywords: ['settings', '设置', '通知', 'notification'],
|
||||
},
|
||||
{
|
||||
id: 'settings-security',
|
||||
title: '安全设置',
|
||||
description: '账户安全和隐私设置',
|
||||
description: '管理您的账户安全设置及安全密钥',
|
||||
url: '/settings',
|
||||
category: 'setting',
|
||||
keywords: ['settings', '设置', '安全', 'security', '隐私'],
|
||||
keywords: ['settings', '安全', 'security', 'privacy', 'keys'],
|
||||
},
|
||||
|
||||
// ==================== 管理员 ====================
|
||||
{
|
||||
id: 'admin-system',
|
||||
title: '系统配置',
|
||||
description: '系统配置和管理',
|
||||
description: '动态修改平台核心运行时配置 (管理员专属)',
|
||||
url: '/admin/system',
|
||||
category: 'admin',
|
||||
keywords: ['admin', '管理', '系统', '配置', 'system'],
|
||||
keywords: ['admin', '管理员', '系统', '配置', 'system', 'configurations'],
|
||||
},
|
||||
{
|
||||
id: 'admin-user-pay',
|
||||
title: '积分配置',
|
||||
description: '管理用户支付等级和配置',
|
||||
url: '/admin/user_pay',
|
||||
id: 'admin-users',
|
||||
title: '用户管理',
|
||||
description: '管理平台注册用户的活跃状态 (管理员专属)',
|
||||
url: '/admin/users',
|
||||
category: 'admin',
|
||||
keywords: ['admin', '管理', '积分', '配置', 'payment', 'config'],
|
||||
keywords: ['admin', '管理员', '用户', '管理', 'users', 'status'],
|
||||
},
|
||||
{
|
||||
id: 'admin-tasks',
|
||||
title: '异步任务管理',
|
||||
description: '下发与排查后台异步定时任务 (管理员专属)',
|
||||
url: '/admin/tasks',
|
||||
category: 'admin',
|
||||
keywords: ['admin', '管理员', '任务', '异步', 'tasks', 'scheduler', 'worker'],
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user