index.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. <template>
  2. <view class="">
  3. <!-- #ifdef MP-WEIXIN-->
  4. <view class="">
  5. <u-navbar :isBack="isBack" :title="title"></u-navbar>
  6. </view>
  7. <!-- #endif -->
  8. <view class="" v-show="!payShow">
  9. <view class="shopInfo">
  10. <image :src="shopDetail.cover" mode=""></image>
  11. <text>{{shopDetail.name}}</text>
  12. </view>
  13. <view class="data">
  14. <text style="color: #000;">付款金额</text>
  15. <view class="price">
  16. <view class="input-bar center" @tap="show">
  17. <view class="icon center">¥</view>
  18. <view class="input" style="display: flex; align-items: center;">
  19. <view style="font-size: 80rpx;">{{filterMoney(orderAmount)}}</view>
  20. <view class="cusor"></view>
  21. </view>
  22. </view>
  23. </view>
  24. <view class="text-center text-base padding-top-20">
  25. <text>*使用联兑通付款有优惠打折</text>
  26. </view>
  27. </view>
  28. <view style="margin-top: -20rpx;">
  29. <channel-list ></channel-list>
  30. </view>
  31. <!-- #ifdef MP-WEIXIN-->
  32. <!-- #endif -->
  33. <amountInput ref="amountInput" confirmText="付款" btnColor="#ff9900" placeholder="请输入交易金额" @change="change"
  34. @confirm="debouncePay"></amountInput>
  35. <u-modal v-model="modalShow" :mask-close-able="true" :showCancelButton="true" @cancel="payOfh5"
  36. @confirm="jumpLDT" cancel-text="直接付款" confirm-color="#FF9447" confirmText="去联兑通支付"
  37. content="去联兑通小程序付款有更多优惠哟~"></u-modal>
  38. </view>
  39. <pay-confirm v-show="payShow" :info="info" @confirm="doWxPay(bills.id)" @cancel="cancelPay"></pay-confirm>
  40. </view>
  41. </template>
  42. <script>
  43. import payConfirm from '@/components/pay-confirm.vue'
  44. import channelList from '@/components/channel-list.vue'
  45. import amountInput from '../../comps/amountInput/amountInput.vue';
  46. export default {
  47. components: {
  48. payConfirm,
  49. channelList,
  50. amountInput
  51. },
  52. data() {
  53. return {
  54. //navbar
  55. title:"收银台",
  56. isBack:true,
  57. //第一次点击支付不需要防抖操作
  58. isFirstPay: true,
  59. orderAmount: '',
  60. //支付bills信息
  61. payShow:false,
  62. info:{},
  63. bills:{},
  64. modalShow: false,
  65. shopId: '',
  66. shopDetail: {},
  67. //支付参数
  68. payParams: {},
  69. //支付结果
  70. payResult: {
  71. isSuccess: false,
  72. msg: "交易失败",
  73. //总价
  74. totalPrice: 0,
  75. //消耗积分值
  76. pointsNum: 0,
  77. //消耗现金值
  78. amountNum: 0,
  79. }
  80. }
  81. },
  82. async onLoad(options) {
  83. if (!this.$isEmpty(options.query)) {
  84. //h5跳转回小程序后重新赋值
  85. let params = options.query.split(";")
  86. this.shopId = params[0]
  87. this.orderAmount = params[1]
  88. } else {
  89. this.shopId = options.id
  90. }
  91. // #ifdef MP-WEIXIN
  92. //如果是新用户通过微信支付扫码进入此页面,跳回首页
  93. if (this.$isEmpty(this.vuex_userId)) {
  94. uni.reLaunch({
  95. url: "/pages/mine/mine?query=" + this.shopId + ";" + this.orderAmount
  96. })
  97. return
  98. }
  99. //如果用户信息为空,阻断
  100. let flag = await this.fetchUserDetail()
  101. if (!flag) {
  102. this.$dialog.showModal('用户信息获取失败', false).then(() => {
  103. uni.reLaunch({
  104. url: "/pages/mine/mine"
  105. })
  106. })
  107. return
  108. }
  109. // #endif
  110. if (this.$isEmpty(this.shopId)) {
  111. this.$dialog.showModal('商户id不能为空', false).then(() => {
  112. uni.navigateBack()
  113. })
  114. return
  115. }
  116. this.fetchShopDetail()
  117. },
  118. onShow() {
  119. console.log(this.orderAmount);
  120. },
  121. methods: {
  122. //防抖支付
  123. debouncePay() {
  124. if (this.isFirstPay) {
  125. this.pay()
  126. this.isFirstPay = false
  127. } else {
  128. this.$u.debounce(this.pay, 500)
  129. }
  130. },
  131. //获取商户信息
  132. fetchShopDetail() {
  133. this.$api.shop.detail({
  134. id: this.shopId
  135. }).then(res => {
  136. if (this.$isEmpty(res.data)) {
  137. this.$dialog.showModal('获取不到商户信息', false).then(() => {
  138. uni.navigateBack({
  139. delta: 1
  140. })
  141. })
  142. } else {
  143. this.shopDetail = res.data
  144. }
  145. }).catch(err => {
  146. this.$dialog.showModal('获取不到商户信息', false).then(() => {
  147. uni.navigateBack({
  148. delta: 1
  149. })
  150. })
  151. })
  152. },
  153. //获取用户信息
  154. async fetchUserDetail() {
  155. let res = await this.$api.loginUser.detail({
  156. id: this.vuex_userId
  157. })
  158. if (this.$isEmpty(res.data)) {
  159. return false
  160. } else {
  161. return true
  162. }
  163. },
  164. show() {
  165. this.$refs.amountInput.show()
  166. },
  167. change(e) {
  168. if (!e) {
  169. this.orderAmount = 0
  170. } else {
  171. this.orderAmount = e
  172. }
  173. },
  174. filterMoney(value) {
  175. if (!value) {
  176. return ''
  177. } else {
  178. value = value.replace(/\$\s?|(,*)/g, '')
  179. return value.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
  180. }
  181. },
  182. async jumpLDT() {
  183. this.$dialog.showLoading('打开中..')
  184. let params = {
  185. path: "/pagesC/pages/checkstand/index",
  186. query: "query=" + this.shopId + ";" + this.orderAmount
  187. }
  188. let res = await this.$api.wxApp.getGenerateScheme(params)
  189. if (!this.$isEmpty(res.data.openlink)) {
  190. location.href = res.data.openlink
  191. } else {
  192. location.href = "weixin://dl/business/?t=X2CyIQDbgtm"
  193. }
  194. uni.hideLoading()
  195. },
  196. async payOfh5() {
  197. let expireTime = this.$dateTime.getExpireTime(5)
  198. let params = {
  199. expireTime,
  200. money: this.orderAmount,
  201. shopId: this.shopId,
  202. }
  203. let resp = await this.$api.pay.getPayOrderPamamsForH5(params)
  204. let payObj = {
  205. orderType: this.$global.orderType.USER_PAY,
  206. orderId: resp.data.id
  207. }
  208. let res = await this.$api.pay.payOrderOfscanCode(payObj)
  209. let qrCodeUrl=JSON.parse(res.data.result).qrCodeUrl
  210. if (this.$isNotEmpty(qrCodeUrl)) {
  211. location.href = qrCodeUrl
  212. } else {
  213. this.$u.toast('支付失败')
  214. }
  215. },
  216. async pay() {
  217. if (!this.orderAmount.length || this.orderAmount == 0) {
  218. this.$u.toast('请输入交易金额')
  219. return
  220. }
  221. // #ifdef H5
  222. this.modalShow = true
  223. // #endif
  224. // #ifdef MP-WEIXIN
  225. this.toWXPay()
  226. // #endif
  227. },
  228. async toWXPay() {
  229. let expireTime = this.$dateTime.getExpireTime(5)
  230. let params = {
  231. userId: this.vuex_userId,
  232. appId: this.$global.wxParams.APPID,
  233. billsTitle: '用户扫码支付',
  234. money: this.orderAmount,
  235. expireTime,
  236. shopId: this.shopId,
  237. openId: this.$cache.get('userInfo').openId,
  238. }
  239. if (this.$isNotEmpty(this.vuex_channel)) {
  240. params.channelId=this.vuex_channel.id
  241. }
  242. let resp = await this.$api.pay.getPayOrderPamams(params)
  243. this.payParams = resp.data
  244. if (resp.data.status == '付款成功') {
  245. this.handelResult(true)
  246. } else if (resp.data.status == '待付款') {
  247. this.bills=resp.data.bills
  248. if (this.bills.discount==-1) {
  249. this.bills.discount=0
  250. }
  251. if (this.bills.cost==this.bills.price) {
  252. this.doWxPay(this.bills.id)
  253. }else{
  254. this.info={
  255. shop:this.shopDetail,
  256. bills:this.bills,
  257. }
  258. this.title="支付确认"
  259. this.isBack=false
  260. this.payShow=true
  261. }
  262. } else {
  263. this.handelResult(false)
  264. }
  265. },
  266. cancelPay(){
  267. this.title="收银台"
  268. this.isBack=true
  269. this.payShow=false
  270. },
  271. async doWxPay(orderId) {
  272. let obj = {
  273. orderType: this.$global.orderType.USER_PAY,
  274. orderId,
  275. payStatus: this.$global.payStatus.IS_WAIT
  276. }
  277. let res = await this.$api.pay.payOrder(obj)
  278. let prePayTn = JSON.parse(res.data.prePayTn)
  279. this.$mpi.requestPayment(prePayTn).then((res) => {
  280. this.handelResult(true)
  281. }).catch(err => {
  282. this.handelResult(false)
  283. })
  284. },
  285. handelResult(flag) {
  286. if (flag) {
  287. this.payResult = {
  288. isSuccess: true,
  289. msg: "交易成功",
  290. totalPrice: this.payParams.totalPrice,
  291. amountNum: this.payParams.bills.price,
  292. pointsNum: this.$digital.floatSub(this.payParams.totalPrice, this.payParams.bills.price),
  293. }
  294. } else {
  295. this.payResult.msg = '交易失败'
  296. this.payResult.isSuccess = false
  297. }
  298. uni.navigateTo({
  299. url: "/pagesC/pages/checkstand/pay-result?payResult=" + JSON.stringify(this.payResult)
  300. })
  301. },
  302. }
  303. }
  304. </script>
  305. <style>
  306. page {
  307. background-color: #ffff;
  308. }
  309. </style>
  310. <style lang="scss" scoped>
  311. .shopInfo {
  312. margin: 60rpx 0 20rpx;
  313. display: flex;
  314. justify-content: center;
  315. align-items: center;
  316. flex-direction: column;
  317. image {
  318. border-radius: 50%;
  319. width: 140rpx;
  320. height: 140rpx;
  321. }
  322. text {
  323. margin-top: 30rpx;
  324. font-size: 32rpx;
  325. }
  326. }
  327. .data {
  328. padding: 50rpx;
  329. display: flex;
  330. justify-content: flex-start;
  331. flex-direction: column;
  332. .price {
  333. &-icon {
  334. font-size: 40rpx;
  335. font-weight: 800;
  336. }
  337. }
  338. }
  339. .center {
  340. display: flex;
  341. justify-content: center;
  342. align-items: center;
  343. }
  344. .input-bar {
  345. height: 150rpx;
  346. border-bottom: 1rpx solid #DDDDDD;
  347. .icon {
  348. width: 15%;
  349. font-size: 70rpx;
  350. font-weight: 900;
  351. height: 100%;
  352. }
  353. .input {
  354. width: 85%;
  355. height: 100%;
  356. overflow: hidden;
  357. font-size: 70rpx;
  358. }
  359. .cusor {
  360. margin-left: 10rpx;
  361. width: 6rpx;
  362. border-radius: 20rpx;
  363. height: 60%;
  364. background-color: #ff9900;
  365. animation: blink 1200ms infinite ease-in-out;
  366. }
  367. }
  368. @keyframes blink {
  369. from {
  370. opacity: 0;
  371. }
  372. }
  373. </style>