• 起因:使用react+react-router做了一个单页面应用,需接入微信支付与分享等功能。由于是个人第一次接触微信接入加之是单页面应用所以遇到了很多问题。所以这里记一下其中之一:分享功能!微信官方说法:所有需要使用...

    起因:使用react+react-router做了一个单页面应用,需接入微信支付与分享等功能。由于是个人第一次接触微信接入加之是单页面应用所以遇到了很多问题。所以这里记一下其中之一:分享功能!

    微信官方说法:

    所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。

    问题:

    我根据这段话的意思每当URL地址变化我就调用了一次wx.config,于是就出现了以下几种状况:
    1:安卓微信6.2.7版
    无法成功分享

    2:安卓微信6.5.7版
    每次都能成功分享

    3:iOS版微信
    无法成功分享

    解决办法:

    1:安卓微信6.2.7版
    将第一次进入页面的地址保存,之后每次页面改变(即URL变化),就调用一次config。url使用第一次进入页面的URL

    2:安卓微信6.5.7版
    每次URL变化都调用config,但是URL使用当前url

    3:iOS版微信
    只需要进入第一个页面之后调用一次

    原因:

    安卓微信由于版本问题不支持pushState的问题已在6.3.31修复了,所以只需要根据系统和微信版本做出相应的分享操作就行了。

    这里给出两个方法用于判断:
    是否为安卓客户端

    function isAndroid() {
        var u = window.navigator.userAgent;
        return u.indexOf('Android') > -1 || u.indexOf('Linux') > -1;
    }

    微信版本是否大于6.3.31

    function weixinVersion() {
        var str = window.navigator.userAgent;
        var v0 = [6,3,31];
        var regExp = /MicroMessenger\/([\d|\.]+)/;
        if (regExp.exec(str)===null) {return}
        var v1 = regExp.exec(str)[1].split('.');
        if (v1.length >= 4) {
            v1 = v1.slice(0,3);
        }
        v1 = v1.map(function(v){
            return parseInt(v, 10);
        });
        if (v1[0] > v0[0]) {
            return true;
        }
        if (v1[0] === v0[0] && v1[1] > v0[1]) {
            return true;
        }
        if (v1[0] === v0[0] && v1[1] === v0[1] && v1[2] >= v0[2]) {
            return true;
        }
        return false;
    }

    差不多讲完了,如果有没说清楚的地方,可以留言,希望能少让人掉坑里吧。
    下一篇会讲以下微信接入支付遇到的坑。

    展开全文
  • 最近一年开发的项目都是微信公众号相关的,遇到了很多坑,没有发现一个相对来说完整的文档,因此自己记录一下,欢迎大家补充。 获取用户的唯一标识  在用户与公众号产生消息交互后,公众号可获得用户的openid...

    最近一年开发的项目都是微信公众号相关的,遇到了很多坑,没有发现一个相对来说完整的文档,因此自己记录一下,欢迎大家补充。

    获取用户的唯一标识

        在用户与公众号产生消息交互后,公众号可获得用户的openid(加密后的微信号,每个用户对每个公众号的openid是唯一的,不同公众号,同一用户的openid不同)

        如果开发者想要把多个公众号、移动应用、小程序之前做账号的统一,则需要UnionID机制

        不管是获取openid还是unionid,前端和微信的交互流程都是一样的, 前端就直接在router.beforeEach中去判断就可以

          

    1. 静默授权

           即用户无需关注 ,无需手动点击授权进入页面自动跳转到回调页,即可拿到用户的openid,用户的感知就是直接进入了回调页,scope 为 snsapi_base

    2. 用户手动授权

         获取openid是需要用户手动授权方可获取,拿到openid可以换取unionid,scope为snsapi_userinfo

         注意:对于已关注公众号的用户,如果用户从公众号的会话或者自定义菜单进入本公众号的网页授权页,即使是scope为snsapi_userinfo,也是静默授权,用户无感知

     // appid 公众号的appid
     // redirect_uri 指的是在微信公众号后台 公众号设置-网页授权域名的回调中配置的
     // url 后端获取到openid后, 需要重定向到前端的url地址,如果地址是hash模式,则"#"需要用特殊字符代替,后端拼接后回跳
    // scope snsapi_base为静默授权,即用户进入接口拿到openid   snsapi_userinfo需要用户手动授权才可以,不仅可以拿到openid,可以拿到用户的Unionid
     window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirect_uri}&response_type=code&scope=snsapi_base&state=${url}#/wechat_redirect`

    前端获取openid的方法:

    1. 将openid作为参数拼接到重定向的url中,尽管前端可以拿到,但是也有一定的问题

             弊端:但是url中拼接用户的openid有一个弊端,就是当用户把带openid的链接分享给别人,当别人进来是不会重新获取的           openid的

            解决办法:在带有openid的页面,隐藏微信的分享和复制链接的功能,但是如果用户有企业微信,依旧可以拿到该链接

        2. 将openid作为参数拼接到重定向的url中,尽管前端可以拿到,但是也有一定的问题

             后端获取到openid后直接打在cookie,然后重定向

            前提:前后端需要同一个域或者是有同一个父域,前后端需要约定好openid的字段名

    jssdk功能

          分享:如果需要每个页面都需要分享自定义的图片和标题,则需要每次都调用wx.config注入一下该页面的配置信息

          其他jssdk功能:需要在wx.config中注册

          

         

     

     

     

     

    展开全文
  • 最近接手了一个vue单页面应用的售票商城,就不可避免的要用到支付,主要讲下微信支付做的过程中遇到的哪些坑。 首先微信支付分为2部分。一个是在微信环境下的支付可以直接调用微信方法。一个是微信浏览器外的H5支付...

    最近接手了一个vue单页面应用的售票商城,就不可避免的要用到支付,主要讲下微信支付做的过程中遇到的哪些坑。

    首先微信支付分为2部分。一个是在微信环境下的支付可以直接调用微信方法。一个是微信浏览器外的H5支付。

    第一步,到支付页时判断用户当前的环境是否在微信浏览器下(用户在商品下单跳到支付页时,在支付页组件created或mounted生命周期里判断)

    let ua = navigator.userAgent.toLowerCase()
    if (ua.match(/MicroMessenger/i) == 'micromessenger') {}
    

    这2段代码就是用来判断微信环境的。
    这2段代码也可以在用户点击的时候判断。我放在生命周期这里的原因是需要判断支付宝在微信环境中不能使用
    所有业务需要,先在生命周期里判断,然后渲染dom。

    第二步,区分环境之后,先说微信浏览器的支付。
    调用微信WeixinJSBridge内置对象,详细可看微信官方文档https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6

      Pay (data) {
          let vm = this
          if (typeof WeixinJSBridge === 'undefined') {
            if (document.addEventListener) {
              document.addEventListener('WeixinJSBridgeReady', vm.onBridgeReady(data), false)
            } else if (document.attachEvent) {
              document.attachEvent('WeixinJSBridgeReady', vm.onBridgeReady(data))
              document.attachEvent('onWeixinJSBridgeReady', vm.onBridgeReady(data))
            }
          } else {
            vm.onBridgeReady(data)
          }
        },
        onBridgeReady (data) {
          let self = this
          WeixinJSBridge.invoke(
            'getBrandWCPayRequest', {
              'appId': data.appId,
              'timeStamp': String(data.timeStamp),    //这里必须要转换为字符串。ios跟android表现不同。后台返回的是数值,但是微信方面必须要json参数都是字符串形式,android会自动转换成字符串(当时我在这里也找了很久的博文才知道的)
              'nonceStr': data.nonceStr,
              'package': data.package,
              'signType': data.signType,
              'paySign': data.paySign
            },
            function (res) {
              if (res.err_msg === 'get_brand_wcpay_request:ok') {
                self.$router.replace({name: 'paymentend'})
              } else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
                self.$vux.toast.text('支付取消!', 'default')
              } else {
                self.$vux.toast.text('支付失败!', 'default')
              }
            }
          )
        }
    

    这个2个方法是调起支付。再调起之前需要做2件事。
    首先你需要获取用户微信授权,获得openId,当然这个过程是后台处理的。前端需要获得到code传递给后台然后返回openId给你。

    if (!this.GetQueryString('code')) {
      this.$vux.toast.text('微信授权中……', 'default')
      let currentUrl = encodeURIComponent(window.location.href)
      window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx70fed7a16aebcd2e&redirect_uri=' + currentUrl + '&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect'
    } else {
      this.code = this.GetQueryString('code')
      // localStorage.setItem('user_code', this.code)
      this.getWeixinOpenID({
        code: this.code
      })
    }
    
    GetQueryString (name) {
          let url = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
          let newUrl = window.location.search.substr(1).match(url)
          if (newUrl != null) {
            return unescape(newUrl[2])
          } else {
            return false
          }
        }
    

    直接上代码。GetQueryString 这个方法是截取当前url上参数值(比如&code=123, GetQueryString (code)获得123)

    那么什么时候获取这个code呢。我个人一开始是在支付页的时候授权获得code,后来因为业务需要。在用户登录之后进入路由跳中间页微信授权登录

    router.beforeEach((to, from, next) => {
      if (checkLogined()) {
        let ua = navigator.userAgent.toLowerCase()
        let userinfos = JSON.parse(localStorage.getItem('jwt'))
        if (ua.match(/MicroMessenger/i) == 'micromessenger') {
          if (!userinfos.openId && to.path !== '/login' && to.path !== '/author') {
            localStorage.setItem('beforeLoginUrl', to.fullPath)
            next({path: '/author'})
            return false
          }
        }
      }
      if (to.meta.checkLogin) {
        if (checkLogined()) {
          next()
        } else {
          Vue.$vux.toast.text('您还没未登录', 'default')
          next({path: '/login', query: {Rurl: from.fullPath}})
        }
      } else {
        next()
      }
    })
    

    localStorage.setItem(‘beforeLoginUrl’, to.fullPath) 这个段主要保存登录之后前往的路由地址。当授权成功之后再接口跳转到这个路由下

          [GETWEIXINOPENID_SUCCESS] (state, openId) {
            state.openId = openId
            let userinfos = JSON.parse(localStorage.getItem('jwt'))
            userinfos.openId = openId
            localStorage.setItem('jwt', JSON.stringify(userinfos))
            router.push(localStorage.getItem('beforeLoginUrl'))
            localStorage.removeItem('beforeLoginUrl')
          }
    

    我的接口都是写在vuex上的。这里获得的openId必须存到本地用户数据里。因为如果用户有授权过。登录之后有带openID的数据的。没有授权过的用户是没有的。
    这样下次路由跳转的时候就不会再进行授权了

    好了到了这里可以说成功了一半。接下来是支付提交,支付提交之前你需要获得微信签名,

        let ua = navigator.userAgent.toLowerCase()
        let orderId = JSON.parse(localStorage.getItem('orderId')).orderId
        if (ua.match(/MicroMessenger/i) == 'micromessenger') {
          this.weixinFlog = false
          let u = navigator.userAgent
          let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
          if (isiOS) {
            if (sessionStorage.getItem('flag')) {
              sessionStorage.removeItem('flag')
            } else {
              sessionStorage.setItem('flag', true)
              location.reload()
            }
          }
          this.$nextTick(() => {
            this.weixinjspay({
              orderId: orderId,
              openId: this.userinfos.openId
            })
          })
        }
    

    直接在下单之后的支付页生命周期里调用接口获得签名数据,这里你需要对ios特别处理一下。 因为ios跟Android表现不同
    https://blog.csdn.net/sky_beyond/article/details/54312433 具体哪里不同可以参考这里。我的处理方法是ios进入支付页时刷新一次。这里的处理方法我看到的有2种,一种是我这样的,另一种是#前加?,查了一些资料说#前加?的不太友好而且具体操作相关的没有找到。我就采取了刷新的方法。对用户而言没影响,感受不出来。,这样处理之后安卓跟ios的支付安全域名一样了。

    到这里差不多就结束了,点击支付的时候调用pay方法,传入获得的签名参数就可以了。支付回调相信你们都明白的这里就不提了。如果有报什么错误。在回调里打alert(JSON.stringify(res))会弹出具体报错信息。报错信息处理可以到官方文档查阅。

    然后微信浏览器外的h5支付。这里另外抱怨一下,我当初做的时候,因为接口有问题,找了很久的资料查没有成功的问题原因。结果是接口有问题。所以有时候多跟后台沟通很重要。(PS:这个项目因为是私活,所以沟通比较困难,一度奔溃)。

    其实h5支付很简单。前端不需要做太多事情。

    let url = '&redirect_url='+encodeURIComponent('http://wap.singlook.net/#/home/rushbuy/payment/paymentend')
    window.location.href = data.mweb_url + url
    

    这里直接贴上代码。 通过后台接口,后台会传回来一个mweb_url的地址你直接跳转就可以唤起微信并支付
    https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4具体看开发文档。我就不把文档里的摘出来了。

    这2段代码 第一段是我的回调地址。支付成功或取消支付都会回跳这个地址。
    这里回报2个常见错误。

    一个是网络环境未能通过安全验证,请稍后再试,这个错误找后台就行了。后台处理,要么后台的代码问题要么是服务器代理问题。
    第二个是商家参数格式有误,请联系商家解决,
    这个问题是我最头疼的。官方文档的解释是:

    1. 当前调起H5支付的referer为空导致,一般是因为直接访问页面调起H5支付,请按正常流程进行页面跳转后发起支付,或自行抓包确认referer值是否为空

    2. 如果是APP里调起H5支付,需要在webview中手动设置referer,如(
      Map extraHeaders = new HashMap();
      extraHeaders.put(“Referer”, “商户申请H5时提交的授权域名”);//例如 http://www.baidu.com ))

    因为我是手机浏览器里打开的网页,所以就看问题1,referer为空导致。当时真的是翻遍了所有的资料都没找出问题所在。最后是项目带头人在我的index.html上看到了这么一句, 我当时就是一张黑人问号脸。我什么时候写过这一句代码? 一直也没往这方面想,所以一直想不通为什么整个项目路由都没带上referer,本以为单页面应用的原因。所以大家如果碰到这个问题。首先先看下index.html上是否带有这句话,我深刻怀疑是脚手架vue-cli下过来的时候自带上的!!!!

    展开全文
  • 最近在开发的时候遇到了一个微信分享的bug,就是无论你在哪个路径下的页面,发送给朋友后点开都只会跳到项目的首页。本来微信分享这个只算是一个小功能,也很好解决,但由于项目的特殊性,使得在这个bug解决起来并...

    前言

    最近在开发的时候遇到了一个微信分享的bug,就是无论你在哪个路径下的页面,发送给朋友后点开都只会跳到项目的首页。本来微信分享这个只算是一个小功能,也很好解决,但由于项目的特殊性,使得在这个bug解决起来并没有那么顺手,所以记录一下备以后翻阅。

    坑点

    • Vue单页面应用,前端通过Hash控制路由——iOS在微信中不能正常地改变浏览器的hash值,分享出去的页面地址被莫名其妙地添加了参数。

    • 微信的安全策略——由于存在js安全域名限制,使得在本地调试更难。

    • jssdk配置签名。

    跳坑方法

    分享地址被奇怪的被带上了参数

    在传统开发中,路由通常都是在后端完成的,但是在Vue单页面中,都是通过控制history interface来控制页面之间的跳转,在我们的项目中我们使用hash的方式,但是在分享给朋友后却发现分享地址被加上了一些参数,比如:

    我分享出去的地址是:market.lenkuntang.cn/#/home,分享后会变成了market.lenkuntang.cn/?from=singlemessage#/home。这到底会不会影响到我们的分享操作呢?这就要了解vue-router的工作原理了,翻看了一下vue-router的源码,发现如下代码:

    // this is delayed until the app mounts
      // to avoid the hashchange listener being fired too early
      setupListeners () {
        const router = this.router
        const expectScroll = router.options.scrollBehavior
        const supportsScroll = supportsPushState && expectScroll
    
        if (supportsScroll) {
          setupScroll()
        }
    
        window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {
          const current = this.current
          if (!ensureSlash()) {
            return
          }
          this.transitionTo(getHash(), route => {
            if (supportsScroll) {
              handleScroll(this.router, route, current, true)
            }
            if (!supportsPushState) {
              replaceHash(route.fullPath)
            }
          })
        })
      }
    复制代码

    hash.js

    原来在vue-router初始化的时候,会监听window对象的hashchange属性,如想发现浏览器的hash值发生变化了,就会调用History.transitionTo方法,关键就在这个方法会传入一个getHash方法为作参数,如果在这种地址market.lenkuntang.cn/?from=singlemessage#/home也能正确地拿到正确的hash的话,那我们就可以断定这种意外对我们的分享是没有影响的。当我们继续去看getHash方法,在hash.js往下翻点会找到这个方法的实现:

    export function getHash (): string {
      // We can't use window.location.hash here because it's not
      // consistent across browsers - Firefox will pre-decode it!
      const href = window.location.href
      const index = href.indexOf('#')
      return index === -1 ? '' : href.slice(index + 1)
    }
    复制代码

    我们可以清楚地知道,当这条地址market.lenkuntang.cn/?from=singlemessage#/home经过getHash之后会直接返回#号后面的字符串,也就是 /home,所以可以得出是不会对我们分享的功能有影响的。

    iOS在微信环境中浏览器地址不变

    在Vue-router实现前端控制路由都是通过HTML5 新增的History Interface接口来控制页面之间的跳转的,在跳转的同时通过修改windowloactionhash属性反映回浏览器的地址,但是当遇到iOS时却意外地发现这个hash属性一直没有被改变,导致每次分享出去的地址都是首页,在网上一查发现这原来是个通病,解决的方法就是引入微信的JsSDK来手动控制分享的地址。

    引入JsSDK所带来的问题

    在引入了JsSDK后,首先要对它进行配置,相关配置项如下:

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名
        jsApiList: [] // 必填,需要使用的JS接口列表
    });
    复制代码

    说明一下这里的参数分别从哪里来,appId是从微信公众号里获取的,timestampnonceStr还有signature是从服务器中返回的。jsApiList可以在所有JS接口列表中找到。

    注:timestampnonceStr其实是可以在前端生成然后传给服务器再参与签名的计算的,但一般在考虑到安全原因,timestamp, nonceStr这些参数应该从服务器返回回来(因为它参与了签名的计算)。

    注意:这里的传入的随机字符串字段nonceStr驼峰命名!!!

    然后就是引入JsSDK中遇到最大的问题——签名问题,要正确地实现使用JsSDK,在服务器端首先要集齐这四种元素:

    • noncestr(随机字符串)
    • jsapi_ticket(通过微信接口获得的ticket)
    • timestamp(时间戳)
    • url(当前网页的URL,不包含#及其后面部分)

    然后把这些元素按字典序(ASCII 码从小到大排序)排后使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串,再对字符串进行sha1加密,字段名和字段值都采用原始值,不进行URL 转义,即可得到所谓的签名。

    注意:这里的传入的随机字符串字段noncestr全小写!!!

    最后附上签名检验工具的地址:mp.weixin.qq.com/debug/cgi-b…

    还有示例代码:demo.open.weixin.qq.com/jssdk/sampl…

    得到签名后再把timestampnonceStrsignature传回给前端进行JsSDK的初始化配置。

    再说计算签名的URL

    这里再说说参与签名的url,因为这里传过去的是当前见面的URL且不包括#及其后面部分,这对于使用Hash模式的单页面应用来说是个好消息,这样就代表我们只需要在页面加载时初始化一次后便可以在所有页面上使用(对于传统的路径导航,因为URL变了所以要重新初始化,也就是说要在使用到的JsSDK功能的页面中都要重新请求后台接口拿签名再初始化!!)。所以,一般来说我们通常会在App.vue这个文件中作JsSDK的初始化操作,当初始化正确后便可在其它页面上直接使用JsSDK接口的功能。

    次外,由于微信存在对JsSDK的使用限定在微信公众号里所设置的JS接口安全域名范围里,所以对于本地调度用的localhost域名来说是不可行的,直接提示invalid url domain,在这里有两种方式可以解决这个问题,一种是通过修改host的方法来实现本地调试,方法如下:

    window系统:

    进入系统盘目录(通常是C盘): C:\Windows\System32\drivers\etc,找到hosts文件,打开后文件末尾添加一条记录127.0.0.1 market.lenkuntang.cn,这条记录的意思是当你访问market.lenkuntang.cn这个地址的时候会重定向到127.0.0.1这个ip地址,从而实现本地调试的目的。

    mac系统

    打开一个finder,然后按快捷键command+shift+G,输入private/etc/hosts回车后就能找到对应的hosts文件,由于是权限问题,是无法直接在那个目录中修改hosts文件的,所以要把文件复制到桌面或者其它有修改权限的目录,然后打开后也是类似window一样在文件末尾添加一条记录127.0.0.1 market.lenkuntang.cn,保存后拖回原目录确定覆盖。

    另一种是使用腾讯云的开发者实验室的在线Web IDE来登录到测试服务器,然后直接在服务器上进行修改,线上验证。但是由于这个Web IDE目前不支持SSH密钥方式登录,只能用账号和密码的方式登录。所以也是有一定的局限性的。

    附上Web IDE工具地址:cloud.tencent.com/developer/l…

    点击其中一个教程,然后选择开始上机下方的使用已有云主机标签,在弹出的登录界面中正确填写你服务器的IP地址和账号密码便可直接登入服务器内进行相关操作。

    • 登录界面

    • 登录成功后的界面

    使用微信开发者工具来本地调试

    当我们配置好了所有东西后,打开浏览器我们可以在控制台的输出中看到JsSDK的相关信息,但是我们却不知道是否可以正确分享,难道我们每次都要使用手机来访问本地服务来验证吗?而且在使用手机来访问本地服务的时候,使用的是本地电脑的ip地址,这样去拿到签名肯定是不对,会报invalid url domain错误,当然也可以改手机的hosts,但是这就不是那么容易改了,安卓的话要root,苹果的话...算了算了。还是换种方法,这个时候我们应该使用微信开发者工具来进行调试,微信开发者工具可以模拟微信环境,可以进行微信想着的操作,所以使用这个工具我们就可以愉快地在本地进行调试啦。

    而且,在遇到需要微信登录的页面时,如何是用普通的浏览器来打开就会跳到微信的授权登录页,而用开发者工具来打开则会像手机一样弹出授权页:

    • 普通浏览器打开

    • 微信开发者工具

    总结

    通过这几天对微信分享的研究,总体对微信的JsSDK的使用有了大概的认识和了解,虽然其中也遇到不少的坑和麻烦的地方,但是既然问题出现就只能尽量地去简化问题再解决它。

    展开全文
  • 在实际开发中,无论是做PC端、WebApp端还是微信公众号等类型的项目的时候,或多或少都会涉及到微信相关的开发,最近公司项目要求实现微信网页授权,并获取微信用户基本信息的功能及微信分享的功能,现在总算完成了,...

    在实际开发中,无论是做PC端、WebApp端还是微信公众号等类型的项目的时候,或多或少都会涉及到微信相关的开发,最近公司项目要求实现微信网页授权,并获取微信用户基本信息的功能及微信分享的功能,现在总算完成了,但开发过程中遇到好几个坑。废话不多说了,开始正题。

    描述点

    1. 微信相关开发知识了解
    2. 怎么样实现微信相关功能本地测试
    3. 微信网页授权
    4. 微信分享

    微信相关开发知识了解

    1. 微信公众号的appId,AppSecret
      1. 当我们注册一个微信公众号后,便能够得到一个appId(每个微信公众号只有一个,一个微信公众号唯一的标识)和appSecret(可以进行重置),这两个信息是进行微信公众号开发必不可少的,因为微信公众号中几乎所有功能的开发都与这两个信息相关。
    2. 微信公众号中IP白名单
      1. 在开发微信公众功能的时候,需要我们添加IP白名单,这样以便能够获取到access_token,关于access_token的介绍请看这里https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183
    3. 网页授权域名以及JS接口安全域名
      1. 网页授权域名:在我们的应用中需要微信用户进行登录、获取微信用户基本信息的时候,需要设置这个域名
      2. JS接口安全域名:在我们的应用中需要实现微信分享等功能,需要设置这个域名。

    怎么样实现微信相关功能本地测试

    相对很多人都对这个问题比较感兴趣,因为在进行涉及到微信公众号中功能开发的时候,默认情况下我们是不能进行本地测试的,也就是说测试都需要将代码进行部署才测试,但这非常不利于我们的测试开发,其实进行本地测试开发很简单,只需要我们有一个域名就可以了,然后将我们本地的ip映射到这个域名上,就可以本地测试了。下面我就说说我是怎么做本地测试的.

    因为购买域名需要进行备案操作之类的,比较麻烦,所以一般第三方平台就可以让我们得到一个域名。我是在natpp(ngrok)这个网站上注册的https://natapp.cn/

    我是花了五元钱购买了一个月的隧道,因为免费的不怎么靠谱,毕竟是免费的,哈哈。

     

    注意,我们不能直接使用这个隧道,因为这个隧道是三级域名,无法用于微信开发,需要绑定一个二级域名或自主域名

    当绑定完域名之后,在本地我们需要将本地ip进行映射穿透操作。

    windows下打开dos窗口,输入 natapp -authtoken 你的隧道的authtoken

     

    将你在上面设置的二级域名添加到上述说的网页授权域名以及JS接口安全域名

     

    接下来便可以进行本地测试了.最后说一下,开发过程中下载微信开发工具进行调试也是不错的选择,下载地址https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455784140

    微信网页授权

    微信网页授权的目的主要是实现三方站点微信的登录、获取微信用户信息等

    实现微信网页授权获取微信用户的基本信息

    先判断当前浏览器是不是微信内置浏览器,微信网页授权api: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

    isweixin() {
    
       const ua = window.navigator.userAgent.toLowerCase();
    
       if(ua.match(/MicroMessenger/i) == 'micromessenger'){
    
         return true;
    
       } else {
    
         return false;
    
       }
    
     },

    1 第一步:用户同意授权,获取code

    2 第二步:通过code换取网页授权access_token

    3 第三步:刷新access_token(如果需要)

    4 第四步:拉取用户信息(需scope为 snsapi_userinfo)

    5 附:检验授权凭证(access_token)是否有效

    微信API里面关于这些都介绍得比较清楚的,我就说说在这个过程中我所遇到的问题,以及解决办法

    在第一步获取code的时候,因为这个code在五分钟之内只能够使用一次,所以必须对这个code进行缓存起来。否则会出现"errcode":40163,"errmsg":"code been used, hints: [ req_id: nOCEBa0466th12 ]"或{"errcode":40029,"errmsg":"invalid code"} 错误。

    微信分享

    微信分享其实用得非常得多,我就简单说下在vue-cli中怎么引入微信分享的sdk,以及怎么样实现分享功能.

    微信分享APi: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

    首先引入sdk:

    npm install weixin-js-sdk --save-dev

    然后通过require或者import引入

     

    import wx from 'weixin-js-sdk';

    微信分享中最重要的是获取到签名,才能够实现微信的分享

    再根据当前的url去获取到所需要的参数来完成签名的验证,参数主要用appId、nonceStr、timestamp、signature,然后通过wx对象的config方法去进行配置验证签名

    wx.config({
    
        debug: false,
    
        appId: appId, // 和获取Ticke的必须一样------必填,公众号的唯一标识
    
        timestamp:timestamp, // 必填,生成签名的时间戳
    
        nonceStr: nonceStr, // 必填,生成签名的随机串
    
        signature: signature,// 必填,签名,见附录1
    
        //需要分享的列表项:发送给朋友,分享到朋友圈,分享到QQ,分享到QQ空间
    
        jsApiList: [
    
         'onMenuShareAppMessage','onMenuShareTimeline',
    
         'onMenuShareQQ','onMenuShareQZone'
    
        ]
    
       });
    //处理验证失败的信息
    
    wx.error(function (res) {
    
     logUtil.printLog('验证失败返回的信息:',res);
    
    });
    
    //处理验证成功的信息
    
    wx.ready(function () {
    
    //       alert(window.location.href.split('#')[0]);
    
     //分享到朋友圈
    
     wx.onMenuShareTimeline({
    
      title: _this.newDetailObj.title, // 分享标题
    
      link: window.location.href.split('#')[0], // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
    
      imgUrl: _this.newDetailObj.thu_image, // 分享图标
    
      success: function (res) {
    
       // 用户确认分享后执行的回调函数
    
       logUtil.printLog("分享到朋友圈成功返回的信息为:",res);
    
       _this.showMsg("分享成功!")
    
      },
    
      cancel: function (res) {
    
       // 用户取消分享后执行的回调函数
    
       logUtil.printLog("取消分享到朋友圈返回的信息为:",res);
    
      }
    
     });
    
     //分享给朋友
    
     wx.onMenuShareAppMessage({
    
      title: _this.newDetailObj.title, // 分享标题
    
      desc: _this.desc, // 分享描述
    
      link: window.location.href.split('#')[0], // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
    
      imgUrl: _this.newDetailObj.thu_image, // 分享图标
    
      type: '', // 分享类型,music、video或link,不填默认为link
    
      dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
    
      success: function (res) {
    
       // 用户确认分享后执行的回调函数
    
       logUtil.printLog("分享给朋友成功返回的信息为:",res);
    
      },
    
      cancel: function (res) {
    
       // 用户取消分享后执行的回调函数
    
       logUtil.printLog("取消分享给朋友返回的信息为:",res);
    
      }
    
     });
    
     //分享到QQ
    
     wx.onMenuShareQQ({
    
      title: _this.newDetailObj.title, // 分享标题
    
      desc: _this.desc, // 分享描述
    
      link: window.location.href.split('#')[0], // 分享链接
    
      imgUrl: _this.newDetailObj.thu_image, // 分享图标
    
      success: function (res) {
    
       // 用户确认分享后执行的回调函数
    
       logUtil.printLog("分享到QQ好友成功返回的信息为:",res);
    
      },
    
      cancel: function (res) {
    
       // 用户取消分享后执行的回调函数
    
       logUtil.printLog("取消分享给QQ好友返回的信息为:",res);
    
      }
    
     });
    
    
    
     //分享到QQ空间
    
     wx.onMenuShareQZone({
    
      title: _this.newDetailObj.title, // 分享标题
    
      desc: _this.desc, // 分享描述
    
      link: window.location.href.split('#')[0], // 分享链接
    
      imgUrl: _this.newDetailObj.thu_image, // 分享图标
    
      success: function (res) {
    
       // 用户确认分享后执行的回调函数
    
       logUtil.printLog("分享到QQ空间成功返回的信息为:",res);
    
      },
    
      cancel: function (res) {
    
       // 用户取消分享后执行的回调函数
    
       logUtil.printLog("取消分享到QQ空间返回的信息为:",res);
    
      }
    
     });
    
    });

    在这个过程中出现的错误就是:config:invalid signature,这个错误就说明签名不对,这时候需要静下心来去想想,然后进行排除,我最后发现原来是当前的url的错误,看了网上很多都是url需要进行编码,我也是这样做的,但一直出现config:invalid signature

    原来的:

    let url = encodeURIComponent(window.location.href.split('#')[0]);

    修改后

    let url = window.location.href.split('#')[0];

    就不错了,最后来看看效果

     

    一般出现这个问题,大部分都是url的问题哦。

    展开全文
  • 这里介绍了一次在微信WebView中使用Vue做单页应用的过程中遇到的一些问题,也是比较常见的问题。文末有亮点,希望大家都来~ 背景 最近因为快过年了,按照微信以往的尿性,小程序的审核总是有各种条条框框,因此为....
  • 直接上需求,我们的vue开发H5单页应用封进微信公众号进行使用,其中有一个重要的微信分享功能,第一次接触,正经八百踩了好几个坑。 1. wxShare是我封装好的接口,需要发起请求获取微信分享认证授权后才能设置...
  • 年初产品引入了微信支付到现在不到半年的时间,一直没有过太大的坑爹经历,自认为微信支付也能hold住了,没想到上周还是被微信支付团队的同学狠狠的摆了一道。在这里留个记录,希望同入此坑的同学能尽快爬上来。 ...
  • 开发单页应用(SPA)时候遇到的微信支付授权目录的坑 ...项目中要在微信底下开发单页应用(SPA),前端技术选型用的vuejs+vue-router,vue-router使用hashbang模式(使用hashbang也是为了避免微信js
  • 在实际开发中,无论是做PC端、WebApp端还是微信公众号等类型的项目的时候,或多或少都会涉及到微信相关的开发,最近公司项目要求实现微信网页授权,并获取微信用户基本信息的功能及微信分享的功能,现在总算完成了,...
  • 在使用vue开发微信单页应用的时候,当配置微信分享需要传参数到后台时,需要使用encodeURIComponent()转换需要分享的链接,不然axios只能获取#号前面的path,造成传入后台的分享地址和wx.config配置的分享地址不一致...
  • 1、由于VUE是单页应用,并且我们用的是nuxt框架,nuxt的mode模式是history模式,并不是hash模式。所以,地址是单一的。 2、当微信链接已进入页面的时候,只会记住当前页面的地址,例如:进如页面的路径是:商城首页=...
  • 项目基于微信公众号开发,业务完全依赖微信授权,也就是用户进入页面已经完成授权获取到用户的OpenId。 需要有一个授权中间页:author.vue 基本实现思路: 无论使用哪个url进入页面都会先触发router.beforeEach...
  • 微信单页web应用,在进行版本迭代的时候,尝尝会遇到一个老大难问题。----缓存 大部分用户,通过链接进入我们的应用,一般都不会去手动刷新一下我们的应用(右上角三个点,然后点击刷新), 这样就会导致我们对...
  • 2.服务器配置进入微信公众平台->开发->基本配置->服务器配置,之后填写服务器地址和令牌,并按照微信官方教程配置即可。下面是我自己的一段Node.js版本的简单服务器配置: var http = require("http"); var url = ...
  • 最近在开发过程中遇到一个问题:开启了history模式下的vue单页面应用,在iOS进行微信自定义分享时一直报错invalid signature,但是在安卓下却一点问题都没有。 在iOS上的表现具体如下: 进入网站,未切换路由,此时...
  • 单页面应用微信服务号下的登录流程 最近我们的小程序涉及到虚拟支付的问题,在ios端的支付被封掉了
  • 因为angular 是单页应用,所以在调用一些手机端可微信接口的地方会很麻烦,这里总结一下在手机端调用分享和调用微信接口的时候出现的问题及解决的办法: 出现问题: 手机端的方法如果有回调,H5需要调用...
  • 路径必须http://test.yw11.com/# 后面带#/ 不能是http://test.yw11.com 否则分享就会直接调往首页
  • 背景 手机型号: 型号:iphone 7 / iphone xs max版本:ios 10.3.1 / ios...Vue应用(vue-router)上使用history模式,在某个页面内调用微信JSSDK相关API,如扫码、分享等,使用当前页面URL总会出现签名错误(invalid s...
1 2 3 4 5 ... 20
收藏数 3,953
精华内容 1,581