sunshibo vor 2 Monaten
Ursprung
Commit
2d69e4f79d
6 geänderte Dateien mit 110 neuen und 9 gelöschten Zeilen
  1. 13 0
      api/dining.js
  2. 5 1
      pages/orderInfo/index.vue
  3. 10 1
      pages/orderInfo/orderDetail.vue
  4. 70 5
      pages/placeOrder/index.vue
  5. 11 1
      pages/result/index.vue
  6. 1 1
      store/user.js

+ 13 - 0
api/dining.js

@@ -61,6 +61,19 @@ export const GetMyOrders = (params) =>
 export const GetOrderInfo = (orderId) =>
   api.get({ url: `/store/order/info/${encodeURIComponent(orderId)}` });
 
+// 订单支付(POST /payment/prePay,入参 orderNo 订单号、payType 支付类型 默认 wechatPayMininProgram、payer 支付用户 openid、price 订单金额、subject 订单标题;返回微信支付调起参数)
+export const PostOrderPay = (params) =>
+  api.get({
+    url: '/payment/prePay',
+    params: {
+      orderNo: params.orderNo,
+      payType: 'wechatPayMininProgram',
+      payer: params.payer,
+      price: params.price,
+      subject: params.subject ?? '订单支付'
+    }
+  });
+
 /**
  * 订单 SSE 接口配置(GET /store/order/sse/{tableId})
  * 仅提供 URL 与 header,实际连接请使用 utils/sse.js 的 createSSEConnection 封装

+ 5 - 1
pages/orderInfo/index.vue

@@ -268,13 +268,17 @@ const handleAddFood = (order) => {
   go(q.length ? `/pages/orderFood/index?${q.join('&')}` : '/pages/orderFood/index');
 };
 
-// 处理结算:带上桌号、人数、订单金额、备注,确认订单页用于展示和提交
+// 处理结算:带上订单ID、桌号、人数、订单金额、备注,确认订单页用于调起支付
 const handleCheckout = (order) => {
+  const orderId = order?.id ?? order?.orderId ?? '';
+  const orderNo = order?.orderNo ?? order?.orderNumber ?? orderId ?? '';
   const tableId = order?.tableId ?? order?.tableNumber ?? '';
   const diners = order?.dinerCount ?? order?.diners ?? '';
   const totalAmount = order?.totalPrice ?? order?.payAmount ?? 0;
   const remark = (order?.remark ?? '').trim().slice(0, 30);
   const q = [];
+  if (orderId !== '') q.push(`orderId=${encodeURIComponent(String(orderId))}`);
+  if (orderNo !== '') q.push(`orderNo=${encodeURIComponent(String(orderNo))}`);
   if (tableId !== '' && tableId != null) q.push(`tableId=${encodeURIComponent(String(tableId))}`);
   if (diners !== '' && diners != null) q.push(`diners=${encodeURIComponent(String(diners))}`);
   if (totalAmount != null && totalAmount !== '') q.push(`totalAmount=${encodeURIComponent(String(totalAmount))}`);

+ 10 - 1
pages/orderInfo/orderDetail.vue

@@ -112,6 +112,8 @@ import { getFileUrl } from "@/utils/file.js";
 import { GetOrderInfo } from "@/api/dining.js";
 
 const payType = ref('confirmOrder'); // confirmOrder 确认下单 confirmPay 确认支付
+/** 当前订单ID,用于「去结算」传参 */
+const detailOrderId = ref('');
 
 // 订单详情(店铺、订单信息)
 const orderDetail = ref({
@@ -199,21 +201,28 @@ const handleConfirmOrder = () => {
   go(q.length ? `/pages/orderFood/index?${q.join('&')}` : '/pages/orderFood/index');
 };
 
-// 去结算:跳转确认订单页,携带桌号、就餐人数、订单金额
+// 去结算:跳转确认订单页,携带订单ID、订单号、桌号、就餐人数、订单金额(用于调起支付)
 const handleConfirmPay = () => {
+  const orderId = detailOrderId.value || '';
+  const orderNo = orderDetail.value?.orderNo ?? '';
   const tableId = orderDetail.value?.tableId || orderDetail.value?.tableNo || '';
   const diners = orderDetail.value?.dinerCount ?? '';
   const totalAmount = priceDetail.value?.total ?? '';
+  const remark = (orderDetail.value?.remark ?? '').trim().slice(0, 30);
   const q = [];
+  if (orderId !== '') q.push(`orderId=${encodeURIComponent(String(orderId))}`);
+  if (orderNo !== '') q.push(`orderNo=${encodeURIComponent(String(orderNo))}`);
   if (tableId !== '') q.push(`tableId=${encodeURIComponent(String(tableId))}`);
   if (diners !== '') q.push(`diners=${encodeURIComponent(String(diners))}`);
   if (totalAmount !== '' && totalAmount != null) q.push(`totalAmount=${encodeURIComponent(String(totalAmount))}`);
+  if (remark !== '') q.push(`remark=${encodeURIComponent(remark)}`);
   go(q.length ? `/pages/placeOrder/index?${q.join('&')}` : '/pages/placeOrder/index');
 };
 
 onLoad(async (e) => {
   if (e.payType) payType.value = e.payType;
   const orderId = e?.orderId ?? e?.id ?? '';
+  detailOrderId.value = orderId;
   if (!orderId) {
     uni.showToast({ title: '缺少订单ID', icon: 'none' });
     return;

+ 70 - 5
pages/placeOrder/index.vue

@@ -110,14 +110,17 @@ import { ref } from "vue";
 import { go } from "@/utils/utils.js";
 import { getFileUrl } from "@/utils/file.js";
 import { useUserStore } from "@/store/user.js";
-import { PostOrderCreate } from "@/api/dining.js";
+import { PostOrderCreate, PostOrderPay } from "@/api/dining.js";
 
 const payType = ref('confirmOrder'); // confirmOrder 确认下单 confirmPay 确认支付
-/** 仅当从订单列表点击「去结算」进入时为 true,底部确认下单按钮才显示金额 */
+/** 仅当从订单列表/结果页等「去结算」进入时为 true,底部显示确认支付 */
 const fromCheckout = ref(false);
+/** 待支付订单ID,确认支付时用于调起微信支付 */
+const payOrderId = ref('');
 
 // 订单信息(从购物车带过来或 URL 参数)
 const orderInfo = ref({
+  orderNo: '',
   tableId: '',
   diners: '',
   contactPhone: '',
@@ -192,9 +195,12 @@ const handleConfirmOrder = async () => {
     });
     uni.hideLoading();
     const orderId = res?.id ?? res?.orderId ?? res?.data?.id ?? res?.data?.orderId;
-    // 结果页「去结算」需带金额和备注,保存本次下单的桌号、人数、金额、备注
+    const orderNo = res?.orderNo ?? res?.data?.orderNo ?? orderId ?? '';
     const total = orderInfo.value.payAmount ?? orderInfo.value.totalAmount ?? 0;
+    // 结果页「去结算」需带 orderId/orderNo/金额/备注,用于确认支付
     uni.setStorageSync('lastPlaceOrderInfo', JSON.stringify({
+      orderId: orderId ?? undefined,
+      orderNo: orderNo ?? undefined,
       tableId: orderInfo.value.tableId,
       diners: orderInfo.value.diners,
       totalAmount: total,
@@ -211,8 +217,65 @@ const handleConfirmOrder = async () => {
   }
 };
 
-const handleConfirmPay = () => {
-  go('/pages/result/index?payType=confirmPay');
+// 确认支付:调起微信支付
+const handleConfirmPay = async () => {
+  const orderId = payOrderId.value || '';
+  if (!orderId) {
+    uni.showToast({ title: '缺少订单ID', icon: 'none' });
+    return;
+  }
+  const userStore = useUserStore();
+  const openid = userStore.getOpenId || '';
+  if (!openid) {
+    uni.showToast({ title: '请先登录', icon: 'none' });
+    return;
+  }
+  const priceAmount = Number(orderInfo.value.payAmount ?? orderInfo.value.totalAmount ?? 0) || 0;
+  if (priceAmount <= 0) {
+    uni.showToast({ title: '订单金额异常', icon: 'none' });
+    return;
+  }
+  const orderNo = orderInfo.value.orderNo || '';
+  if (!orderNo) {
+    uni.showToast({ title: '缺少订单号', icon: 'none' });
+    return;
+  }
+  // 后端要求金额乘 100 传入(分)
+  const price = Math.round(priceAmount * 100);
+  uni.showLoading({ title: '拉起支付...' });
+  try {
+    const res = await PostOrderPay({
+      orderNo,
+      payer: openid,
+      price,
+      subject: '订单支付'
+    });
+    uni.hideLoading();
+   console.log(res)
+    uni.requestPayment({
+      provider: 'wxpay',
+      timeStamp:res.timestamp,
+      nonceStr:res.nonce,
+      package: res.prepayId,
+      signType:res.signType,
+      paySign:res.sign,
+      success: () => {
+        uni.showToast({ title: '支付成功', icon: 'success' });
+        setTimeout(() => go(`/pages/result/index?id=${encodeURIComponent(orderId)}`), 1500);
+      },
+      fail: (err) => {
+        const msg = err?.errMsg ?? err?.message ?? '支付失败';
+        if (String(msg).includes('cancel')) {
+          uni.showToast({ title: '已取消支付', icon: 'none' });
+        } else {
+          uni.showToast({ title: msg || '支付失败', icon: 'none' });
+        }
+      }
+    });
+  } catch (e) {
+    uni.hideLoading();
+    uni.showToast({ title: e?.message ?? '获取支付参数失败', icon: 'none' });
+  }
 };
 
 onLoad((options) => {
@@ -220,6 +283,8 @@ onLoad((options) => {
   const userStore = useUserStore();
   const contactPhone = userStore.getUserInfo?.phone ?? userStore.getUserInfo?.contactPhone ?? userStore.getUserInfo?.mobile ?? '';
   orderInfo.value.contactPhone = contactPhone;
+  if (options?.orderId != null && options?.orderId !== '') payOrderId.value = options.orderId;
+  if (options?.orderNo != null && options?.orderNo !== '') orderInfo.value.orderNo = options.orderNo;
   if (options?.tableId) orderInfo.value.tableId = options.tableId;
   if (options?.diners) orderInfo.value.diners = options.diners;
   if (options?.remark != null && options?.remark !== '') orderInfo.value.remark = decodeURIComponent(options.remark);

+ 11 - 1
pages/result/index.vue

@@ -17,6 +17,8 @@ import { ref } from "vue";
 import { go } from "@/utils/utils.js";
 import { getFileUrl } from "@/utils/file.js";
 
+const resultOrderId = ref(''); // 本页 URL 上的订单ID(下单成功跳转时带的 id)
+
 // 去加餐:从缓存取桌号、人数并带上,点餐页依赖 tableid、diners 拉取列表和购物车
 const handleGoAddFood = () => {
   const tableid = uni.getStorageSync('currentTableId') ?? '';
@@ -29,6 +31,8 @@ const handleGoAddFood = () => {
 
 // 去结算:带上桌号、人数、金额、备注,确认订单页才显示金额并走「确认支付」
 const handleGoSettle = () => {
+  let orderId = '';
+  let orderNo = '';
   let tableId = '';
   let diners = '';
   let totalAmount = '';
@@ -37,15 +41,20 @@ const handleGoSettle = () => {
     const raw = uni.getStorageSync('lastPlaceOrderInfo');
     if (raw) {
       const data = JSON.parse(raw);
+      orderId = data?.orderId ?? resultOrderId.value ?? '';
+      orderNo = data?.orderNo ?? '';
       tableId = data?.tableId ?? '';
       diners = data?.diners ?? '';
       totalAmount = data?.totalAmount != null ? String(data.totalAmount) : '';
       remark = (data?.remark ?? '').trim().slice(0, 30);
     }
+    if (!orderId) orderId = resultOrderId.value;
   } catch (e) {
     console.error('读取下单信息失败', e);
   }
   const q = [];
+  if (orderId !== '') q.push(`orderId=${encodeURIComponent(String(orderId))}`);
+  if (orderNo !== '') q.push(`orderNo=${encodeURIComponent(String(orderNo))}`);
   if (tableId !== '') q.push(`tableId=${encodeURIComponent(tableId)}`);
   if (diners !== '') q.push(`diners=${encodeURIComponent(diners)}`);
   if (totalAmount !== '') q.push(`totalAmount=${encodeURIComponent(totalAmount)}`);
@@ -53,7 +62,8 @@ const handleGoSettle = () => {
   go(q.length ? `/pages/placeOrder/index?${q.join('&')}` : '/pages/placeOrder/index');
 };
 
-onLoad((e) => {
+onLoad((options) => {
+  resultOrderId.value = options?.id ?? '';
 });
 </script>
 

+ 1 - 1
store/user.js

@@ -17,7 +17,7 @@ export const useUserStore = defineStore({
       return this.token || uni.getStorageSync(TOKEN) || "";
     },
     getOpenId() {
-      return this.openId || uni.getStorageSync(OPEN_ID) || "";
+      return this.openId || uni.getStorageSync(USER_INFO).openId || "";
     },
   },
   actions: {