useWechatMiniPay.js
5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import { computed, ref } from 'vue'
import Taro from '@tarojs/taro'
import { getWechatPayParamsAPI } from '@/api'
import { clearSessionId } from '@/utils/request'
import { hasAuth, silentAuth } from '@/utils/authRedirect'
/**
* @description 微信小程序支付能力封装
* - 可复用于测试页、WebView 容器页、后续其他按钮点击场景
* - 统一处理:授权、获取支付参数、拉起 requestPayment、状态回传
*/
export const useWechatMiniPay = () => {
const auth_loading = ref(false)
const pay_loading = ref(false)
const sessionid = ref('')
const last_result_text = ref('等待开始测试')
const is_authed = computed(() => !!sessionid.value)
const sessionid_preview = computed(() => {
if (!sessionid.value) return '暂无'
if (sessionid.value.length <= 18) return sessionid.value
return `${sessionid.value.slice(0, 8)}...${sessionid.value.slice(-8)}`
})
const update_result_text = (text, options = {}) => {
last_result_text.value = text
if (typeof options.on_status === 'function') {
options.on_status(text)
}
}
const sync_auth_state = () => {
const current_sessionid = Taro.getStorageSync('sessionid') || ''
sessionid.value = current_sessionid
return current_sessionid
}
const refresh_auth = async (options = {}) => {
auth_loading.value = true
try {
if (options.force_refresh) {
clearSessionId()
}
await silentAuth(null, null, {
show_loading: options.show_loading !== false,
})
sync_auth_state()
update_result_text('静默授权成功,可以继续测试支付。', options)
return { code: 1, msg: '静默授权成功' }
} catch (error) {
sync_auth_state()
const message = error?.message || '静默授权失败'
update_result_text(message, options)
return { code: 0, msg: message, data: error || null }
} finally {
auth_loading.value = false
}
}
const pay_by_order_id = async (raw_order_id, options = {}) => {
const normalized_order_id = String(raw_order_id || '').trim()
if (!normalized_order_id) {
const message = '请先输入订单 ID'
Taro.showToast({
title: message,
icon: 'none',
})
update_result_text(message, options)
return { code: 0, status: 'invalid', msg: message, data: null }
}
if (!hasAuth()) {
if (options.auto_auth !== false) {
const auth_res = await refresh_auth({
...options,
force_refresh: false,
show_loading: true,
})
if (!auth_res?.code) {
return {
code: 0,
status: 'auth_fail',
msg: auth_res?.msg || '授权失败',
data: auth_res?.data || null,
}
}
} else {
const message = '当前未授权,请先重新授权'
Taro.showToast({
title: message,
icon: 'none',
})
update_result_text(message, options)
return { code: 0, status: 'auth_required', msg: message, data: null }
}
} else {
sync_auth_state()
}
pay_loading.value = true
update_result_text('正在请求支付参数...', options)
try {
const pay_res = await getWechatPayParamsAPI({ order_id: normalized_order_id })
if (!pay_res?.code || !pay_res?.data) {
const message = pay_res?.msg || '获取支付参数失败'
update_result_text(message, options)
return { code: 0, status: 'params_fail', msg: message, data: pay_res?.data || null }
}
const pay_data = pay_res.data
update_result_text('已获取支付参数,准备拉起微信支付弹框...', options)
const pay_result = await new Promise((resolve) => {
Taro.requestPayment({
timeStamp: pay_data.timeStamp,
nonceStr: pay_data.nonceStr,
package: pay_data.package,
signType: pay_data.signType,
paySign: pay_data.paySign,
success: (res) => resolve({ ok: true, res }),
fail: (err) => resolve({ ok: false, err }),
})
})
if (pay_result?.ok) {
const message = '支付流程已提交成功,微信支付返回 success。'
update_result_text(message, options)
return { code: 1, status: 'success', msg: message, data: pay_result.res || null }
}
const err_msg = pay_result?.err?.errMsg || '支付未完成'
const message = `微信支付已拉起,结果:${err_msg}`
update_result_text(message, options)
const is_cancelled = String(err_msg).toLowerCase().includes('cancel')
return {
code: 0,
status: is_cancelled ? 'cancel' : 'fail',
msg: message,
data: pay_result?.err || null,
}
} catch (error) {
const message = error?.message || '拉起支付失败'
update_result_text(message, options)
return { code: 0, status: 'exception', msg: message, data: error || null }
} finally {
pay_loading.value = false
}
}
sync_auth_state()
return {
auth_loading,
pay_loading,
sessionid,
is_authed,
sessionid_preview,
last_result_text,
sync_auth_state,
refresh_auth,
pay_by_order_id,
}
}