index.vue 7.7 KB

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