layout: post

title: ASP.NET MVC 微信JS-SDK认证

category: .net

date: 2016-11-01 00:00:00

tags:

  • .net
  • javascript

写在前面

前阵子因为有个项目需要做微信自定义分享功能,因而去研究了下微信JS-SDK相关知识。

此文做个简单的记(tu)录(cao)...

开始

所有的东西都从文档开始:微信JSSDK说明文档

项目需要用到的是分享接口 不过使用微信JS-SDK之前,需要做JS接口认证。

认证如下:

步骤一:绑定域名

步骤二:引入JS文件

步骤三:通过config接口注入权限验证配置

步骤四:通过ready接口处理成功验证

步骤五:通过error接口处理失败验证

步骤一中允许使用域名/子域名,只要xx.com/xxx.txt或者xx.com/mp/xxx.txt能访问就好。域名认证通过之后,此域名下的所有端口的网站都可以使用JS-SDK。

步骤二没什么问题,略过。

步骤三最磨人,下面单独讲解。

config接口注入权限验证配置

先来一段说明:

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用
(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,
目前Android微信客户端不支持pushState的H5新特性,
所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,
//若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名,见附录1
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});

看到这里肯定懵逼了,这是都什么鬼...怎么玩啊。

提示我们去看附录1...看完之后总结如下:

  1. 使用config接口注入权限验证配置,重点是生成合法的signatrue
  2. 生成signature需要通过appid和secret获取token
  3. 时间戳和调用接口URL必不可少
  4. 此操作需要服务端完成,不能使用客户端实现

整个过程变成:

  1. 通过appid和secret获取access_token,接着使用token获取jsapi_ticket;

  2. 拿到jsapi_ticket之后,把jsapi_ticket、时间戳、随机字符串、接口调用页面URL 拼接成完整字符串,使用sha1算法加密得到signature。

  3. 最后返回至页面,在wx.config里面填入appid,上一步的时间戳timestamp,上一部的随机字符串、sha1拿到的signature,想要使用的JS接口。

废话少说,直接上代码吧。

代码时间

    public class WeiXinController : Controller
{
public static readonly string appid =
System.Web.Configuration.WebConfigurationManager.AppSettings["wxappid"]; public static readonly string secret =
System.Web.Configuration.WebConfigurationManager.AppSettings["wxsecret"]; public static readonly bool isDedug =
System.Web.Configuration.WebConfigurationManager.AppSettings["IsDebug"] =="true"; public static string _ticket = ""; public static DateTime _lastTimestamp; public ActionResult Info(string url,string noncestr)
{
if (string.IsNullOrEmpty(_ticket) ||
_lastTimestamp == null || (_lastTimestamp - DateTime.Now).Milliseconds > 7200)
{
var resultString = HTTPHelper.GetHTMLByURL("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
+ appid + "&secret=" + secret);
dynamic resultValue = JsonConvert.DeserializeObject<dynamic>(resultString);
if (resultValue == null || resultValue.access_token == null
|| resultValue.access_token.Value == null)
{
return Json(new { issuccess = false,
error = "获取token失败" });
}
var token = resultValue.access_token.Value; resultString = HTTPHelper.GetHTMLByURL
("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" +
token + "&type=jsapi");
dynamic ticketValue = JsonConvert.DeserializeObject<dynamic>(resultString);
if (ticketValue == null || ticketValue.errcode == null
|| ticketValue.errcode.Value != 0 || ticketValue.ticket == null)
return Json(new { issuccess = false,
error = "获取ticketValue失败" });
_ticket = ticketValue.ticket.Value;
_lastTimestamp = DateTime.Now;
var timestamp = GetTimeStamp();
var hexString = string.Format("jsapi_ticket={0}&noncestr={3}&timestamp={1}&url={2}",
_ticket, timestamp, url,noncestr); return Json(new {
issuccess = true,
sha1value = GetSHA1Value(hexString),
timestamp = timestamp,
url = url,
appid = appid,
debug=isDedug,
tiket=_ticket
}); }
else
{
var timestamp = GetTimeStamp();
var hexString = string.Format("jsapi_ticket={0}&noncestr=1234567890123456&timestamp={1}&url={2}",
_ticket, timestamp, url);
return Json(new {
issuccess = true, sha1value = GetSHA1Value(hexString),
timestamp = timestamp, url = url,
appid = appid, debug = isDedug,tiket = _ticket
});
}
} private string GetSHA1Value(string sourceString)
{
var hash = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(sourceString));
return string.Join("",
hash.Select(b => b.ToString("x2")).ToArray());
} private static string GetTimeStamp()
{ TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); } } public class HTTPHelper
{
public static string GetHTMLByURL(string url)
{
string htmlCode = string.Empty;
try
{
HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
webRequest.Timeout = 30000;
webRequest.Method = "GET";
webRequest.UserAgent = "Mozilla/4.0";
webRequest.Headers.Add("Accept-Encoding", "gzip, deflate");
HttpWebResponse webResponse = (System.Net.HttpWebResponse)webRequest.GetResponse();
//获取目标网站的编码格式
string contentype = webResponse.Headers["Content-Type"];
Regex regex = new Regex("charset\\s*=\\s*[\\W]?\\s*([\\w-]+)", RegexOptions.IgnoreCase);
if (webResponse.ContentEncoding.ToLower() == "gzip")//如果使用了GZip则先解压
{
using (System.IO.Stream streamReceive = webResponse.GetResponseStream())
{
using (var zipStream = new System.IO.Compression.GZipStream(streamReceive, System.IO.Compression.CompressionMode.Decompress))
{
//匹配编码格式
if (regex.IsMatch(contentype))
{
Encoding ending = Encoding.GetEncoding
(regex.Match(contentype).Groups[1].Value.Trim());
using (StreamReader sr = new System.IO.StreamReader(zipStream, ending))
{
htmlCode = sr.ReadToEnd();
}
}
else
{
using (StreamReader sr = new System.IO.StreamReader(zipStream, Encoding.UTF8))
{
htmlCode = sr.ReadToEnd();
}
}
}
}
}
else
{
using (System.IO.Stream streamReceive = webResponse.GetResponseStream())
{
var encoding = Encoding.Default;
if (contentype.Contains("utf"))
encoding = Encoding.UTF8;
using (System.IO.StreamReader sr = new System.IO.StreamReader(streamReceive, encoding))
{
htmlCode = sr.ReadToEnd();
} }
}
return htmlCode;
}
catch (Exception ex)
{
return "";
}
}
}

PS:这里要注意缓存一下_ticket(即access_token),照微信文档说的,access_token两个小时内有效,不需要频繁调用。而且获取access_token的接口有调用次数的限制,如果超过了次数,就不允许调用了。

PPS:建议noncestr和URL由前台传入比较适合,使用 var theWebUrl = window.location.href.split('#')[0] 获取URL,noncestr就随意了。

PPPS:遇到诡异的invalid signature的时候,首先检查url参数,然后检查noncestr,再不行重启一下程序获取一个新的token回来继续玩。

PPPPS:成果在这里,SNH48解救行动(流量预警:HTML5游戏,预计获得-15M+流量,非wifi条件祝好运。)。微信打开,直接分享或者完成游戏之后分享都可以看到自定义分享内容。

完整代码:liguobao/WeixinAPI · GitHub(测试前记得把web.config里面的appid和wxsecret改成自己的)

ASP.NET MVC 微信JS-SDK认证的更多相关文章

  1. 七天学会ASP.NET MVC (四)——用户授权认证问题

    小编应各位的要求,快马加鞭,马不停蹄的终于:七天学会 Asp.Net MVC 第四篇出炉,在第四天的学习中,我们主要了学习如何在MVC中如何实现认证授权等问题,本节主要讲了验证错误时的错误值,客户端验 ...

  2. ASP.NET MVC - 安全、身份认证、角色授权和ASP.NET Identity

    ASP.NET MVC - 安全.身份认证.角色授权和ASP.NET Identity ASP.NET MVC内置的认证特性 AuthorizeAttribute特性(System.Web.Mvc)( ...

  3. 七天学会ASP.NET MVC (四)——用户授权认证问题 【转】

    http://www.cnblogs.com/powertoolsteam/p/MVC_four.html 小编应各位的要求,快马加鞭,马不停蹄的终于:七天学会 Asp.Net MVC 第四篇出炉,在 ...

  4. C#/ASP.NET MVC微信公众号接口开发之从零开发(四) 微信自定义菜单(附源码)

    C#/ASP.NET MVC微信接口开发文章目录: 1.C#/ASP.NET MVC微信公众号接口开发之从零开发(一) 接入微信公众平台 2.C#/ASP.NET MVC微信公众号接口开发之从零开发( ...

  5. C#/ASP.NET MVC微信公众号接口开发之从零开发(三)回复消息 (附源码)

    C#/ASP.NET MVC微信接口开发文章目录: 1.C#/ASP.NET MVC微信公众号接口开发之从零开发(一) 接入微信公众平台 2.C#/ASP.NET MVC微信公众号接口开发之从零开发( ...

  6. ASP.NET MVC 微信公共平台开发之获取用户消息并处理

    ASP.NET MVC 微信公共平台开发 获取用户消息并处理 获取用户消息 用户发送的消息是在微信服务器发送的一个HTTP POST请求中包含的,获取用户发送的消息要从POST请求的数据流中获取 微信 ...

  7. ASP.NET MVC 微信公共平台开发之验证消息的真实性

    ASP.NET MVC 微信公共平台开发 验证消息的真实性 在MVC Controller所在项目中添加过滤器,在过滤器中重写 public override void OnActionExecuti ...

  8. 实战微信JS SDK开发:贺卡制作与播放(1)

    前段时间忙于CanTK 2.0的开发,所以博客一直没有更新.CanTK 2.0主要增强了游戏和富媒体的开发,现在编码和测试基本完成了,等文档完成了再正式发布,里面有不少激动人心的功能,等发布时再一一细 ...

  9. 微信JS SDK接入的几点注意事项

    微信JS SDK接入,主要可以先参考官网说明文档,总结起来有几个步骤: 1.绑定域名:先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”.备注:登录后可在“开发者中心”查看对 ...

随机推荐

  1. poj3259 Wormholes【Bellman-Ford或 SPFA判断是否有负环 】

    题目链接:poj3259 Wormholes 题意:虫洞问题,有n个点,m条边为双向,还有w个虫洞(虫洞为单向,并且通过时间为倒流,即为负数),问你从任意某点走,能否穿越到之前. 贴个SPFA代码: ...

  2. WC2018 滚粗记

    虽然又考炸了但还是总结一下.. $day0$:没有什么很重要的事.. $day1$:除了听(dong)课(mian)以外没有什么很重要的事.. $day2$:除了听(dong)课(mian)以外没有什 ...

  3. bzoj2000 [Hnoi2010]stone 取石头游戏

    Description A 公司正在举办一个智力双人游戏比赛----取石子游戏,游戏的获胜者将会获得 A 公司提供的丰厚奖金,因此吸引了来自全国各地的许多聪明的选手前来参加比赛. 与经典的取石子游戏相 ...

  4. BZOJ1009:[HNOI2008]GT考试(AC自动机,矩乘DP)

    Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字. 他的不吉利数学A1A2...Am(0< ...

  5. 跟着大神学Mongo,Mongodb主从复制本机简单操作总结

    原文链接:http://www.cnblogs.com/huangxincheng/archive/2012/03/04/2379755.html 本机安装MongoDB不在介绍,本文Mongo小菜鸟 ...

  6. 以EF形式操作mysql数据库

    1.引入Nuget包: 2.书写EF操作上下文 public class MySqlContext:DbContext { protected override void OnConfiguring( ...

  7. 设计一个方法injectBeforeAsyncSend,能够实现如下功能:在发起异步请求之前打印出请求的类型、URL、method、body、timestamp 等信息。

    异步请求逻辑注入 工作中我们需要对异步请求的请求信息打印日志,但是又不能耦合在业务代码中打印.请设计一个方法injectBeforeAsyncSend,能够实现如下功能:在发起异步请求之前打印出请求的 ...

  8. duplicate symbols for architecture arm64 导入的类库字符重复

    这个错误大部分时候是引用库重复定义的问题. 项目需要,同时引用ZBar和QQ授权登录SDK,由于二者均使用了Base64处理数据,XCode编译时报错: duplicate symbol _base6 ...

  9. 『ACM C++』 Codeforces | 1005D - Polycarp and Div 3

    今天佛了,魔鬼周一,在线教学,有点小累,但还好,今天AC了一道,每日一道,还好达成目标,还以为今天完不成了,最近任务越来越多,如何高效完成该好好思考一下了~最重要的还是学业的复习和预习. 今日兴趣新闻 ...

  10. 路由(二) router-link的使用

    main.js import Vue from 'vue'import App from './App'import VueRouter from 'vue-router'import footer ...