基于vue2的h5页面实现拉起支付宝app支付且轮询支付结果

*只有前端部分

 

1.首先data需要储存几个值:

      payUrl: "", // 订单支付跳转链接
      isFetchCode: false, //正在生成订单
      payStatus: "", // 订单状态,用于判断是否还需要继续请求订单支付结果接口
      userDown: false, // 用户点击已支付完成按钮
      timer: null, // 轮询计时器
      goZfbSrc: null, // 用于解决ios系统下safari浏览器不支持window新开窗口的计时器

以及其他订单进行中弹窗、支付成功弹窗等状态管理

 

2.用户点击支付后,请求后端接口,拿到支付宝跳转链接:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// 点击购买,获取商品支付地址
    async showQrCode() {
      if (this.isFetchCode) return;
      this.isFetchCode = true;
      try {
        const { code, msg, data } = await api.createOrder({
          ...传参
        });
        if (code === 0 && data) {
          const { jump_url, orderno, create_dt } = data;
          // 获取订单编号及下单时间
          this.orderno = orderno;
          this.createTime = create_dt;
          this.payUrl = jump_url;
          // 关闭下单弹窗
          this.payVisible = false;
          // 打开订单进行中弹窗
          this.codeVisible = true;
          // 支付宝支付
          if (this.payType === "alipay_mobile") {
            // 微信浏览器中选择支付宝支付,弹窗复制支付链接,提示用户在外部浏览器打开进行支付
            const browser = window.navigator.userAgent.toLowerCase();
            if (browser.match(/MicroMessenger/i) == "micromessenger") {
              this.copyVisible = true;
            } else {
              // 跳转支付宝
              this.payStatus = "waiting";
              this.pollOrder();
              this.goZfbSrc = setTimeout(() => {
                window.open(jump_url, "_blank");
                clearTimeout(this.goZfbSrc);
              });
              // window.location.replace(jump_url);
              // const a = document.createElement("a");
              // a.setAttribute("href", jump_url);
              // a.setAttribute("target", "支付");
              // document.body.appendChild(a);
              // a.click();
              // document.body.removeChild(a);
 
              // const form = document.createElement("form");
              // form.action = jump_url;
              // form.target = "_blank";
              // form.method = "POST";
              // document.body.appendChild(form);
              // form.submit();
 
              // const tempPage = window.open("_blank");
              // tempPage.location = jump_url;
 
              // window.open(jump_url, "_ blank");
            }
          } else {
            // 微信支付
            this.$toast("微信支付");
            // this.initiatePayment();
          }
        } else if (code === 87) {
          // 限购,打开限购弹窗
          this.$refs.fail.visible = true;
        } else if (code === 83) {
          this.$toast(
            "订单生成失败,请重新选择商品购买,如有疑问请咨询客服查询"
          );
        } else {
          this.$toast(msg || "获取失败");
        }
      } catch (err) {
        //
      } finally {
        this.isFetchCode = false;
      }
    },

  

肉眼可见为了这个该死的sarari尝试了多少种方案= =无论是创建a标签手动触发点击事件,还是通过创建表单通过提交表单的方式拉起,还是直接使用window.open开新窗口,都不可以,最终是利用了setTimeout这个利器才解决这个问题。

而safari不允许的原因也很简单,它默认开启了阻止弹出窗口的策略,禁用了通过代码调用超链接在新标签打开页面的功能,避免window.open被滥用。但这个阻止弹出窗口的操作,并不是完全禁止,而是会根据用户的行为来判断这次window.open()是否属于流氓操作。

所以,聪明的程序员利用setTimeout运行于主线程的这个特点,把打开链接的操作放到setTimeout里运行即可,这样就不会被浏览器认定为代码操作,避免了被拦截。

谢谢你,大佬。(虎目含泪)

 

2.实现拉起app之后,接着就是页面轮询了:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 间隔刷新订单支付状态
pollOrder() {
  this.timer = setInterval(() => {
    if (this.payStatus === "waiting" && this.codeVisible) {
      // 未完成且订单进行中的弹窗未关闭,则继续请求
      this.queryPayStatus();
    } else {
      // 已成功完成/关闭弹窗,清空计时器
      clearInterval(this.timer);
      this.timer = null;
    }
  }, 3000);
},

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 查询支付状态
async queryPayStatus() {
  try {
    const { code } = await api.orderPolling({
      orderno: this.orderno,
    });
    if (code === 0) {
      this.payStatus = "success";
      this.codeVisible = false;
      this.sucVisible = true;
      clearInterval(this.timer);
    } else if (code === 22) {
      this.payStatus = "";
      this.$toast("订单已失效,请重新购买");
      this.codeVisible = false;
      clearInterval(this.timer);
    } else {
      // 如果是用户手动查询,弹出状态提示
      if (this.userDown) {
        this.$toast("订单未完成支付,请确认支付状态");
        this.userDown = false;
      }
    }
  } catch (err) {
    //
  } finally {
    //
  }
},

  

3.以及手动点击查询:

1
2
3
4
5
// 用户点击刷新支付状态
userSearchStatus() {
  this.userDown = true;
  this.queryPayStatus();
},

  

 那么简单的h5页面拉起支付宝支付就完成鸟~

posted @   芝麻小仙女  阅读(162)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2022-12-19 js处理树形数组扁平化
点击右上角即可分享
微信分享提示