前端之家收集整理的这篇文章主要介绍了
.NET之微信小程序获取用户UnionID,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
前言:
@H_
502_2@ 在实际项目开发中我们经常会遇到账号统一的问题,如何在不同端或者是不同的
登录方式下保证同一个会员或者
用户账号唯一(便于
用户信息的管理)。这段时间就有一个这样的需求,之前有个客户做了一个
微信小程序商城(店主端的),然后现在又要做一个会员购物端的
小程序商场。首先之前
用户登录凭证都是使用微信openid来做的唯一标识,而现在客户需求是要做到
用户在会员端
小程序跳转到到店主端
小程序假如之前该
用户微信是在店主端审核通过的
用户则不需要在进行资料提交审核操作,直接
登录。所以,所以我们使用了UnionID来进行关联,如下是我们现在项目的基本流程(画的丑莫见怪)。
@H_
502_2@

说说UnionID机制:
@H_
502_2@ 如果开发者拥有多个移动应用、网站应用、和公众帐号(
包括小程序),可通过 UnionID 来区分
用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(
包括小程序),
用户的 UnionID 是唯一的。换句话说,同一
用户,对同一个微信开放平台下的不同应用,unionid是相同的。
@H_
502_2@官方UnionID机制详细说明:
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/union-id.html
微信开放平台绑定小程序流程:
@H_
502_2@
登录微信开放平台 — 管理中心 —
小程序 — 绑定
小程序(直接使用微信官方图)
@H_
502_2@

调用接口 wx.getUserInfo,从解密数据(encryptedData)中获取 UnionID(推荐使用):
@H_
502_2@推荐使用原因:无需关注微信公众号即可
获取到UnionID。
@H_
502_2@
调用接口wx.getUserInfo前提:
用户允许授权
获取用户信息!
开发者后台校验与解密开放数据:
@H_
502_2@ 微信为了保证
用户信息,把
用户通过wx.getUserInfo接口
获取到的相关敏感信息进行了加密。加密方式对称加密(后面会提到),首先我们需要通过
微信小程序登录流程获取到
用户的session_key(会话密钥),然后我们可以报
获取到的会话密钥使用缓存存起来,在通过
用户授权
获取用户相关信息,如下是
用户授权成功
获取到的
用户信息:
@H_
502_2@

基本流程图如下:
@H_
502_2@

@H_
502_2@
@H_
502_2@
(encryptedData)加密数据解密算法:
@H_
502_2@开发者如需要
获取敏感数据,需要对接口返回的
加密数据(encryptedData) 进行对称解密。 解密算法如下:
- 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
- 对称解密的目标密文为 Base64_Decode(encryptedData)。
- 对称解密秘钥 aeskey = Base64_Decode(session_key),aeskey 是16字节。
- 对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回
@H_
502_2@很遗憾的是微信居然没有为我们大.Net提供解密算法demo,实属让人不算,最后自己根据网上的资料还是配上了符合微信对称加密的解密算法。
@H_
502_2@
代码实现:
@H_
502_2@首先关于session_key(会话密钥)的
获取,请看下面的wx.login+code2Session 方式
调用接口wx.getUserInfo获取encryptedData(加密数据)和iv(初始向量):
// 用户已经授权
wx.getUserInfo({
success: function(res) {
console.log(res);
var userInfo = res.userInfo 用户基本信息
let sessionKey = wx.getStorageSync("session_key");临时会话密钥,通过小程序登录流程获取到的
请求.net webapi解密接口
wx.request({
url: 'https://www.xxxtest.com/api/User_oAuth/DecryptSensitiveData',data: {
sessionKey:sessionKey,encryptedData:res.encryptedData,iv:res.iv
},header: {
content-type': application/json' 默认值
},success (res) {
解密返回过来的UnionID
console.log(res.data)
}
})
}
})
})
.Net WebApi 解密数据接口:
/// <summary>
/// 解密微信对称加密数据,获取用户联合运营编号
</summary>
<param name="sessionKey">临时会话秘钥</param>
<param name="encryptedData">微信用户敏感加密数据<param name="iv">解密初始向量<returns></returns>
[HttpGet]
public IHttpActionResult DecryptSensitiveData(string sessionKey,string encryptedData,1)">string iv)
{
try
{
var getUnionId=DecryptByAesBytes(encryptedData,sessionKey,iv);
return Json(new { code =1,msg=解密成功",result= getUnionId });
}
catch (Exception ex)
{
new { code = 0,msg = 解密失败,原因:"+ex.Message });
}
}
#region AES对称解密
AES解密
待解密的字节数组解密密钥字节数组IV初始化向量字节数组<param name="cipher">运算模式<param name="padding">填充模式<returns></returns>
private static string DecryptByAesBytes(
{
非空验证
if (!string.IsNullOrWhiteSpace(encryptedData) && !string.IsNullOrWhiteSpace(sessionKey) && !.IsNullOrWhiteSpace(iv))
{
var decryptBytes = Convert.FromBase64String(encryptedData.Replace(' ',+));
var keyBytes = Convert.FromBase64String(sessionKey.Replace(var ivBytes = Convert.FromBase64String(iv.Replace());
var aes = new AesCryptoServiceProvider
{
Key = keyBytes,IV = ivBytes,Mode = CipherMode.CBC,Padding = PaddingMode.PKCS7
};
var outputBytes = aes.CreateDecryptor().TransformFinalBlock(decryptBytes,1)">0var decryptResult = Encoding.UTF8.GetString(outputBytes);
dynamic decryptData = JsonConvert.DeserializeObject(decryptResult,1)">new { unionid = "" }.GetType());
JJHL.Utility.Loghelper.WriteLog(AES对称解密结果为:" + decryptResult);
return decryptData.unionid;
}
else
{
return ;
}
}
(Exception e)
{
JJHL.Utility.Loghelper.WriteLog(AES对称解密失败原因: e.Message);
;
}
}
#endregion
所遇异常:参数使用Convert.FromBase64String转化时,提示“Base-64字符数组的无效长度” 的问题:
@H_
502_2@原因:加密参数中的"+"通过地址栏传过来时,
后台会解析为空格(遇到的概率比较小)。
@H_
502_2@
解决:最好的做法是 使用encryptedData.Replace("+","%2B")先将空格编码,然后再作为参数传给另一
页面传递,这样
页面在
提取参数时才会将“%2B”解码为加号.但这儿为了简化,将空格直接还原为"+"或者是直接在
后台将空格替换为“+”encryptedData.Replace(' ','+');
直接通过 wx.login + code2Session
获取到该用户 UnionID:
其实这个方式就是实现了小程序的登录流程,微信官方详细说明:
@H_
502_2@
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
@H_
502_2@优点:无需
用户授权。
@H_
502_2@前提:
用户需要关注该微信公众号。
小程序端调用接口wx.login获取code凭证,在通过请求auth.code2Session接口获取用户信息(UnionID,openid,session_key会话密钥)两种方式:
1.直接通过wx.login请求到code凭证后,在请求该地址获取用户信息:
GET:https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
@H_
502_2@详细说明请看微信官方文档(
代码略):
https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
2.通过请求wx.login获取code凭证,在向.net webapi后端请求code2Session接口:
@H_
502_2@原因:因为我们需要对
获取的
用户信息做相关业务逻辑处理。
/**
*封装用户promise登录,通过code凭证获取用户信息(UnionID,session_key会话密钥)
*/
userLogin: function() {
var that = this;
定义promise方法
return Promise(function(resolve,reject) {
调用登录接口
wx.login({
success: function(res) {
if (res.code) {
console.log(用户登录授权code为: res.code);
调用wx.request请求传递code凭证换取用户openid,并获取后台用户信息
wx.request({
url: https://www.xxxx.xxx.api/User_oAuth/GetUserInfo后台请求用户信息方法
data: {
code: res.code code凭证
':if (res.data.errcode == ) {
存入session缓存中
console.log(res.data.openid);微信用户唯一标识
console.log(res.data.UnionID);微信开发平台联合ID
console.log(res.data.session_key);会话密钥
//***注意****
//注意:这里是直接把session_key缓存起来,在上面wx.getUserInfo会使用到
wx.setStorageSync("session_key",res.data.session_key);
promise机制放回成功数据
resolve(res.data);
}
{ reject(error); }
},fail: function(res)
{
reject(res);
wx.showToast({ title: 系统错误 })
},complete: () => { } complete接口执行后的回调函数,无论成功失败都会调用
}) }
{
reject(");
}}
})
})}
.Net WebApi 请求用户信息接口:
获取用户信息
<param name="code">信息数据code凭证public IHttpActionResult GetUserInfo( code)
{
string AppSecret = 小程序秘钥;
string AppId = 应用程序标识;
请求目标地址和参数(authorization_code授权类型,此处只需填写 authorization_code)
string OauthUrl = https://api.weixin.qq.com/sns/jscode2session?appid=" + AppId + &secret=" + AppSecret + &js_code=" + code + &grant_type=authorization_code";序列化解析数据
var Result = HttpGet(OauthUrl);
new { openid = Result.openid,errcode = Result.errcode,UnionID = Result.unionid,session_key = Result.session_key });
}
(Exception ex)
{
new { errcode = 获取用户信息失败 ex.Message });
}
}
请求code2Session接口获取用户信息
<param name="requestDataAndUrl">目标地址和参数public WxOauthModle HttpGet( requestDataAndUrl)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestDataAndUrl);
request.Method = GET;
request.ContentType = text/html;charset=UTF-8;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = StreamReader(myResponseStream,Encoding.UTF8);
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close();
return JsonConvert.DeserializeObject<WxOauthModle>(retString);
}
public class WxOauthModle
{
<summary>
用户唯一标识
</summary>
string openid { get; set; }
会话秘钥
string session_key { 联立编号
string unionid { 错误码
int errcode { 错误信息
string errmsg { ; }
}
关于微信网页开发通过UnionID机制解决用户在不同公众号,或在公众号、移动应用之间帐号统一问题:
@H_
502_2@详情说明请点击:
https://www.cnblogs.com/Can-daydayup/p/9368844.html