微信小程序分享到朋友圈之曲线救国

作者: 极乐叔 | 来源:发表于2017-12-07 15:39 被阅读136次

    遇到的问题

    经过多次重大更新,微信始终没有开放小程序直接分享到朋友圈的相关api。

    曲线救国

    我们直接开门见山,用间接的方式来实现微信小程序分享到朋友圈

    这里先来罗列一下实现思路

    1. 通过微信api申请小程序二维码
      获取小程序二维码接口文档

    2. 下载二维码到服务器并返回url

    3. 小程序接收url并从服务器下载图片

      wx.downloadFile

    4. 小程序将下载好的图片保存至用户相册

      wx.saveImageToPhotosAlbum

    实现过程

    首先通过阅读获取小程序二维码接口文档获取申请小程序二维码的接口

    这里我使用的是不限次的二维码接口即B方案

    代码示例:

    wx.request({
      method: 'POST',
      url: app.apiUrl + '/miniprogram/qrcode',
      data: {
        appid: app.appid,
        page: 'pages/activityInfo/activityInfo',
        scene: 'id:' + this.data.activity.id
      },
      header: {
        'content-type': 'application/x-www-form-urlencoded',
        'X-TOKEN': app.jwt
      },
      success(res) {
        res = res.data // 这里我是从服务器直接返回保存好的图片url
        ... // 后文介绍保存过程
      },
      fail() {
        wx.hideLoading()
        app.$alert('分享失败', 'wrong', _this)
      }
    })
    
    

    发送请求前我们需要准备好页面的page(开头不能带有“/”)路径及scene(页面参数)

    文档中对scene字段只有简单的描述并没有给到实际示例,这里其实很容易误导新人,不知道这个scene具体应该如何使用。

    最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)

    以上是官方对scene的介绍

    其实这里就是一个单纯的字符串,至于参数如何传递我们完全可以自行设计,自己喜欢就好。一定要注意官方有限制使用的特殊字符(!#$&'()*+,/:;=?@-._~) 这里我使用的是key:value;key:value形式,当用户扫码后通过onLoad(options)来获取scene

    onLoad (options) {
        // 因为这里要跟正常url传参做区分,所以要先判断scene是否存在
        if (options.scene) {
          let scene = decodeURIComponent(options.scene) // 官方要求一定要先decodeURIComponent才能正常使用scene
          scene = scene.split(';')
          let obj = {}
          for (let i = 0; i < scene.length; i++) {
            let item = scene[i].split(':')
            obj[item[0]] = item[1]
          }
          // 将options.id 替换为scene中提取的id 以保证后续业务不受影响
          options.id = obj.id
        }
    } 
    
    

    服务端实现

    服务端我用的是golang

    没有什么原因,就因为该项目的后端是golang搭建的,自己也在练习golang,所以服务端代码写的没有任何水平,还请路过的大神指点一二,这里主要介绍实现思路

    func GetMiniProgramQrcode(c *gin.Context) {
        // 获取应用的appid
        appid := c.PostForm("appid")
        // 后端获取小程序传来的page及scene
        page := c.PostForm("page")
        scene := c.PostForm("scene")
    
        // 考虑到反复请求微信接口的耗时及服务器io消耗,我打算把图片通过MD5(page+scene)的方式命名
        h := md5.New()
        h.Write([]byte(page + scene)) // 需要加密的字符串
        cipherStr := h.Sum(nil)
        result := hex.EncodeToString(cipherStr)
        exist, _ := model.PathExists("服务器文件存储路径" + result + ".jpg") // 检测图片是否已经存在(即之前是否有人分享过相同页面)
        if exist {
            // 若二维码文件存在直接返回路径
            c.String(200, "URL访问路径"+result+".jpg")
        } else {
            // 不存在则直接请求微信获取二维码
            token, ok := GetAccessToken(appid) // 首先获取access_token 这里大家根据自己的业务方式来获取
            if !ok {
                c.JSON(200, gin.H{
                    "code": 4001,
                    "msg":  "accesstoken 获取失败",
                })
            } else {
                // 向微信请求小程序二维码图片
                // 这里需要注意!!! 官方只介绍了通过该接口以post的形式传参,但其实参数是要严格的json格式传递才能正常获取
                resp, err := http.Post("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+token,
                    "application/x-www-form-urlencoded",
                    strings.NewReader(`{"page":"`+page+`", "scene":"`+scene+`"}`))
                if err != nil {
                    fmt.Println(err)
                }
    
                defer resp.Body.Close()
                body, err := ioutil.ReadAll(resp.Body)
                if err != nil {
                    // handle error
                }
                // 图片写入本地
                err = ioutil.WriteFile("服务器文件存储路径"+result+".jpg", body, 0755)
                if err != nil {
                    fmt.Println(err)
                    c.JSON(200, gin.H{
                        "code": 4002,
                        "msg":  "文件写入服务器失败",
                    })
                }else{
                    // 写入成功 直接返回url
                    c.String(200, "URL访问路径"+result+".jpg")
                }
            }
        }
    }
    
    

    通过上述逻辑我们可以正常获取到图片url地址 接下来就是将图片下载到小程序本地并保存到用户相册中

    // 接着第一块代码片中省略部分 我们已经获取到服务器返回的二维码图片url(res)
    wx.downloadFile({ // 调用wx.downloadFile接口将图片下载到小程序本地
      url: app.webUrl + res,
      success(res) { // 下载成功后会生成一个临时文件路径 res.tempFilePath(这时res变量已经被新的回调替换了哦,已经不是服务器返回来的res了)
        wx.saveImageToPhotosAlbum({ // 接着调用wx.saveImageToPhotosAlbum将图片保存到用户手机相册,该接口需要用户授权才可以使用,在调用过程中微信会自动弹框请求授权,如果用户拒绝则直接调用fail回调,且一段时间内不会重新请求,这里大家可以通过微信权限设置接口重新引导用户授权
          filePath: res.tempFilePath,
          success(res) {
            wx.hideLoading()
            wx.showModal({ // 保存成功后记得提醒用户二维码已经存到他的手机相册了哦
              title: '分享二维码已保存到系统相册',
              content: '快去分享给朋友,让更多的朋友发现这里的美好',
              success: function (res) {
                if (res.confirm) {
                  console.log('用户点击确定')
                } else if (res.cancel) {
                  console.log('用户点击取消')
                }
                _this.shareCancle()
              }
            })
          },
          fail(res) {
            wx.hideLoading()
            app.$alert('分享失败', 'wrong', _this)
          }
        })
      },
      fail: function (res) {
        wx.hideLoading()
        app.$alert('分享失败', 'wrong', _this)
      }
    })
    
    

    如此就完成了微信小程序分享到朋友圈的功能,感觉也是有点艰辛啊。

    本文作者:holdno
    原文地址:微信小程序分享到朋友圈之曲线救国-教程-小程序社区-微信小程序-微信小程序开发社区-小程序开发论坛-微信小程序联盟

    开启赞赏

    相关文章

      网友评论

      • MacSam:小程序调服务端接口,接口获取图片但不保存图片,而是直接返回给小程序io流,然后小程序downloadFile,感觉理论上可以,大佬有想过么

      本文标题:微信小程序分享到朋友圈之曲线救国

      本文链接:https://www.haomeiwen.com/subject/fiodixtx.html