submitorder.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // import { models, db, _ } from '../../utils/cloudbase.js'
  2. import { getDB, getModels, getCommand, getTempFileURLs, getClient } from '../../utils/cloudbase.js'
  3. Page({
  4. data: {
  5. products: [],
  6. totalAmount: 0,
  7. dingweiimg: '',
  8. youjiantouimg: '',
  9. selectedAddress: '',
  10. transactionId: '',
  11. outTradeNo: '',
  12. },
  13. async onLoad() {
  14. const selectedItems = wx.getStorageSync('checkoutItems') || [];
  15. // 标准化 quantity 字段
  16. const products = selectedItems.map(item => ({
  17. ...item,
  18. quantity: item.num || item.num_index
  19. }));
  20. this.setData({ products }, () => {
  21. this.calculateTotal();
  22. });
  23. const fileIDs = [
  24. 'cloud://honghgaier-5guiffgcf17a2eea.686f-honghgaier-5guiffgcf17a2eea-1373037829/images/icon/dingwei.png',
  25. 'cloud://honghgaier-5guiffgcf17a2eea.686f-honghgaier-5guiffgcf17a2eea-1373037829/images/icon/youjiantou.png',
  26. ];
  27. const fileList = await getTempFileURLs(fileIDs)
  28. this.setData({
  29. dingweiimg: fileList[0].tempFileURL,
  30. youjiantouimg: fileList[1].tempFileURL,
  31. })
  32. // // 并发下载多个 fileID
  33. // Promise.all(
  34. // fileIDs.map(fileID => wx.cloud.downloadFile({ fileID }))
  35. // ).then(results => {
  36. // // 每个 result 对应一个下载结果
  37. // const tempFilePaths = results.map(r => r.tempFilePath);
  38. // console.log('全部下载成功:', tempFilePaths);
  39. // this.setData({
  40. // dingweiimg: tempFilePaths[0],
  41. // youjiantouimg: tempFilePaths[1],
  42. // });
  43. // }).catch(err => {
  44. // console.error('有文件下载失败:', err);
  45. // });
  46. },
  47. decreaseQuantity(e) {
  48. const index = e.currentTarget.dataset.index;
  49. let products = this.data.products;
  50. if (products[index].quantity > 1) {
  51. products[index].quantity--;
  52. this.setData({ products });
  53. this.calculateTotal();
  54. }
  55. },
  56. increaseQuantity(e) {
  57. const index = e.currentTarget.dataset.index;
  58. let products = this.data.products;
  59. products[index].quantity++;
  60. this.setData({ products });
  61. this.calculateTotal();
  62. },
  63. onChange(e) {
  64. const { id } = e.currentTarget.dataset;
  65. const { detail } = e;
  66. const products = this.data.products.map(item => {
  67. if (item._id === id) {
  68. return { ...item, quantity: detail };
  69. }
  70. return item;
  71. });
  72. this.setData({ products }, () => {
  73. this.calculateTotal();
  74. });
  75. },
  76. calculateTotal() {
  77. let totalAmount = 0;
  78. this.data.products.forEach(item => {
  79. totalAmount += item.specList[item.specs_index].price * item.quantity;
  80. });
  81. this.setData({ totalAmount });
  82. },
  83. // async handlePay() {
  84. // // 1. 检查是否选择了收货地址
  85. // if (!this.data.selectedAddress || !this.data.selectedAddress._id) {
  86. // wx.showToast({
  87. // title: '请选择收货地址',
  88. // icon: 'none',
  89. // });
  90. // return;
  91. // }
  92. // console.log(this.data.selectedAddress, 'this.data.selectedAddress');
  93. // const outTradeNo = Math.round(Math.random() * 10 ** 13) + Date.now();
  94. // const userInfo = wx.getStorageSync('userInfo') || {};
  95. // // 2. 判断 products 是否已有 orders_id,如果没有再创建订单
  96. // const needCreateOrders = this.data.products.filter(item => !item.orders_id);
  97. // let ordersResult = [];
  98. // if (needCreateOrders.length > 0) {
  99. // const orderPromises = needCreateOrders.map(item => {
  100. // return models.orders.create({
  101. // data: {
  102. // adresses_id: this.data.selectedAddress._id,
  103. // merchandise_id: item._id, //商品id
  104. // school_id: userInfo.school_id,
  105. // groupbuy_id: item.specList[item.specs_index]._id || "", //规格id
  106. // specs_index: item.specs_index, //规格下标
  107. // real_money: item.specList[item.specs_index].price * item.quantity, //付款金额
  108. // way: 0, //订单方式
  109. // user_id: userInfo._id,
  110. // num_index: item.quantity, //商品数量
  111. // order_id: String(outTradeNo), //订单号
  112. // status: 0, // 待支付
  113. // },
  114. // envType: "prod",
  115. // });
  116. // });
  117. // try {
  118. // ordersResult = await Promise.all(orderPromises);
  119. // console.log("新订单创建结果: ", ordersResult.map(r => r.data));
  120. // } catch (err) {
  121. // console.error("订单创建失败: ", err);
  122. // wx.showToast({ title: '订单创建失败', icon: 'none' });
  123. // return;
  124. // }
  125. // } else {
  126. // console.log("订单已存在,无需重复创建");
  127. // }
  128. // // 3. 调用云函数下单
  129. // wx.cloud.callFunction({
  130. // name: 'wxpayFunctions',
  131. // data: {
  132. // type: 'wxpay_order',
  133. // description: "购买商品",
  134. // out_trade_no: outTradeNo,
  135. // amount: {
  136. // total: this.data.totalAmount * 100, // 微信支付单位为分
  137. // currency: 'CNY'
  138. // },
  139. // },
  140. // success: (res) => {
  141. // console.log('下单结果: ', res);
  142. // const paymentData = res.result?.data;
  143. // this.setData({
  144. // outTradeNo,
  145. // transactionId: paymentData.transaction_id
  146. // });
  147. // wx.requestPayment({
  148. // timeStamp: paymentData?.timeStamp,
  149. // nonceStr: paymentData?.nonceStr,
  150. // package: paymentData?.packageVal,
  151. // paySign: paymentData?.paySign,
  152. // signType: 'RSA',
  153. // success: async (payRes) => {
  154. // console.log('支付成功: ', payRes);
  155. // // 4. 支付成功后更新订单状态为待收货 (status=1)
  156. // try {
  157. // const updatePromises = this.data.products.map(item => {
  158. // // 如果已有 orders_id 就用它,否则用 order_id
  159. // const idToUpdate = item.orders_id || null;
  160. // if (!idToUpdate) {
  161. // // 没有 orders_id,之前创建的订单会通过 order_id + merchandise_id 更新
  162. // return models.orders.update({
  163. // data: { status: 1 },
  164. // filter: {
  165. // where: {
  166. // $and: [
  167. // { order_id: { $eq: String(outTradeNo) } },
  168. // { merchandise_id: { $eq: item._id } }
  169. // ]
  170. // }
  171. // },
  172. // envType: "prod"
  173. // });
  174. // } else {
  175. // // 已有订单直接用 _id 更新
  176. // return models.orders.update({
  177. // data: { status: 1 },
  178. // filter: {
  179. // where: { _id: { $eq: idToUpdate } }
  180. // },
  181. // envType: "prod"
  182. // });
  183. // }
  184. // });
  185. // const results = await Promise.all(updatePromises);
  186. // console.log("支付成功,订单更新结果:", results);
  187. // wx.showToast({
  188. // title: '支付成功',
  189. // icon: 'success',
  190. // duration: 1500,
  191. // success() {
  192. // wx.navigateBack();
  193. // // wx.reLaunch({
  194. // // url: '/subpackages/order/order?type=' + encodeURIComponent(1)
  195. // // });
  196. // }
  197. // });
  198. // } catch (err) {
  199. // console.error("支付成功,更新订单状态失败:", err);
  200. // }
  201. // },
  202. // fail: (payErr) => {
  203. // console.error('支付失败: ', payErr);
  204. // wx.showToast({ title: '支付失败', icon: 'none' });
  205. // // 支付失败订单仍保持status=0(待支付)
  206. // }
  207. // });
  208. // },
  209. // fail: (err) => {
  210. // console.error('下单失败: ', err);
  211. // wx.showToast({ title: '下单失败', icon: 'none' });
  212. // }
  213. // });
  214. // },
  215. async handlePay() {
  216. wx.showLoading({ title: '提交订单中...', mask: true }); // 🚀 防止多次点击
  217. let client = await getClient(); // 跨小程序 SDK
  218. const models = await getModels()
  219. // 1. 检查是否选择收货地址
  220. const { selectedAddress, products, totalAmount } = this.data;
  221. if (!selectedAddress?._id) {
  222. wx.hideLoading(); // ❗️记得关闭
  223. wx.showToast({ title: '请选择收货地址', icon: 'none' });
  224. return;
  225. }
  226. const outTradeNo = Math.round(Math.random() * 10 ** 13) + Date.now();
  227. const userInfo = wx.getStorageSync('userInfo') || {};
  228. // 2. 创建订单(如果没有 orders_id)
  229. const needCreateOrders = products.filter(item => !item.orders_id);
  230. let ordersResult = [];
  231. if (needCreateOrders.length) {
  232. try {
  233. const orderPromises = needCreateOrders.map(item => models.orders.create({
  234. data: {
  235. adresses_id: selectedAddress._id,
  236. merchandise_id: item._id,
  237. school_id: userInfo.school_id,
  238. groupbuy_id: item.specList[item.specs_index]?._id || "",
  239. specs_index: item.specs_index,
  240. real_money: item.specList[item.specs_index].price * item.quantity,
  241. way: 0,
  242. user_id: userInfo._id,
  243. num_index: item.quantity,
  244. order_id: String(outTradeNo),
  245. status: 0
  246. },
  247. envType: "prod",
  248. }));
  249. ordersResult = await Promise.all(orderPromises);
  250. console.log("新订单创建结果:", ordersResult.map(r => r.data));
  251. } catch (err) {
  252. console.error("订单创建失败:", err);
  253. wx.showToast({ title: '订单创建失败', icon: 'none' });
  254. return;
  255. }
  256. } else {
  257. console.log("订单已存在,无需重复创建");
  258. }
  259. // 2. 获取小程序B openid
  260. const openid = await new Promise((resolve, reject) => {
  261. wx.login({
  262. success: async res => {
  263. if (!res.code) return reject('获取 code 失败');
  264. try {
  265. const r = await client.callFunction({
  266. name: 'getopenid',
  267. data: { code: res.code }
  268. });
  269. if (r.result?.openid) resolve(r.result.openid);
  270. else reject(r.result || '获取 openid 失败');
  271. } catch (err) {
  272. reject(err);
  273. }
  274. },
  275. fail: err => reject(err)
  276. });
  277. });
  278. console.log('拿到小程序B openid:', openid);
  279. // 3. 调用云函数下单\
  280. try {
  281. const res = await client.callFunction({
  282. name: 'wxpayFunctions',
  283. data: {
  284. type: 'wxpay_order',
  285. description: "购买商品",
  286. out_trade_no: outTradeNo,
  287. amount: { total: totalAmount * 100, currency: 'CNY' },
  288. openid: openid
  289. }
  290. });
  291. console.log(res, 'resresresresresres');
  292. const paymentData = res.result?.data;
  293. if (!paymentData) throw new Error('下单返回数据异常');
  294. this.setData({
  295. outTradeNo,
  296. transactionId: paymentData.transaction_id
  297. });
  298. wx.hideLoading(); // ✅ 支付前关闭 loading
  299. // 4. 调用微信支付
  300. wx.requestPayment({
  301. timeStamp: paymentData.timeStamp,
  302. nonceStr: paymentData.nonceStr,
  303. package: paymentData.packageVal,
  304. paySign: paymentData.paySign,
  305. signType: 'RSA',
  306. success: async () => {
  307. console.log('支付成功');
  308. // 支付成功后批量更新订单状态为待收货
  309. try {
  310. // 1. 更新已有订单_id 的订单(单条)
  311. const updateByIdPromises = products
  312. .filter(item => item.orders_id)
  313. .map(item => models.orders.update({
  314. data: { status: 1 },
  315. filter: { where: { _id: { $eq: item.orders_id } } },
  316. envType: "prod"
  317. }));
  318. // 2. 更新创建订单时生成的所有订单(可能多条)使用 order_id
  319. const updateByOrderIdPromise = models.orders.updateMany({
  320. data: { status: 1 },
  321. filter: { where: { order_id: { $eq: String(outTradeNo) } } },
  322. envType: "prod"
  323. });
  324. await Promise.all([...updateByIdPromises, updateByOrderIdPromise]);
  325. wx.showToast({
  326. title: '支付成功',
  327. icon: 'success',
  328. duration: 1500,
  329. success() { wx.navigateBack(); }
  330. });
  331. } catch (err) {
  332. console.error("支付成功,更新订单状态失败:", err);
  333. }
  334. },
  335. fail: (payErr) => {
  336. console.error('支付失败:', payErr);
  337. wx.showToast({ title: '支付失败', icon: 'none' });
  338. }
  339. });
  340. } catch (err) {
  341. console.error('下单失败:', err);
  342. wx.showToast({ title: '下单失败', icon: 'none' });
  343. }
  344. },
  345. setGridView() {
  346. wx.navigateTo({
  347. url: '/subpackages/addresslist/addresslist'
  348. });
  349. }
  350. });