• 小程序开发系列(六)获取群信息


    小程序最近发布了新功能,转发到群中的页面,再点击的时候可以获取群信息,比如群ID,那要如何实现呢?

    1.在页面中开启“转发”功能

    代码如下

     onLoad: function () {
        wx.showShareMenu({
          withShareTicket: true
        });
      },

    2.在页面中设置“转发”参数

     //转发
      onShareAppMessage: function () {
        return {
          title: '转发XXXX',
          path: '/pages/retrospect/retrospect',
          success: function (res) {
            // 转发成功
            var shareTickets = res.shareTickets;
            var shareTicket = shareTickets;
            wx.getShareInfo({
              shareTicket: shareTicket,
              success: function (res) {
                console.log('success');
                console.log(res);
                //console.log(res);
                wx.showToast({
                  title: '转发成功',
                  duration: 5000
                })
              },
              fail: function (res) {
                console.log('fail');
                console.log(res);
                wx.showToast({
                  title: 'fail:' + res.errMsg,
                  duration: 5000
                })
              }
            });
          },
          fail: function (res) {
            // 转发失败
          }
        }
      }
    注:在转发的时候可以获取到shareTicket,使用shareTicket调用wx.getShareInfo可以得到群信息,具体实现请参看后面的代码。

    3.响应用户从转发的群中进入

    app.js的onLaunch在小程序启动时会触发一次,且直到小程序销毁。app.js中的onShow在小程序显示的时候会触发,只要显示就触发,所以会触发多次。在onLaunch和onShow函数中的参数options可以拿到shareTicket,具体要如何触发需要结合自身场景,简单的示例代码如下,

    App({
      onLaunch: function (options) {
        //this.checkLogin(options.shareTicket);
        this.globalData.shareInfo=null;
      },
      onShow: function (options) {
        this.checkLogin(options.shareTicket);
      },
      checkLogin: function (shareTicket) {
        var that = this;
        wx.checkSession({
          success: function () {
            if (!that.globalData.session) {
              that.login(shareTicket);
            };
          },
          fail: function () {
            that.login(shareTicket);
          }
        })
      },
      //登录
      login: function (shareTicket) {
        var that = this
        wx.login({
          success: function (r) {
            if (r.code) {
              that.decodeSession(r.code, shareTicket);
            }
            wx.getUserInfo({
              success: function (res) {
                that.globalData.userInfo = res.userInfo;
              }
            })
          }
        })
      },
      //解密session信息
      decodeSession: function (code, shareTicket) {
        var that = this;
        wx.request({
          url: urls.WeiXin.FetchSessionInfo,//向后端发起换取session_key请求的URL
          data: {
            code: code
          },
          success: function (re) {
            if (re.data.Status == 0) {
              that.globalData.session = {
                openid: re.data.Data.openid,
                key: re.data.Data.session_key
              };
              if (shareTicket) {
                that.getShareInfo(shareTicket);
              }
            }
            else {
              that.globalData.session = null;
            }
          }
        })
      },
      //获取群信息
      getShareInfo: function (shareTicket) {
        var that = this;
        wx.getShareInfo({
          shareTicket: shareTicket,
          success: function (res) {
            wx.request({
              url: urls.WeiXin.Encrypt,//向后端发起解密请求的URL
              data: {
                encryptData: res.encryptedData,
                encryptSessionKey: that.globalData.session.key,
                iv: res.iv
              },
              success: function (re) {
                var msg='';
                if (re.data.Status == 0) {
                  that.globalData.shareInfo =JSON.parse(re.data.Data);
                  msg = '来自群转发';
                }
                else {
                  that.globalData.session = null;
                  msg=re.data.Message;
                }
                wx.showToast({
                  title: msg,
                  duration: 5000
                })
              }
            })        
          },
          fail: function (res) {
            console.log('fail');
            console.log(res.errMsg);
            wx.showToast({
              title: 'fail:' + res.errMsg,
              duration: 5000
            })
          }
        });
      },
      globalData: {
        userInfo: null,
        session: null,
        shareInfo: null
      }
    })
    注:

    (1).必须要在执行wx.login登录后才能拿到群信息,否则getShareInfo会提示"you need login".

    (2).登录得到的code拿到后端去换取session_key和openId,后面换取的数据是加密的需要进行解密才能得到session_key和openId.

    (3).getShareInfo拿到的数据是加密的数据,需要传到后端去解密,解密时需要encryptData、session_key和iv。其中encryptData和iv在getShareInfo的res中可以拿到,session_key在登录的时候可以换取得到。

    4.换取session_key

    后端使用asp.net的MVC中的C层,即控制器来处理。具体可以参看网络中的相关文章。

    session控制器的代码如下

     /// <summary>
        /// 微信会话
        /// </summary>
        public class WXSessionController : ApiController
        {
            #region FetchSessionInfo
            /// <summary>
            /// 获取SESSION信息
            /// </summary>
            /// <returns></returns>
            [HttpGet]
            public BaseDataPackage<WXSessionInfoPackage> FetchSessionInfo(string code)
            {
                var result = new BaseDataPackage<WXSessionInfoPackage>();
                var data = WXSession.FetchSessionInfo(code);
                result.Data = data;
                if (data != null && data.IsOK())
                {
                    result.Status = StatusCode.OK;
                    result.Message = "OK";
                }
                else
                {
                    result.Status = StatusCode.FAIL;
                    result.Message = data.errmsg;
                }
                return result;
            }
            #endregion
        }
     public class BaseDataPackage<T>
        {
            public BaseDataPackage();
    
            public int Status { get; set; }
            public string Message { get; set; }
            public T Data { get; set; }
    
            public bool IsOK(){return Status==0;}
        }
    //
        // 摘要:
        //     WebApi请求的状态码
        public class StatusCode
        {
            //
            // 摘要:
            //     请求成功
            public const int OK = 0;
            //
            // 摘要:
            //     失败
            public const int FAIL = 1;
            //
            // 摘要:
            //     异常
            public const int EXCEPTION = 2;
    }
     public class WXSessionInfoPackage : WXPackageBase
        {
            public string openid { get; set; }
    
            public string session_key { get; set; }
        }
        public class WXPackageBase
        {
            #region 属性
            public int errcode { get; set; } = StatusCode.OK;
    
            public string errmsg { get; set; }
            #endregion
    
            #region IsOK
            public bool IsOK()
            {
                if (errcode == StatusCode.OK)
                {
                    return true;
                }
    
                return false;
            }
            #endregion
        }

      public class WXSession
        {
    /// <summary>
            /// code 换取 session_key、openid
            /// </summary>
            public const string SNS_JSCODE2SESSION = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
    
            #region FetchSessionInfo
            public static WXSessionInfoPackage FetchSessionInfo(string code)
            {
    	    //AppId和AppSecret从微信的小程序页面中复制下来即可
                string url = string.Format(SNS_JSCODE2SESSION,AppId, AppSecret, code);
                var sessionInfo = HttpHelper.Get<WXSessionInfoPackage>(url);
                if (sessionInfo != null)
                {
                    sessionInfo.session_key = Encrypt(sessionInfo.session_key);
                    sessionInfo.openid = Encrypt(sessionInfo.openid);
                }
                return sessionInfo;
            }
            #endregion
    
            #region Encrypt
            /// <summary>
            /// 对session的数据加密
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            public static string Encrypt(string data)
            {
                if (string.IsNullOrEmpty(data))
                {
                    return data;
                }
                var buff = Encoding.UTF8.GetBytes(data);
                var dest = Convert.ToBase64String(buff);
                return dest;
            }
            #endregion
    
            #region Descrypt
            /// <summary>
            /// 对session的数据解密
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            public static string Descrypt(string data)
            {
                if (string.IsNullOrEmpty(data))
                {
                    return data;
                }
                var buff = Convert.FromBase64String(data);
                var dest = Encoding.UTF8.GetString(buff);
                return dest;
            }
            #endregion
        }


    
    

    注:为了数据的安全,获取到的session_key和openid作了加密处理,即Encrypt方法,Encrypt的实现依需要而不同,比如可以使用简单的base64加密等。为此需要有一个对应的解密方法Decrypt.

    附HttpHelper.Get方法

     /// <summary>
        /// HTTP帮助类
        /// </summary>
        public class HttpHelper
        {
            #region Get
            /// <summary>
            /// 执行基本的命令方法,以Get方式
            /// </summary>
            /// <param name="apiurl">请求的URL</param>
            /// <param name="headers">请求头的key-value字典</param>
            /// <param name="needReturnHeader">true:返回响应头,数据将以{Header:headerDict,Data:responseStr}的json格式返回,
            /// 其中headerDict为响应头的字典格式的数据,responseStr为请求返回的响应字符串.false:直接返回响应数据</param>
            /// <returns></returns>
            public static string Get(string apiurl, Dictionary<string, string> headers = null, bool needReturnHeader = false)
            {
                WebRequest request = WebRequest.Create(apiurl);
                request.Method = RequestMethod.GET;
                if (headers != null)
                {
                    foreach (var keyValue in headers)
                    {
                        request.Headers.Add(keyValue.Key, keyValue.Value);
                    }
                }
                WebResponse response = request.GetResponse();
                Stream stream = response.GetResponseStream();
                Encoding encode = Encoding.UTF8;
                StreamReader reader = new StreamReader(stream, encode);
                string resultJson = reader.ReadToEnd();
                if (needReturnHeader)
                {
                    Dictionary<string, string> headerDict = new Dictionary<string, string>();
                    foreach (var key in response.Headers.AllKeys)
                    {
                        headerDict.Add(key, response.Headers[key]);
                    }
                    var temp = new
                    {
                        Header = headerDict,
                        Data = resultJson
                    };
                    return temp.ToJson();
                }
                else
                {
                    return resultJson;
                }
            }
    #endregion
    }
    微信开发工具拿到的session_key


    5.解密群信息

       public class WXEncrypt
        {
            #region Decrypt
            /// <summary>
            /// 解密数据
            /// </summary>
            /// <param name="encryptStrOfBase64">base64加密后的字符串,如果没有进行URL编码直接传输,加号在传输时会变成空格,
    此时建议替换成%2B传输.wx.request会默认进行URL编码。</param>
            /// <param name="encryptSessionKey">加密后的sessionKey</param>
            /// <param name="iv"></param>
            /// <returns></returns>
            public static string Decrypt(string encryptStrOfBase64, string encryptSessionKey, string iv)
            {
                var sessionKey = WXSession.Descrypt(encryptSessionKey);
                encryptStrOfBase64 = encryptStrOfBase64.Replace("%2B", "+");
                if (sessionKey.Length % 3 == 1)
                {
                    sessionKey += "==";
                }
                else if (sessionKey.Length % 3 == 2)
                {
                    sessionKey += "=";
                }
                var Key = Convert.FromBase64String(sessionKey);
                var Iv = Convert.FromBase64String(iv);
                byte[] dataByte = AesEncryptHelper.Decrypt(encryptStrOfBase64, Iv, Key);
                string dataStr = Encoding.UTF8.GetString(dataByte);
                return dataStr;
            }
            #endregion

       /// <summary>
        /// AES算法
        /// </summary>
        public class AesEncryptHelper
        {
            #region Decrypt
            /// <summary>
            /// 解密
            /// </summary>
            /// <param name="encryptStrOfBase64"></param>
            /// <param name="Iv"></param>
            /// <param name="Key"></param>
            /// <returns></returns>
            public static byte[] Decrypt(String encryptStrOfBase64, byte[] Iv, byte[] Key)
            {
                RijndaelManaged aes = new RijndaelManaged();
                aes.KeySize = 256;
                aes.BlockSize = 128;
                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.None;
                aes.Key = Key;
                aes.IV = Iv;
                var decrypt = aes.CreateDecryptor(aes.Key, aes.IV);
                byte[] xBuff = null;
                using (var ms = new MemoryStream())
                {
                    using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
                    {
                        byte[] xXml = Convert.FromBase64String(encryptStrOfBase64);
                        byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
                        Array.Copy(xXml, msg, xXml.Length);
                        cs.Write(xXml, 0, xXml.Length);
                    }
                    xBuff = decode(ms.ToArray());
                }
                return xBuff;
            }
    
    
            #region decode
            private static byte[] decode(byte[] decrypted)
            {
                int pad = (int)decrypted[decrypted.Length - 1];
                if (pad < 1 || pad > 32)
                {
                    pad = 0;
                }
                byte[] res = new byte[decrypted.Length - pad];
                Array.Copy(decrypted, 0, res, 0, decrypted.Length - pad);
                return res;
            }
            #endregion
    
            #endregion
    }
    解密结果

    转载请注明出处。






  • 相关阅读:
    MySQL ------ MySQL常用语句的语法 (三十四)
    .NET ----- 多级联动
    .NET ------ 两种传参方式
    .NET----- 对下拉框的控制
    MySQL ------ 改善性能(三十三)
    html5:新特性(新增标签、新增标签属性)
    css:布局技巧(margin负值、鼠标经过显示边框、文字围绕图片显示、三角形使用技巧、css初始化)
    css:vertical-align&文字溢出(vertical-align属性、溢出的文字显示为省略号)
    css:三角&用户界面(三角形效果、鼠标样式、输入框与文本域的优化)
    shiro:入门(概念、RBAC模型、入门程序)
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7604889.html
Copyright © 2020-2023  润新知