fix: 代理

This commit is contained in:
luo
2026-09-12 11:27:50 +08:00
parent d3d257cdf8
commit 2308d82d0f
44 changed files with 5470 additions and 200 deletions

View File

@@ -47,6 +47,11 @@ export interface AgentRecharge {
recharge_source?: AgentRechargeSource | null
recharge_source_name?: string | null
payment_voucher_key?: string[] | string // 凭证附件列表;历史数据可能为单字符串或逗号字符串
external_transaction_no?: string | null // 线下人工申报的交易流水号,与在线 payment_transaction_id 互不覆盖
offline_payment_method_id?: number | null // 线下收款方式字典ID,仅线下充值有值
offline_payment_method_code?: string | null // 线下收款方式稳定编码快照
offline_payment_method_name?: string | null // 线下收款方式名称快照
other_voucher_key?: string[] | null // 其他凭证对象存储Key列表,仅线下充值有值
rejection_reason?: string | null // 拒绝原因
remark?: string // 运营备注
submitter_name?: string | null // 提交人名称
@@ -98,6 +103,9 @@ export interface CreateAgentRechargeOfflineRequest {
payment_method: 'offline'
shop_id: number
payment_voucher_key: string[] // 线下支付凭证附件列表(payment_method=offline 时必填)
offline_payment_method_id: number // 线下收款方式字典ID,取自收款方式字典启用项
external_transaction_no: string // 线下交易流水号,OCR 预填后人工确认
other_voucher_key?: string[] // 其他凭证对象存储Key列表,最多 5 个
remark?: string // 运营备注,最多 1000 字
}
@@ -112,6 +120,19 @@ export interface AgentRechargePaymentMethods {
max_amount: number
}
// 代理自充可用支付方式和金额范围(GET /api/admin/agent-self-recharge-payment-methods)
export type AgentSelfRechargePaymentMethods = AgentRechargePaymentMethods
// 识别付款凭证中的交易流水号请求
export interface AgentRechargePaymentVoucherOcrRequest {
payment_voucher_key: string // 付款凭证对象存储Key,必须指向已上传的图片类型附件
}
// 识别付款凭证中的交易流水号响应(只返回交易流水号预填值)
export interface AgentRechargePaymentVoucherOcrResponse {
external_transaction_no: string
}
// 在线充值支付及钱包到账状态
export interface AgentRechargePaymentStatusResponse {
recharge_id: number

View File

@@ -0,0 +1,302 @@
/**
* 员工代收款相关类型定义
*
* 依据后端 OpenAPI(员工代收款分组):
* - 列表响应为 { items, page, size, total }
* - 账单状态与申请状态均为数字枚举
* - 金额单位为「分」,附件字段为对象存储 Key 数组
*/
import type { BaseResponse, PaginationParams } from './common'
// ========== 收款方式字典 ==========
export interface EmployeeCollectionPaymentMethod {
id: number
code: string
name: string
sort: number
enabled: boolean
remark?: string | null
created_at?: string | null
updated_at?: string | null
}
/** 收款方式列表查询参数,后端返回 { items, page, size, total } */
export interface EmployeeCollectionPaymentMethodQueryParams {
page?: number
page_size?: number
enabled?: boolean
keyword?: string
}
export interface CreateEmployeeCollectionPaymentMethodRequest {
code: string
name: string
sort?: number
enabled?: boolean
remark?: string
}
export interface UpdateEmployeeCollectionPaymentMethodRequest {
code?: string
name?: string
sort?: number
enabled?: boolean
remark?: string
}
// ========== 通用列表结构 ==========
/** 后端列表统一返回 { items, page, size, total } */
export interface EmployeeCollectionListData<T> {
items?: T[] | null
list?: T[] | null
total?: number
page?: number
size?: number
page_size?: number
}
// ========== 员工代收款账单 ==========
/** 账单状态:0 待核销 / 1 部分核销 / 2 已核销 / 3 已关闭 */
export type EmployeeCollectionBillStatus = number
/** 账单责任人(员工)快照 */
export interface EmployeeCollectionDebtorSnapshot {
account_id?: number | null
account_name?: string | null
account_type?: string | null
[key: string]: unknown
}
/** 账单客户 / 店铺快照 */
export interface EmployeeCollectionCustomerSnapshot {
shop_id?: number | null
seller_shop_id?: number | null
buyer_id?: number | null
buyer_type?: string | null
buyer_nickname?: string | null
asset_identifier?: string | null
[key: string]: unknown
}
export interface EmployeeCollectionBill {
id: number
source_type?: string | null
source_type_name?: string | null
source_id?: number | null
source_no?: string | null
debtor_account_id?: number | null
debtor_snapshot?: EmployeeCollectionDebtorSnapshot | null
customer_snapshot?: EmployeeCollectionCustomerSnapshot | null
receivable_amount?: number | null // 应收金额(分)
received_amount?: number | null // 已核销金额(分)
reserved_amount?: number | null // 审批中预占金额(分)
remaining_amount?: number | null // 未核销金额(分)
status: EmployeeCollectionBillStatus
status_name?: string | null
approval_pending?: boolean // 是否存在审批中的核销申请
closed_reason?: string | null
closed_at?: string | null
created_at?: string | null
updated_at?: string | null
}
/** 核销申请详情中的账单分摊 */
export interface EmployeeCollectionAllocation {
id?: number
bill_id: number
amount: number // 本次分摊金额(分)
status?: number | null // 0 审批中预占 / 1 已通过 / 2 已驳回或已释放
status_name?: string | null
bill_status?: number | null
bill_status_name?: string | null
bill_source_type?: string | null
bill_source_no?: string | null
bill_receivable_amount?: number | null
bill_received_amount?: number | null
bill_reserved_amount?: number | null
created_at?: string | null
released_at?: string | null
}
/** 账单详情中的核销分摊(含所属核销申请信息) */
export interface EmployeeCollectionBillAllocation {
id?: number
amount: number
application_id?: number | null
application_status?: number | null
application_status_name?: string | null
attempt_id?: number | null
status?: number | null
status_name?: string | null
created_at?: string | null
released_at?: string | null
}
/** 来源订单退款冲销关联(账单详情 refunds) */
export interface EmployeeCollectionBillRefund {
id?: number
refund_id?: number
source_order_id?: number
refund_amount?: number | null // 本次退款成功金额(分)
reduced_amount?: number | null // 实际冲减应收金额(分)
bill_receivable_amount?: number | null // 冲销前账单应收金额快照(分)
outcome?: string | null // closed_full / reduced / hint_only
outcome_name?: string | null
created_at?: string | null
}
/** 账单详情(接口返回 { bill, refunds, allocations, applications }) */
export interface EmployeeCollectionBillDetailData {
bill: EmployeeCollectionBill
refunds?: EmployeeCollectionBillRefund[] | null
allocations?: EmployeeCollectionBillAllocation[] | null
applications?: EmployeeCollectionBillApplication[] | null
}
/** 账单统计 */
export interface EmployeeCollectionBillStatistics {
receivable_total: number // 应收总金额(分)
received_total: number // 已收款(已核销)总金额(分)
unsettled_total: number // 未结(未核销)总金额(分)
pending_bill_count: number // 待处理账单数量
}
export interface EmployeeCollectionBillQueryParams extends PaginationParams {
source_type?: string
source_no?: string
status?: EmployeeCollectionBillStatus
debtor_account_id?: number
customer_id?: number
created_from?: string
created_to?: string
}
export interface CloseEmployeeCollectionBillRequest {
reason: string
}
export type CloseEmployeeCollectionBillResult = EmployeeCollectionBill
// ========== 核销申请 ==========
/** 申请状态:0 审批中 / 1 已通过 / 2 已驳回 / 3 已撤销或已关闭 */
export type EmployeeCollectionApplicationStatus = number
/** 审批尝试记录(历史材料不被覆盖) */
export interface EmployeeCollectionApplicationAttempt {
id?: number
attempt_no?: number
approval_instance_id?: number | null
approval_status?: number | null // 通用审批实例状态
approval_status_name?: string | null
approval_opinion?: string | null
acting_reason?: string | null
external_transaction_no?: string | null
paid_amount?: number | null
paid_at?: string | null
payer_name?: string | null
payment_method_id?: number | null
payment_method_code?: string | null
payment_method_name?: string | null
payment_voucher_keys?: string[] | null
remark?: string | null
submitted_by_account_id?: number | null
allocation_snapshot?: Array<Record<string, string>> | null
created_at?: string | null
}
export interface EmployeeCollectionApplication {
id: number
applicant_account_id?: number | null
acting_operator_id?: number | null // 0 表示本人办理
acting_reason?: string | null
payment_method_id?: number | null
payment_method_code?: string | null
payment_method_name?: string | null
paid_amount?: number | null // 人工确认的付款金额(分)
paid_at?: string | null
payer_name?: string | null
external_transaction_no?: string | null
payment_voucher_keys?: string[] | null
remark?: string | null
status: EmployeeCollectionApplicationStatus
status_name?: string | null
terminal_reason?: string | null
decided_at?: string | null
latest_approval_instance_id?: number | null
latest_attempt_id?: number | null
created_at?: string | null
updated_at?: string | null
}
/** 账单详情中的核销申请(含该申请的审批尝试记录) */
export interface EmployeeCollectionBillApplication extends EmployeeCollectionApplication {
attempts?: EmployeeCollectionApplicationAttempt[] | null
}
/** 申请详情(接口返回 { application, allocations, attempts }) */
export interface EmployeeCollectionApplicationDetailData {
application: EmployeeCollectionApplication
allocations?: EmployeeCollectionAllocation[] | null
attempts?: EmployeeCollectionApplicationAttempt[] | null
}
export interface EmployeeCollectionApplicationQueryParams extends PaginationParams {
status?: EmployeeCollectionApplicationStatus
applicant_account_id?: number
payment_method_id?: number
created_from?: string
created_to?: string
}
export interface EmployeeCollectionAllocationRequest {
bill_id: number
amount: number
}
export interface EmployeeCollectionApplicationRequest {
payment_method_id: number
paid_amount: number
paid_at: string
payer_name: string
external_transaction_no: string
payment_voucher_keys: string[]
remark?: string
allocations: EmployeeCollectionAllocationRequest[]
acting_reason?: string
}
export interface EmployeeCollectionApplicationSubmitResult {
allocations?: EmployeeCollectionAllocation[] | null
application?: EmployeeCollectionApplication | null
approval_instance_id?: number | null
approval_status?: number | null
approval_status_name?: string | null
attempt?: EmployeeCollectionApplicationAttempt | null
}
// ========== 响应类型 ==========
export type EmployeeCollectionPaymentMethodListResponse = BaseResponse<
EmployeeCollectionPaymentMethod[] | EmployeeCollectionListData<EmployeeCollectionPaymentMethod>
>
export type EmployeeCollectionPaymentMethodResponse = BaseResponse<EmployeeCollectionPaymentMethod>
export type DeleteEmployeeCollectionPaymentMethodResponse = BaseResponse<null>
export type EmployeeCollectionBillListResponse = BaseResponse<
EmployeeCollectionListData<EmployeeCollectionBill>
>
export type EmployeeCollectionBillResponse = BaseResponse<EmployeeCollectionBillDetailData>
export type EmployeeCollectionBillStatisticsResponse =
BaseResponse<EmployeeCollectionBillStatistics>
export type CloseEmployeeCollectionBillResponse = BaseResponse<CloseEmployeeCollectionBillResult>
export type EmployeeCollectionApplicationListResponse = BaseResponse<
EmployeeCollectionListData<EmployeeCollectionApplication>
>
export type EmployeeCollectionApplicationResponse =
BaseResponse<EmployeeCollectionApplicationDetailData>
export type EmployeeCollectionApplicationSubmitResponse =
BaseResponse<EmployeeCollectionApplicationSubmitResult>

View File

@@ -135,4 +135,5 @@ export * from './audit'
// 企业微信审批配置相关
export * from './wecom'
// 员工代收款相关
export * from './employeeCollection'

View File

@@ -45,6 +45,14 @@ export interface PaymentMerchant {
updated_at: string
}
/**
* 支付商户详情:仅在详情页短暂使用,凭证字段经过脱敏/白名单处理,
* 不用于列表、编辑表单或持久化状态。
*/
export interface PaymentMerchantDetail extends PaymentMerchant {
credentials: PaymentCredentials
}
export interface PaymentMerchantQueryParams extends PaginationParams {
/** 可选:按名称模糊筛选 */
name?: string
@@ -132,6 +140,7 @@ export interface UpdateWechatAuthorizationRequest {
export type PaymentMerchantResponse = BaseResponse<PaymentMerchant>
export type PaymentMerchantPageResponse = BaseResponse<PaymentMerchantPageResult>
export type PaymentMerchantDetailResponse = BaseResponse<PaymentMerchantDetail>
export type PaymentMerchantPoolResponse = BaseResponse<PaymentMerchantPool>
export type PaymentMerchantPoolPageResponse = BaseResponse<PaymentMerchantPoolPageResult>
export type WechatAuthorizationResponse = BaseResponse<WechatAuthorizationConfig>
@@ -205,3 +214,146 @@ export interface PaymentMerchantPoolMemberOption {
payment_method: PaymentMerchantMethod
enabled: boolean
}
/**
* 商户凭证字段枚举:必填键由 `payment_method` 与 `provider_type` 组合决定,
* 可选键为允许附带但非必须的字段,键名与渠道配置字段一致。
*/
export interface PaymentCredentialFieldSpec {
required: string[]
optional: string[]
}
export const PAYMENT_CREDENTIAL_FIELD_SPECS: Record<
PaymentMerchantProviderType,
PaymentCredentialFieldSpec
> = {
wechat: {
required: [
'wx_mch_id',
'wx_api_v3_key',
'wx_cert_content',
'wx_key_content',
'wx_serial_no',
'wx_notify_url'
],
optional: ['wx_api_v2_key']
},
wechat_v2: {
required: ['wx_mch_id', 'wx_api_v2_key', 'wx_notify_url'],
optional: []
},
fuiou: {
required: [
'fy_mchnt_cd',
'fy_ins_cd',
'fy_term_id',
'fy_private_key',
'fy_public_key',
'fy_api_url',
'fy_notify_url'
],
optional: []
},
alipay: {
required: [
'ali_app_id',
'ali_private_key',
'ali_public_key',
'ali_notify_url',
'ali_return_url'
],
optional: ['ali_production', 'ali_pay_expire_minutes']
}
}
export function getPaymentCredentialFieldSpec(
providerType: PaymentMerchantProviderType
): PaymentCredentialFieldSpec {
return PAYMENT_CREDENTIAL_FIELD_SPECS[providerType] || { required: [], optional: [] }
}
/** 凭证字段中的布尔字段:值必须为布尔值 */
export const PAYMENT_CREDENTIAL_BOOLEAN_KEYS: string[] = ['ali_production']
/** 凭证字段中的整数字段:值必须为正整数 */
export const PAYMENT_CREDENTIAL_INTEGER_KEYS: string[] = ['ali_pay_expire_minutes']
/** `merchant_identity` 必须与其值保持一致的凭证字段 */
export const PAYMENT_MERCHANT_IDENTITY_KEYS: Record<PaymentMerchantProviderType, string> = {
wechat: 'wx_mch_id',
wechat_v2: 'wx_mch_id',
fuiou: 'fy_mchnt_cd',
alipay: 'ali_app_id'
}
export interface PaymentCredentialEntryInput {
key: string
value: string
}
export interface PaymentCredentialValidationResult {
credentials: PaymentCredentials | null
error: string
}
/**
* 校验并转换商户凭证输入:字段枚举、必填键、值类型与商户标识一致性。
*/
export function buildPaymentCredentials(
providerType: PaymentMerchantProviderType,
merchantIdentity: string,
entries: PaymentCredentialEntryInput[]
): PaymentCredentialValidationResult {
const spec = getPaymentCredentialFieldSpec(providerType)
const allowedKeys = [...spec.required, ...spec.optional]
const credentials: Record<string, PaymentCredentialValue> = {}
for (const entry of entries) {
const key = entry.key.trim()
if (!key) {
return { credentials: null, error: '请填写凭证字段名' }
}
if (!allowedKeys.includes(key)) {
return { credentials: null, error: `凭证字段 ${key} 不属于当前服务商支持的字段` }
}
if (!entry.value) {
return { credentials: null, error: `请填写凭证字段 ${key} 的值` }
}
if (Object.prototype.hasOwnProperty.call(credentials, key)) {
return { credentials: null, error: `凭证字段 ${key} 重复` }
}
if (PAYMENT_CREDENTIAL_BOOLEAN_KEYS.includes(key)) {
if (entry.value !== 'true' && entry.value !== 'false') {
return { credentials: null, error: `凭证字段 ${key} 必须为布尔值 true 或 false` }
}
credentials[key] = entry.value === 'true'
continue
}
if (PAYMENT_CREDENTIAL_INTEGER_KEYS.includes(key)) {
const numberValue = Number(entry.value)
if (!Number.isInteger(numberValue) || numberValue <= 0) {
return { credentials: null, error: `凭证字段 ${key} 必须为正整数` }
}
credentials[key] = numberValue
continue
}
credentials[key] = entry.value
}
for (const key of spec.required) {
if (!Object.prototype.hasOwnProperty.call(credentials, key)) {
return { credentials: null, error: `缺少必填凭证字段 ${key}` }
}
}
const identityKey = PAYMENT_MERCHANT_IDENTITY_KEYS[providerType]
if (identityKey && credentials[identityKey] !== merchantIdentity.trim()) {
return { credentials: null, error: `商户标识必须与凭证字段 ${identityKey} 的值一致` }
}
return { credentials, error: '' }
}

View File

@@ -1,6 +1,9 @@
import type { BaseResponse, PaginationData, PaginationParams } from './common'
export type WecomBusinessType = 'refund_approval' | 'offline_recharge_approval'
export type WecomBusinessType =
| 'refund_approval'
| 'offline_recharge_approval'
| 'employee_collection_approval'
export interface WecomApplication {
id: number