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. 使用ant进行邮件发送,ant发送已存在的html文件

    Jenkins上使用发送邮件功能一直有问题,放弃Jenkins配置,使用ant的进行发送邮件,参考文档可以: https://www.jianshu.com/p/04cfce59890a 我这里是要发 ...

  2. Oracle中序列的操作以及使用前对序列的初始化

    Oracle中序列的操作以及使用前对序列的初始化   一 创建序列 create sequence myseq start with 1 increment by 1 nomaxvalue minva ...

  3. 系统架构的定义(与系统)-architecture

    architecture⟨system⟩ fundamental concepts or properties of a system in its environment embodied in i ...

  4. android 智能提示

    <AutoCompleteTextView android:id="@+id/autoCompleteTextView" android:completionThreshol ...

  5. css百分比问题——`top`、`left`、'translate'的百分比参照谁?

    比如 top.left.transform属性的translate方法,他们的百分比都是相较谁而言的? top.left是基于父元素的: .parent { position: relative; b ...

  6. react系列(一)JSX语法、组件概念、生命周期介绍

    JSX React中,推出了一种新的语法取名为JSX,它给了JS中写HTML标签的能力,不需要加引号.JSX的语法看起来是一种模板,然而它在编译以后,会转成JS语法,只是书写过程中的语法糖. JSX的 ...

  7. ESP8266 wifi干扰钓鱼实现

    说明:绝大部分都是对着下面的参考文章来做的.这里只把基本流程和我自己遇到的问题写一下.如有其他问题可以访问文章末的参考文章进行查找! esp8266模块 我们需要购买一块esp8266模块,如下图所示 ...

  8. windows安装多个版本的jdk,解决java-version和javac-version版本不一致的问题

    系统先装了jdk1.8 ,环境变量里配置的是jdk1.8,java -version 与javac -version 版本一致. 然后安装了jdk1.6 ,环境变量java_home 改成了1.6,但 ...

  9. memcache和redis的区别和联系

    一.区别 Memcache : 1,对每个key的数据最大是1M. 2,对各种技术支持比较全面,session可以存储memcache中,各种框架(例如thinkphp)对memcache支持比较好. ...

  10. Spring Cloud 微服务入门(二)--Spring Cloud 架构

    Spring Cloud整体核心架构:Rest服务,在Spring Cloud配置过程中,都是遵循Rest风格规范,在Rest处理中,必不可少两个对象端:服务的提供者(provider)和服务消费者( ...