小程序開發系列(六)獲取群信息


小程序最近發布了新功能,轉發到群中的頁面,再點擊的時候可以獲取群信息,比如群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
}
解密結果

轉載請注明出處。







免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM