初始化2
This commit is contained in:
293
app/api/payment/index.ts
Normal file
293
app/api/payment/index.ts
Normal file
@@ -0,0 +1,293 @@
|
||||
/**
|
||||
* 支付模块 API 封装
|
||||
* 支持:微信 JSAPI / 支付宝 / Native / 余额
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
import type { ApiResult } from '@/api'
|
||||
import { SERVER_API_URL } from '@/config/setting'
|
||||
|
||||
/** 支付方式 */
|
||||
export type PayType = 'wechat' | 'alipay' | 'native' | 'balance' | number
|
||||
|
||||
/** 支付渠道 */
|
||||
export type PayChannel = 'wechat_jsapi' | 'alipay_wap' | 'wechat_native' | 'balance'
|
||||
|
||||
/** 支付参数 */
|
||||
export interface PayParams {
|
||||
orderNo: string
|
||||
orderId?: number
|
||||
payType: PayChannel
|
||||
/** 微信 JSAPI 必填:用户 openid */
|
||||
openId?: string
|
||||
/** 微信 JSAPI 必填:支付主体类型 */
|
||||
subject?: string
|
||||
/** 支付主体描述 */
|
||||
body?: string
|
||||
/** 支付金额(分) */
|
||||
totalAmount?: number
|
||||
/** 前端回调 URL */
|
||||
returnUrl?: string
|
||||
}
|
||||
|
||||
/** 微信 JSAPI 支付参数 */
|
||||
export interface WechatJsapiParams {
|
||||
orderNo: string
|
||||
openId: string
|
||||
subject: string
|
||||
body?: string
|
||||
totalAmount?: number
|
||||
returnUrl?: string
|
||||
}
|
||||
|
||||
/** 支付宝 WAP/Web 支付参数 */
|
||||
export interface AlipayParams {
|
||||
orderNo: string
|
||||
subject: string
|
||||
body?: string
|
||||
totalAmount?: number
|
||||
returnUrl?: string
|
||||
}
|
||||
|
||||
/** Native 支付参数 */
|
||||
export interface NativeParams {
|
||||
orderNo: string
|
||||
subject: string
|
||||
body?: string
|
||||
totalAmount?: number
|
||||
}
|
||||
|
||||
/** 支付结果 */
|
||||
export interface PayResult {
|
||||
codeUrl?: string // Native 支付二维码链接
|
||||
qrcode?: string // 二维码内容
|
||||
paymentUrl?: string // 跳转支付链接
|
||||
payUrl?: string // 支付链接
|
||||
prepayId?: string // 预支付订单号
|
||||
mwebUrl?: string // 微信 H5 支付链接
|
||||
tradeNo?: string // 交易流水号
|
||||
orderNo?: string // 订单号
|
||||
orderId?: number // 订单ID
|
||||
}
|
||||
|
||||
/** 支付状态 */
|
||||
export interface PayStatus {
|
||||
paid: boolean
|
||||
payStatus: number // 0 未支付,1 已支付
|
||||
orderStatus: number // 订单状态
|
||||
payTime?: string // 支付时间
|
||||
transactionId?: string // 微信/支付宝交易号
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一支付接口
|
||||
* @deprecated 使用具体渠道接口
|
||||
*/
|
||||
export async function createPayment(data: Record<string, unknown>): Promise<PayResult> {
|
||||
const res = await request.post<ApiResult<PayResult>>(
|
||||
SERVER_API_URL + '/system/payment/create',
|
||||
data
|
||||
)
|
||||
if (res.data.code === 0) {
|
||||
return res.data.data!
|
||||
}
|
||||
return Promise.reject(new Error(res.data.message))
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信 JSAPI 支付
|
||||
* 适用于微信内置浏览器 / 公众号 / 小程序环境
|
||||
*/
|
||||
export async function createWechatJsapiPay(params: WechatJsapiParams): Promise<PayResult> {
|
||||
const res = await request.post<ApiResult<PayResult>>(
|
||||
SERVER_API_URL + '/system/wx-jsapi-pay/unified-order',
|
||||
params
|
||||
)
|
||||
if (res.data.code === 0) {
|
||||
return res.data.data!
|
||||
}
|
||||
return Promise.reject(new Error(res.data.message))
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信 H5 支付
|
||||
* 适用于非微信浏览器
|
||||
*/
|
||||
export async function createWechatH5Pay(params: { orderNo: string; subject: string; body?: string; totalAmount?: number; returnUrl?: string }): Promise<PayResult> {
|
||||
const res = await request.post<ApiResult<PayResult>>(
|
||||
SERVER_API_URL + '/system/wx-h5-pay/unified-order',
|
||||
params
|
||||
)
|
||||
if (res.data.code === 0) {
|
||||
return res.data.data!
|
||||
}
|
||||
return Promise.reject(new Error(res.data.message))
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信 Native 支付(扫码支付)
|
||||
*/
|
||||
export async function createWechatNativePay(params: NativeParams): Promise<PayResult> {
|
||||
const res = await request.post<ApiResult<PayResult>>(
|
||||
SERVER_API_URL + '/system/wx-native-pay/unified-order',
|
||||
params
|
||||
)
|
||||
if (res.data.code === 0) {
|
||||
return res.data.data!
|
||||
}
|
||||
return Promise.reject(new Error(res.data.message))
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝 WAP/Web 支付
|
||||
*/
|
||||
export async function createAlipayPay(params: AlipayParams): Promise<PayResult> {
|
||||
const res = await request.post<ApiResult<PayResult>>(
|
||||
SERVER_API_URL + '/system/alipay/unified-order',
|
||||
params
|
||||
)
|
||||
if (res.data.code === 0) {
|
||||
return res.data.data!
|
||||
}
|
||||
return Promise.reject(new Error(res.data.message))
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询支付状态
|
||||
*/
|
||||
export async function queryPayStatus(orderNo: string): Promise<PayStatus> {
|
||||
const res = await request.get<ApiResult<PayStatus>>(
|
||||
SERVER_API_URL + '/system/payment/query-status',
|
||||
{ params: { orderNo } }
|
||||
)
|
||||
if (res.data.code === 0) {
|
||||
return res.data.data!
|
||||
}
|
||||
return Promise.reject(new Error(res.data.message))
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订单
|
||||
*/
|
||||
export async function cancelOrder(orderId: number): Promise<void> {
|
||||
const res = await request.post<ApiResult<void>>(
|
||||
SERVER_API_URL + '/system/order/cancel',
|
||||
{ orderId }
|
||||
)
|
||||
if (res.data.code !== 0) {
|
||||
return Promise.reject(new Error(res.data.message))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款
|
||||
*/
|
||||
export async function applyRefund(orderId: number, reason?: string): Promise<void> {
|
||||
const res = await request.post<ApiResult<void>>(
|
||||
SERVER_API_URL + '/system/order/refund',
|
||||
{ orderId, reason }
|
||||
)
|
||||
if (res.data.code !== 0) {
|
||||
return Promise.reject(new Error(res.data.message))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前环境
|
||||
*/
|
||||
export function detectPayEnvironment(): 'wechat' | 'alipay' | 'desktop' | 'mobile' {
|
||||
const ua = navigator.userAgent.toLowerCase()
|
||||
|
||||
// 微信环境
|
||||
if (/micromessenger/.test(ua)) {
|
||||
return 'wechat'
|
||||
}
|
||||
|
||||
// 支付宝环境
|
||||
if (/alipayclient/.test(ua)) {
|
||||
return 'alipay'
|
||||
}
|
||||
|
||||
// 移动端
|
||||
if (/mobile|android|iphone|ipad|tablet/i.test(ua)) {
|
||||
return 'mobile'
|
||||
}
|
||||
|
||||
// 桌面端
|
||||
return 'desktop'
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测是否在微信内置浏览器
|
||||
*/
|
||||
export function isWechatBrowser(): boolean {
|
||||
return /micromessenger/.test(navigator.userAgent.toLowerCase())
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测是否在支付宝内置浏览器
|
||||
*/
|
||||
export function isAlipayBrowser(): boolean {
|
||||
return /alipayclient/.test(navigator.userAgent.toLowerCase())
|
||||
}
|
||||
|
||||
/**
|
||||
* 调起微信 JSAPI 支付
|
||||
* 需要先引入微信 JSSDK 并完成签名
|
||||
*/
|
||||
export function callWechatJsapi(params: {
|
||||
appId: string
|
||||
timestamp: string
|
||||
nonceStr: string
|
||||
package: string
|
||||
signType?: string
|
||||
paySign: string
|
||||
}): Promise<'ok'> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof window.WeixinJSBridge === 'undefined') {
|
||||
// 尝试通过 WeChat JSSDK 调用
|
||||
if (typeof window.jWeixin !== 'undefined') {
|
||||
window.jWeixin.chooseWXPay({
|
||||
...params,
|
||||
success: () => resolve('ok'),
|
||||
fail: (err: unknown) => reject(err)
|
||||
})
|
||||
} else {
|
||||
reject(new Error('微信 JSSDK 未加载'))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
window.WeixinJSBridge.invoke(
|
||||
'getBrandWCPayRequest',
|
||||
{
|
||||
appId: params.appId,
|
||||
timeStamp: params.timestamp,
|
||||
nonceStr: params.nonceStr,
|
||||
package: params.package,
|
||||
signType: params.signType || 'MD5',
|
||||
paySign: params.paySign
|
||||
},
|
||||
(res: { err_msg: string }) => {
|
||||
if (res.err_msg === 'get_brand_wcpay_request:ok') {
|
||||
resolve('ok')
|
||||
} else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
|
||||
reject(new Error('用户取消支付'))
|
||||
} else {
|
||||
reject(new Error(res.err_msg))
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// 扩展 Window 类型
|
||||
declare global {
|
||||
interface Window {
|
||||
WeixinJSBridge?: {
|
||||
invoke: (api: string, params: Record<string, unknown>, callback: (res: { err_msg: string }) => void) => void
|
||||
}
|
||||
jWeixin?: {
|
||||
chooseWXPay: (params: Record<string, unknown> & { success?: () => void; fail?: (err: unknown) => void }) => void
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user