This article describes the introduction of C# development of WeChat portals and applications using WeChat JSSDK to implement the check-in function
As WeChat gradually opens more JSSDK interfaces, we can use custom web pages ways to call more WeChat interfaces to achieve our richer interface functions and effects. For example, we can call various mobile phone hardware on the page to obtain information, such as camera photography, GPS information, scanning QR codes, etc. This book This article introduces how to use these JSSDK interfaces to implement the check-in function, where check-in requires reporting geographical coordinates and addresses, calling the camera to take pictures in real time, and obtaining relevant information about the current user, etc.
1. Description of JSSDK
WeChat JS-SDK is a web development toolkit based on WeChat provided by WeChat public platform for web developers. By using WeChat JS-SDK, web developers can use WeChat to efficiently use the capabilities of mobile phone systems such as taking pictures, selecting pictures, voice, and location. At the same time, they can directly use WeChat's unique capabilities such as sharing, scanning, coupons, and payment. , providing WeChat users with a better web experience.
The interface categories currently supported by JSSDK include the following categories: basic interface, sharing interface, image interface, audio interface, intelligent interface, device information, geographical location, shake peripherals, interface operation, WeChat scan , WeChat store, WeChat coupons, WeChat payment, with the integration of all WeChat functions, it is estimated that more interfaces will be opened one after another.
Enter the [Developer Documentation] module in the WeChat backend, and we can see the functional classification and introduction of the corresponding JSSDK, as shown below.
From the right side, we can see the usage instructions of each interface in detail. Basically, the usage methods of JSSDK are similar, so you can pass the debugging and master one or two of them, and the others Just follow the instructions and follow them.
1) Steps to use JSSDK
Step 1: Bind domain name
First log in to the WeChat public platform and enter the "Function Settings" of "Official Account Settings" to fill in the "JS Interface" "Secure Domain Name". As shown below, set it up on the public platform.
#Note: After logging in, you can view the corresponding interface permissions in the "Developer Center".
Step 2: Introduce JS files
Introduce the following JS files on the page that needs to call the JS interface (https is supported): http://res.wx.qq .com/open/js/jweixin-1.0.0.js
If you need to use the shake peripheral function, please introduce http://res.wx.qq.com/open/js/jweixin-1.1 .0.js
Note: Supports loading using AMD/CMD standard module loading method
Of course, we generally edit the page. In order to facilitate more effects, other JS may be introduced. Such as JQuery class library and so on. In addition, we can also implement richer functions based on WeUI's jquery-weui class library. The following is the JS reference in our case code.
<script src="~/Content/wechat/jquery-weui/lib/jquery-2.1.4.js"></script> <script src="~/Content/wechat/jquery-weui/js/jquery-weui.js"></script> <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js"></script>
Step 3: Inject permission verification configuration through the config interface
All pages that need to use JS-SDK must first inject configuration information, otherwise it will not be called (the same URL only needs to be called once, The web app of the SPA that changes the URL can be called every time the URL changes. Currently, the Android WeChat client does not support the new H5 feature of pushState, so using pushState to implement the web app page will cause the signature to fail. This problem will occur in Android 6 .2).
wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: '', // 必填,公众号的唯一标识 timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名,见附录1 jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 });
The above configuration is the core of JSSDK. It needs to configure the corresponding appid, timestamp, and nonceStr. There is nothing special about it. The most noteworthy thing is the implementation mechanism of signature, so that we can do it in the background. Just generate the corresponding value and assign it to the JS page. This is also the safest approach.
The following code is the HTML code in the Asp.net view page in our actual project, as shown below.
<script language="javascript"> var appid = '@ViewBag.appid'; var noncestr = '@ViewBag.noncestr'; var signature = '@ViewBag.signature'; var timestamp = '@ViewBag.timestamp'; wx.config({ debug: false, appId: appid, // 必填,公众号的唯一标识 timestamp: timestamp, // 必填,生成签名的时间戳 nonceStr: noncestr, // 必填,生成签名的随机串 signature: signature, // 必填,签名,见附录1 jsApiList: [ 'checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'translateVoice', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'onVoicePlayEnd', 'pauseVoice', 'stopVoice', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'closeWindow', 'scanQRCode', 'chooseWXPay', 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard' ] });
Step 4: Successful verification through ready interface processing
wx.ready(function(){ // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口, //则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 });
This ready interface is the processing content after the page is successfully loaded. Generally, we need to do a lot of operations, including Only after the page is loaded can the relevant objects be called for assignment, processing and other operations.
For example, after the page is ready, we can use the following JS code to obtain the corresponding GPS coordinates and other operations.
wx.ready(function () { wx.getLocation({ type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02' success: function (res) { var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90 var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。 var speed = res.speed; // 速度,以米/每秒计 var accuracy = res.accuracy; // 位置精度 $("#lblLoacation").text(latitude + "," + longitude); } }); });
Step 5: Handle failed verification through the error interface
wx.error(function(res){ // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看, // 也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 });
This error interface is also used to process exception information. Under normal circumstances, users can be prompted here for errors.
2), signature algorithm
签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
即signature=sha1(string1)。 示例:
noncestr=Wm3WZYTPz0wzccnW jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg timestamp=1414587457 url=http://mp.weixin.qq.com?params=value
步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value
步骤2. 对string1进行sha1签名,得到signature:
0f9de62fce790f9a083d5c99e95740ceb90c27ed
注意事项
1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
2.签名用的url必须是调用JS接口页面的完整URL。
3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。
如出现invalid signature 等错误详见附录5常见错误及解决办法。
以上就是JSSDK总体的使用流程,虽然看起来比较抽象,但是基本上也就是这些步骤了。
上面的过程是具体的参数处理逻辑,我们要对应到C#代码的签名实现,需要对几个变量进行处理,下面是对应的生成noncestr、timestamp、以及签名等操作的代码。
/// <summary> /// 生成时间戳,标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数 /// </summary> /// <returns>时间戳</returns> private static string GetTimeStamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); } /// <summary> /// 生成随机串,随机串包含字母或数字 /// </summary> /// <returns>随机串</returns> private static string GetNonceStr() { return Guid.NewGuid().ToString().Replace("-", ""); }
还有我们要实现JSSDK签名的处理,必须先根据几个变量,构建好URL字符串,具体的处理过程,我们可以把它们逐一放在一个Hashtable里面,如下代码所示。
/// <summary> /// 获取JSSDK所需要的参数信息,返回Hashtable结合 /// </summary> /// <param name="appId">微信AppID</param> /// <param name="jsTicket">根据Token获取到的JSSDK ticket</param> /// <param name="url">页面URL</param> /// <returns></returns> public static Hashtable GetParameters(string appId, string jsTicket, string url) { string timestamp = GetTimeStamp(); string nonceStr = GetNonceStr(); // 这里参数的顺序要按照 key 值 ASCII 码升序排序 string rawstring = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + url + ""; string signature = GetSignature(rawstring); Hashtable signPackage = new Hashtable(); signPackage.Add("appid", appId); signPackage.Add("noncestr", nonceStr); signPackage.Add("timestamp", timestamp); signPackage.Add("url", url); signPackage.Add("signature", signature); signPackage.Add("jsapi_ticket", jsTicket); signPackage.Add("rawstring", rawstring); return signPackage; }
我们注意到URL参数的字符串组合:
string rawstring = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + url + "";
这里我们拼接好URL参数后,就需要使用签名的规则来实现签名的处理了,签名的代码如下所示,注释代码和上面代码等同。
/// <summary> /// 使用SHA1哈希加密算法生成签名 /// </summary> /// <param name="rawstring">待处理的字符串</param> /// <returns></returns> private static string GetSignature(string rawstring) { return FormsAuthentication.HashPasswordForStoringInConfigFile(rawstring, "SHA1").ToLower(); ////下面和上面代码等价 //SHA1 sha1 = new SHA1CryptoServiceProvider(); //byte[] bytes_sha1_in = System.Text.UTF8Encoding.Default.GetBytes(rawstring); //byte[] bytes_sha1_out = sha1.ComputeHash(bytes_sha1_in); //string signature = BitConverter.ToString(bytes_sha1_out); //signature = signature.Replace("-", "").ToLower(); //return signature; }
这样我们有了对应的值后,我们就可以把它们的参数全部放在集合里面了供使用。
/// <summary> /// 获取用于JS-SDK的相关参数列表(该方法对accessToken和JSTicket都进行了指定时间的缓存处理,多次调用不会重复生成) /// 集合里面包括jsapi_ticket、noncestr、timestamp、url、signature、appid、rawstring /// </summary> /// <param name="appid">应用ID</param> /// <param name="appSecret">开发者凭据</param> /// <param name="url">页面URL</param> /// <returns></returns> public Hashtable GetJSAPI_Parameters(string appid, string appSecret, string url) { string accessToken = GetAccessToken(appid, appSecret); string jsTicket = GetJSAPI_Ticket(accessToken); return JSSDKHelper.GetParameters(appid, jsTicket, url); }
下面我们通过具体的代码案例来介绍使用的过程。
2、签到功能的实现处理
其实签到,都可以在微信公众号和企业号实现,微信的企业号可能实现更佳一些,不过他们使用JSSDK的接口操作是一样的,我们可以拓展过去就可以了。这里介绍微信公众号JSSDK实现签到的功能处理。
签到的功能,我们希望记录用户的GPS位置信息,还有就是利用拍照功能,拍一个照片同时上传到服务器,这样我们就可以实现整个业务效果了。
首先我们来设计签到的界面,代码及效果如下所示。
界面预览效果如下所示:
我们来看看微信JSSDK里面对于【获取地理位置接口】的说明:
wx.getLocation({ type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02' success: function (res) { var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90 var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。 var speed = res.speed; // 速度,以米/每秒计 var accuracy = res.accuracy; // 位置精度 } });
以及图形接口里面【拍照或从手机相册中选图接口】的说明:
wx.chooseImage({ count: 1, // 默认9 sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 success: function (res) { var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片 } });
上传图片到微信服务器接口如下所示。
wx.uploadImage({ localId: '', // 需要上传的图片的本地ID,由chooseImage接口获得 isShowProgressTips: 1, // 默认为1,显示进度提示 success: function (res) { var serverId = res.serverId; // 返回图片的服务器端ID } });
备注:上传图片有效期3天,可用微信多媒体接口下载图片到自己的服务器,此处获得的 serverId 即 media_id。
根据这几个接口,我们来对它们进行包装,以实现我们的业务需求。根据我们的需要,我们对JSSDK接口进行了调用,如下所示。
<script language="javascript"> var appid = '@ViewBag.appid'; var noncestr = '@ViewBag.noncestr'; var signature = '@ViewBag.signature'; var timestamp = '@ViewBag.timestamp'; wx.config({ debug: false, appId: appid, // 必填,公众号的唯一标识 timestamp: timestamp, // 必填,生成签名的时间戳 nonceStr: noncestr, // 必填,生成签名的随机串 signature: signature, // 必填,签名,见附录1 jsApiList: [ 'checkJsApi', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'getNetworkType', 'openLocation', 'getLocation' ] }); wx.ready(function () { wx.getLocation({ type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02' success: function (res) { var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90 var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。 var speed = res.speed; // 速度,以米/每秒计 var accuracy = res.accuracy; // 位置精度 $("#lblLoacation").text(latitude + "," + longitude); //解析坐标地址 var location = latitude + "," + longitude; $.ajax({ type: 'GET', url: '/JSSDKTest/GetAddress?location=' + location, //async: false, //同步 //dataType: 'json', success: function (json) { $("#lblAddress").text(json); }, error: function (xhr, status, error) { $.messager.alert("提示", "操作失败" + xhr.responseText); //xhr.responseText } }); } }); wx.getNetworkType({ success: function (res) { var networkType = res.networkType; // 返回网络类型2g,3g,4g,wifi $("#lblNetwork").text(networkType); } }); chooseImage(); }); </script>
其中的chooseImage()是我们在页面开始的时候,让用户拍照的操作,具体JS代码如下所示。
//拍照显示 var localIds; function chooseImage() { wx.chooseImage({ count: 1, // 默认9 sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['camera'], // 可以指定来源是相册还是相机,默认二者都有 success: function (res) { localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片 $("#imgUpload").attr("src", localIds); } }); }
但用户使用摄像头拍照后,就会返回一个res.localIds集合,因为我们拍照一个,那么可以把它直接赋值给图片对象,让它显示当前拍照的图片。
拍照完成,我们单击【签到】应该把图片和相关的坐标等信息上传到服务器的,图片首先是保存在微信服务器的,上传图片有效期3天,可用微信多媒体接口下载图片到自己的服务器,此处获得的 serverId 即 media_id。
为了实现我们自己的业务数据,我们需要把图片集相关信息存储在自己的服务器,这样才可以实现信息的保存,最后提示【签到操作成功】,具体过程如下所示。
//上传图片 var serverId; function upload() { wx.uploadImage({ localId: localIds[0], success: function (res) { serverId = res.serverId; //提交数据到服务器 //提示信息 $.toast("签到操作成功"); }, fail: function (res) { alert(JSON.stringify(res)); } }); }
另外,我们为了实现单击图片控件,实现重新拍照的操作,以及签到的事件处理,我们对控件的单击处理进行了绑定,如下代码所示。
document.querySelector('#imgUpload').onclick = function () { chooseImage(); }; $(document).on("click", "#btnSignIn", function () { if (localIds == undefined || localIds== null) { $.toast('请先拍照', "forbidden"); return; } //调用上传图片获得媒体ID upload(); });
The above is the detailed content of Introduction to developing WeChat portals and applications using C# to implement the check-in function using WeChat JSSDK. For more information, please follow other related articles on the PHP Chinese website!