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

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

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

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

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

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

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

 

二、前端登录获取Code

官方文档

uni-app

  

  

小程序获取用户手机号和用户openid和昵称服务器端代码(C#)_第1张图片

 

三、后端解密

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

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


 

  1. 版本1

     
  2. 版本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
    {
        /// 
        /// wxapi 的摘要说明
        /// 
        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
        {
     
            /// 
            /// 获取链接返回数据
            /// 
            /// 链接
            /// 请求类型
            /// 
            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;
     
            /// 
            /// AES解密
            /// 
            /// 输入的数据encryptedData
            /// key
            /// 向量128
            /// 解密后的字符串
            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 实体类
        /// 
        /// 微信用户类
        /// 
        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; }
        }
        /// 
        /// 微信用户数据水印
        /// 
        public class data
        {
            public string appid { get; set; }
            public string timestamp { get; set; }
        }
        /// 
        /// 微信小程序验证返回结果
        /// 
        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. 版本3

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

    否则会出现下列情况
    小程序获取用户手机号和用户openid和昵称服务器端代码(C#)_第2张图片

    一、搭建后台服务器(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(html);
                return rep;
            }  
        }
    }
    
  4.  

     

    新建实体类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
    
      
      
    
    

     

     

    //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)
            }
          }
        })
      } 
    })
  5. 版本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;  
        }
 
  
 
}

 

你可能感兴趣的:(C#,小程序,小程序,微信)