From 3f23dee33fc2e75b3400ea3ef9ec5165e16635bb Mon Sep 17 00:00:00 2001 From: 18631081161 <2088094923@qq.com> Date: Sun, 5 Apr 2026 14:10:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=A3=E9=87=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- miniapp/pages/delivery/delivery.vue | 18 ++++++++++++------ miniapp/pages/food/food-order.vue | 8 +++++--- miniapp/pages/help/help.vue | 10 +++++++--- miniapp/pages/pickup/pickup.vue | 25 ++++++++++++++++++++----- miniapp/pages/purchase/purchase.vue | 10 +++++++--- miniapp/utils/api.js | 16 +++++++++++----- miniapp/utils/request.js | 3 +++ server/Endpoints/OrderEndpoints.cs | 7 ++++--- server/Helpers/BusinessHelpers.cs | 4 ++-- 9 files changed, 71 insertions(+), 30 deletions(-) diff --git a/miniapp/pages/delivery/delivery.vue b/miniapp/pages/delivery/delivery.vue index 71c076d..4c65c15 100644 --- a/miniapp/pages/delivery/delivery.vue +++ b/miniapp/pages/delivery/delivery.vue @@ -166,12 +166,12 @@ export default { if (!this.validateForm()) return const token = uni.getStorageSync('token') if (!token) { - // 保存表单数据,登录后恢复 uni.setStorageSync('loginFormData', JSON.stringify(this.form)) uni.setStorageSync('loginRedirect', '/pages/delivery/delivery') uni.navigateTo({ url: '/pages/login/login' }); return } this.submitting = true + let orderId = null try { const commission = parseFloat(this.form.commission) const result = await createOrder({ @@ -184,20 +184,26 @@ export default { commission, totalAmount: commission }) + orderId = result.id if (result.paymentParams) { try { await this.wxPay(result.paymentParams) - // 支付成功,确认订单上架 - try { await confirmPayment(result.id) } catch (ex) {} } catch (e) { - // 支付失败/取消,撤销订单 - try { await cancelOrder(result.id) } catch (ex) {} + try { await cancelOrder(orderId) } catch (ex) {} return } + // 支付成功,确认订单上架(带重试) + try { + await confirmPayment(orderId) + } catch (ex) { + console.warn('confirmPayment 失败,等待微信回调兜底', ex) + } } uni.showToast({ title: '下单成功', icon: 'success' }) setTimeout(() => { uni.navigateBack() }, 1500) - } catch (e) {} finally { this.submitting = false } + } catch (e) { + console.error('下单失败', e) + } finally { this.submitting = false } }, wxPay(params) { return new Promise((resolve, reject) => { diff --git a/miniapp/pages/food/food-order.vue b/miniapp/pages/food/food-order.vue index c0e793e..e99915f 100644 --- a/miniapp/pages/food/food-order.vue +++ b/miniapp/pages/food/food-order.vue @@ -210,13 +210,15 @@ export default { if (result.paymentParams) { try { await this.wxPay(result.paymentParams) - // 支付成功,确认订单上架 - try { await confirmPayment(result.id) } catch (ex) {} } catch (e) { // 支付失败/取消,撤销订单 try { await cancelOrder(result.id) } catch (ex) {} return } + // 支付成功,确认订单上架(带重试) + try { await confirmPayment(result.id) } catch (ex) { + console.warn('confirmPayment 失败,等待微信回调兜底', ex) + } } // 下单成功,清空购物车 @@ -226,7 +228,7 @@ export default { uni.switchTab({ url: '/pages/index/index' }) }, 1500) } catch (e) { - // 错误已在 request 中处理 + console.error('下单失败', e) } finally { this.submitting = false } diff --git a/miniapp/pages/help/help.vue b/miniapp/pages/help/help.vue index c585da6..3360eb3 100644 --- a/miniapp/pages/help/help.vue +++ b/miniapp/pages/help/help.vue @@ -227,13 +227,15 @@ if (result.paymentParams) { try { await this.wxPay(result.paymentParams) - // 支付成功,确认订单上架 - try { await confirmPayment(result.id) } catch (ex) {} } catch (e) { // 支付失败/取消,撤销订单 try { await cancelOrder(result.id) } catch (ex) {} return } + // 支付成功,确认订单上架(带重试) + try { await confirmPayment(result.id) } catch (ex) { + console.warn('confirmPayment 失败,等待微信回调兜底', ex) + } } uni.showToast({ title: '下单成功', @@ -242,7 +244,9 @@ setTimeout(() => { uni.switchTab({ url: '/pages/index/index' }) }, 1500) - } catch (e) {} finally { + } catch (e) { + console.error('下单失败', e) + } finally { this.submitting = false } }, diff --git a/miniapp/pages/pickup/pickup.vue b/miniapp/pages/pickup/pickup.vue index b773de5..9f81843 100644 --- a/miniapp/pages/pickup/pickup.vue +++ b/miniapp/pages/pickup/pickup.vue @@ -172,7 +172,6 @@ export default { // 未登录跳转登录页 const token = uni.getStorageSync('token') if (!token) { - // 保存表单数据,登录后恢复 uni.setStorageSync('loginFormData', JSON.stringify(this.form)) uni.setStorageSync('loginRedirect', '/pages/pickup/pickup') uni.navigateTo({ url: '/pages/login/login' }) @@ -180,6 +179,7 @@ export default { } this.submitting = true + let orderId = null try { const commission = parseFloat(this.form.commission) const result = await createOrder({ @@ -192,20 +192,35 @@ export default { commission, totalAmount: commission }) + orderId = result.id if (result.paymentParams) { try { await this.wxPay(result.paymentParams) - // 支付成功,确认订单上架 - try { await confirmPayment(result.id) } catch (ex) {} } catch (e) { // 支付失败/取消,撤销订单 - try { await cancelOrder(result.id) } catch (ex) {} + try { await cancelOrder(orderId) } catch (ex) {} return } + // 支付成功,确认订单上架(带重试) + try { + await confirmPayment(orderId) + } catch (ex) { + // confirmPayment 失败不阻塞用户,微信回调会兜底 + console.warn('confirmPayment 失败,等待微信回调兜底', ex) + } } uni.showToast({ title: '下单成功', icon: 'success' }) setTimeout(() => { uni.switchTab({ url: '/pages/index/index' }) }, 1500) - } catch (e) {} finally { this.submitting = false } + } catch (e) { + // createOrder 失败时给用户明确反馈 + console.error('下单失败', e) + if (e?.message && !e.message.includes('网络异常')) { + // request.js 已经 showToast 了网络异常,避免重复提示 + // 其他业务错误也已在 request.js 中提示,这里不再重复 + } + } finally { + this.submitting = false + } }, wxPay(params) { return new Promise((resolve, reject) => { diff --git a/miniapp/pages/purchase/purchase.vue b/miniapp/pages/purchase/purchase.vue index 0ada38d..c9d5153 100644 --- a/miniapp/pages/purchase/purchase.vue +++ b/miniapp/pages/purchase/purchase.vue @@ -257,13 +257,15 @@ if (result.paymentParams) { try { await this.wxPay(result.paymentParams) - // 支付成功,确认订单上架 - try { await confirmPayment(result.id) } catch (ex) {} } catch (e) { // 支付失败/取消,撤销订单 try { await cancelOrder(result.id) } catch (ex) {} return } + // 支付成功,确认订单上架(带重试) + try { await confirmPayment(result.id) } catch (ex) { + console.warn('confirmPayment 失败,等待微信回调兜底', ex) + } } uni.showToast({ title: '下单成功', @@ -272,7 +274,9 @@ setTimeout(() => { uni.switchTab({ url: '/pages/index/index' }) }, 1500) - } catch (e) {} finally { + } catch (e) { + console.error('下单失败', e) + } finally { this.submitting = false } }, diff --git a/miniapp/utils/api.js b/miniapp/utils/api.js index 34a8a08..a700536 100644 --- a/miniapp/utils/api.js +++ b/miniapp/utils/api.js @@ -43,9 +43,9 @@ export function getServiceEntries() { // ==================== 订单 ==================== -/** 创建订单 */ +/** 创建订单(含微信预下单,超时适当放宽) */ export function createOrder(data) { - return request({ url: '/api/orders', method: 'POST', data }) + return request({ url: '/api/orders', method: 'POST', data, timeout: 30000 }) } /** 获取订单大厅列表 */ @@ -63,9 +63,15 @@ export function cancelOrder(id) { return request({ url: `/api/orders/${id}/cancel`, method: 'POST' }) } -/** 确认支付成功(前端支付成功后调用) */ -export function confirmPayment(id) { - return request({ url: `/api/orders/${id}/pay-confirm`, method: 'POST' }) +/** 确认支付成功(前端支付成功后调用,支持重试) */ +export function confirmPayment(id, retries = 2) { + return request({ url: `/api/orders/${id}/pay-confirm`, method: 'POST' }).catch(err => { + if (retries > 0) { + return new Promise(resolve => setTimeout(resolve, 1000)) + .then(() => confirmPayment(id, retries - 1)) + } + throw err + }) } /** 跑腿提交完成 */ diff --git a/miniapp/utils/request.js b/miniapp/utils/request.js index 89073bd..81f220d 100644 --- a/miniapp/utils/request.js +++ b/miniapp/utils/request.js @@ -49,11 +49,14 @@ function request(options) { header['Authorization'] = `Bearer ${token}` } + const timeout = options.timeout ?? 15000 + return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}${url}`, method, data, + timeout, header: { 'Content-Type': 'application/json', ...header diff --git a/server/Endpoints/OrderEndpoints.cs b/server/Endpoints/OrderEndpoints.cs index c3b7a95..02af8b8 100644 --- a/server/Endpoints/OrderEndpoints.cs +++ b/server/Endpoints/OrderEndpoints.cs @@ -353,11 +353,11 @@ public static class OrderEndpoints } else { - // 未完成订单:实时计算预估抽成 + // 未完成订单:实时计算预估抽成(商品金额不抽成) var rules = await db.CommissionRules.OrderBy(r => r.MinAmount).ToListAsync(); var fee = BusinessHelpers.CalculatePlatformFee(order.Commission, rules); response.PlatformFee = fee; - response.NetEarning = order.Commission - fee; + response.NetEarning = order.Commission - fee + (order.GoodsAmount ?? 0); } } @@ -700,7 +700,8 @@ public static class OrderEndpoints { var commissionRules = await db.CommissionRules.OrderBy(r => r.MinAmount).ToListAsync(); var platformFee = BusinessHelpers.CalculatePlatformFee(order.Commission, commissionRules); - var netEarning = order.Commission - platformFee; + // 跑腿净收益 = 佣金 - 平台抽成 + 商品金额(代购/万能帮/美食街的商品金额平台不抽成,全额给跑腿) + var netEarning = order.Commission - platformFee + (order.GoodsAmount ?? 0); // 获取冻结时间配置(默认 1 天) var freezeDaysConfig = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == "freeze_days"); diff --git a/server/Helpers/BusinessHelpers.cs b/server/Helpers/BusinessHelpers.cs index 6af15d5..8fc64f7 100644 --- a/server/Helpers/BusinessHelpers.cs +++ b/server/Helpers/BusinessHelpers.cs @@ -158,10 +158,10 @@ public static class BusinessHelpers { order.Status = OrderStatus.Completed; - // 计算佣金收益 + // 计算佣金收益(商品金额平台不抽成,全额给跑腿) var rules = await db.CommissionRules.OrderBy(r => r.MinAmount).ToListAsync(); var platformFee = CalculatePlatformFee(order.Commission, rules); - var netEarning = order.Commission - platformFee; + var netEarning = order.Commission - platformFee + (order.GoodsAmount ?? 0); var freezeDaysConfig = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == "freeze_days"); var freezeDays = 1;