payOrder.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. <template>
  2. <div class="wrapper">
  3. <div class="box">
  4. <div class="block block-1">
  5. <image class="img" src="@/pages/cart/static/pay.png" />
  6. <p class="ptips">收银台</p>
  7. <p class="ptips">剩余支付时间:
  8. <u-count-down :show-days="false" :show-border="true" font-size="28" color="#008ffa"
  9. border-color="#008ffa" ref="uCountDown" :timestamp="autoCancel"></u-count-down>
  10. </p>
  11. <p class="ptips">
  12. 支付金额
  13. <span>¥{{ cashierParams.price | unitPrice }}</span>
  14. </p>
  15. </div>
  16. </div>
  17. <div class="__pay_form__">
  18. </div>
  19. <div class="block-4" v-if="cashierParams.price > 0">
  20. <div class="payItem">支付方式</div>
  21. <div class="payItem" v-for="(item, index) in payList" :key="index">
  22. <u-row class="row">
  23. <div class="col1" @click="awaitPay(item, index)" size="100" style="text-align:left;">
  24. <div v-if="item == 'ALIPAY'">
  25. <u-icon class="method_icon" name="zhifubao-circle-fill" color="#008ffa" size="80"></u-icon>
  26. <span class="method_name">支付宝</span>
  27. </div>
  28. <div v-if="item == 'WECHAT'">
  29. <u-icon class="method_icon" name="weixin-circle-fill" color="#00c98b" size="80"></u-icon>
  30. <span class="method_name">微信</span>
  31. </div>
  32. <div v-if="item == 'WALLET'">
  33. <u-icon class="method_icon" name="red-packet-fill" color="#dd6161" size="80"></u-icon>
  34. <span class="method_name">余额支付(当前余额:¥{{ walletValue | unitPrice }})</span>
  35. </div>
  36. </div>
  37. <div class="col3" @click="awaitPay(item)" textAlign="right">
  38. <u-icon size="26" color="#b1b1b1" name="arrow-right"></u-icon>
  39. </div>
  40. </u-row>
  41. </div>
  42. </div>
  43. </div>
  44. </template>
  45. <script>
  46. import * as API_Trade from "@/api/trade";
  47. export default {
  48. data() {
  49. return {
  50. //路径传参
  51. routerVal: "",
  52. //收银台参数
  53. cashierParams: "",
  54. //支付方式集合
  55. payList: "",
  56. //支付sn
  57. sn: "",
  58. //订单类型
  59. orderType: "",
  60. //支付异常
  61. exception: {},
  62. //支付表单
  63. payForm: {},
  64. //支付类型 APP/WECHAT_MP/H5/NATIVE app/微信小程序/h5/二维码
  65. paymentType: "",
  66. // 支付客户端 APP/NATIVE/JSAPI/H5
  67. paymentClient: "",
  68. //余额
  69. walletValue: 0.0,
  70. // 支付倒计时
  71. autoCancel: 0,
  72. };
  73. },
  74. onLoad(val) {
  75. this.routerVal = val;
  76. //初始化参数
  77. // #ifdef APP-PLUS
  78. this.paymentType = "APP";
  79. this.paymentClient = "APP";
  80. //#endif
  81. // #ifdef MP-WEIXIN
  82. this.paymentType = "WECHAT_MP";
  83. this.paymentClient = "MP";
  84. //#endif
  85. // #ifdef H5
  86. this.paymentType = "H5";
  87. //如果是微信浏览器,则使用公众号支付,否则使用h5,
  88. // 区别是:h5是通过浏览器外部调用微信app进行支付,而JSAPI则是 在微信浏览器内部,或者小程序 调用微信支付
  89. this.paymentClient = this.isWeiXin() ? "JSAPI" : "H5";
  90. //#endif
  91. },
  92. onBackPress(e) {
  93. if (e.from == "backbutton") {
  94. uni.redirectTo({
  95. url: "/pages/order/myOrder?status=0",
  96. });
  97. return true; //阻止默认返回行为
  98. }
  99. },
  100. mounted() {
  101. this.cashierData();
  102. },
  103. methods: {
  104. navigateTo(url) {
  105. uni.navigateTo({
  106. url,
  107. });
  108. },
  109. // 获取收银详情
  110. cashierData() {
  111. let parms = {};
  112. if (this.routerVal.recharge_sn) {
  113. this.sn = this.routerVal.recharge_sn;
  114. this.orderType = "RECHARGE";
  115. } else if (this.routerVal.trade_sn) {
  116. this.sn = this.routerVal.trade_sn;
  117. this.orderType = "TRADE";
  118. } else {
  119. this.sn = this.routerVal.order_sn;
  120. this.orderType = "ORDER";
  121. }
  122. parms.sn = this.sn;
  123. parms.orderType = this.orderType;
  124. parms.clientType = this.paymentType;
  125. API_Trade.getCashierData(parms).then((res) => {
  126. this.cashierParams = res.data.result;
  127. // #ifdef MP-WEIXIN
  128. this.payList = res.data.result.support.filter((item) => {
  129. return item != "ALIPAY";
  130. });
  131. // #endif
  132. // #ifndef MP-WEIXIN
  133. this.payList = res.data.result.support;
  134. // #endif
  135. this.walletValue = res.data.result.walletValue;
  136. this.autoCancel =
  137. (res.data.result.autoCancel - new Date().getTime()) / 1000;
  138. });
  139. },
  140. awaitPay(payment){
  141. this.pay(payment)
  142. },
  143. //订单支付
  144. async pay(payment) {
  145. // 支付编号
  146. const sn = this.sn;
  147. // 交易类型【交易号|订单号】
  148. const orderType = this.orderType;
  149. const clientType = this.paymentType;
  150. let params = {
  151. sn,
  152. orderType,
  153. clientType,
  154. };
  155. //支付方式 WECHAT/ALIPAY
  156. const paymentMethod = payment;
  157. // 客户端类型 APP/NATIVE/JSAPI/H5
  158. const paymentClient = this.paymentClient;
  159. // #ifdef APP-PLUS
  160. //APP pay
  161. // 初始化支付签名
  162. await API_Trade.initiatePay(paymentMethod, paymentClient, params).then(
  163. (signXml) => {
  164. //如果支付异常
  165. if (!signXml.data.success) {
  166. uni.showModal({
  167. content: signXml.data.message,
  168. showCancel: false,
  169. })
  170. return;
  171. }
  172. let payForm = signXml.data.result;
  173. console.log(payForm)
  174. let paymentType = paymentMethod === "WECHAT" ? "wxpay" : "alipay";
  175. uni.requestPayment({
  176. provider: paymentType,
  177. orderInfo: payForm,
  178. success: (e) => {
  179. console.log(e);
  180. uni.showToast({
  181. icon: "none",
  182. title: "支付成功!",
  183. });
  184. uni.navigateTo({
  185. url: "/pages/payment/success?paymentType=" +
  186. paymentType +
  187. "&payPrice=" +
  188. this.cashierParams.price,
  189. });
  190. },
  191. fail: (e) => {
  192. console.log(e);
  193. this.exception = e;
  194. uni.showModal({
  195. content: "支付失败,如果您已支付,请勿反复支付",
  196. showCancel: false,
  197. });
  198. },
  199. });
  200. }
  201. );
  202. //APP pay
  203. // #endif
  204. //#ifdef H5
  205. //H5 pay
  206. await API_Trade.initiatePay(paymentMethod, paymentClient, params).then(
  207. (res) => {
  208. let response = res.data;
  209. //如果非支付宝支付才需要进行判定,因为支付宝h5支付是直接输出的,没有返回所谓的消息状态
  210. if(paymentMethod !== "ALIPAY"){
  211. //如果支付异常
  212. if (!response.success) {
  213. uni.showModal({
  214. content: response.message,
  215. showCancel: false,
  216. })
  217. return;
  218. }
  219. }
  220. if (paymentMethod === "ALIPAY") {
  221. document.write(response);
  222. } else if (paymentMethod === "WECHAT") {
  223. if (this.isWeiXin()) {
  224. //微信公众号支付
  225. WeixinJSBridge.invoke(
  226. "getBrandWCPayRequest",
  227. response.result,
  228. function(res) {
  229. if (res.err_msg == "get_brand_wcpay_request:ok") {
  230. // 使用以上方式判断前端返回,微信团队郑重提示:
  231. //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
  232. uni.showToast({
  233. icon: "none",
  234. title: "支付成功!",
  235. });
  236. uni.navigateTo({
  237. url: "/pages/cart/payment/success?paymentMethod=" +
  238. paymentMethod +
  239. "&payPrice=" +
  240. this.cashierParams.price,
  241. });
  242. } else {
  243. uni.showModal({
  244. content: "支付失败,如果您已支付,请勿反复支付",
  245. showCancel: false,
  246. });
  247. }
  248. }
  249. );
  250. } else {
  251. window.location.href = JSON.parse(response.result).h5_url;
  252. }
  253. } else if (paymentMethod === "WALLET") {
  254. uni.showToast({
  255. title: response.message,
  256. icon: "none",
  257. });
  258. if (response.success) {
  259. uni.navigateTo({
  260. url: "/pages/cart/payment/success?paymentMethod=" +
  261. paymentMethod +
  262. "&payPrice=" +
  263. this.cashierParams.price,
  264. });
  265. }
  266. }
  267. }
  268. );
  269. //H5pay
  270. // #endif
  271. //#ifdef MP-WEIXIN
  272. //微信小程序
  273. await API_Trade.initiatePay(paymentMethod, paymentClient, params).then(
  274. (res) => {
  275. let response = res.data.result;
  276. //如果支付异常
  277. if (!res.data.success) {
  278. uni.showModal({
  279. content: res.data.message,
  280. showCancel: false,
  281. })
  282. return;
  283. }
  284. if (paymentMethod === "WECHAT") {
  285. uni.requestPayment({
  286. provider: "wxpay",
  287. appid: response.appid,
  288. timeStamp: response.timeStamp,
  289. nonceStr: response.nonceStr,
  290. package: response.package,
  291. signType: response.signType,
  292. paySign: response.paySign,
  293. success: (e) => {
  294. console.log(e);
  295. uni.showToast({
  296. icon: "none",
  297. title: "支付成功!",
  298. });
  299. uni.navigateTo({
  300. url: "/pages/cart/payment/success?paymentMethod=" +
  301. paymentType +
  302. "&payPrice=" +
  303. this.cashierParams.price,
  304. });
  305. },
  306. fail: (e) => {
  307. console.log(e);
  308. this.exception = e;
  309. uni.showModal({
  310. content: "支付失败,如果您已支付,请勿反复支付",
  311. showCancel: false,
  312. });
  313. },
  314. });
  315. } else {
  316. uni.showToast({
  317. icon: "none",
  318. title: "支付成功!",
  319. });
  320. uni.navigateTo({
  321. url: "/pages/cart/payment/success?paymentMethod=" +
  322. paymentMethod +
  323. "&payPrice=" +
  324. this.cashierParams.price,
  325. });
  326. }
  327. }
  328. );
  329. // #endif
  330. },
  331. isWeiXin() {
  332. var ua = window.navigator.userAgent.toLowerCase();
  333. if (ua.match(/MicroMessenger/i) == "micromessenger") {
  334. return true;
  335. } else {
  336. return false;
  337. }
  338. },
  339. },
  340. };
  341. </script>
  342. <style scoped lang="scss">
  343. .method_icon {
  344. vertical-align: middle;
  345. }
  346. .method_name {
  347. font-size: 28rpx;
  348. color: #999;
  349. padding-left: 24rpx;
  350. }
  351. .row {
  352. display: flex;
  353. width: 100%;
  354. }
  355. /deep/ .u-row {
  356. width: 100% !important;
  357. display: flex;
  358. justify-content: space-between !important;
  359. }
  360. .method_name,
  361. .col1 {
  362. overflow: hidden;
  363. text-overflow: ellipsis;
  364. white-space: nowrap;
  365. }
  366. .col1 {
  367. text-align: center;
  368. flex: 99;
  369. }
  370. .col3 {
  371. text-align: right;
  372. flex: 1;
  373. }
  374. .payItem {
  375. padding: 13px 25rpx;
  376. border-top: 1px solid #f9f9f9;
  377. line-height: 100rpx;
  378. font-size: 36rpx;
  379. color: #333;
  380. }
  381. .ptips {
  382. font-size: 32rpx;
  383. margin: 20rpx 0;
  384. color: #333;
  385. >span {
  386. font-size: 40rpx;
  387. color: #df5a52;
  388. margin-left: 10rpx;
  389. }
  390. }
  391. .img {
  392. width: 392rpx !important;
  393. height: 296rpx !important;
  394. }
  395. .wrapper {
  396. min-height: 100vh;
  397. height: auto;
  398. background: #f9f9f9;
  399. }
  400. .block-4 {
  401. background: #fff;
  402. color: $u-tips-color;
  403. >p {
  404. padding: 8rpx;
  405. }
  406. }
  407. .box {
  408. background: #fff;
  409. padding: 40rpx 0;
  410. // justify-content: center; //这个是X轴居中
  411. // align-items: center; //这个是 Y轴居中
  412. }
  413. .block {
  414. text-align: center;
  415. display: block;
  416. width: 100%;
  417. image {
  418. width: 200rpx;
  419. height: 200rpx;
  420. }
  421. }
  422. .block-1 {
  423. margin-top: 80rpx;
  424. }
  425. .btns {
  426. margin: 0 20rpx;
  427. }
  428. </style>