小程序开发系列(六)获取群信息
小程序最近发布了新功能,转发到群中的页面,再点击的时候可以获取群信息,比如群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 }解密结果
转载请注明出处。

浙公网安备 33010602011771号