c#实现微信公众号开发--服务号通过oauth2获取用户信息

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/daobaqin/article/details/80295302

    2018年春节策划了一个“带现金红包的贺年卡”微信号推广活动,先说下效果:2个小时实现新增关注用户4万多户,活动页面PV达到16.8万,后因红包预算费用原因结束活动。

    实现原理:每个人都可以在服务号内发送一张自己的图片,生成定制贺卡,分享后(朋友圈、点对点发给好友、发送到微信群),好友可以打开页面,查看自己送出的祝福,同时还能领现金红包立即到账,并且:自己还能收到回礼红包,钱都由活动方来出,当然啦,领红包的前提是要关注指定微信公众号。

    每个人打开活动页面后,利用oauth2获取自己的openid,分享或转发时带上自己的openid,别人打开自己分享的贺卡页面时,获取分享人的openid,用来给其发送回礼红包,同时页面又会获取新打开人员自己的openid,用于领红包。就这样,可以实现无限级裂变传播。

    现将通过h5网页获取用户openid的方法步骤简要小结如下:

    1、准备认证过的微信服务号、web服务器、通过备案的域名;

    2、在公众号设置=》功能设置中设置“网页授权获取用户信息”中,设置自己服务器的域名,也就是公众号JS安全域名;

    3、以下为获取openid的核心代码;

第一个页面,用来获取code

testdir.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="testdir.aspx.cs" Inherits="testdir" %>


testdir.aspx.cs

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Linq;
using System.IO;
using System.Net;
using System.Text;
using System.Xml.Linq;
using Newtonsoft.Json;  
using Newtonsoft.Json.Converters; 
using Newtonsoft.Json.Linq; 


    public partial class testdir : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            string openid = Request.QueryString["openid"];
            string periods = Request.QueryString["periods"];
    Response.Redirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的appid&redirect_uri=http://你的域名/testdirsec.aspx?openid="+openid+"|"+ periods +"&response_type=code&scope=snsapi_base&state=123#wechat_redirect");
        }
    }
   

第二个页面,用code来获取openid

testdirsec.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="testdirsec.aspx.cs" Inherits="testdirsec" %>


testdirsec.aspx.cs

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Linq;
using System.IO;
using System.Net;
using System.Text;
using System.Xml.Linq;
using Newtonsoft.Json;  
using Newtonsoft.Json.Converters; 
using Newtonsoft.Json.Linq; 
using GetOpenId;

    public partial class testdirsec : System.Web.UI.Page
    {
        
        protected void Page_Load(object sender, EventArgs e)
        {
    string all = Request.QueryString["openid"];  //因为oauth2只能传递一个自定义参数,顾自行分割
            string[] array=all.Split(new Char[] { '|' });
            string fromopenid=array[0];
            string periods=array[1];
            string code = Request.QueryString["code"]; 
            CGetOpenId goi=new CGetOpenId();
            

string openid  = goi.GetOpenId(code);
Response.Redirect("test.aspx?openid=" + openid + "&periods=" + periods +"&fromopenid=" + fromopenid);

        }
    }
   


第三个页面,活动页面,这里只把核心代码展现出来,常规布局没有罗列

test.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="test.aspx.cs" Inherits="test" %>


<!DOCTYPE html>


<html>
<head id="Head1" runat="server">
    <title>我要抢红包</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css">

    <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap-theme.min.css">
    
    <style>
    body 
    { 
      -webkit-text-size-adjust: 100% !important; 
      text-size-adjust: 100% !important; 
      -moz-text-size-adjust: 100% !important; 
    } 
    
    input[type="button"], input[type="submit"], input[type="reset"] 
    {
      -webkit-appearance: none;
    }


    textarea
    {
      -webkit-appearance: none;
    } 
      
    .divtitle{text-align:center;width:100%;height: 120px;line-height: 120px;font-size: 50px;color:#ffffff;}
    .btnsubmit
    {      
      width:85%;
      font-size:60px;
      height:120px;
      border-radius:10px;
      background-color:#dddd00;
      color: #6f280f;
    }
      
    
    </style>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>



    <script>
    $.getUrlParam = function (name) {  
          var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");  
          var r = window.location.search.substr(1).match(reg);  
          if (r != null) return unescape(r[2]); return null;  
      } 
  
      var test = window.location.href;
      var periods=$.getUrlParam('periods') ;
      var openid=$.getUrlParam('openid');
  
    $.ajax({
          type:"post",
          dataType:"json",
          contentType:"application/json;charset:utf-8",
          data:JSON.stringify({"url":test}),
          url:"settest/getset.ashx",
          success:function(data)
          { 
              console.log(data);
              wx.config({
                    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId: '你的公众号appid', // 必填,公众号的唯一标识
                    timestamp: data.timestamp, // 必填,生成签名的时间戳
                    nonceStr: data.nonceStr, // 必填,生成签名的随机串
                    signature: data.signature,// 必填,签名
                    jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage'] // 必填,需要使用的JS接口列表
                });
                 wx.ready(function() {
                         
                        wx.onMenuShareTimeline({
                            title: "跟我一起抢红包,我已抢到了,好东西必须分享", // 分享标题,朋友圈
                            link:"http://你的域名与路径/testdir.aspx?openid="+ openid +"&periods="+periods , // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                            imgUrl: "http://你的域名与路径/llhb1.jpg" , // 分享图标
                            success: function () {
                                // 用户确认分享后执行的回调函数
                            },
                            cancel: function () {
                                // 用户取消分享后执行的回调函数
                            }
                        });
                        wx.onMenuShareAppMessage({
                            title: "跟我一起抢红包", // 分享标题,点对点发送信息给个人或到群里
                            desc: '我已抢到了,好东西必须分享', // 分享描述
                            link:"http://你的域名与路径/testdir.aspx?openid="+ openid +"&periods="+periods , // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                            imgUrl: "http://你的域名与路径/llhb1.jpg" , // 分享图标
                            type: '', // 分享类型,music、video或link,不填默认为link
                            dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
                            success: function () {
                            // 用户确认分享后执行的回调函数
                            },
                            cancel: function () {
                            // 用户取消分享后执行的回调函数
                            }
                            });
                  })
          }
      })
    </script>
</head>


<body style="text-align:center;width:100%;margin:0 auto;background-color: #ffffff;">
    <form id="form1" runat="server">


    <asp:Label runat="server" id="lblfromopenid"/></br></br>
<asp:Label runat="server" id="lblopenid"/></br></br>
    <asp:Label runat="server" id="lblperiods"/></br></br>
<asp:Label runat="server" id="lblaccesstoken"/></br></br>
<asp:Label runat="server" id="lbuserinfo"/></br></br>
<asp:Label runat="server" id="lbuserinfo1"/>
    </form>
</body>

</html>


test.aspx.cs

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.IO;
using System.Text;
using System.Net;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Newtonsoft.Json;  
using Newtonsoft.Json.Converters; 
using Newtonsoft.Json.Linq; 


public partial class test : System.Web.UI.Page
{
string fromopenid,openid,periods;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
fromopenid = Request.QueryString["fromopenid"];
openid = Request.QueryString["openid"];
periods = Request.QueryString["periods"];
lblfromopenid.Text = "fromopenid:" + fromopenid;
lblopenid.Text = "openid:" + openid;
lblperiods.Text = periods;
string strResult="";
string strurl="https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openid + "&lang=zh_CN";    //获取用户信息的 AccessToken 
try
{
HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(strurl);
//myReq.Timeout = timeout;
HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();
Stream myStream = HttpWResp.GetResponseStream();
StreamReader sr = new StreamReader(myStream, Encoding.UTF8);
StringBuilder strBuilder = new StringBuilder();
while (-1 != sr.Peek())
{
strBuilder.Append(sr.ReadLine());
}
strResult = strBuilder.ToString();
}
catch
{
    strResult = "err";
}
JObject obj = (JObject)JsonConvert.DeserializeObject(HttpUtility.UrlDecode(strResult));

}
}

}

至此,获取openid已经实现,下面两个文件是用到的类和服务器端处理文件

GetOpenId.cs  //内含CGetOpenId类,放在App_Code目录下的,当然如果编译项目的话dll文件就在bin目录下了

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Newtonsoft.Json;  
using Newtonsoft.Json.Converters; 
using Newtonsoft.Json.Linq; 


namespace GetOpenId
{
    public  class CGetOpenId : System.Web.UI.Page
    {
   public string GetOpenId(string code)
   {
string strResult="";
string openid="";
string strurl="https://api.weixin.qq.com/sns/oauth2/access_token?appid=你的公众号appid&secret=你的公众号secret&code="+ code +"&grant_type=authorization_code";


try
{
HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(strurl);
//myReq.Timeout = timeout;
HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();
Stream myStream = HttpWResp.GetResponseStream();
StreamReader sr = new StreamReader(myStream, Encoding.UTF8);
StringBuilder strBuilder = new StringBuilder();
while (-1 != sr.Peek())
{
strBuilder.Append(sr.ReadLine());
}
strResult = strBuilder.ToString();
}
catch
{
    strResult = "err";
}
JObject obj = (JObject)JsonConvert.DeserializeObject(HttpUtility.UrlDecode(strResult));
openid = obj["openid"].ToString().Replace("\"", "");
return openid;
   }
    }
}


getset.ashx  //在test.aspx中使用,放在服务器settest目录中

<% @ webhandler language="C#" class="getset" %>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.IO;
using System.Net;
using System.Text;
using System.Drawing;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Newtonsoft.Json;  
using Newtonsoft.Json.Converters; 
using Newtonsoft.Json.Linq;   
using System.Security.Cryptography;
using System.Web.Script.Serialization;
using GetToken;
using GetJSAPI;

public class getset : IHttpHandler
{


public void ProcessRequest(HttpContext ctx)
{
StreamReader sr=new StreamReader(ctx.Request.InputStream);
string stream = sr.ReadToEnd();
JObject jsonObj=JObject.Parse(stream);
string url=jsonObj["url"].ToString().Replace("\"","");
GetAT gt=new GetAT();
string accesstoken=gt.GetToken();
Getjsapi gj=new Getjsapi();
string jsapi=gj.GetAPI();
string timestamp=GetTimeStamp();
string nonceStr="Wm3WZYTfasdPz0wzccnW";
HttpContext.Current.Response.ContentType = "text/plain";
string content="jsapi_ticket="+jsapi+"&noncestr="+nonceStr+"&timestamp="+timestamp+"&url="+url;
string sign=SHA1(content, Encoding.UTF8);
Dictionary<String, String> dicList = new Dictionary<String, String>();
dicList.Add("timestamp", timestamp);
dicList.Add("nonceStr", nonceStr);
dicList.Add("signature", sign);

string json =(new JavaScriptSerializer()).Serialize(dicList);


ctx.Response.Write(json);

}
//使用系统自带SHA加密
public  string SHA1(string content, Encoding encode)  
{  
try  
{  
SHA1 sha1 = new SHA1CryptoServiceProvider();  
byte[] bytes_in = encode.GetBytes(content);  
byte[] bytes_out = sha1.ComputeHash(bytes_in);  
//sha1.Dispose();  
string result = BitConverter.ToString(bytes_out);  
result = result.Replace("-", "");  
return result;  
}  
catch (Exception ex)  
{  
throw new Exception("SHA1" + ex.Message);  
}  
}  
//获取时间戳
public  string GetTimeStamp()  
{  
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);  
return Convert.ToInt64(ts.TotalSeconds).ToString();  
}  
public bool IsReusable
{
    get { return true; } 
}



GetToken.cs  //在getset.ashx中使用,放在App_Code目录中

//用于获取基础access_token,这个与网页access_token不同,每天使用次数上限为2000,单次有效期7200秒,所以使用数据库保存

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Newtonsoft.Json;  
using Newtonsoft.Json.Converters; 
using Newtonsoft.Json.Linq; 
using DbOperate;


namespace GetToken
{
    public  class GetAT : System.Web.UI.Page
    {
public string GetToken()
{
SqlConnection Conn = new SqlConnection(SqlServerDB.ConnStr);
Conn.Open();
SqlCommand Comm = new SqlCommand();
Comm.Connection = Conn;
SqlDataReader dr;


string accesstoken="";
Comm.CommandText = "select appid,secret,accesstoken,DATEDIFF(second, get_date, getdate()) hour_num from weixin_accesstoken ";
dr=Comm.ExecuteReader();
if(dr.Read())
{
  if(Convert.ToInt32(dr["hour_num"].ToString())<=7000)
  {    
  accesstoken=dr["accesstoken"].ToString();
  dr.Close();
  }
  else
  {
  string strResult;
  string strurl="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ dr["appid"].ToString() +"&secret="+ dr["secret"].ToString()  +"";
  try
  {
  HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(strurl);
  //myReq.Timeout = timeout;
  HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();
  Stream myStream = HttpWResp.GetResponseStream();
  StreamReader sr = new StreamReader(myStream, Encoding.UTF8);
  StringBuilder strBuilder = new StringBuilder();
  while (-1 != sr.Peek())
  {
  strBuilder.Append(sr.ReadLine());
  }
  strResult = strBuilder.ToString();
  }
  catch
  {
  strResult = "err";
  }
  //accesstoken=strResult;
  //return strResult;
  JObject obj = (JObject)JsonConvert.DeserializeObject(HttpUtility.UrlDecode(strResult));
  accesstoken = obj["access_token"].ToString().Replace("\"", "");
  dr.Close();
  Comm.CommandText = "update weixin_accesstoken set accesstoken='"+ accesstoken +"',get_date=getdate()  ";
  Comm.ExecuteScalar();
   }
  
}


if (Conn.State == ConnectionState.Open)
{
   Conn.Close();
   Conn.Dispose();
}


return accesstoken;
}
    }

}


GetJSAPI.cs.cs  //在getset.ashx中使用,放在App_Code目录中

//用于获取time_ticket,也是单次有效时限7200秒,用数据库保存

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Newtonsoft.Json;  
using Newtonsoft.Json.Converters; 
using Newtonsoft.Json.Linq; 
using GetToken;
using DbOperate;


namespace GetJSAPI
{
    public  class Getjsapi : System.Web.UI.Page
    {
public string GetAPI()
{
SqlConnection Conn = new SqlConnection(SqlServerDB.ConnStr);
Conn.Open();
SqlCommand Comm = new SqlCommand();
Comm.Connection = Conn;
SqlDataReader dr;

string ticket="";
Comm.CommandText = "select ticket,DATEDIFF(second, get_date, getdate()) time from weixin_jsapi ";
dr=Comm.ExecuteReader();
if(dr.Read())
{
if(Convert.ToInt32(dr["time"].ToString())<=7000)
{
ticket=dr["ticket"].ToString();
dr.Close();
}
else
{
GetAT gt=new GetAT();
string accesstoken=gt.GetToken();
string strResult;
string strurl="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+accesstoken+"&type=jsapi";
try
{
HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(strurl);
//myReq.Timeout = timeout;
HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();
Stream myStream = HttpWResp.GetResponseStream();
StreamReader sr = new StreamReader(myStream, Encoding.UTF8);
StringBuilder strBuilder = new StringBuilder();
while (-1 != sr.Peek())
{
strBuilder.Append(sr.ReadLine());
}
strResult = strBuilder.ToString();
}
catch
{
strResult = "err";
}
//accesstoken=strResult;
//return strResult;
JObject obj = (JObject)JsonConvert.DeserializeObject(HttpUtility.UrlDecode(strResult));
ticket = obj["ticket"].ToString().Replace("\"", "");
dr.Close();
Comm.CommandText = "update weixin_jsapi set ticket='"+ ticket +"',get_date=getdate()  ";
Comm.ExecuteScalar();
}
  
}

if (Conn.State == ConnectionState.Open)
{
Conn.Close();
Conn.Dispose();
}

return ticket;
}
}
}


展开阅读全文

没有更多推荐了,返回首页