parkingFeeDetail.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. import moment from 'moment';
  2. import { mapState } from 'vuex';
  3. import log from '@/utils/log.js';
  4. import { compare } from '@/utils/location.js';
  5. import uni from '@/utils/uniHooks';
  6. import { initWxJsSdkConfig } from '@/utils/login';
  7. import { getAppIdByGroupIdAndMallId, getIsWxh5, getPlatform } from '@/utils';
  8. import { Dialog, Toast } from 'vant';
  9. import { ordersAndPrepay } from '@/api/parking';
  10. // import checkOutResponse from '@/api/mockData/checkout.hz.response'
  11. export default {
  12. name: 'parkingFeeDetail',
  13. data() {
  14. return {
  15. hasDiscount: false,
  16. parkFee: {},
  17. refreshTime: 180, // 停车场重置费用倒计时3分钟
  18. // 微服务接口字段
  19. isShowDescription: true, // 缴费说明true:显示全部 false:显示部分
  20. btnLoading: false,
  21. popup: false,
  22. msData: {},
  23. };
  24. },
  25. beforeRouteLeave(to, from, next) {
  26. // 设置下一个路由的 meta
  27. if (/index|home/.test(to.name)) {
  28. // 不在缓存列表中,从cachedViews缓存列表中移除
  29. this.$store.commit('cachedViews/DEL_CACHED_VIEW', from);
  30. }
  31. next();
  32. },
  33. created() {
  34. setTimeout(() => {
  35. uni.setNavigationBarTitle({
  36. title: '停车支付',
  37. });
  38. }, 300);
  39. this.pageInit();
  40. },
  41. computed: {
  42. ...mapState({
  43. orderDetail: (state) => state.order.orderDetail,
  44. discountDesc: (state) => state.order.discountDesc,
  45. enableNewMemberPoints: (state) => state.order.enableNewMemberPoints,
  46. enablePoints: (state) => state.order.enablePoints,
  47. integralDesc: (state) => state.order.integralDesc,
  48. enableCoupon: (state) => state.order.enableCoupon,
  49. maxOneDayCoupons: (state) => state.order.maxOneDayCoupons,
  50. coupons: (state) => state.order.coupons,
  51. couponDesc: (state) => state.order.couponDesc,
  52. enablePaperCoupons: (state) => state.order.enablePaperCoupons,
  53. custTypeId: (state) => state.custTypeId,
  54. usingTotalDiscount: (state) => state.order.usingTotalDiscount,
  55. actualPayFee: (state) => state.order.actualPayFee,
  56. available: (state) => state.order.available,
  57. member: (state) => state.member,
  58. maxPointsTime: (state) => state.order.maxPointsTime,
  59. pointsTime: (state) => state.order.pointsTime,
  60. pointsPerHour: (state) => state.order.pointsPerHour,
  61. usePoints: (state) => state.order.usePoints,
  62. usePointsTime: (state) => state.order.usePointsTime,
  63. enableConsume: (state) => state.order.enableConsume,
  64. unitAmount: (state) => state.order.unitAmount,
  65. unlicensedInfo: state => state.unlicensedInfo,
  66. endlessLoop: (state) => state.endlessLoop,
  67. appId: state => state.appId,
  68. }),
  69. // 支付按钮状态
  70. payBtnDisabled() {
  71. // 当存在待支付金额 或者 用户登陆
  72. return !this.orderDetail?.parkingRecord?.totalFeeInYuan || (JSON.stringify(this.member) !== '{}' && !this.orderDetail.parkInfo);
  73. },
  74. // integralDesc() {
  75. // if (this.pointsTime > 0) {
  76. // // 深圳特殊处理(单位:金额)
  77. // if (this.orderDetail.parkInfo.parkMallCode === 5 || this.orderDetail.parkInfo.parkMallCode === 999) {
  78. // return `已选择兑换${this.pointsTime}元`;
  79. // }
  80. // return `已选择兑换${this.pointsTime}小时`;
  81. // }
  82. // if (this.bonusCopy < this.integral) {
  83. // return `${this.integral}积分可停车1小时`;
  84. // }
  85. // if (this.orderDetail.parkInfo.parkMallCode === 3 && app.globalData.member?.currnentintegral >= this.integral && !this.bonus) {
  86. // return `今日已达上限`;
  87. // }
  88. // return `${this.available}积分可减免`;
  89. // },
  90. },
  91. filters: {
  92. parkingTime(val) {
  93. const days = parseInt(val / 60 / 24)
  94. const hours = parseInt((val / 60) % 24)
  95. const minutes = parseInt(val % 60)
  96. if (days > 0) {
  97. return `${days}天 ${hours}小时 ${minutes}分钟`
  98. }
  99. if (hours > 0) {
  100. return `${hours}小时 ${minutes}分钟`
  101. }
  102. return `${minutes}分钟`
  103. },
  104. },
  105. methods: {
  106. // 前往支付
  107. async toPay() {
  108. const { parkingRecord, discountInfo = {}, parkingRule = {}} = this.orderDetail;
  109. const { coupons, points } = discountInfo
  110. const { hourPrice } = parkingRule
  111. try {
  112. const params = {
  113. // vehicleNo: '', // 车牌号
  114. // points
  115. parkingRecord: {
  116. ...parkingRecord,
  117. vehicleNo: parkingRecord.vehicleNo,
  118. enterTime: parkingRecord.enterTime,
  119. serviceMin: parkingRecord.serviceMin,
  120. totalFee: parkingRecord.totalFeeInYuan, //应缴
  121. actualPayFee: this.actualPayFee, //应付金额
  122. },
  123. discountInfo: {
  124. usingTotalDiscount: discountInfo?.usingTotalDiscount || 0, //优惠金额"
  125. actualUsedDiscount: discountInfo?.usingTotalDiscount || 0, //实际优惠金额
  126. },
  127. };
  128. // 积分
  129. if (points?.length && points[0].discountFee > 0) {
  130. // 15 兑换 5元
  131. const { pointsPerUnit, unitAmount, discountFee, available } = points[0]
  132. params.discountInfo.points = {
  133. "discountTime": discountFee / hourPrice * 60,
  134. "discountFee": discountFee,
  135. "discountPoints": discountFee / hourPrice * pointsPerUnit
  136. }
  137. }
  138. // 优惠券
  139. if (coupons?.length) {
  140. const selectedCoupons = coupons.filter(elm => {
  141. const selected = elm.hasOwnProperty('selected') ? elm.selected : elm.defaultSelected;
  142. return selected
  143. }).map(elm => {
  144. elm.discountTime = elm.discountFee / hourPrice * 60
  145. return elm
  146. })
  147. if (selectedCoupons.length) {
  148. params.discountInfo.coupons = selectedCoupons
  149. }
  150. }
  151. console.log('下单时的参数', params);
  152. const res = await ordersAndPrepay(params);
  153. // console.log('orderDetail', res);
  154. if (res?.paymentType === 'NO_FEE_PAY') {
  155. this.btnLoading = false;
  156. this.$router.replace({
  157. path: this.getPagePath(),
  158. });
  159. // 支付成功
  160. return
  161. }
  162. this.kerryPayment(res.sessionId);
  163. } catch (err) {
  164. console.log(err);
  165. }
  166. },
  167. kerryPayment(session = '011cad54-735f-4e92-8f1b-f22bdfe073cd', payParams) {
  168. const platform = getPlatform();
  169. let appId = uni.getStorageSync('appid');
  170. let openId = uni.getStorageSync('openid') || this.openid;
  171. if (platform === 'miniprogram') {
  172. // appId = 'wx92c3e55fbef6b2af';
  173. // appId = 'wxd830fe4d1e04988e';
  174. appId = this.appId;
  175. }
  176. const params = {
  177. region: 'cn',
  178. payChannel: 'OFFICIAL_ACCOUNT',
  179. // payChannel: 'MOBILE_WEB',
  180. payOption: 'WECHATPAY',
  181. appId: appId,
  182. // openId: 'oudWQ5SCDElfn-IQH6eBR5JesOz4', // 下的appid: wxd830fe4d1e04988e
  183. openId,
  184. };
  185. // console.log(1854, params);
  186. this.$md(params);
  187. // let path = `/profileApi/payment/v1/services/session/${session}/transactions`;
  188. let path = `${window.profileApi}/payment/v1/services/session/${session}/transactions`;
  189. this.$request({
  190. url: path,
  191. data: params,
  192. method: 'POST',
  193. header: JSON.parse(uni.getStorageSync('handleUser')),
  194. })
  195. .then(async (res) => {
  196. // this.Toastloading.clear();
  197. // console.log(1795, res);
  198. if (res.data?.code == '000000') {
  199. const prepayJson = res.data.data.params;
  200. const platform = getPlatform();
  201. // TODO: h5环境判断
  202. if (platform === 'micromessenger') {
  203. const weixinH5PayRes = await this.weixinH5Pay(prepayJson);
  204. // 微信支付完成,判断结果
  205. console.log(1784, weixinH5PayRes);
  206. // errMsg: 'requestPayment:ok'
  207. if (weixinH5PayRes?.errMsg === 'requestPayment:ok') {
  208. this.$store.commit('cachedViews/DEL_CACHED_VIEW', {
  209. name: 'parkingFeeDetail'
  210. });
  211. this.$router.replace({
  212. // path: 'parkingFeeSuccess?carno=' + this.parkInfo.carno,
  213. path: this.getPagePath(),
  214. });
  215. } else {
  216. this.reCreateParkOrder();
  217. }
  218. } else {
  219. window.toWXSendMsg({
  220. type: 'openWxPay',
  221. options: {
  222. provider: 'wxpay',
  223. timeStamp: prepayJson.timeStamp,
  224. nonceStr: prepayJson.nonceStr,
  225. package: prepayJson.package,
  226. signType: prepayJson.signType,
  227. paySign: prepayJson.paySign,
  228. },
  229. });
  230. window.subscribe('wxPayOver', (options) => {
  231. // this.Toastloading.clear();
  232. // console.log('微信支付结束之后的返回参数', options);
  233. // T-ODO: 在 qa 新发版前,只提示支付成功的信息(已处理成功信息)
  234. if (options?.wxPayOver === 'fail') {
  235. console.log('支付失败');
  236. this.reCreateParkOrder();
  237. } else {
  238. this.btnLoading = false;
  239. this.$router.replace({
  240. // path: 'parkingFeeSuccess?vehicleNo=' + this.$route.query.vehicleNo,
  241. path: this.getPagePath(),
  242. });
  243. }
  244. });
  245. }
  246. } else {
  247. this.reCreateParkOrder();
  248. }
  249. })
  250. .catch((err) => {
  251. console.log(1854, err);
  252. this.reCreateParkOrder();
  253. });
  254. },
  255. // 支付失败后返还优惠券
  256. failedParkOrder() {
  257. // this.Toastloading.clear();
  258. const param = {
  259. orderno: this.parkInfo.orderno,
  260. };
  261. this.$md(param);
  262. uni
  263. .request({
  264. url: this.$baseURL + 'api/1.0/park/failedParkOrder',
  265. data: param,
  266. method: 'POST',
  267. header: JSON.parse(uni.getStorageSync('handleUser')),
  268. })
  269. .then((res) => {
  270. this.reCreateParkOrder();
  271. })
  272. .catch((err) => {
  273. this.reCreateParkOrder();
  274. });
  275. },
  276. // 支付失败弹框 重新创建订单
  277. reCreateParkOrder() {
  278. // console.log('支付失败弹框 重新创建订单');
  279. Dialog.alert({
  280. title: '提示',
  281. message: '支付失败',
  282. confirmButtonColor: '#333',
  283. }).then(() => {
  284. this.$refs.countDown.reset(); // 停车场重置费用倒计时3分钟
  285. this.$store.dispatch('order/orderInit', {
  286. gateId: this.$route.query?.gateId,
  287. vehicleNo: this.$route.query?.vehicleNo,
  288. endlessLoop: this.endlessLoop
  289. })
  290. this.btnLoading = false;
  291. // this.createParkOrder();
  292. });
  293. // uni.showModal({
  294. // showCancel: false,
  295. // title: '提示',
  296. // content: '支付失败',
  297. // complete: (r) => {
  298. // this.createParkOrder();
  299. // },
  300. // });
  301. },
  302. // 初始化
  303. async pageInit() {
  304. // console.log(247, checkOutResponse);
  305. // this.msData.detail = checkOutResponse
  306. // 停车优惠
  307. // this.discounts(this.msData.detail)
  308. // 积分减免
  309. // 优惠券
  310. // 纸质优惠券
  311. // 优惠金额
  312. // 应付金额
  313. // this.$store.commit('order/SET_ORDER_DETAIL', checkOutResponse);
  314. try {
  315. console.log('无牌车扫码出场', this.unlicensedInfo, this.endlessLoop);
  316. // return
  317. this.$store.dispatch('order/orderInit', {
  318. vehicleNo: this.$route.query.vehicleNo,
  319. gateId: this.$route.query?.gateId,
  320. endlessLoop: this.endlessLoop,
  321. callback: (res) => {
  322. setTimeout(() => {
  323. this.$store.dispatch('clearUnlicensed');
  324. }, 700);
  325. // 如果 无牌车扫码出场扫码 无需缴费,直接展示无需缴费页面
  326. if(/unlicensedOut/.test(res.code) && res?.unlicensed) {
  327. this.$router.replace({
  328. path: 'parkingFeeMsg?type=pay',
  329. });
  330. return
  331. }
  332. // 如果是无需缴费的话,提示用户无需缴费
  333. if (res?.orderDetail?.parkingRecord?.totalFee <= 0) {
  334. this.$store.dispatch('order/orderInitRule', res.orderDetail);
  335. setTimeout(() => {
  336. Dialog.alert({
  337. message: '当前无需缴费',
  338. confirmButtonColor: '#333',
  339. }).then(() => {
  340. this.$router.back()
  341. });
  342. }, 1000)
  343. return
  344. }
  345. if (/NOT_FOUND|PARKING_RECORD_NOT_FOUND/.test(res.code)) {
  346. // 当前车辆没有查到账单
  347. this.$router.replace({
  348. path: 'parkingFeePayment',
  349. query: {
  350. msg: res.langMessage,
  351. vehicleNo: this.$route.query.vehicleNo,
  352. },
  353. });
  354. return
  355. }
  356. if (/LOCAL_PARK_ERROR|INTERNAL_SERVER_ERROR|VALIDATION_FAILED|PLEASE_SCAN_QRCODE/g.test(res.code)) {
  357. setTimeout(() => {
  358. this.$router.back()
  359. }, 1000)
  360. }
  361. }
  362. });
  363. setTimeout(() => {
  364. this.$store.dispatch('clearUnlicensed');
  365. }, 1200);
  366. } catch (err) {
  367. console.log('查询车辆是否在场的报错信息?', err, err.code === "INTERNAL_SERVER_ERROR");
  368. // 如果网络异常(这里是因为订单页面存在空白场景,才需要单独处理报错交互)
  369. if (err.code === "INTERNAL_SERVER_ERROR") {
  370. this.$router.back()
  371. }
  372. }
  373. },
  374. // 停车优惠
  375. discounts() {
  376. if (!this.enableConsume && orderDetail.parkInfo.parkMallCode !== 2) {
  377. return Toast({
  378. message: '暂无可用优惠',
  379. });
  380. }
  381. this.$router.push({
  382. path: 'parkingFeeDiscounts',
  383. });
  384. },
  385. setColor() {
  386. window?.toWXSendMsg({
  387. type: 'uni_func',
  388. funcName: 'setNavigationBarColor',
  389. options: {
  390. frontColor: '#000000',
  391. backgroundColor: '#2151C5',
  392. },
  393. });
  394. // uni.setNavigationBarColor({
  395. // frontColor: '#000000',
  396. // backgroundColor: '#FAFBFF',
  397. // });
  398. },
  399. // 是否展示优惠信息
  400. // isShowDiscounts(params) {
  401. // console.log(277, params?.parkingRule?.enableCoupon);
  402. // return params?.parkingRule?.enableCoupon
  403. // },
  404. //
  405. // 计算优惠信息
  406. discountssss(params) {
  407. // console.log(275, params);
  408. // console.log(275, params.discountInfo);
  409. // console.log(275, params.discountInfo.consume);
  410. return 1;
  411. },
  412. coupon() {
  413. // 如果没有电子券的话,提示用户
  414. if (this.coupons.length === 0) {
  415. uni.showToast({
  416. title: '暂无可使用的优惠券,请前往积分商城兑换优惠券'
  417. })
  418. return
  419. }
  420. this.$router.push({
  421. path: 'parkingFeeCoupon',
  422. });
  423. },
  424. paperCoupon() { },
  425. duration() { },
  426. couponCount() { },
  427. // 重置倒计时
  428. resetCountDown() {
  429. this.$refs.countDown.reset();
  430. this.$store.dispatch('order/orderInit', {
  431. gateId: this.$route.query?.gateId,
  432. vehicleNo: this.$route.query?.vehicleNo,
  433. endlessLoop: this.endlessLoop
  434. })
  435. // 重新创建订单
  436. // this.createParkOrder();
  437. },
  438. //缴费说明隐藏显示
  439. togglePayinstruction() {
  440. this.isShowDescription = !this.isShowDescription;
  441. },
  442. // 积分修改框
  443. showPointsMathPopup() {
  444. this.popup = true;
  445. },
  446. cancelPointsMathPopup() {
  447. this.$store.dispatch('order/cancelPointsMath', () => {
  448. this.popup = false;
  449. });
  450. },
  451. savePointsMathPopup() {
  452. this.$store.dispatch('order/savePointsMath', () => {
  453. this.popup = false;
  454. });
  455. },
  456. // 获取成功缴费之后前往的页面
  457. getPagePath() {
  458. let pagePath = 'parkingFeeSuccess?vehicleNo=' + this.$route.query.vehicleNo
  459. console.log('临时车流程', this.endlessLoop);
  460. if (this.$route.query.vehicleNo.indexOf('临') > -1 && this.endlessLoop || this.$route.query.gateId) {
  461. pagePath = 'parkingFeeMsg?type=pay'
  462. }
  463. return pagePath
  464. },
  465. pointsMathCallback({type, message}) {
  466. // console.log(465, type);
  467. Toast({
  468. message: message,
  469. icon: 'none',
  470. });
  471. },
  472. //
  473. setDescription() {
  474. if ( this?.orderDetail?.parkInfo?.description.length > 0 ) {
  475. let reg = /[;;]/g;
  476. return this.orderDetail.parkInfo.description.replace(reg, '\r\n').replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>');
  477. }
  478. return ''
  479. }
  480. },
  481. };