feat(payment): 新增微信支付宝积分充值与对账
This commit is contained in:
187
web/src/services/api/payments.ts
Normal file
187
web/src/services/api/payments.ts
Normal file
@@ -0,0 +1,187 @@
|
||||
import { apiClient, request } from "@/services/api/request";
|
||||
|
||||
export type PaymentProvider = {
|
||||
id: "wechat-native" | "alipay-page-pay" | string;
|
||||
pluginId: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
checkoutMode: "qr_code" | "redirect";
|
||||
enabled: boolean;
|
||||
pluginEnabled: boolean;
|
||||
configured: boolean;
|
||||
closeAfterMinutes: number;
|
||||
};
|
||||
|
||||
export type TopupProduct = {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
amountFen: number;
|
||||
creditsMicrocredits: number;
|
||||
enabled: boolean;
|
||||
sortOrder: number;
|
||||
createdBy: string;
|
||||
updatedBy: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type PaymentOrderStatus = "created" | "pending" | "closing" | "closed" | "credited" | "create_failed";
|
||||
|
||||
export type PaymentOrder = {
|
||||
id: string;
|
||||
userId?: string;
|
||||
merchantOrderNo: string;
|
||||
productId: string;
|
||||
productName: string;
|
||||
providerId: string;
|
||||
amountFen: number;
|
||||
currency: "CNY" | string;
|
||||
creditsMicrocredits: number;
|
||||
status: PaymentOrderStatus;
|
||||
providerStatus?: string;
|
||||
providerTradeNo?: string;
|
||||
checkout: {
|
||||
mode: "qr_code" | "redirect" | "";
|
||||
value?: string;
|
||||
url?: string;
|
||||
expiresAt?: string;
|
||||
};
|
||||
expiresAt: string;
|
||||
providerPaidAt?: string;
|
||||
creditedAt?: string;
|
||||
closedAt?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type PaymentConfigField = {
|
||||
name: string;
|
||||
type: "string" | "password" | "textarea" | "url" | string;
|
||||
label?: string;
|
||||
required?: boolean;
|
||||
secret?: boolean;
|
||||
default?: unknown;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
export type AdminPaymentProvider = PaymentProvider & {
|
||||
configId?: string;
|
||||
configEnabled: boolean;
|
||||
version: number;
|
||||
values: Record<string, string>;
|
||||
secretConfigured: Record<string, boolean>;
|
||||
configFields: PaymentConfigField[];
|
||||
updatedAt?: string;
|
||||
};
|
||||
|
||||
export function listPaymentProviders() {
|
||||
return request<{ providers: PaymentProvider[] }>(apiClient.get("/payments/providers"));
|
||||
}
|
||||
|
||||
export function listTopupProducts() {
|
||||
return request<{ products: TopupProduct[] }>(apiClient.get("/payments/products"));
|
||||
}
|
||||
|
||||
export function createPaymentOrder(input: { productId: string; providerId: string; idempotencyKey: string }) {
|
||||
return request<{ order: PaymentOrder }>(apiClient.post("/payments/orders", input));
|
||||
}
|
||||
|
||||
export function getPaymentOrder(id: string) {
|
||||
return request<{ order: PaymentOrder }>(apiClient.get(`/payments/orders/${encodeURIComponent(id)}`));
|
||||
}
|
||||
|
||||
export function queryPaymentOrder(id: string) {
|
||||
return request<{ order: PaymentOrder }>(apiClient.post(`/payments/orders/${encodeURIComponent(id)}/query`));
|
||||
}
|
||||
|
||||
export function closePaymentOrder(id: string) {
|
||||
return request<{ order: PaymentOrder }>(apiClient.post(`/payments/orders/${encodeURIComponent(id)}/close`));
|
||||
}
|
||||
|
||||
export function refreshPaymentCheckout(id: string) {
|
||||
return request<{ order: PaymentOrder }>(apiClient.post(`/payments/orders/${encodeURIComponent(id)}/checkout/refresh`));
|
||||
}
|
||||
|
||||
export function listAdminPaymentProviders() {
|
||||
return request<{ providers: AdminPaymentProvider[] }>(apiClient.get("/admin/payments/providers"));
|
||||
}
|
||||
|
||||
export function updateAdminPaymentProvider(id: string, input: { enabled: boolean; closeAfterMinutes: number; values: Record<string, string> }) {
|
||||
return request<{ provider: AdminPaymentProvider }>(apiClient.put(`/admin/payments/providers/${encodeURIComponent(id)}/config`, input));
|
||||
}
|
||||
|
||||
export function listAdminTopupProducts() {
|
||||
return request<{ products: TopupProduct[] }>(apiClient.get("/admin/payments/products"));
|
||||
}
|
||||
|
||||
export type TopupProductInput = Pick<TopupProduct, "name" | "amountFen" | "creditsMicrocredits" | "enabled" | "sortOrder"> & { description?: string };
|
||||
|
||||
export function createAdminTopupProduct(input: TopupProductInput) {
|
||||
return request<{ product: TopupProduct }>(apiClient.post("/admin/payments/products", input));
|
||||
}
|
||||
|
||||
export function updateAdminTopupProduct(id: string, input: TopupProductInput) {
|
||||
return request<{ product: TopupProduct }>(apiClient.put(`/admin/payments/products/${encodeURIComponent(id)}`, input));
|
||||
}
|
||||
|
||||
export function listAdminPaymentOrders(params: { status?: string; keyword?: string; page?: number; limit?: number } = {}) {
|
||||
return request<{ orders: PaymentOrder[]; total: number; page: number; limit: number }>(apiClient.get("/admin/payments/orders", { params }));
|
||||
}
|
||||
|
||||
export function queryAdminPaymentOrder(id: string) {
|
||||
return request<{ order: PaymentOrder }>(apiClient.post(`/admin/payments/orders/${encodeURIComponent(id)}/query`));
|
||||
}
|
||||
|
||||
export function closeAdminPaymentOrder(id: string) {
|
||||
return request<{ order: PaymentOrder }>(apiClient.post(`/admin/payments/orders/${encodeURIComponent(id)}/close`));
|
||||
}
|
||||
|
||||
export type PaymentReconciliationStatus = "running" | "completed" | "failed";
|
||||
|
||||
export type PaymentReconciliationResult = "matched" | "recovered" | "local_order_not_found" | "provider_record_missing" | "amount_mismatch" | "trade_no_mismatch" | "credit_failed";
|
||||
|
||||
export type PaymentReconciliationRun = {
|
||||
id: string;
|
||||
providerId: string;
|
||||
configId: string;
|
||||
billDate: string;
|
||||
status: PaymentReconciliationStatus;
|
||||
totalItems: number;
|
||||
matchItems: number;
|
||||
recoveredItems: number;
|
||||
errorItems: number;
|
||||
error?: string;
|
||||
startedBy?: string;
|
||||
startedAt: string;
|
||||
completedAt?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type PaymentReconciliationItem = {
|
||||
id: string;
|
||||
runId: string;
|
||||
providerId: string;
|
||||
paymentOrderId?: string;
|
||||
merchantOrderNo: string;
|
||||
providerTradeNo?: string;
|
||||
amountFen: number;
|
||||
currency: string;
|
||||
result: PaymentReconciliationResult;
|
||||
resolved: boolean;
|
||||
detail?: string;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
export function runAdminPaymentReconciliation(input: { providerId: string; billDate: string }) {
|
||||
return request<{ run: PaymentReconciliationRun }>(apiClient.post("/admin/payments/reconciliations", input));
|
||||
}
|
||||
|
||||
export function listAdminPaymentReconciliations(params: { providerId?: string; status?: string; page?: number; limit?: number } = {}) {
|
||||
return request<{ runs: PaymentReconciliationRun[]; total: number; page: number; limit: number }>(apiClient.get("/admin/payments/reconciliations", { params }));
|
||||
}
|
||||
|
||||
export function listAdminPaymentReconciliationItems(id: string, params: { result?: string; page?: number; limit?: number } = {}) {
|
||||
return request<{ run: PaymentReconciliationRun; items: PaymentReconciliationItem[]; total: number; page: number; limit: number }>(apiClient.get(`/admin/payments/reconciliations/${encodeURIComponent(id)}/items`, { params }));
|
||||
}
|
||||
@@ -17,8 +17,8 @@ export type BackendPlugin = {
|
||||
export type WorkflowPluginStatus = "enabled" | "disabled" | "invalid" | string;
|
||||
|
||||
export type PluginManagement = {
|
||||
origin: "official" | "uploaded";
|
||||
kind: "protocol" | "application";
|
||||
origin: "official" | "system" | "uploaded";
|
||||
kind: "protocol" | "application" | "payment";
|
||||
activationScope: "system" | "user";
|
||||
configurationScope: "none" | "system" | "user";
|
||||
};
|
||||
|
||||
@@ -14,11 +14,12 @@ export type CreditAccount = {
|
||||
export type CreditLedgerEntry = {
|
||||
id: string;
|
||||
userId: string;
|
||||
type: "redeem" | "admin_grant" | "consume" | "refund" | "admin_adjustment" | "signup_bonus" | "checkin_bonus";
|
||||
type: "redeem" | "payment_topup" | "admin_grant" | "consume" | "refund" | "admin_adjustment" | "signup_bonus" | "checkin_bonus";
|
||||
amountMicrocredits: number;
|
||||
availableAfterMicrocredits: number;
|
||||
reservedAfterMicrocredits: number;
|
||||
billingOrderId?: string;
|
||||
paymentOrderId?: string;
|
||||
model?: string;
|
||||
channelId?: string;
|
||||
scene?: string;
|
||||
@@ -65,7 +66,7 @@ export type ChannelModel = {
|
||||
priceVersion: number;
|
||||
capabilityVersion?: number;
|
||||
capabilityConfig?: import("@/lib/model-capabilities").ModelCapabilityConfig;
|
||||
priceTiers: ChannelModelPriceTier[];
|
||||
priceTiers: ChannelModelPriceTier[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
@@ -73,8 +74,8 @@ export type ChannelModel = {
|
||||
export type ChannelModelPriceTier = {
|
||||
id: string;
|
||||
channelModelId: string;
|
||||
selector: Record<string, string>;
|
||||
selectorKey: string;
|
||||
selector: Record<string, string>;
|
||||
selectorKey: string;
|
||||
resolution: string;
|
||||
videoSeconds: number;
|
||||
providerModelKey: string;
|
||||
@@ -100,7 +101,7 @@ export type ChannelModelMutation = {
|
||||
protocol?: ChannelModel["protocol"];
|
||||
enabled?: boolean;
|
||||
capabilityConfig?: ChannelModel["capabilityConfig"];
|
||||
priceTiers?: Array<Omit<ChannelModelPriceTier, "id" | "channelModelId" | "selectorKey" | "priceVersion" | "createdAt" | "updatedAt">>;
|
||||
priceTiers?: Array<Omit<ChannelModelPriceTier, "id" | "channelModelId" | "selectorKey" | "priceVersion" | "createdAt" | "updatedAt">>;
|
||||
billingMode?: ChannelModel["billingMode"];
|
||||
unitPriceMicrocredits?: number;
|
||||
inputTokenPriceMicrocredits?: number;
|
||||
@@ -285,7 +286,7 @@ export function updateAdminChannelModel(channelId: string, id: string, input: Ch
|
||||
}
|
||||
|
||||
export function deleteAdminChannelModel(channelId: string, id: string) {
|
||||
return request<{ ok: boolean }>(api.delete(`/admin/channels/${encodeURIComponent(channelId)}/models/${encodeURIComponent(id)}`));
|
||||
return request<{ ok: boolean }>(api.delete(`/admin/channels/${encodeURIComponent(channelId)}/models/${encodeURIComponent(id)}`));
|
||||
}
|
||||
|
||||
export type AdminFinanceListParams = { keyword?: string; status?: string; validity?: string; page?: number; limit?: number };
|
||||
|
||||
Reference in New Issue
Block a user