feat: 延期微信支付在微信内直接拉起
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 19m17s
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 19m17s
- 微信支付下单带 app_type;拿到 pay_config 后与套餐购买一样拉起微信支付,继续支付同样处理 - 微信内打开时支付方式默认微信;取消支付保留同一请求号,再次确认不重复建单
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import request from '@/utils/request.js';
|
||||
import { APP_TYPE } from '@/utils/env.js';
|
||||
|
||||
// 实名即生效套餐沉默期 H5 接口(后端 Iteration/8-11,/api/c/v1/package-silence)。
|
||||
// 资格、试算、下单关闭默认错误提示,由页面按沉默期错误码给出客户能看懂的文案。
|
||||
@@ -24,10 +25,13 @@ export const packageSilenceApi = {
|
||||
},
|
||||
|
||||
createOrder({ package_usage_id, days, payment_method, request_id }) {
|
||||
const data = { package_usage_id, days, payment_method, request_id };
|
||||
// 微信支付带上应用类型:后端在微信内直接下 JSAPI 单,返回 pay_config 拉起支付
|
||||
if (payment_method === 'wechat') data.app_type = APP_TYPE;
|
||||
return request({
|
||||
url: `${BASE}/orders`,
|
||||
method: 'POST',
|
||||
data: { package_usage_id, days, payment_method, request_id },
|
||||
data,
|
||||
showError: false
|
||||
});
|
||||
},
|
||||
|
||||
@@ -155,6 +155,7 @@
|
||||
));
|
||||
|
||||
const showToast = (title) => uni.showToast({ title, icon: 'none', duration: 2500 });
|
||||
const isInWechatBrowser = () => typeof navigator !== 'undefined' && /micromessenger/i.test(navigator.userAgent);
|
||||
|
||||
const loadEligibility = async () => {
|
||||
loading.value = true;
|
||||
@@ -166,7 +167,7 @@
|
||||
assetApi.getInfo(userStore.state.identifier).catch(() => null)
|
||||
]);
|
||||
eligibility.value = data;
|
||||
paymentOptions.value = getSilencePaymentOptions(info?.allowed_payment_methods);
|
||||
paymentOptions.value = getSilencePaymentOptions(info?.allowed_payment_methods, isInWechatBrowser());
|
||||
if (!paymentOptions.value.some((option) => option.value === paymentMethod.value)) {
|
||||
paymentMethod.value = paymentOptions.value[0]?.value || '';
|
||||
}
|
||||
@@ -248,15 +249,17 @@
|
||||
request_id: requestIds.get(days, paymentMethod.value)
|
||||
});
|
||||
lastOrderId.value = order?.id || 0;
|
||||
if (!order?.qr_content) {
|
||||
if (!order?.qr_content && !order?.pay_config) {
|
||||
showToast('订单已创建,请在"我的延期订单"中继续支付');
|
||||
openOrders();
|
||||
return;
|
||||
}
|
||||
await openSilencePayment(order, SILENCE_REFRESH_TARGET.EXTENSION);
|
||||
const result = await openSilencePayment(order, SILENCE_REFRESH_TARGET.EXTENSION);
|
||||
// 微信内直接支付完成:立即查订单结果(不经过支付页回跳)
|
||||
if (result?.paid) await checkLastOrder();
|
||||
} catch (error) {
|
||||
// 网络异常时后端可能已建单:保留 request_id,客户再次点击会拿到同一笔订单。
|
||||
if (!error?.paymentResultUnknown) requestIds.reset();
|
||||
// 网络异常时后端可能已建单、取消微信支付时订单仍待支付:保留 request_id,客户再次点击会拿到同一笔订单。
|
||||
if (!error?.paymentResultUnknown && !error?.cancelled) requestIds.reset();
|
||||
showToast(getSilenceErrorMessage(error, '下单失败,请稍后重试'));
|
||||
if (Number(error?.code) === 1271) await loadEligibility();
|
||||
} finally {
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
];
|
||||
});
|
||||
|
||||
const canContinuePay = computed(() => order.value?.status === 'pending_payment' && !!order.value?.qr_content);
|
||||
const canContinuePay = computed(() => order.value?.status === 'pending_payment' && (!!order.value?.qr_content || !!order.value?.pay_config));
|
||||
const canCancel = computed(() => order.value?.status === 'pending_payment');
|
||||
const cancelling = ref(false);
|
||||
|
||||
@@ -91,7 +91,8 @@
|
||||
|
||||
const continuePay = async () => {
|
||||
try {
|
||||
await openSilencePayment(order.value, SILENCE_REFRESH_TARGET.ORDER_DETAIL);
|
||||
const result = await openSilencePayment(order.value, SILENCE_REFRESH_TARGET.ORDER_DETAIL);
|
||||
if (result?.paid) await load();
|
||||
} catch (error) {
|
||||
uni.showToast({ title: error?.message || '拉起支付失败', icon: 'none' });
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ test('延期支付方式只取 wechat、alipay 与资产允许方式的交集,
|
||||
assert.deepEqual(getSilencePaymentOptions(['wechat', 'wallet', 'alipay']).map((item) => item.value), ['alipay', 'wechat']);
|
||||
assert.deepEqual(getSilencePaymentOptions(['wallet']), []);
|
||||
assert.deepEqual(getSilencePaymentOptions(undefined), []);
|
||||
assert.deepEqual(getSilencePaymentOptions(['alipay', 'wechat'], true).map((item) => item.value), ['wechat', 'alipay']);
|
||||
});
|
||||
|
||||
test('延期天数校验:整数且在 min~max 内', () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { markPendingPaymentRefresh, openAlipayPayment } from '@/utils/payment.js';
|
||||
import { isValidWechatPayConfig, markPendingPaymentRefresh, openAlipayPayment, wechatH5Pay } from '@/utils/payment.js';
|
||||
import { isPaymentLink } from '@/utils/silence.js';
|
||||
|
||||
export const SILENCE_REFRESH_TARGET = {
|
||||
@@ -19,6 +19,10 @@ const isInWechat = () => typeof navigator !== 'undefined' && /micromessenger/i.t
|
||||
* 在微信外且为链接时直接跳转;其余情况进入延期支付页展示二维码与链接。
|
||||
*/
|
||||
export const openSilencePayment = (order, refreshTarget) => {
|
||||
// 微信内直接支付(JSAPI):与套餐购买一致,用 pay_config 拉起微信支付
|
||||
if (order?.pay_config && isValidWechatPayConfig(order.pay_config)) {
|
||||
return wechatH5Pay(order.pay_config).then(() => ({ paid: true }));
|
||||
}
|
||||
const content = String(order?.qr_content || '').trim();
|
||||
if (!content) return Promise.reject(new Error('支付内容为空'));
|
||||
|
||||
|
||||
@@ -67,10 +67,11 @@ export const getSilenceErrorMessage = (error, fallback = '操作失败,请稍
|
||||
|
||||
export const isSilenceFeatureDisabled = (error) => Number(error?.code) === 1274;
|
||||
|
||||
/** 延期可用支付方式:资产允许的支付方式与 wechat、alipay 取交集,支付宝优先 */
|
||||
export const getSilencePaymentOptions = (allowedMethods) => {
|
||||
/** 延期可用支付方式:资产允许的支付方式与 wechat、alipay 取交集;微信内打开时微信优先,否则支付宝优先 */
|
||||
export const getSilencePaymentOptions = (allowedMethods, preferWechat = false) => {
|
||||
const allowed = Array.isArray(allowedMethods) ? allowedMethods : [];
|
||||
return SILENCE_PAYMENT_METHODS
|
||||
const order = preferWechat ? ['wechat', 'alipay'] : SILENCE_PAYMENT_METHODS;
|
||||
return order
|
||||
.filter((method) => allowed.includes(method))
|
||||
.map((value) => ({ value, label: SILENCE_PAYMENT_LABELS[value] }));
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user