?‍? 写在开头

点赞 + 收藏 === 学会???

前言:判断是不是微信内,是微信内就用jsApi支付(屏蔽支付宝),不是微信内就用H5支付

此实例为vue2实例,需要vue3的宝子可以自行转换,流程上没啥区别

var ua = window.navigator.userAgent.toLowerCase();if (ua.match(/MicroMessenger/i) == "micromessenger") {this.showAliPay = false;return true;} else {this.showAliPay = true;return false;}

一、jsApi支付

1、跳转到中间页,也可不跳转,在中间页进行一系列的操作
2、访问这个地址拿到code授权,并传给后端拿openid,拿到openid存到缓存里,下次进页面优先读取缓存的openid,没有再去找微信拿,完整代码如下
const localOpenId = localStorage.getItem("wexin-openid-wxc951e84c27099161");if (localOpenId) {  this.handleType(localOpenId);  return;}var appid = "wxc951e84c27099161"; //个人公众号appidvar appsecret = "778ef263f6e1d648d50daa1c5147884b";var mpPrefix = "wexin-openid-";this.redirect = encodeURIComponent(window.location.href); //重定向回来的地址// 判断是否是ios微信浏览器var wx_code = this.getUrlParam("code"); // 截取url中的code//获取code的地址。获取成功重定向后地址栏中将会带有code,判断没有code的话,就跳转到微信官方链接上获取,获取成功后会再重定向回来,注意url是需要使用encodeURIComponent处理一下编码的if (!wx_code) {  // scope: 必传;应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )  // 静默授权  window.location.href =    "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +    appid +    "&redirect_uri=" +    this.redirect +    "&response_type=code&scope=snsapi_base&state=123#wechat_redirect";} else {  // 获取到了code,找后端拿openid  axios    .post(      `http://api.test.chiyanjiasu.com/wx/mp/openId?appid=${appid}&appsecret=${appsecret}&code=${wx_code}`    )    .then((res) => {      // data是形参名,代表返回的数据      if (res.errcode) {        alert(res.errmsg);        return;      }      localStorage.setItem(mpPrefix + appid, res.data.openid);      this.handleType(res.data.openid); // 找后端拿orderId    })    .catch((error) => {      console.log("error", error);    });

3、拿链接里的值,和判断是否是微信方法

getUrlParam: function (name) {  var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");  var r = window.location.search.substr(1).match(reg);  if (r != null) return unescape(r[2]);  return null;},isWeChat() {  let ua = window.navigator.userAgent.toLowerCase();  return ua.match(/MicroMessenger/i) == "micromessenger"; // 判定为true则是微信浏览器,false则不是},

4、传给后端拿orderId(订单编号)

 

handleType(openId) {      const info = JSON.parse(localStorage.getItem("productInfo"));      const obj = {        amount: 1,        rtype: 2,        productId: info.id,        price: info.price,        totalPrice: info.price * 1,        buyTime: info.buyTime,        openId,        jsApi: 1,      };      userPayType(obj).then((result) => {        window.WeixinJSBridge.invoke(          "getBrandWCPayRequest",          {            appId: result.jsApiData.appId, //公众号ID,由商户传入            timeStamp: result.jsApiData.timeStamp, //时间戳,自1970年以来的秒数            nonceStr: result.jsApiData.nonceStr, //随机串            package: result.jsApiData.package,            signType: result.jsApiData.signType, //微信签名方式:            paySign: result.jsApiData.sign, //微信签名          },          function (res) {            if (res.err_msg == "get_brand_wcpay_request:ok") {              // 使用以上方式判断前端返回,微信团队郑重提示:              //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。            }          }        );        this.getPayResult(result.orderId);      });    },

5、循环查询订单是否完成

// 循环查询订单是否完成    async getPayResult(orderId) {      const data = await getResult({ orderId: orderId });      if (data == "poll") {        //2秒轮询        this.timerPay = setTimeout(() => {          this.getPayResult(orderId);        }, 2000);      } else {        if (data == "success") {          this.$router.push({            name: "oldRecharge",            query: {              orderId: orderId,            },          });        }      }

二、h5支付

1、调后端接口拿h5跳转链接,

1)如果是支付宝,定义returnUrl为重定向通知链接

2)如果是微信,在后面拼接&redirect_url= 为重定向通知链接(需要带上订单编号,因为支付宝重定向链接会自动带上订单编号,但是微信不会带上订单编号)

hanldType(n, flag) {      // h5支付      const obj = {        amount: 1,        rtype: n,        productId: this.activeItem.id,        price: this.activeItem.price,        totalPrice: this.activeItem.price * 1,        buyTime: this.activeItem.buyTime,      };      if (flag) { // 带flag代表支付宝        obj.returnUrl = location.origin + "/#/public/oldRecharge"      }      userPayType(obj).then((res) => {        const weiXinRedirectUrl=encodeURIComponent(location.origin + "/#/public/oldRecharge?charset=UTF-8&out_trade_no="+res.orderId)        window.location.href=flag?res.redirectUrl:res.redirectUrl+'&redirect_url='+weiXinRedirectUrl        this.show = false;        this.getPayResult(res.orderId);      });    },

2、跳转回来的时候查询链接上是否有‘out_trade_no’,并查询结果

if (location.href.includes("out_trade_no") && !sessionStorage.getItem('isSearchDingDan')) {      sessionStorage.setItem('isSearchDingDan',true);      this.getPayResult(this.getUrlParam("out_trade_no"));    }

 

// 循环查询订单是否完成    async getPayResult(orderId) {      const data = await getResult({ orderId });      if (data == "poll") {        //2秒轮询        this.timerPay = setTimeout(() => {          this.getPayResult(orderId);        }, 2000);      } else {        if (data == "success") {          // this.$toast({ msg: "恭喜您支付成功!", type: "success" ,time: 3000});          this.showMiddle=true;          setTimeout(() => {            this.showMiddle=false;            history.pushState({},'','/#/public/oldRecharge');            sessionStorage.removeItem('isSearchDingDan')          }, 3000);        }      }    },

完整代码

1、主页面oldRecharge页面

<template>  <div class="recharge-index">    <Header />    <van-swipe :autoplay="3000" lazy-render class="my-swipe">      <van-swipe-item v-for="image in images" :key="image">        <img :src="image" />      </van-swipe-item>    </van-swipe>    <ul class="recharge-list clearfix">      <li        v-for="(item, index) in list"        :key="index"        @click="handleChecked(index, item)"        :class="{ active: activeIndex == index }"      >        <div class="useableTime">          {{            item.name.split("-")[0].indexOf("缤纷夏日活动") != -1              ? item.buyTime / (3600 * 1000) + "小时"              : item.name + "小时"          }}        </div>        <div class="unitMoney">          约<span>{{ (item.price / (item.buyTime / (3600 * 1000))).toFixed(2) }}</span          >元/小时        </div>        <div class="payMoney">          优惠价:{{ item.price }}<span>¥{{ item.originPrice }}</span>        </div>      </li>    </ul>    <div class="rechargeRule">      <p>温馨提示</p>      <span>1.所有充值的套餐时长均为可暂停且永久有效的。</span>      <span>2.公众号套餐与PC客户端及官网保持一致,该页面充值后时</span>      <span>  长即刻到账,在公众号及客户端可查看时长余额等。</span>    </div>    <p class="rechargeRead">      <span @click="checkBoolen = !checkBoolen"        ><img          :src="            checkBoolen ? require('./images/icon6.png') : require('./images/icon5.png')          "        />阅读并同意</span      ><label @click="hanldGoRouter">《服务条款》</label>    </p>    <div class="rechargeFooter">      <p>        金额:<label>¥</label><span>{{ activeItem.price }}</span>      </p>      <div @click="handleBuy()">支付</div>    </div>    <Service />    <van-popup class="popup-style" v-model="show" overlay-class="pay" position="bottom">      <h3>确认订单</h3>      <p>        充值时长:<span>{{ activeItem.buyTime/(3600*1000) + "小时" }}</span>      </p>      <p>        应付金额:<span>¥{{ activeItem.price }}</span>      </p>      <div class="payDivBox">        <div @click="handleWeXinOrAliPay('alipay', 1)" v-if="showAliPay">          <img src="./images/icon09.png" alt="" />          <div>支付宝支付</div>        </div>        <div @click="handleWeXinOrAliPay('weixin', 2)">          <img src="./images/icon10.png" alt="" />          <div>微信支付</div>        </div>      </div>    </van-popup>    <div class="dialogVisual" v-show="showMiddle">      <div class="maskLayer"></div>      <div class="dialogContent">        <img src="./images/xiaoyan.png" />        <p>充值成功!</p>      </div>    </div>  </div></template> <script>import Header from "./components/header";import { Swipe, SwipeItem } from "vant";import { rechargeList, userPayType, getResult } from "@/api/user";import Service from "./components/fwtk.vue";import Vue from "vue";import { Popup } from "vant";Vue.use(Popup);Vue.use(Swipe);Vue.use(SwipeItem);export default {  components: {    Header,    Service,  },  data() {    return {      list: [],      myswiper: null,      listIndex: {},      show: false,      images: [require("./images/banner.png")],      checkBoolen: false,      activeIndex: 0,      loading: false,      activeItem: {},      showAliPay: false,      showMiddle:false    };  },  computed: {    logoShow() {      return this.$store.state.logoShow;    },    userInfo() {      return this.$store.state.userInfo;    },  },  mounted() {    this.isWeiXin();    if (this.$route.query.orderId) {      this.show = false;      this.$toast({ msg: "恭喜您支付成功!", type: "success" });    }    this.getList();    if (location.href.includes("out_trade_no") && !sessionStorage.getItem('isSearchDingDan')) {      sessionStorage.setItem('isSearchDingDan',true);      this.getPayResult(this.getUrlParam("out_trade_no"));    }  },  methods: {    async getList() {      const data = await rechargeList();      if (!data) {        return;      }      this.list = data.list;      this.activeItem = this.list[0] || {};      this.loading = false;    },    // 循环查询订单是否完成    async getPayResult(orderId) {      const data = await getResult({ orderId });      if (data == "poll") {        //2秒轮询        this.timerPay = setTimeout(() => {          this.getPayResult(orderId);        }, 2000);      } else {        if (data == "success") {          // this.$toast({ msg: "恭喜您支付成功!", type: "success" ,time: 3000});          this.showMiddle=true;          setTimeout(() => {            this.showMiddle=false;            history.pushState({},'','/#/public/oldRecharge'); // 不刷新页面把url截取            sessionStorage.removeItem('isSearchDingDan')          }, 3000);        }      }    },    isWeiXin() {      var ua = window.navigator.userAgent.toLowerCase();      if (ua.match(/MicroMessenger/i) == "micromessenger") {        this.showAliPay = false;        return true;      } else {        this.showAliPay = true;        return false;      }    },    handleBuy(n) {      if(!this.checkBoolen){        this.$toast({ msg: "请阅读并同意<p><<服务条款>></p>", type: "warning"});        return      }      const token = localStorage.getItem("token");      if (token && this.userInfo) {        this.show = true;      } else {        this.$store.dispatch("setLogoShow", true);      }    },    hanldGoRouter() {      this.$store.commit("setXieyiShowModal", true);    },    handleWeXinOrAliPay(typeName, n) {      if (typeName === "weixin") {        // 微信支付        if (this.isWeiXin()) {          // // 微信内jsApi支付          localStorage.setItem("productInfo", JSON.stringify(this.activeItem));          this.$router.push("/public/rechargeRedirect");        } else {          // 微信外h5支付          this.hanldType(n);        }      } else {        // 支付宝h5支付        this.hanldType(n, true);      }    },    getUrlParam(name) {      var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");      var r = (window.location.search||window.location.hash).substr(1).match(reg);      if (r != null) return unescape(r[2]);      return null;    },    hanldType(n, flag) {      // h5支付      const obj = {        amount: 1,        rtype: n,        productId: this.activeItem.id,        price: this.activeItem.price,        totalPrice: this.activeItem.price * 1,        buyTime: this.activeItem.buyTime,      };      if (flag) {        obj.returnUrl = location.origin + "/#/public/oldRecharge"      }      userPayType(obj).then((res) => {        const weiXinRedirectUrl=encodeURIComponent(location.origin + "/#/public/oldRecharge?charset=UTF-8&out_trade_no="+res.orderId)        window.location.href=flag?res.redirectUrl:res.redirectUrl+'&redirect_url='+weiXinRedirectUrl        this.show = false;        this.getPayResult(res.orderId);      });    },    handleChecked(index, item) {      this.activeIndex = index;      this.activeItem = item;    },  },};</script> <style scoped lang="less">... </style>

2、重定向页面

<template>  <div>    <img src="../images/xiaoyan2.png"/>    <p>加载中,请稍后...</p>  </div></template> <script>import { userPayType, getResult } from "@/api/user";import axios from "axios"; export default {  data() {    return {      redirect: "",      timerPay: null,    };  },  mounted() {    const localOpenId = localStorage.getItem("wexin-openid-wxc951e84c27099161");    if (localOpenId) {      this.handleType(localOpenId);      return;    }    var appid = "wxc951e84c27099161"; //个人公众号appid    var appsecret = "778ef263f6e1d648d50daa1c5147884b";    var mpPrefix = "wexin-openid-";    this.redirect = encodeURIComponent(window.location.href); //重定向回来的地址    // 判断是否是ios微信浏览器    var wx_code = this.getUrlParam("code"); // 截取url中的code    //获取code的地址。获取成功重定向后地址栏中将会带有code,判断没有code的话,就跳转到微信官方链接上获取,获取成功后会再重定向回来,注意url是需要使用encodeURIComponent处理一下编码的    if (!wx_code) {      // scope: 必传;应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )      // 静默授权      window.location.href =        "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +        appid +        "&redirect_uri=" +        this.redirect +        "&response_type=code&scope=snsapi_base&state=123#wechat_redirect";    } else {      // 获取到了code,找后端拿openid      axios        .post(          `http://api.test.chiyanjiasu.com/wx/mp/openId?appid=${appid}&appsecret=${appsecret}&code=${wx_code}`        )        .then((res) => {          // data是形参名,代表返回的数据          if (res.errcode) {            alert(res.errmsg);            return;          }          localStorage.setItem(mpPrefix + appid, res.data.openid);          this.handleType(res.data.openid);        })        .catch((error) => {          console.log("error", error);        });    }  },  destroyed() {    clearTimeout(this.timerPay)  },  methods: {    getUrlParam: function (name) {      var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");      var r = window.location.search.substr(1).match(reg);      if (r != null) return unescape(r[2]);      return null;    },    isWeChat() {      let ua = window.navigator.userAgent.toLowerCase();      return ua.match(/MicroMessenger/i) == "micromessenger"; // 判定为true则是微信浏览器,false则不是    },    handleType(openId) {      const info = JSON.parse(localStorage.getItem("productInfo"));      const obj = {        amount: 1,        rtype: 2,        productId: info.id,        price: info.price,        totalPrice: info.price * 1,        buyTime: info.buyTime,        openId,        jsApi: 1,      };      userPayType(obj).then((result) => {        window.WeixinJSBridge.invoke(          "getBrandWCPayRequest",          {            appId: result.jsApiData.appId, //公众号ID,由商户传入            timeStamp: result.jsApiData.timeStamp, //时间戳,自1970年以来的秒数            nonceStr: result.jsApiData.nonceStr, //随机串            package: result.jsApiData.package,            signType: result.jsApiData.signType, //微信签名方式:            paySign: result.jsApiData.sign, //微信签名          },          function (res) {            if (res.err_msg == "get_brand_wcpay_request:ok") {              // 使用以上方式判断前端返回,微信团队郑重提示:              //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。            }          }        );        this.getPayResult(result.orderId);      });    },    // 循环查询订单是否完成    async getPayResult(orderId) {      const data = await getResult({ orderId: orderId });      if (data == "poll") {        //2秒轮询        this.timerPay = setTimeout(() => {          this.getPayResult(orderId);        }, 2000);      } else {        if (data == "success") {          this.$router.push({            name: "oldRecharge",            query: {              orderId: orderId,            },          });        }      }    },  },};</script>

本文转载于:https://juejin.cn/post/7550619805817913379

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]