Pay.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. <template>
  2. <view>
  3. <navbar :config="config" backColor="#999999"></navbar>
  4. <view class="pay-nums-box">
  5. <view class="pay-title">
  6. 充值金额
  7. </view>
  8. <view class="pay-num">
  9. <text class="pay-tag">¥</text>
  10. <u-input class="pay-money" v-model="money" type="digit" />
  11. </view>
  12. </view>
  13. <view class="pay-way-box">
  14. <view class="pay-way">
  15. <text class="pay-title">充值方式</text>
  16. <view class="pay-item" @click.stop="pay_mode = 1">
  17. <view class="pay-item-left">
  18. <text class="iconfont3 pay-item-icon" style="color: #09BB07;">&#xe68a;</text>
  19. <text class="pay-item-name">微信支付</text>
  20. </view>
  21. <view :class="['pay-item-right', pay_mode === 1 ? 'active-pay-item' : '']"></view>
  22. </view>
  23. <view class="pay-item" @click.stop="pay_mode = 2">
  24. <view class="pay-item-left">
  25. <text class="iconfont3 pay-item-icon" style="color: #06B4FD;">&#xe60a;</text>
  26. <text class="pay-item-name">支付宝</text>
  27. </view>
  28. <view :class="['pay-item-right', pay_mode === 2 ? 'active-pay-item' : '']"></view>
  29. </view>
  30. <!-- <view class="pay-item" @click.stop="pay_mode = 10">
  31. <view class="pay-item-left">
  32. <text class="iconfont3 pay-item-icon" style="color: #06B4FD;">&#xe60a;</text>
  33. <text class="pay-item-name">支付宝(Adapay)</text>
  34. </view>
  35. <view :class="['pay-item-right', pay_mode === 10 ? 'active-pay-item' : '']"></view>
  36. </view> -->
  37. <!-- <view class="pay-item" @click.stop="pay_mode = 12">
  38. <view class="pay-item-left">
  39. <text class="iconfont3 pay-item-icon" style="color: #06B4FD;">&#xe60a;</text>
  40. <text class="pay-item-name">支付宝(慧收钱)</text>
  41. </view>
  42. <view :class="['pay-item-right', pay_mode === 12 ? 'active-pay-item' : '']"></view>
  43. </view>
  44. <view class="pay-item" @click.stop="pay_mode = 14">
  45. <view class="pay-item-left">
  46. <text class="iconfont3 pay-item-icon" style="color: #06B4FD;">&#xe607;</text>
  47. <text class="pay-item-name">银行卡支付</text>
  48. </view>
  49. <view :class="['pay-item-right', pay_mode === 14 ? 'active-pay-item' : '']"></view>
  50. </view> -->
  51. <view class="pay-btn" @click.stop="goPayBtn">
  52. 充值
  53. </view>
  54. <!-- <view class="pay-btn" @click.stop="showBanksModel = true" v-if="pay_mode == 14">
  55. 选择快捷银行卡支付
  56. </view> -->
  57. </view>
  58. </view>
  59. <!-- 银行卡弹窗 -->
  60. <u-popup v-model="showBanksModel" mode="bottom" height="65%" border-radius="20" closeable safe-area-inset-bottom
  61. :mask-close-able="false" z-index="500">
  62. <view class="banks-content">
  63. <view class="add" @click="banksHandler()">+ 管理银行卡</view>
  64. <view class="header">银行卡支付</view>
  65. <template>
  66. <view class="banks" v-if="banksList.length > 0">
  67. <scroll-view class="scroll-box" scroll-y="true">
  68. <radio-group>
  69. <label class="item" :class="{'gray': !item.valid}" v-for="(item, index) in banksList" :key="item.id"
  70. @click="payBankWay(14, item.id)">
  71. <view class="box">
  72. <image :src="item.logo" mode="widthFix"></image>
  73. <text class="bank_name">{{item.local_bank_name || item.bank_name}}</text>
  74. <text>{{item.local_bank_card_type_name}}</text>
  75. </view>
  76. <view class="box">
  77. <view class="name">({{$mUtil.bankAccount(item.card_id)}})</view>
  78. <radio :value="String(item.id)" :checked="card_id == item.id" />
  79. </view>
  80. </label>
  81. </radio-group>
  82. </scroll-view>
  83. </view>
  84. <noData v-if="banksList.length <= 0"></noData>
  85. </template>
  86. <view class="banks-pay" @click="$u.throttle(goPayBtn, 500)" v-if="banksList.length">
  87. <text class=" txt">确认支付</text>
  88. </view>
  89. <view class="banks-pay" @click="banksHandler()" v-else>
  90. <text class="txt">请先添加银行卡</text>
  91. </view>
  92. </view>
  93. </u-popup>
  94. <u-modal v-model="showPayModel" ref="payModel" title="确认支付" :show-cancel-button="true" @confirm="payConfirm"
  95. @cancel="payCancel" :async-close="true" z-index="900">
  96. <view class="slot-content">
  97. <view class="paybody">
  98. <view class="header-text">
  99. <text>请输入银行预留手机号发送的短信验证,切记他人索取拒绝提供。</text>
  100. </view>
  101. <view class="sms">
  102. <u-input v-model="sms_code" type="number" maxlength="6" :clearable="false" placeholder="请输入预留手机号验证码" />
  103. <view class="retry-gary" :class="{'retry': codeCount > 0}" @click="retrySms()"><text
  104. v-if="codeCount > 0">{{codeCount}}S后</text>重发</view>
  105. </view>
  106. <!-- <u-message-input mode="bottomLine" :maxlength="6"></u-message-input> -->
  107. </view>
  108. </view>
  109. </u-modal>
  110. </view>
  111. </template>
  112. <script>
  113. let timer
  114. import {
  115. directBuy
  116. } from "@/api/personal-center.js"
  117. import noData from "@/components/noData/nodata.vue"
  118. export default {
  119. components: {
  120. noData
  121. },
  122. data() {
  123. return {
  124. config: {
  125. back: true, //false是tolbar页面 是则不写
  126. title: '充值',
  127. color: '#1A1A1A',
  128. // autoBack:true,
  129. //背景颜色;参数一:透明度(0-1);参数二:背景颜色(array则为线性渐变,string为单色背景)
  130. backgroundColor: [1, "#fff"],
  131. statusBarFontColor: '#1A1A1A'
  132. },
  133. money: '',
  134. pay_mode: 1, // 支付方式
  135. showBanksModel: false,
  136. showPayModel: false,
  137. banksList: [], // 有效银行卡
  138. card_id: '', // 银行卡id
  139. sms_code: '', // 银行卡支付短信验证码
  140. codeCount: 10, // 银行卡支付短信验证码重发倒计时
  141. payment_id: '', // 预支付id,
  142. };
  143. },
  144. onShow() {
  145. this.getBanks()
  146. },
  147. methods: {
  148. getBanks() {
  149. this.$http.get('/usercard/list?valid=1').then(res => {
  150. if (res.code == 200) {
  151. this.banksList = res.list
  152. this.banksList.map(item => {
  153. item.logo = this.$mConfig.bankLink + item.local_bank_mark
  154. })
  155. }
  156. })
  157. },
  158. goPayBtn() {
  159. if (!this.money) {
  160. this.$mUtil.toast("请输入充值金额")
  161. return false
  162. } else if (!this.$mConfig.twoMinNum.test(this.money)) {
  163. this.$mUtil.toast("最多输入两位小数")
  164. return false
  165. };
  166. uni.showLoading({
  167. mask: true,
  168. title: '充值中...'
  169. })
  170. let data = {
  171. pay_mode: this.pay_mode, //1微信 2支付宝 0 余额
  172. money: this.money,
  173. client: "app",
  174. }
  175. // if (this.pay_mode == 12) {
  176. // let locationObj = uni.getStorageSync('locationObj')
  177. // data.longitude = locationObj.longitude.toFixed(4)
  178. // data.latitude = locationObj.latitude.toFixed(4)
  179. // }
  180. // if (this.pay_mode == 14) {
  181. // data.card_id = this.card_id
  182. // if (!this.card_id) {
  183. // if (this.banksList.length) {
  184. // return this.$mUtil.toast('请先选择银行卡');
  185. // }
  186. // return this.$mUtil.toast('请先添加银行卡');
  187. // }
  188. // }
  189. this.$http.post(directBuy, data).then(res => {
  190. if (res && res.code == 200) {
  191. let target = res.data.data
  192. console.log(target, 111111111)
  193. if (this.pay_mode == 1) {
  194. uni.requestPayment({
  195. provider: "wxpay",
  196. orderInfo: {
  197. appid: target.appid, // 微信开放平台 - 应用 - AppId,注意和微信小程序、公众号 AppId 可能不一致
  198. noncestr: target.noncestr, // 随机字符串
  199. package: target.package, // 固定值
  200. partnerid: target.partnerid, // 微信支付商户号
  201. prepayid: target.prepayid, // 统一下单订单号
  202. timestamp: target.timestamp, // 时间戳(单位:秒)
  203. sign: target.sign // 签名,这里用的 MD5/RSA 签名
  204. },
  205. success: (res) => {
  206. this.$mUtil.toast('支付成功');
  207. setTimeout(() => {
  208. uni.navigateBack({
  209. delta: 1
  210. })
  211. }, 1000);
  212. },
  213. fail(e) {
  214. uni.hideLoading()
  215. console.log('fail:' + JSON.stringify(err));
  216. }
  217. })
  218. } else if (this.pay_mode == 2) {
  219. uni.requestPayment({
  220. provider: 'alipay',
  221. orderInfo: target.prePayOrderInfo,
  222. success: res => {
  223. this.$mUtil.toast('支付成功');
  224. setTimeout(() => {
  225. uni.navigateBack({
  226. delta: 1
  227. })
  228. }, 1000);
  229. },
  230. fail: function(err) {
  231. uni.hideLoading()
  232. console.log('fail:' + JSON.stringify(err));
  233. }
  234. });
  235. }
  236. // else if (this.pay_mode == 10) {
  237. // // #ifdef APP-PLUS
  238. // setTimeout(() => {
  239. // this.showTip()
  240. // }, 3000)
  241. // if (target.expend) {
  242. // this.jumpPay(target.expend.pay_info)
  243. // } else if (target.status == 'failed') {
  244. // this.$mUtil.toast(target.error_msg);
  245. // }
  246. // // #endif
  247. // } else if (this.pay_mode == 12) {
  248. // // #ifdef APP-PLUS
  249. // setTimeout(() => {
  250. // this.showTip()
  251. // }, 3000)
  252. // if (target.qrCode) {
  253. // this.jumpPay(target.qrCode)
  254. // } else if (target.orderStatus == 'FAIL') {
  255. // this.$mUtil.toast(target.respMsg);
  256. // }
  257. // // #endif
  258. // } else if (this.pay_mode == 14) {
  259. // this.showPayModel = true
  260. // this.payment_id = target.id
  261. // this.codeCount = 10
  262. // timer = setInterval(() => {
  263. // this.codeCount--
  264. // if (this.codeCount == 0) {
  265. // clearInterval(timer)
  266. // }
  267. // }, 1000)
  268. // }
  269. // uni.hideLoading()
  270. // this.integral_able = res.data.integral_able;
  271. // uni.setStorageSync("personal", res.data)
  272. } else {
  273. // this.isLogin = false
  274. uni.hideLoading()
  275. this.$mUtil.toast('充值失败');
  276. }
  277. }).catch(err => {
  278. uni.hideLoading()
  279. this.$mUtil.toast('充值失败');
  280. })
  281. },
  282. jumpPay(qrCode) {
  283. if (qrCode) {
  284. let url = `alipays://platformapi/startapp?saId=10000007&qrcode=${qrCode}`
  285. if (plus.os.name == 'iOS') {
  286. plus.runtime.launchApplication({
  287. pname: 'com.eg.android.AlipayGphone',
  288. action: url,
  289. }, err => {
  290. console.log("err:" + JSON.stringify(err))
  291. this.$mUtil.toast('支付跳转失败,请选择其它支付方式');
  292. });
  293. } else if (plus.os.name == 'Android') {
  294. plus.runtime.openURL(url, err => {
  295. console.log("err:" + JSON.stringify(err))
  296. this.$mUtil.toast('支付跳转失败,请选择其它支付方式');
  297. }, 'com.eg.android.AlipayGphone');
  298. }
  299. }
  300. },
  301. showTip() {
  302. uni.showModal({
  303. title: '确认支付',
  304. content: '请确认当前充值订单是否支付',
  305. success: (success) => {
  306. if (success.confirm) {
  307. console.log('用户点击确定');
  308. setTimeout(() => {
  309. uni.navigateBack({
  310. delta: 1
  311. })
  312. }, 1000);
  313. } else if (success.cancel) {
  314. console.log('用户点击取消');
  315. }
  316. }
  317. });
  318. },
  319. banksHandler() {
  320. uni.navigateTo({
  321. url: '/pages/order/banks/list'
  322. })
  323. },
  324. payBankWay(e, id) {
  325. this.pay_mode = e;
  326. this.card_id = id
  327. },
  328. retrySms() {
  329. if (this.codeCount > 0) return this.$mUtil.toast('请稍后重试');
  330. this.codeCount = 10
  331. uni.showLoading({
  332. title: '重发中...',
  333. mask: true
  334. })
  335. this.$http.post('/pay/order/kjRepeatSendSms', {
  336. payment_id: this.payment_id
  337. }).then(res => {
  338. uni.hideLoading()
  339. if (res.code == 200) {
  340. this.$mUtil.toast('短信验证码重发成功');
  341. } else {
  342. this.$mUtil.toast('服务异常! 请重试');
  343. }
  344. }).catch(err => {
  345. uni.hideLoading()
  346. // this.$mUtil.toast('服务异常!');
  347. })
  348. },
  349. payConfirm() {
  350. this.$refs.payModel.clearLoading()
  351. if (!this.sms_code) {
  352. return this.$mUtil.toast('短信验证码不能为空');
  353. }
  354. uni.showLoading({
  355. title: '充值中...',
  356. mask: true
  357. })
  358. this.$http.post('/pay/order/kjPayConfirm', {
  359. payment_id: this.payment_id,
  360. sms_code: this.sms_code
  361. }).then(res => {
  362. if (res.code == 200) {
  363. setTimeout(() => {
  364. uni.hideLoading()
  365. uni.navigateBack({
  366. delta: 1
  367. })
  368. }, 1000)
  369. }
  370. }).catch(err => {
  371. uni.hideLoading()
  372. })
  373. },
  374. payCancel() {
  375. this.$mUtil.toast('已取消充值');
  376. },
  377. }
  378. }
  379. </script>
  380. <style lang="scss" scoped>
  381. $padding: 60rpx;
  382. // page{
  383. // background-color: #f5f5f5;
  384. // }
  385. .pay-nums-box {
  386. width: 100%;
  387. height: 277rpx;
  388. background-color: #f5f5f5;
  389. padding: 0 $padding;
  390. display: flex;
  391. flex-direction: column;
  392. justify-content: center;
  393. .pay-title {
  394. font-size: 32rpx;
  395. font-family: PingFang SC, PingFang SC-Bold;
  396. font-weight: 700;
  397. color: #333333;
  398. }
  399. .pay-num {
  400. width: 100%;
  401. height: 120rpx;
  402. border-bottom: 1rpx solid #CCCCCC;
  403. display: flex;
  404. justify-content: space-between;
  405. align-items: center;
  406. .pay-tag {
  407. font-size: 60rpx;
  408. font-family: PingFang SC, PingFang SC-Bold;
  409. font-weight: 700;
  410. color: #000000;
  411. flex-shrink: 0;
  412. padding-right: 5px;
  413. }
  414. .pay-money {
  415. // height: 100%;
  416. // .u-input__input{
  417. // height: 100%;
  418. // }
  419. .uni-input-placeholder {
  420. font-size: 28rpx;
  421. font-family: PingFang SC, PingFang SC-Regular;
  422. font-weight: 400;
  423. color: #cccccc;
  424. }
  425. .uni-input-input {
  426. color: #000000;
  427. }
  428. }
  429. }
  430. }
  431. .pay-way-box {
  432. width: 100%;
  433. background-color: #f5f5f5;
  434. }
  435. .pay-way {
  436. width: 100%;
  437. // min-height: calc(100vh - 277rpx );
  438. background-color: #fff;
  439. border-radius: 40rpx 40rpx 0 0;
  440. padding: 50rpx 60rpx 0;
  441. .pay-title {
  442. font-size: 32rpx;
  443. font-family: PingFang SC, PingFang SC-Bold;
  444. font-weight: 700;
  445. color: #333333;
  446. }
  447. .pay-item {
  448. margin-top: 30rpx;
  449. display: flex;
  450. justify-content: space-between;
  451. align-items: center;
  452. .pay-item-left {
  453. display: flex;
  454. align-items: center;
  455. .pay-item-icon {
  456. font-size: 58rpx;
  457. }
  458. .pay-item-name {
  459. font-size: 28rpx;
  460. font-family: PingFang SC, PingFang SC-Regular;
  461. font-weight: 400;
  462. color: #666666;
  463. padding-left: 18rpx;
  464. }
  465. }
  466. .pay-item-right {
  467. flex-shrink: 0;
  468. width: 36rpx;
  469. height: 36rpx;
  470. background: #ffffff;
  471. border: 2rpx solid #3775f6;
  472. border-radius: 50%;
  473. }
  474. .active-pay-item {
  475. position: relative;
  476. &:before {
  477. content: '';
  478. position: absolute;
  479. left: 50%;
  480. top: 50%;
  481. width: 18rpx;
  482. height: 18rpx;
  483. background: #FA6138;
  484. border-radius: 50%;
  485. transform: translate(-50%, -50%);
  486. }
  487. }
  488. }
  489. .pay-btn {
  490. margin-top: 137rpx;
  491. width: 100%;
  492. // width: 630px;
  493. height: 90rpx;
  494. line-height: 90rpx;
  495. background: #3d93fc;
  496. border-radius: 45rpx;
  497. font-size: 32rpx;
  498. font-family: PingFang SC, PingFang SC-Regular;
  499. font-weight: 400;
  500. color: #ffffff;
  501. text-align: center;
  502. }
  503. }
  504. .paybody {
  505. padding: 20rpx 30rpx;
  506. /deep/ .u-input {
  507. border-bottom: 2rpx solid #dcdfe6;
  508. }
  509. .header-text {
  510. margin-bottom: 20rpx;
  511. }
  512. .sms {
  513. display: flex;
  514. align-items: center;
  515. .retry-gary {
  516. display: flex;
  517. align-items: center;
  518. justify-content: center;
  519. width: 180rpx;
  520. margin-left: 40rpx;
  521. padding: 20rpx 10rpx;
  522. background-color: #FA6138;
  523. border-radius: 10rpx;
  524. color: #fff;
  525. }
  526. .retry {
  527. background-color: gray;
  528. }
  529. }
  530. }
  531. .banks-content {
  532. height: 100%;
  533. padding: 80rpx 30rpx 0;
  534. .add {
  535. position: absolute;
  536. top: 30rpx;
  537. left: 30rpx;
  538. font-size: 30rpx;
  539. font-weight: bold;
  540. color: #FA6138;
  541. }
  542. .header {
  543. position: absolute;
  544. top: 30rpx;
  545. left: 50%;
  546. font-size: 30rpx;
  547. font-weight: bold;
  548. transform: translateX(-50%);
  549. }
  550. .no-data-view {
  551. margin-top: 10vh !important;
  552. }
  553. .banks-pay {
  554. display: flex;
  555. justify-content: center;
  556. align-items: center;
  557. width: 80%;
  558. position: fixed;
  559. bottom: 20rpx;
  560. left: 50%;
  561. color: #fff;
  562. border-radius: 10rpx;
  563. padding: 20rpx 0;
  564. text-align: center;
  565. font-size: 30rpx;
  566. transform: translateX(-50%);
  567. background-color: #FA6138;
  568. .txt {
  569. margin-right: 10rpx;
  570. }
  571. }
  572. .banks {
  573. width: 100%;
  574. height: 80%;
  575. overflow: hidden;
  576. .scroll-box {
  577. width: 100%;
  578. height: 100%;
  579. }
  580. }
  581. .item {
  582. // height: 100rpx;
  583. // display: flex;
  584. // align-items: center;
  585. display: block;
  586. padding: 20rpx 0;
  587. border-bottom: 1rpx solid #E6E5E5;
  588. .box {
  589. display: flex;
  590. justify-content: space-between;
  591. align-items: center;
  592. &:first-child {
  593. margin-bottom: 10rpx;
  594. }
  595. .bank_name {
  596. font-size: 30rpx;
  597. font-weight: bold;
  598. }
  599. }
  600. image {
  601. width: 200rpx;
  602. height: auto;
  603. }
  604. .bank-icon {
  605. margin-right: 10rpx;
  606. color: #2f77f1;
  607. font-size: 50rpx;
  608. flex-shrink: 0;
  609. }
  610. .name {
  611. margin-right: 20rpx;
  612. font-size: 26rpx;
  613. overflow: hidden;
  614. text-overflow: ellipsis;
  615. white-space: nowrap;
  616. }
  617. .unbind {
  618. margin-left: auto;
  619. color: red;
  620. flex-shrink: 0;
  621. }
  622. }
  623. .gray {
  624. color: gray;
  625. .bank-icon {
  626. color: gray;
  627. }
  628. }
  629. }
  630. </style>