隐藏

C#小程序获取用户手机号和用户openid和昵称服务器端代码

发布:2023/8/24 16:21:54作者:管理员 来源:本站 浏览次数:583

一、注意事项(先了解微信小程序的规则,知己知彼,才能解决问题)

1、微信小程序获取用户手机号,每次都会弹窗询问


2、获取用户信息(包括昵称、性别、城市、openid等),只弹窗一次 (根据手机号做授权验证用不到这里)


3、微信小程序可以利用缓存,但是有时间限制


4、获取手机号和openid—>是需要到自己服务器后台解密—>解密需要用到session_key—>session_key需要微信login接口(从前端)获取code然后传到后台服务器调用微信接口获取


5、通过自己服务器后台使用code获取数据之后,code则会失效


二、前端登录获取Code

官方文档


uni-app


<template>  

   <view class="content">  

       <button @click="login">Login</button>  

       <button open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber">getPhoneNumber</button>  

   </view>  

</template>  

<script>  

   export default {  

       data() {  

           return {}  

       },  

       methods: {  

           login(e) {  

               uni.login({  

                   success: (res) => {  

                       console.log("login", res);  

                   }  

               })  

           },  

           onGetPhoneNumber(e) {  

               console.log("onGetPhoneNumber", e);  

               console.log(e.detail.errMsg);  

               console.log(e.detail.iv);  

               console.log(e.detail.encryptedData);  

               uni.showModal({  

                   title: "onGetPhoneNumber",  

                   content: e.detail.errMsg  

               })  

           }  

       }  

   }  

</script>

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h3dDAxMDE_size_16_color_FFFFFF_t_70


三、后端解密

如何查看小程序的AppID和AppSecret?


ASP.NET WEBAPI作服务端开发小程序实现微信授权用户登录实例


版本1

版本2

   using AIOWeb.Models;

   using Newtonsoft.Json;

   using Newtonsoft.Json.Linq;

   using System;

   using System.Collections.Generic;

   using System.Data;

   using System.Data.SqlClient;

   using System.Linq;

   using System.Web;

   namespace AIOWeb

   {

       /// <summary>

       /// wxapi 的摘要说明

       /// </summary>

       public class wxapi : IHttpHandler

       {

           public void ProcessRequest(HttpContext context)

           {

               context.Response.ContentType = "text/plain";

               string code = "";

               string iv = "";

               string encryptedData = "";

               try

               {

                   code = HttpContext.Current.Request.QueryString["code"].ToString();

                   iv = HttpContext.Current.Request.QueryString["iv"].ToString();

                   encryptedData = HttpContext.Current.Request.QueryString["encryptedData"].ToString();

               }

               catch (Exception ex)

               {

                   context.Response.Write(ex.ToString());

               }

               string Appid = "wxdb2641f85b04f1b3";

               string Secret = "8591d8cd7197b9197e17b3275329a1e7";

               string grant_type = "authorization_code";

               //向微信服务端 使用登录凭证 code 获取 session_key 和 openid

               string url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + Appid + "&secret=" + Secret + "&js_code=" + code + "&grant_type=" + grant_type;

               string type = "utf-8";

               AIOWeb.Models.GetUsersHelper GetUsersHelper = new AIOWeb.Models.GetUsersHelper();

               string j = GetUsersHelper.GetUrltoHtml(url, type);//获取微信服务器返回字符串

               //将字符串转换为json格式

               JObject jo = (JObject)JsonConvert.DeserializeObject(j);

               result res = new result();

               try

               {

                   //微信服务器验证成功

                   res.openid = jo["openid"].ToString();

                   res.session_key = jo["session_key"].ToString();

               }

               catch (Exception)

               {

                   //微信服务器验证失败

                   res.errcode = jo["errcode"].ToString();

                   res.errmsg = jo["errmsg"].ToString();

               }

               if (!string.IsNullOrEmpty(res.openid))

               {

                   //用户数据解密

                   GetUsersHelper.AesIV = iv;

                   GetUsersHelper.AesKey = res.session_key;

                   string result = GetUsersHelper.AESDecrypt(encryptedData);

                   //存储用户数据

                   JObject _usrInfo = (JObject)JsonConvert.DeserializeObject(result);

                   userInfo userInfo = new userInfo();

                   userInfo.openId = _usrInfo["openId"].ToString();

                   try //部分验证返回值中没有unionId

                   {

                       userInfo.unionId = _usrInfo["unionId"].ToString();

                   }

                   catch (Exception)

                   {

                       userInfo.unionId = "unionId";

                   }

                   userInfo.nickName = _usrInfo["nickName"].ToString();

                   userInfo.gender = _usrInfo["gender"].ToString();

                   userInfo.city = _usrInfo["city"].ToString();

                   userInfo.province = _usrInfo["province"].ToString();

                   userInfo.country = _usrInfo["country"].ToString();

                   userInfo.avatarUrl = _usrInfo["avatarUrl"].ToString();

                   object watermark = _usrInfo["watermark"].ToString();

                   object appid = _usrInfo["watermark"]["appid"].ToString();

                   object timestamp = _usrInfo["watermark"]["timestamp"].ToString();

                   #region

                   //创建连接池对象(与数据库服务器进行连接)

                   SqlConnection conn = new SqlConnection("server=127.0.0.1;database=Test;uid=sa;pwd=1");

                   //打开连接池

                   conn.Open();

                   //创建命令对象

                   string Qrystr = "SELECT * FROM WeChatUsers WHERE openId='" + userInfo.openId + "'";

                   SqlCommand cmdQry = new SqlCommand(Qrystr, conn);

                   object  obj = cmdQry.ExecuteScalar();

                   if ((Object.Equals(obj, null)) || (Object.Equals(obj, System.DBNull.Value)))

                   {

                       string str = "INSERT INTO WeChatUsers ([UnionId] ,[OpenId],[NickName],[Gender],[City],[Province],[Country],[AvatarUrl],[Appid],[Timestamp],[Memo],[counts])VALUES('" + userInfo.unionId + "','" + userInfo.openId + "','" + userInfo.nickName + "','" + userInfo.gender + "','" + userInfo.city + "','" + userInfo.province + "','" + userInfo.country + "','" + userInfo.avatarUrl + "','" + appid.ToString() + "','" + timestamp.ToString() + "','来自微信小程序','1')";

                       SqlCommand cmdUp = new SqlCommand(str, conn);

                       // 执行操作

                       try

                       {

                           int row = cmdUp.ExecuteNonQuery();

                       }

                       catch (Exception ex)

                       {

                           context.Response.Write(ex.ToString());

                       }

                   }

                   else

                   {

                       //多次访问,记录访问次数counts   更新unionId是预防最初没有,后期关联后却仍未记录

                       string str = "UPDATE dbo.WeChatUsers SET counts = counts+1,UnionId = '" + userInfo.unionId + "' WHERE OpenId='" + userInfo.openId + "'";

                       SqlCommand cmdUp = new SqlCommand(str, conn);

                       int row = cmdUp.ExecuteNonQuery();

                   }

                   //关闭连接池

                   conn.Close();

                   #endregion

                   //返回解密后的用户数据

                   context.Response.Write(result);

               }

               else

               {

                   context.Response.Write(j);

               }

           }

           public bool IsReusable

           {

               get

               {

                   return false;

               }

           }

       }

   }

   GetUsersHelper 帮助类

   using System;

   using System.Collections.Generic;

   using System.IO;

   using System.Linq;

   using System.Security.Cryptography;

   using System.Text;

   using System.Threading.Tasks;

   namespace AIOWeb.Models

   {

       public class GetUsersHelper

       {

           /// <summary>

           /// 获取链接返回数据

           /// </summary>

           /// <param name="Url">链接</param>

           /// <param name="type">请求类型</param>

           /// <returns></returns>

           public  string GetUrltoHtml(string Url, string type)

           {

               try

               {

                   System.Net.WebRequest wReq = System.Net.WebRequest.Create(Url);

                   // Get the response instance.

                   System.Net.WebResponse wResp = wReq.GetResponse();

                   System.IO.Stream respStream = wResp.GetResponseStream();

                   // Dim reader As StreamReader = New StreamReader(respStream)

                   using (System.IO.StreamReader reader = new System.IO.StreamReader(respStream, Encoding.GetEncoding(type)))

                   {

                       return reader.ReadToEnd();

                   }

               }

               catch (System.Exception ex)

               {

                   return ex.Message;

               }

           }

           #region 微信小程序用户数据解密

           public static string AesKey;

           public static string AesIV;

           /// <summary>

           /// AES解密

           /// </summary>

           /// <param name="inputdata">输入的数据encryptedData</param>

           /// <param name="AesKey">key</param>

           /// <param name="AesIV">向量128</param>

           /// <returns name="result">解密后的字符串</returns>

           public string AESDecrypt(string inputdata)

           {

               try

               {

                   AesIV = AesIV.Replace(" ", "+");

                   AesKey = AesKey.Replace(" ", "+");

                   inputdata = inputdata.Replace(" ", "+");

                   byte[] encryptedData = Convert.FromBase64String(inputdata);

                   RijndaelManaged rijndaelCipher = new RijndaelManaged();

                   rijndaelCipher.Key = Convert.FromBase64String(AesKey); // Encoding.UTF8.GetBytes(AesKey);

                   rijndaelCipher.IV = Convert.FromBase64String(AesIV);// Encoding.UTF8.GetBytes(AesIV);

                   rijndaelCipher.Mode = CipherMode.CBC;

                   rijndaelCipher.Padding = PaddingMode.PKCS7;

                   ICryptoTransform transform = rijndaelCipher.CreateDecryptor();

                   byte[] plainText = transform.TransformFinalBlock(encryptedData, 0, encryptedData.Length);

                   string result = Encoding.UTF8.GetString(plainText);

                   return result;

               }

               catch (Exception)

               {

                   return null;

               }

           }

           #endregion

       }

   }

   ===============================================后补:实体类========================================

   using System;

   using System.Collections.Generic;

   using System.Linq;

   using System.Web;

   namespace AIOWeb.Models

   {

       public class wechat

       {

       }

       #region 实体类

       /// <summary>

       /// 微信用户类

       /// </summary>

       public class userInfo

       {

           public string openId { get; set; }

           public string nickName { get; set; }

           public string gender { get; set; }

           public string city { get; set; }

           public string province { get; set; }

           public string country { get; set; }

           public string avatarUrl { get; set; }

           public string unionId { get; set; }

           public data watermark { get; set; }

       }

       /// <summary>

       /// 微信用户数据水印

       /// </summary>

       public class data

       {

           public string appid { get; set; }

           public string timestamp { get; set; }

       }

       /// <summary>

       /// 微信小程序验证返回结果

       /// </summary>

       public class result

       {

           public string openid { get; set; }

           public string session_key { get; set; }

           public string errcode { get; set; }

           public string errmsg { get; set; }

       }

       #endregion

   }

版本3


微信小程序获取手机号需要完成认证,才能获取得到


否则会出现下列情况

1


一、搭建后台服务器(WebApI)


新建webapi2空控制器 OnLoginController


using Newtonsoft.Json;

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using System.Net;

using System.Net.Http;

using System.Security.Cryptography;

using System.Text;

using System.Web.Http;

using WebApplication1.Models;//引入实体类命名空间

using System.Web.Http.Cors;//跨域请求命名空间

namespace WebApplication1.Controllers

{

//跨域请求

 [EnableCors(origins:"*",headers:"*",methods:"*")]

 [RoutePrefix("api/OnLogin")]

   public class OnLoginController : ApiController

   {

       [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=wxb2f63b12a7371f2a&secret=110dc84617c235b5809a7f5d8d43af3a&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;

       }  

   }

}

新建实体类RepParamrep ,保存session\_key和open\_id

   namespace WebApplication1.Models

   {

       public class RepParamrep

       {

           public string session_key { get; set; }

           public string openid { get; set; }

       }

   }

解析手机号码

\[Route(“Get”)\]  

\[HttpGet\]  

public string Get(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 "";

       }

   }

二、设计前端界面及逻辑

   //index.wxss

   <view>

     <button class="cu-btn bg-blue margin-tb-xs lg" hidden="{

        {hid1}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">授权</button>

     <button class="cu-btn bg-blue margin-tb-xs lg" hidden="{

        {hid2}}" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">进入</button>

   </view>

   //index.js

   const app = getApp();

   Page({

     data: {

       userPhone: '',

       userNicheng: '',

       hid1: false,

       hid2: true

     },

     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:44358/api/OnLogin/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

             })

           },

           fail:function(res){

             console.log(res.errMsg)

           }

         })

       }

     }

   })

   //app.js

   App({

     globalData:{

       session_key:'',

       openid:''

     },

     onLaunch: function() {

       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:44358/api/OnLogin/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)

           }

         }

       })

     }

   })

版本4


<% @ webhandler language=”C#” class=”AverageHandler” %>

using System;

using System.Net;

using System.Web;

using System.Collections.Generic;

using System.Text;

using System.Security.Cryptography;

using System.IO;

using LitJson;


public class AverageHandler : IHttpHandler

{

public bool IsReusable

{ get { return true; } }

public void ProcessRequest(HttpContext ctx)

{

   ctx.Response.ContentType = "application/json";

   HttpRequest Request = ctx.Request;

   string text = Request["encryptedData"];

   string IV = Request["iv"];

   //小程序appid和appsecret配置

   string appid = "小小星星亮晶晶";

   string secret = "小小星星亮晶晶";

   string code = Request["code"];//微信获取登录的口令

   Stream s_re = WebRequest.Create("https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+secret+"&js_code="+code+"&grant_type=authorization_code").GetResponse().GetResponseStream();

   StreamReader sr = new StreamReader(s_re, Encoding.UTF8);

   string strLine = sr.ReadToEnd();

   sr.Close();

   try

   {

       JsonData jo = JsonMapper.ToObject(strLine);

       string Key = jo["session_key"].ToString();

       //string weixinID = jo["openid"].ToString();

       string str= AES_decrypt(text,Key,IV);

       ctx.Response.Write(str);

    }

       catch (Exception ex)

    {

        //return "";

    }

}

public string AES_decrypt(string encryptedDataStr, string key, string iv)  

       {  

           RijndaelManaged rijalg = new RijndaelManaged();  

           //-----------------    

           //设置 cipher 格式 AES-128-CBC    

           rijalg.KeySize = 128;  

           rijalg.Padding = PaddingMode.PKCS7;  

           rijalg.Mode = CipherMode.CBC;  

           rijalg.Key = Convert.FromBase64String(key);  

           rijalg.IV = Convert.FromBase64String(iv);  

           byte[] encryptedData= Convert.FromBase64String(encryptedDataStr);  

           //解密    

           ICryptoTransform decryptor = rijalg.CreateDecryptor(rijalg.Key, rijalg.IV);  

           string result;  

           using (MemoryStream msDecrypt = new MemoryStream(encryptedData))  

           {  

               using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))  

               {  

                   using (StreamReader srDecrypt = new StreamReader(csDecrypt))  

                   {  

                       result = srDecrypt.ReadToEnd();  

                   }  

               }  

           }  

           return result;  

       }

}