原文源自https://blog.csdn.net/weixin_43803985/article/details/103910205
原文这是老版本的,.net6的话,需要更改接口名称
接口名称是get,参数个数不一样,不知道这里能不能叫重载,.net6里面不支持,所以需要更改名称
1.根据原文代码板块实现
首先还是把代码正确贴进去吧
1.1微信小程序首页app,js
// app.js
App({
onLaunch() {
// 展示本地存储能力
const logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
console.log(res)
if (res.code) {
console.log("code========" + JSON.stringify(res));
//发起网络请求
wx.request({
url: 'https://localhost:7122/api/Login/Get/Get',
data: {
code: res.code
},
success: data => {
console.log("data" + JSON.stringify(data.data));
this.globalData.session_key = data.data.session_key;
this.globalData.openid = data.data.openid;
console.log("openid" + this.globalData.openid);
},
fail:data=>{
console.log(data)
}
})
} else {
console.log('登录失败!' + res.errMsg)
}
}
})
},
globalData: {
userInfo: null,
selectedIndex:0,
session_key:'',
openid:''
}
})
剩下的比如appstatus这些需要的参数就自己加,这边只是获取手机号
通过wx.login()获取code然后通过
wx.request({
url: 'https://localhost:7122/api/Login/Get/Get',
data: {
code: res.code
},
})
发送至后端换取openId, sessionKey, unionId
再来看看后端这个接口代码如何实现
1.2后端换取openId, sessionKey, unionId
对应的控制器里面贴进去就好了
[Route("Get")]
[HttpGet]
public object Get(string code)
{
string cod = code;
string html = string.Empty;
string url = "https://api.weixin.qq.com/sns/jscode2session?appid="your_appid"&secret="your_secret"&js_code=" + cod + "&grant_type=authorization_code";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = "GET";
request.ContentType = "text/html;charset=UTF-8";
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
Stream ioStream = response.GetResponseStream();
StreamReader sr = new StreamReader(ioStream, Encoding.UTF8);
html = sr.ReadToEnd();
sr.Close();
ioStream.Close();
response.Close();
RepParamrep rep = JsonConvert.DeserializeObject<RepParamrep>(html);
return rep;
}
在model里面加入对应的类用于存储openId, sessionKey(只要能返回这两个值就行了)
public class RepParamrep
{
public string session_key { get; set; }
public string openid { get; set; }
}
至此第一步就完成了。
1.3前端传参
前端wxml连接到函数就好了
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
userinfo: {}, // 添加一个userinfo属性用于存储用户信息
number: '', // Global variable to store the phone number
userPhone: '',
userNicheng: '',
hid1: false,
hid2: true,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// You can add any other initialization code here
},
bindGetUserInfo: function(e) {
this.setData({
userNicheng: e.detail.userInfo.nickName,
hid1: true,
hid2: false
})
},
getPhoneNumber: function(e) {
var that = this;
console.log("getPhoneNumberok" + e.detail.errMsg);
if (e.detail.errMsg == "getPhoneNumber:ok") {
wx.request({
url: 'https://localhost:7122/api/Login/GetPhone/Get',
data: {
encryptedData: e.detail.encryptedData,
iv: e.detail.iv,
session_key: app.globalData.session_key
},
method: "get",
success: function(res) {
console.log(res)
that.setData({
userPhone: res.data,
}) ,
app.globalData.userInfo = res.data;
},
fail:function(res){
console.log(res.errMsg)
}
})
}
},
onShow() {
if (typeof this.getTabBar === 'function' &&
this.getTabBar()) {
this.getTabBar().setData({
//唯一标识(其它设置不同的整数)
selected: 3
})
}
},
})
;
将对应参数传递过去即可最后赋值给userinfo
1.4后端换取
[Route("Get")]
[HttpGet]
public string GetPhone(string encryptedData, string iv, string session_key)
{
string _telPhone = getPhoneNumber(encryptedData, iv, session_key);
return _telPhone;
}
private string getPhoneNumber(string encryptedData, string IV, string Session_key)
{
try{
byte[] encryData = Convert.FromBase64String(encryptedData);
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Key = Convert.FromBase64String(Session_key);
rijndaelCipher.IV = Convert.FromBase64String(IV);
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
ICryptoTransform transform = rijndaelCipher.CreateDecryptor();
byte[] plainText = transform.TransformFinalBlock(encryData, 0, encryData.Length);
string result = Encoding.Default.GetString(plainText);
dynamic model = Newtonsoft.Json.Linq.JToken.Parse(result) as dynamic;
return model.phoneNumber;
}
catch (Exception ex)
{
return "";
}
}
这样就将手机号传递至前端了
2.login解析
本来也不准备写解析,毕竟自己也不会,还是觉得应该知其然知其所以然。
之前了解我认为的步骤是code从微信的接口https://api.weixin.qq.com/sns/jscode2session?
// 定义一个公共方法 Get,该方法接收一个字符串参数 code 并返回一个 object。
public object Get(string code)
{
// 把传入的 code 参数赋值给一个局部变量 cod。
string cod = code;
// 初始化一个空字符串 html。
string html = string.Empty;
// 构造一个 URL,这个 URL 是用来请求微信 API 的,其中包含了 appid、secret 和 js_code 等参数。
// 注意:在实际应用中,直接把 appid 和 secret 写在代码中是不安全的,应该从配置文件或环境变量中读取。
string url = "https://api.weixin.qq.com/sns/jscode2session?appid="+yourappid+"&secret="+yoursecret+"&js_code=" + cod + "&grant_type=authorization_code";
// 创建一个 HttpWebRequest 对象 request,并设置其 URL 为上面构造的 URL。
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
// 设置 HTTP 请求方法为 GET。
request.Method = "GET";
// 设置请求的内容类型为 text/html,字符集为 UTF-8。
request.ContentType = "text/html;charset=UTF-8";
// 发送请求,并获取响应。
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
// 获取响应流。
Stream ioStream = response.GetResponseStream();
// 使用 StreamReader 读取响应流中的数据,编码为 UTF-8。
StreamReader sr = new StreamReader(ioStream, Encoding.UTF8);
// 把流中的所有数据读取到一个字符串中,并赋值给 html 变量。
html = sr.ReadToEnd();
// 关闭 StreamReader。
sr.Close();
// 关闭响应流。
ioStream.Close();
// 关闭响应。
response.Close();
// 使用 JsonConvert 把 html(它实际上是一个 JSON 字符串)反序列化为 RepParamrep 对象。
RepParamrep rep = JsonConvert.DeserializeObject<RepParamrep>(html);
// 返回反序列化得到的对象。
return rep;
}
来换取对应参数,最后通过解密获取手机号
调用微信的 API 来通过 js_code 获取 session 信息。其中涉及到了 HTTP 请求的发送、响应的接收、以及 JSON 数据的反序列化等操作。需要注意的是,代码中的 appid 和 secret 直接硬编码在了代码中,这种做法在生产环境中是不推荐的,应该从安全的地方(如环境变量、加密的配置文件等)读取这些敏感信息。这里推荐放入appsettings.json里面,方便实际更改与测试。
这是解密解析,使用提供的密钥(Session_key)和初始化向量(IV)来解密加密的电话号码(encryptedData)。解密后,电话号码被从返回的JSON对象中提取出来并返回。
// 定义一个名为getPhoneNumber的方法,它接收三个字符串参数:encryptedData, IV, Session_key,并返回一个字符串
private string getPhoneNumber(string encryptedData, string IV, string Session_key)
{
try
{
// 将encryptedData从Base64格式转换为字节数组
byte[] encryData = Convert.FromBase64String(encryptedData);
// 创建一个RijndaelManaged类的实例,这是一个用于执行Rijndael对称加密算法的类
RijndaelManaged rijndaelCipher = new RijndaelManaged();
// 将Session_key从Base64格式转换为字节数组,并设置为Rijndael算法的密钥
rijndaelCipher.Key = Convert.FromBase64String(Session_key);
// 将IV从Base64格式转换为字节数组,并设置为Rijndael算法的初始化向量
rijndaelCipher.IV = Convert.FromBase64String(IV);
// 设置Rijndael算法的模式为CBC(Cipher Block Chaining)
rijndaelCipher.Mode = CipherMode.CBC;
// 设置Rijndael算法的填充模式为PKCS7
rijndaelCipher.Padding = PaddingMode.PKCS7;
// 创建一个解密器对象
ICryptoTransform transform = rijndaelCipher.CreateDecryptor();
// 使用解密器对象对输入的加密数据进行解密,得到明文数据
byte[] plainText = transform.TransformFinalBlock(encryData, 0, encryData.Length);
// 将解密后的字节数组转换为字符串,使用默认的字符编码
string result = Encoding.Default.GetString(plainText);
// 使用Newtonsoft.Json.Linq.JToken类将解密后的字符串解析为JSON对象,并将其转换为动态类型
dynamic model = Newtonsoft.Json.Linq.JToken.Parse(result) as dynamic;
// 从解析的JSON对象中提取phoneNumber字段的值,并返回
return model.phoneNumber;
}
catch (Exception ex)
{
// 如果在尝试过程中发生任何异常,则捕获该异常并返回一个空字符串
return "";
}
}
解密略微麻烦,推荐了解过程能够使用即可,毕竟这也是为了安全性着想。