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


