この記事では、WeChat JSSDK を使用してチェックイン機能を実装する WeChat ポータルとアプリケーションの C# 開発の概要について説明します
WeChat が徐々により多くの JSSDK インターフェイスをオープンするにつれて、カスタマイズされた Web ページを使用してより多くの WeChat インターフェイスを呼び出して、WeChat の機能を実現できます。たとえば、ページ上でさまざまな携帯電話ハードウェアを呼び出して、カメラ写真、GPS 情報、QR コードのスキャンなどの情報を取得できます。この記事では、これらの JSSDK インターフェイスを使用して署名を実装する方法を紹介します。 -in. 機能のうち、チェックインには地理的座標と住所の報告、カメラを呼び出してリアルタイムで写真を撮影すること、現在のユーザーの関連情報を取得することが必要です。
1. JSSDKの説明
WeChat JS-SDKは、Web開発者向けのWeChatパブリックプラットフォームが提供するWeChatベースのWeb開発ツールキットです。 WeChat JS-SDK を使用すると、Web 開発者は WeChat を使用して、写真の撮影、写真の選択、音声、位置情報などの携帯電話システムの機能を効率的に使用できると同時に、共有、共有などの WeChat の独自の機能を直接使用できます。スキャン、クーポン、支払いなど、WeChat ユーザーに優れた Web エクスペリエンスを提供します。
現在 JSSDK でサポートされているインターフェイス カテゴリには、次のカテゴリが含まれます: 基本インターフェイス、共有インターフェイス、画像インターフェイス、オーディオ インターフェイス、スマート インターフェイス、デバイス情報、地理的位置、シェイク周辺機器、インターフェイス操作、WeChat スキャン、WeChat ストア、WeChat クーポン、 WeChat 決済は、WeChat のすべての機能が統合され、さらに多くのインターフェースが次々にオープンされると推定されています。
WeChat バックエンドの [開発者ドキュメント] モジュールに入ると、以下に示すように、対応する JSSDK の機能分類と紹介が表示されます。
右側から、各インターフェイスの使用方法の詳細が表示されます。基本的に、JSSDK の使用方法は似ているため、デバッグをパスして 1 つまたは 2 つをマスターすれば、残りはそれに従うことになります。同じ指示です。
1) JSSDK を使用する手順
ステップ 1: ドメイン名をバインドする
まず、WeChat パブリック プラットフォームにログインし、「公式アカウント設定」の「機能設定」に入り、「JS インターフェース セキュリティ ドメイン名」を入力します。 。以下のようにパブリックプラットフォーム上に設置します。
注: ログイン後、「開発者センター」で対応するインターフェースの権限を表示できます。
ステップ 2: JS ファイルを導入する
JS インターフェイスを呼び出す必要があるページに次の JS ファイルを導入します (https がサポートされています): http://res.wx.qq.com/open/js/jweixin -1.0.0 .js
シェイク周辺機能を使用する必要がある場合は、http://res.wx.qq.com/open/js/jweixin-1.1.0.jsをインポートしてください
注: の使用をサポートしていますAMD/CMD 標準モジュールのロード メソッドのロード
もちろん、より効果を高めるために、通常はページを編集します。JQuery クラス ライブラリなどの他の JS も導入する場合があります。さらに、WeUI の jquery-weui クラス ライブラリに基づいて、より豊富な関数を実装することもできます。以下は、ケース コードの JS リファレンスです。
<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>
ステップ 3: 設定インターフェイスを介して権限検証設定を挿入する
JS-SDK を使用する必要があるすべてのページは、最初に設定情報を挿入する必要があります。そうしないと、設定情報は呼び出されません (SPA の場合、同じ URL を呼び出す必要があるのは 1 回だけです) URL を変更する Web アプリ 現在、Android WeChat クライアントは新しい H5 機能の PushState をサポートしていないため、Web アプリ ページを実装するために PushState を使用すると、この問題が発生します。 Android 6.2 で修正される予定です)。
wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: '', // 必填,公众号的唯一标识 timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名,见附录1 jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 });
上記の設定は、対応する appid、timestamp、および nonceStr を設定する必要があります。最も注目すべき点は、対応する署名を生成できることです。バックグラウンドで JS ページに値を割り当てるだけです。これも最も安全な方法です。
次のコードは、実際のプロジェクトの Asp.net ビュー ページの HTML コードです。
<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' ] });
ステップ 4: Ready インターフェイスを介して成功の検証を処理する
wx.ready(function(){ // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口, //则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 });
この Ready インターフェイスは、ページが正常に読み込まれた後の処理内容であり、通常、多くの操作を実行する必要があり、ページが読み込まれた後にのみ呼び出すことができます。関連するオブジェクトの割り当て、処理、その他の操作が行われます。
たとえば、ページの準備ができたら、次の JS コードを使用して、対応する GPS 座標やその他の操作を取得できます。
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); } }); });
ステップ 5: エラー インターフェイスを通じて失敗した検証を処理する
wx.error(function(res){ // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看, // 也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 });
このエラー インターフェイスは、通常の状況では、ここでユーザーにエラーの入力を求めるプロンプトが表示されることもあります。
2)、署名アルゴリズム
签名生成规则如下:参与签名的字段包括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(); });
以上がC# を使用して WeChat ポータルとアプリケーションを開発し、WeChat JSSDK を使用してチェックイン機能を実装する方法の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。