import request from '@/utils/request'; import type { ApiResult, PageResult } from '@/api'; import type { AppSubscription, AppSubscriptionQueryParam, SubscribeParam, SubscribeResult, GeneratePayQrcodeParam, GeneratePayQrcodeResult, CheckStatusResult, PayResult, WechatNativePayResult, MpPrepayParam, MpPrepayResult, MpConfirmParam, BalanceResult } from './model'; /** * websopy 特殊接口域名(与项目主 API 域名不同) * 后端 Controller: com.gxwebsoft.app.controller.AppSubscriptionController * @RequestMapping("/api/app/subscription"),后端无 context-path * 因此完整 URL = https://websopy-api.websoft.top + /api/app/subscription/xxx */ const WEBSOPY_API_BASE = 'https://websopy-api.websoft.top/api'; const BASE = `${WEBSOPY_API_BASE}/app/subscription`; /** * 我的订阅列表(分页) * GET /app/subscription/my/page */ export async function pageMySubscriptions( params: AppSubscriptionQueryParam ): Promise> { const res = await request.get>>( `${BASE}/my/page`, { params } ); if (res.data.code === 0) { return ( res.data.data || { list: [], count: 0 } ); } return Promise.reject(new Error(res.data.message)); } /** * 订阅详情(按ID) * GET /app/subscription/detail/{id} */ export async function getSubscriptionDetail( id: number ): Promise { const res = await request.get>( `${BASE}/detail/${id}` ); if (res.data.code === 0) { return res.data.data as AppSubscription; } return Promise.reject(new Error(res.data.message)); } /** * 根据订阅编号查询详情(小程序入口用) * GET /app/subscription/detail-by-no/{subscriptionNo} */ export async function getSubscriptionDetailByNo( subscriptionNo: string ): Promise { const res = await request.get>( `${BASE}/detail-by-no/${subscriptionNo}` ); if (res.data.code === 0) { return res.data.data as AppSubscription; } return Promise.reject(new Error(res.data.message)); } /** * 查询支付状态(前端轮询用) * GET /app/subscription/check-status/{subscriptionNo} */ export async function checkSubscriptionStatus( subscriptionNo: string ): Promise { const res = await request.get>( `${BASE}/check-status/${subscriptionNo}` ); if (res.data.code === 0) { return res.data.data as CheckStatusResult; } return Promise.reject(new Error(res.data.message)); } /** * 检查是否已购买某应用 * GET /app/subscription/check-purchased/{productId} * 返回 boolean */ export async function checkPurchased( productId: number ): Promise { const res = await request.get>( `${BASE}/check-purchased/${productId}` ); if (res.data.code === 0) { return res.data.data === true; } return Promise.reject(new Error(res.data.message)); } /** * 获取当前用户余额 * GET /app/subscription/balance */ export async function getBalance(): Promise { const res = await request.get>(`${BASE}/balance`); if (res.data.code === 0) { return ( res.data.data || { balance: 0 } ); } return Promise.reject(new Error(res.data.message)); } /** * 创建订阅 * POST /app/subscription/subscribe * 免费应用直接激活,付费应用创建待支付记录 */ export async function subscribe( data: SubscribeParam ): Promise { const res = await request.post>( `${BASE}/subscribe`, data ); if (res.data.code === 0) { return res.data.data as SubscribeResult; } return Promise.reject(new Error(res.data.message)); } /** * 生成支付小程序码(同时创建订阅记录) * POST /app/subscription/generate-pay-qrcode */ export async function generatePayQrcode( data: GeneratePayQrcodeParam ): Promise { const res = await request.post>( `${BASE}/generate-pay-qrcode`, data ); if (res.data.code === 0) { return res.data.data as GeneratePayQrcodeResult; } return Promise.reject(new Error(res.data.message)); } /** * 发起支付 * POST /app/subscription/pay/{id}?method=balance|wechat&envVersion=xxx * - method=balance:余额支付,返回 PayResult * - method=wechat:微信 Native 支付,返回小程序码 WechatNativePayResult */ export async function paySubscription( id: number, method: 'balance' | 'wechat' = 'wechat', envVersion?: string ): Promise { const res = await request.post>( `${BASE}/pay/${id}`, undefined, { params: { method, envVersion } } ); if (res.data.code === 0) { return res.data.data as PayResult | WechatNativePayResult; } return Promise.reject(new Error(res.data.message)); } /** * 小程序 JSAPI 预支付下单 * POST /app/subscription/mp-prepay/{id} * Body: { openid } */ export async function mpPrepay( id: number, data: MpPrepayParam ): Promise { const res = await request.post>( `${BASE}/mp-prepay/${id}`, data ); if (res.data.code === 0) { return res.data.data as MpPrepayResult; } return Promise.reject(new Error(res.data.message)); } /** * 小程序支付成功确认 * POST /app/subscription/mp-confirm/{subscriptionNo} * Body: { transactionId? } */ export async function mpConfirm( subscriptionNo: string, data?: MpConfirmParam ): Promise { const res = await request.post>( `${BASE}/mp-confirm/${subscriptionNo}`, data ); if (res.data.code === 0) { return ( res.data.data || { paid: true, subscriptionNo } ); } return Promise.reject(new Error(res.data.message)); } /** * 续费:基于已有订阅创建续费订单并生成支付码(一步完成,对齐后端 /renew-pay) * POST /app/subscription/renew-pay/{id}?period=month&method=wechat&envVersion=trial * - method=balance:余额支付,返回 PayResult(paid/balance) * - method=wechat:微信支付,返回小程序码 WechatNativePayResult(miniappQrcode) * 后端会基于原 expireTime 或 now(取较大者)延长到期时间 */ export async function renewSubscription( id: number, period: 'month' | 'year' = 'month', method: 'balance' | 'wechat' = 'wechat', envVersion?: string ): Promise { const res = await request.post>( `${BASE}/renew-pay/${id}`, undefined, { params: { period, method, envVersion } } ); if (res.data.code === 0) { return res.data.data as PayResult | WechatNativePayResult; } return Promise.reject(new Error(res.data.message)); } /** * 退订/取消 * POST /app/subscription/cancel/{id} */ export async function cancelSubscription(id: number): Promise { const res = await request.post>(`${BASE}/cancel/${id}`); if (res.data.code === 0) { return res.data.message || '退订成功'; } return Promise.reject(new Error(res.data.message)); } /** * 启用/禁用 * POST /app/subscription/toggle-enable/{id}?enabled=true|false */ export async function toggleEnable( id: number, enabled: boolean ): Promise { const res = await request.post>( `${BASE}/toggle-enable/${id}`, undefined, { params: { enabled } } ); if (res.data.code === 0) { return res.data.message || (enabled ? '已启用' : '已禁用'); } return Promise.reject(new Error(res.data.message)); }