• Vue项目中常见问题(56)微信支付业务的实现


    目录

    gitee仓库地址:https://gitee.com/CMD-UROOT/sph-project/commits/master

    前言:

     业务需求1:实现二维码

     1.安装qrcode

     2.引入qrcode

     3.使用qrcode

     4.二维码放入结构中

     5.扫码支付业务

      查询支付订单状态接口

      5.1写接口api

     长轮询 和短轮询是什么?

     5.2二维码展示出来需要做一件事长轮询

     5.3支付成功与失败的判断

     5.4paysuccess静态组件搭建

     5.5paysuccess路由组件注册引入

     5.6 问题出现

    完整代码:


    gitee仓库地址:https://gitee.com/CMD-UROOT/sph-project/commits/master

    大家根据上传历史进行查找你需要的代码

    前言:

    上一篇文章我们利用ElementUI已经实现了点击立即支付按钮,弹出弹出框的操作

     业务需求1:实现二维码

    我们需要在弹出框中生成一个二维码,市场上有许多插件,是可以生成二维码的

    我们打开这个网址  npm

    搜索qrcode  或者直接打开这个网址:  qrcode - npm

     

     1.安装qrcode

    npm i qrcode --save

    2.引入qrcode

    在pages/Pay/index.vue中:引入qrcode

    也就是我们需要使用qrcode的组件中去引用

     

     3.使用qrcode

     我们知道在我们的项目中

    支付页面的数据中有一个payInfo里面有一个codeUrl数据是字符串,我们要利用这个字符串来生成二维码

    在pages/Pay/index.vue中:

     打印:点击立即支付控制台弹出二维码地址

     点进地址:就是一个二维码了

     4.二维码放入结构中

    二维码需要在弹出框的中间进行展示

    所以:

    在pages/Pay/index.vue中:

     

     5.扫码支付业务

    扫码支付可能成功,也可能失败,如果成功需要跳转路由,如果失败需要提示支付失败,支付成功与失败,是后台返回的,所以我们需要发请求

    那么需要发多少次请求呢,因为支付是用户行为,我们将来得向服务器问,用户支付成功还是失败,我们需要一直问

    也就是说当弹出框弹出来的时候,就需要一直向后台询问,用户支付的情况

    查询支付订单状态接口

    请求地址:/api/payment/weixin/queryPayStatus/{orderId}

    请求方式:get

    参数:orderId

     

     5.1写接口api

    在api/index.js中: 

    知识点

    轮询 和短轮询是什么?

    长轮询:

    http 长轮询是服务器收到请求后如果有数据, 立刻响应请求; 如果没有数据就会 hold 一段时间,这段时间内如果有数据立刻响应请求; 如果时间到了还没有数据, 则响应 http 请求;浏览器受到 http 响应后立在发送一个同样http 请求查询是否有数据;

    短轮询

    http端轮询是服务器收到请求不管是否有数据都直接响应 http 请求; 浏览器受到 http 响应隔一段时间在发送同样的http 请求查询是否有数据;

    两者相同点:
    可以看出 http 长轮询和 http 短轮询的都会 hold 一段时间;

    两者不同点
    间隔发生在服务端还是浏览器端: http 长轮询在服务端会 hold 一段时间, http 短轮询在浏览器端 “hold”一段时间;

    5.2二维码展示出来需要做一件事长轮询

    也就是说当弹出框弹出来的时候,就需要一直向后台询问,用户支付的情况

    (有的人肯定会说,为什么不用户支付后点击确认这个点来判断用户是否支付成功,非要用什么长轮询,一直询问后台,那么麻烦,那你得思考一个问题,万一用户支付完了断网了,用户还需要重新支付一次再点击确定吗?)

    在pages/Pay/index.vue中:定义一个timer

     

    测试:

    当我们点击立即支付按钮的时候,只要一弹出弹出框,就会一直向服务器发请求,我们这里利用的是定时器来控制发请求

     如果我们扫描支付了,就会看到控制台出现:

     5.3支付成功与失败的判断

    如果支付成功,我们需要隐藏支付的弹出框,清除定时器 ,存储code为200,跳转路由

    存储code是为了,验证用户是否支付成功,支付成功code为200,这个时候用户再点击已支付成功按钮,才能跳转到支付成功的页面

    在pages/Pay/index.vue中:

     

    完整代码:

    1. // 弹出框
    2. async open(){
    3. //生成二维码(地址)
    4. let url = await QRCode.toDataURL(this.payInfo.codeUrl)
    5. // console.log(url)
    6.   this.$alert(`<img src=${url} />`, '请微信支付', {
    7. dangerouslyUseHTMLString: true, //是否将 message 属性作为 HTML 片段处理
    8. center:true, //是否居中布局
    9. showCancelButton:true, //是否显示取消按钮
    10. cancelButtonText:"支付遇见问题",//取消按钮的文本内容
    11. confirmButtonText:"已支付成功",//支付按钮的文本内容
    12. showClose:true,//右上角的叉子没了
    13. });
    14. //你需要知道支付成功|失败
    15. //支付成功,路由跳转,如果支付失败,提示信息
    16. //定时器没有,开启一个新的定时器
    17. if(!this.timer){
    18. this.timer = setInterval(async()=>{
    19. //发请求获取用户支付状态
    20. let result = await this.$API.reqPayStatus(this.orderId)
    21. // console.log(result)
    22. //如果code==200
    23. if(result.code==200){
    24. //第一步:清除定时器
    25. clearInterval(this.timer)
    26. this.timer = null
    27. //保存支付成功返回的code
    28. this.code = result.code
    29. //关闭弹出框
    30. this.$msgbox.close()
    31. //跳转到下一路由
    32. this.$router.push('/paysuccess')
    33. }
    34. },1000)
    35. }
    36. }

    但是跳转下一路由我们这里还没写,我们这里写一下:

    5.4paysuccess静态组件搭建

    在pages文件下新建PaySuccess文件,里面在创建一个index.vue

    pages/PaySucess/index.vue里面的完整代码:

    1. <template>
    2. <div class="paysuccess">
    3. <div class="success">
    4. <h3>
    5. <img src="./images/right.png" width="48" height="48">
    6. 恭喜您,支付成功啦!
    7. </h3>
    8. <div class="paydetail">
    9. <p class="button">
    10. <router-link class="btn-look" to="/center">查看订单</router-link>
    11. <router-link class="btn-goshop" to="/">继续购物</router-link>
    12. </p>
    13. </div>
    14. </div>
    15. </div>
    16. </template>
    17. <script>
    18. export default {
    19. name: 'PaySuccess',
    20. }
    21. </script>
    22. <style lang="less" scoped>
    23. .paysuccess {
    24. margin: 20px auto;
    25. padding: 25px;
    26. border: 1px solid rgb(211, 211, 211);
    27. width: 1200px;
    28. width: 1148px;
    29. .success {
    30. width: 500px;
    31. margin: 0 auto;
    32. h3 {
    33. margin: 20px 0;
    34. font-weight: 700;
    35. font-size: 20px;
    36. line-height: 30px;
    37. img {
    38. max-width: 100%;
    39. vertical-align: middle;
    40. border: 0;
    41. margin-right: 14px;
    42. }
    43. }
    44. .paydetail {
    45. margin-left: 66px;
    46. font-size: 15px;
    47. .button {
    48. margin: 30px 0;
    49. line-height: 26px;
    50. a {
    51. display: inline-block;
    52. box-sizing: border-box;
    53. text-align: center;
    54. vertical-align: middle;
    55. cursor: pointer;
    56. border-radius: 2px;
    57. user-select: none;
    58. font-size: 18px;
    59. padding: 4px 20px;
    60. line-height: 22px;
    61. text-decoration: none;
    62. &.btn-look {
    63. margin-right: 13px;
    64. color: #fff;
    65. background-color: #e1251b;
    66. border: 1px solid #e1251b;
    67. }
    68. &.btn-goshop {
    69. color: #666;
    70. background-color: #eee;
    71. border: 1px solid #e1e1e1;
    72. }
    73. }
    74. }
    75. }
    76. }
    77. }
    78. </style>

     5.5paysuccess路由组件注册引入

     测试一下:没问题,可以使用

     5.6 问题出现

    出现这个页面的时候,我们并没有支付的情况下,我们点击已支付成功, 弹出框也会消失,正常业务逻辑是要支付以后点击已支付成功,弹出框才会消失的

     比如用户真的支付成功了,应该跳转到支付成功的页面

    用户假的支付成功了,应该弹出一个让用户继续支付

    用户点击支付遇见问题,应该弹一个联系管理员之类的

    ElementUI官网:Element - The world's most popular Vue UI framework

    这个时候我们利用ElementUI官网的MessageBox里面的beforeClose来解决这个问题,

    因为上面提到的三种情况,都是在MessageBox关闭前执行的,所以这个方法,就是在关闭之前在帮你执行一些事情

     在pages/Pay/index.vue中:

    写上这个回调后,我们再点击支付遇见问题,和已支付成功,就不会关闭了,他要等待我们把里面的函数处理完了,才会进行下一步操作 

    但是问题来了,我们怎么知道我们点击的按钮是谁,我们得区分按钮

    ElementUI那张图已经说的很清楚了

    测试:

    第一个参数是可以用户区分是哪个按钮

     第二个参数:当前组件实例

     

     第三个参数:关闭弹出框的方法 

    我们可以调用这个done(),可以让我们点击已支付成功和支付遇到问题的时候,关闭弹出框

    完整代码:

    1. // 弹出框
    2. async open(){
    3. //生成二维码(地址)
    4. let url = await QRCode.toDataURL(this.payInfo.codeUrl)
    5. // console.log(url)
    6.   this.$alert(`<img src=${url} />`, '请微信支付', {
    7. dangerouslyUseHTMLString: true, //是否将 message 属性作为 HTML 片段处理
    8. center:true, //是否居中布局
    9. showCancelButton:true, //是否显示取消按钮
    10. cancelButtonText:"支付遇见问题",//取消按钮的文本内容
    11. confirmButtonText:"已支付成功",//支付按钮的文本内容
    12. showClose:false,//右上角的叉子没了
    13. //关闭弹出框的配置值
    14. beforeClose:(type,instance,done)=>{
    15. // console.log(type,instance,done)
    16. //type:区分取消|确定按钮
    17. //instance:当前组件实例
    18. //done:关闭弹出框的方法
    19. if(type=='cancel'){
    20. alert('请联系管理员华哥')
    21. //清除定时器
    22. clearInterval(this.timer)
    23. this.timer = null
    24. //关闭弹出框
    25. done()
    26. }else{
    27. //判断是否真的支付了
    28. if(this.code==200){
    29. clearInterval(this.timer)
    30. this.timer = null
    31. done()
    32. //跳转到下一路由
    33. this.$router.push('/paysuccess')
    34. }
    35. }
    36. }
    37. });
    38. //你需要知道支付成功|失败
    39. //支付成功,路由跳转,如果支付失败,提示信息
    40. //定时器没有,开启一个新的定时器
    41. if(!this.timer){
    42. this.timer = setInterval(async()=>{
    43. //发请求获取用户支付状态
    44. let result = await this.$API.reqPayStatus(this.orderId)
    45. // console.log(result)
    46. //如果code==200
    47. if(result.code==200){
    48. //第一步:清除定时器
    49. clearInterval(this.timer)
    50. this.timer = null
    51. //保存支付成功返回的code
    52. this.code = result.code
    53. //关闭弹出框
    54. this.$msgbox.close()
    55. //跳转到下一路由
    56. this.$router.push('/paysuccess')
    57. }
    58. },1000)
    59. }
    60. }

    注意上面完整代码中新增的代码,我截图放下面了

    这个时候我们点击支付遇到问题:

    不付款 点击已支付成功,不会有任何反应

    付款后 点击已支付成功,会跳转到支付成功的页面:

     还有一点就是我们可以不用支付,点击已支付成功跳转到支付成功的页面

    开发人员:为了自己方便,这里的判断先不要了

    到此微信支付功能就实现了

  • 相关阅读:
    微信小程序文字上下无缝轮播(滚动效果)
    Spring Boot 集成 ElasticSearch
    Postgresql 学习记录,模式,分区表,触发器,事务,窗口函数,视图,建表,约束等
    MIPI CSI-2笔记(16) -- 数据格式(YUV图像数据)
    The sorting algorithm including selection, bubble, and insertion
    Minecraft 1.12.2 彩色渐变字体 模组发布
    UnoCSS框架常用语法
    前端进击笔记第十七节 提升开发效率:数据抽象与配置化
    前端 JS 经典:Math 常用方法汇总
    537. 复数乘法
  • 原文地址:https://blog.csdn.net/qq_46368050/article/details/124964457