result.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. <!-- 支付结果页面 -->
  2. <template>
  3. <!-- result:{{result}} -->
  4. <view class="pay-result-box ss-flex-col ss-row-center ss-col-center">
  5. <!-- 信息展示 -->
  6. <view class="pay-waiting ss-m-b-30" v-if="payResult === 'waiting'" />
  7. <image class="pay-img ss-m-b-30" v-if="payResult === 'success'"
  8. :src="sheep.$url.static('/static/images/order_pay_success.gif')" />
  9. <image class="pay-img ss-m-b-30" v-if="['failed', 'closed'].includes(payResult)"
  10. :src="sheep.$url.static('/static/images/order_paty_fail.gif')" />
  11. <view class="tip-text ss-m-b-30" v-if="payResult === 'success'">{{ t('order.payment_successful') }}</view>
  12. <view class="tip-text ss-m-b-30" v-if="payResult === 'failed'">{{ t('order.payment_failed') }}</view>
  13. <view class="tip-text ss-m-b-30" v-if="payResult === 'closed'">{{ t('order.order_closed') }}</view>
  14. <view class="tip-text ss-m-b-30" v-if="payResult === 'waiting'">{{ t('order.checking_payment_result') }}</view>
  15. <view class="pay-total-num ss-flex" v-if="payResult === 'success'">
  16. <view>¥{{ fen2yuan(state.orderInfo.price) }}</view>
  17. </view>
  18. <!-- 操作区 -->
  19. <view class="btn-box ss-flex ss-row-center ss-m-t-50">
  20. <button class="back-btn ss-reset-button" @tap="goBack">
  21. {{ t('order.return_home') }}
  22. </button>
  23. <!-- <button class="check-btn ss-reset-button" v-if="payResult === 'failed'" @tap="
  24. sheep.$router.redirect('/pages/pay/index', { id: state.id, orderType: state.orderType })
  25. ">
  26. {{ t('order.retry_payment') }}
  27. </button> -->
  28. <button class="check-btn ss-reset-button" v-if="payResult === 'success' && !isTopUp" @tap="goOrderList">
  29. {{ t('order.view_order') }}
  30. </button>
  31. <button class="check-btn ss-reset-button" v-if="payResult === 'success' && isTopUp" @tap="goWallet">
  32. {{ t('order.view_wallet') }}
  33. </button>
  34. <!-- TODO 非繁人:拼团接入 -->
  35. <!-- <button class="check-btn ss-reset-button" v-if="payResult === 'success' && state.tradeOrder.type === 3"
  36. @tap="sheep.$router.redirect('/pages/activity/groupon/order')">
  37. {{ t('order.my_group_buying') }}
  38. </button> -->
  39. </view>
  40. <!-- TODO 非繁人:订阅 -->
  41. <!-- #ifdef MP -->
  42. <!-- <view class="subscribe-box ss-flex ss-m-t-44">
  43. <image class="subscribe-img" :src="sheep.$url.static('/static/images/cargo.png')" />
  44. <view class="subscribe-title ss-m-r-48 ss-m-l-16">{{ t('order.get_realtime_shipping_info') }}</view>
  45. <view class="subscribe-start" @tap="subscribeMessage">{{ t('order.subscribe_now') }}</view>
  46. </view> -->
  47. <!-- #endif -->
  48. </view>
  49. </template>
  50. <script setup>
  51. import {
  52. ref,
  53. onMounted,
  54. reactive,
  55. computed,
  56. watchEffect
  57. } from 'vue';
  58. import axios from 'axios';
  59. import 'https://wx.gtimg.com/pay_h5/goldplan/js/jgoldplan-1.0.0.js';
  60. import {
  61. onLoad,
  62. onHide,
  63. onShow
  64. } from '@dcloudio/uni-app';
  65. import {
  66. isEmpty
  67. } from 'lodash';
  68. import sheep from '@/sheep';
  69. import PayOrderApi from '@/sheep/api/pay/order';
  70. import {
  71. fen2yuan
  72. } from '../../sheep/hooks/useGoods';
  73. import OrderApi from '@/sheep/api/trade/order';
  74. import {
  75. showWalletModal,
  76. colseWalletModal
  77. } from '@/sheep/hooks/useModal';
  78. import { t } from '@/locale'
  79. const order = ref({});
  80. const result = ref({});
  81. const url = ref('https://payapp.weixin.qq.com');
  82. // 获取地址栏字段
  83. const getQueryVal = () => {
  84. const queryStr = window.location.href.split("?")[1]; // 地址栏字符串
  85. const strArr = queryStr.split('&');
  86. if (strArr.length) {
  87. strArr.forEach((val) => {
  88. const subStrArr = val.split('=');
  89. result.value[subStrArr[0]] = subStrArr[1];
  90. });
  91. }
  92. };
  93. // 用于展示商家小票
  94. const showCustomPage = () => {
  95. console.log("showCustomPage")
  96. const customData = JSON.stringify({
  97. action: 'onIframeReady',
  98. displayStyle: 'SHOW_CUSTOM_PAGE',
  99. // height: 900
  100. });
  101. parent.postMessage(customData, url.value);
  102. };
  103. const state = reactive({
  104. id: 0, // 支付单号
  105. orderType: 'goods', // 订单类型
  106. result: 'unpaid', // 支付状态
  107. orderInfo: {}, // 支付订单信息
  108. tradeOrder: {}, // 商品订单信息,只有在 orderType 为 goods 才会请求。目的:【我的拼团】按钮的展示
  109. counter: 0, // 获取结果次数
  110. });
  111. // 支付结果 result => payResult
  112. const payResult = computed(() => {
  113. if (state.result === 'unpaid') {
  114. return 'waiting';
  115. }
  116. if (state.result === 'paid') {
  117. return 'success';
  118. }
  119. if (state.result === 'failed') {
  120. return 'failed';
  121. }
  122. if (state.result === 'closed') {
  123. return 'closed';
  124. }
  125. });
  126. // 是否充值消费分订单
  127. const isTopUp = computed(() => {
  128. return result.value.out_trade_no.includes("top-up") ;
  129. });
  130. // 获得订单信息
  131. async function getOrderInfo(payOrderNo) {
  132. state.counter++;
  133. // 1. 加载订单信息
  134. const {
  135. data,
  136. code
  137. } = await PayOrderApi.getFuYouPayOrderByStatus(payOrderNo);
  138. if (code === 0) {
  139. state.orderInfo = data;
  140. if (!state.orderInfo || state.orderInfo.status === 30) {
  141. // 支付关闭
  142. state.result = 'closed';
  143. return;
  144. }
  145. if (state.orderInfo.status !== 0) {
  146. // 非待支付,可能是已支付,可能是已退款
  147. state.result = 'paid';
  148. // #ifdef MP
  149. subscribeMessage();
  150. // #endif
  151. // 特殊:获得商品订单信息
  152. // if (state.orderType === 'goods') {
  153. // const {
  154. // data,
  155. // code
  156. // } = await PayOrderApi.getByStatus2(state.orderInfo.merchantOrderId);
  157. // if (code === 0) {
  158. // state.tradeOrder = data;
  159. // }
  160. // }
  161. return;
  162. }
  163. }
  164. // 2.1 情况三一:未支付,且轮询次数小于三次,则继续轮询
  165. if (state.counter < 3 && state.result === 'unpaid') {
  166. setTimeout(() => {
  167. getOrderInfo(payOrderNo);
  168. }, 1500);
  169. }
  170. // 2.2 情况二:超过三次检测才判断为支付失败
  171. if (state.counter >= 3) {
  172. state.result = 'failed';
  173. }
  174. }
  175. // onShow(() => {
  176. // if (isEmpty(state.orderInfo)) {
  177. // return;
  178. // }
  179. // getOrderInfo(state.id);
  180. // });
  181. // onHide(() => {
  182. // state.result = 'unpaid';
  183. // state.counter = 0;
  184. // });
  185. // 组件挂载后执行
  186. onMounted(async () => {
  187. await showCustomPage();
  188. await getQueryVal();
  189. await getOrderInfo(result.value.out_trade_no);
  190. // if (!result.value.out_trade_no) {
  191. // parent.alert('没有订单号,请联系管理员!');
  192. // } else {
  193. // queryOrderInfo();
  194. // }
  195. });
  196. // 返回首页
  197. const goBack = () => {
  198. const mchData = {
  199. action: 'jumpOut',
  200. jumpOutUrl: `${location.origin}/#/pages/index/index?points=${state.orderInfo.jf}&socialStatus=${state.orderInfo.sj}`
  201. };
  202. console.log(mchData.jumpOutUrl)
  203. const postData = JSON.stringify(mchData);
  204. parent.postMessage(postData, url.value);
  205. };
  206. // 跳转到订单
  207. const goOrderList = () => {
  208. console.log(state.orderInfo)
  209. const mchData = {
  210. action: 'jumpOut',
  211. jumpOutUrl: `${location.origin}/#/pages/order/list?type=2&points=${state.orderInfo.jf}&socialStatus=${state.orderInfo.sj}`
  212. };
  213. console.log(mchData.jumpOutUrl)
  214. const postData = JSON.stringify(mchData);
  215. parent.postMessage(postData, url.value);
  216. };
  217. const goWallet = () => {
  218. const mchData = {
  219. action: 'jumpOut',
  220. jumpOutUrl: `${location.origin}/#/pages/user/wallet/score`
  221. };
  222. const postData = JSON.stringify(mchData);
  223. parent.postMessage(postData, url.value);
  224. }
  225. </script>
  226. <style lang="scss" scoped>
  227. @keyframes rotation {
  228. 0% {
  229. transform: rotate(0deg);
  230. }
  231. 100% {
  232. transform: rotate(360deg);
  233. }
  234. }
  235. .score-img {
  236. width: 36rpx;
  237. height: 36rpx;
  238. margin: 0 4rpx;
  239. }
  240. .pay-result-box {
  241. // padding: 60rpx 0;
  242. height:100vh;
  243. background:#fff;
  244. .pay-waiting {
  245. margin-top: 20rpx;
  246. width: 60rpx;
  247. height: 60rpx;
  248. border: 10rpx solid rgb(233, 231, 231);
  249. border-bottom-color: rgb(204, 204, 204);
  250. border-radius: 50%;
  251. display: inline-block;
  252. // -webkit-animation: rotation 1s linear infinite;
  253. animation: rotation 1s linear infinite;
  254. }
  255. .pay-img {
  256. width: 130rpx;
  257. height: 130rpx;
  258. }
  259. .tip-text {
  260. font-size: 30rpx;
  261. font-weight: bold;
  262. color: #333333;
  263. }
  264. .pay-total-num {
  265. font-size: 36rpx;
  266. font-weight: 500;
  267. color: #333333;
  268. font-family: OPPOSANS;
  269. }
  270. .btn-box {
  271. width: 100%;
  272. .back-btn {
  273. width: 190rpx;
  274. height: 70rpx;
  275. font-size: 28rpx;
  276. border: 2rpx solid #dfdfdf;
  277. border-radius: 35rpx;
  278. font-weight: 400;
  279. color: #595959;
  280. }
  281. .check-btn {
  282. width: 190rpx;
  283. height: 70rpx;
  284. font-size: 28rpx;
  285. border: 2rpx solid #dfdfdf;
  286. border-radius: 35rpx;
  287. font-weight: 400;
  288. color: #595959;
  289. margin-left: 32rpx;
  290. }
  291. }
  292. .subscribe-box {
  293. .subscribe-img {
  294. width: 44rpx;
  295. height: 44rpx;
  296. }
  297. .subscribe-title {
  298. font-weight: 500;
  299. font-size: 32rpx;
  300. line-height: 36rpx;
  301. color: #434343;
  302. }
  303. .subscribe-start {
  304. color: var(--ui-BG-Main);
  305. font-weight: 700;
  306. font-size: 32rpx;
  307. line-height: 36rpx;
  308. }
  309. }
  310. }
  311. </style>