Files
jczxw-pc/app/api/app/subscription/index.ts
2026-04-23 16:30:57 +08:00

115 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 应用订阅 API
* 前端路径:/api/app/subscription → 后端 /api/app/subscription
*/
import request from '@/utils/request'
import type { ApiResult, PageResult } from '@/api'
import { APP_API_URL } from '@/config/setting'
import type { AppSubscription, AppSubscriptionParam, SubscribeResult } from './model'
const BASE = APP_API_URL + '/subscription'
/** 统一成功码判断:兼容 code=0旧约定和 code=200Spring Boot 默认) */
const ok = (code: number) => code === 0 || code === 200
// ============ 订阅操作 ============
/** 创建订阅(免费直接激活,付费创建待支付) */
export async function createSubscription(data: {
productId: number
priceType: 'free' | 'one_time' | 'subscription'
subscriptionPeriod?: 'month' | 'year'
quantity?: number
}) {
const res = await request.post<ApiResult<SubscribeResult>>(BASE + '/subscribe', data)
if (ok(res.data.code)) return res.data.data
return Promise.reject(new Error(res.data.message))
}
/** 获取用户余额 */
export async function getUserBalance(): Promise<{ balance: number }> {
const res = await request.get<ApiResult<{ balance: number }>>(BASE + '/balance')
if (ok(res.data.code)) return res.data.data ?? { balance: 0 }
return Promise.reject(new Error(res.data.message))
}
/** 发起支付(支持微信/余额支付) */
export async function paySubscription(id: number, method: 'wechat' | 'balance' | 'alipay' = 'wechat') {
const res = await request.post<ApiResult<unknown>>(BASE + '/pay/' + id, null, {
params: { method }
})
if (ok(res.data.code)) return res.data.data
return Promise.reject(new Error(res.data.message))
}
/** 查询支付状态(轮询用),同时返回订单详情 */
export async function checkPayStatus(subscriptionNo: string) {
const res = await request.get<ApiResult<{
paid: boolean
payStatus: number
status: string
payTime?: string
transactionId?: string
// 订单详情(供支付页直接使用,无需再调 getSubscription
id?: number
subscriptionNo?: string
productId?: number
productName?: string
productLogo?: string
priceType?: string
payPrice?: number
subscriptionPeriod?: string
}>>(BASE + '/check-status/' + subscriptionNo)
if (ok(res.data.code)) return res.data.data
return Promise.reject(new Error(res.data.message))
}
// ============ 我的订阅 ============
/** 我的订阅列表(分页) */
export async function mySubscriptions(params?: AppSubscriptionParam) {
const res = await request.get<ApiResult<PageResult<AppSubscription>>>(BASE + '/my/page', { params })
if (ok(res.data.code)) return res.data.data
return Promise.reject(new Error(res.data.message))
}
/** 订阅详情 */
export async function getSubscription(id: number) {
const res = await request.get<ApiResult<AppSubscription>>(BASE + '/detail/' + id)
if (ok(res.data.code)) return res.data.data
return Promise.reject(new Error(res.data.message))
}
// ============ 订阅管理 ============
/** 续费 */
export async function renewSubscription(id: number, period: 'month' | 'year') {
const res = await request.post<ApiResult<unknown>>(BASE + '/renew/' + id, null, { params: { period } })
if (ok(res.data.code)) return res.data.data
return Promise.reject(new Error(res.data.message))
}
/** 退订/取消 */
export async function cancelSubscription(id: number) {
const res = await request.post<ApiResult<unknown>>(BASE + '/cancel/' + id)
if (ok(res.data.code)) return res.data.message
return Promise.reject(new Error(res.data.message))
}
/** 启用/禁用 */
export async function toggleEnable(id: number, enabled: boolean) {
const res = await request.post<ApiResult<unknown>>(BASE + '/toggle-enable/' + id, null, { params: { enabled } })
if (ok(res.data.code)) return res.data.message
return Promise.reject(new Error(res.data.message))
}
// ============ 查询 ============
/** 检查是否已购买某应用 */
export async function checkPurchased(productId: number) {
const res = await request.get<ApiResult<boolean>>(BASE + '/check-purchased/' + productId)
if (ok(res.data.code)) return res.data.data ?? false
// 接口未实现时静默返回 false不影响主流程
return false
}