WeChat H5 開発は openApi を呼び出します
WeChat ハードウェア プラットフォームは、物と人、物と物を接続するために WeChat によって開始された IoT ソリューションです。つまり、WeChatを通じてさまざまなスマートデバイスを制御できるのです。たとえば、一部の Bluetooth デバイス、エアコン、テレビなどです。
私はハードウェアについてはあまり詳しくありません (電子情報を専攻していますが) ハードウェアは北杭大学の 2 人の大学院生によって開発されており、私は H5 カスタム パネルの開発を担当しています。 . 初めて公式ドキュメントを読んだときは混乱しました jssdk、jsapi、Airkiss、openApi、直接接続 SDK、どれを使えばいいのか分かりません 基本的に公式フォーラムで質問しても結果は出ません。私はいくつかの WeChat ハードウェア グループに参加して質問しましたが、多くの開発者が私と同じような質問を複数のグループに投稿しており、その様子はとても悲しかったです。 wxthings にメールを送って質問すると、返事が返ってくると嬉しいですが、たいていは一言だけです。散々文句を言いましたが、やはり問題は解決しなければなりません。結局のところ、WeChat に接続できるというデバイスの機能が大きなセールスポイントであることがわかりましたので、この記事を書きました。
1. アクセスプロセス
つまり、まずパブリックアカウントを取得し、次にデバイス機能を有効にして製品 (つまり、スマートデバイス) を追加する必要があります。これらのプロセスに関する公式文書は比較的明確なので、詳細には触れません。私たちが選択したアクセス ソリューションは、WeChat Hardware Cloud の標準アクセス ソリューションです。
設定パネル
私が話している H5 パネルの開発とは、WeChat で開かれる H5 コントロール ページ、WeChat ハードウェア クラウドとの通信方法、デバイスのステータスを読み取って設定する方法を指します。製品を追加する過程で、設定パネルがあります
標準パネルを選択した場合、WeChat は 3 種類の標準パネルを公式に提供します:
それぞれ、エアコン、スイッチ、照明です。カスタマイズされている場合は、アドレスを入力します。標準パネルの場合はサーバーは必要ありませんが、カスタマイズされたパネルの場合 独自のサーバーが必要です。そうしないと、WeChat クラウド から送信されたメッセージを処理できません。
サーバー構成を有効にする
サーバーアドレスを設定する場合、正常に有効にする前に、要件に従って応答を処理する必要があることに注意してください。
クリックして有効にすると、WeChat Cloud は署名、タイムスタンプ、乱数、およびランダムな文字列を検証後にWeChat Cloudに返します。返されたランダムな文字列を取得すると、正常に有効にすることができます。たとえば、定義したアドレスが http://www.xxx.com/device/ReceiveWXMsg の場合、まずコードをサーバーにアップロードし、[WeChat Cloud がこのアドレスにデータを投稿する] をクリックします。 WeChat がサーバーにデータを送信するたびに、この検証が最初に送信されます (つまり、検証なしで返された場合、セキュリティの問題が発生します)。
public string ReceiveWXMsg() { var signature = Request.QueryString["signature"]; var timestamp = Request.QueryString["timestamp"]; var echostr = Request.QueryString["echostr"]; var nonce = Request.QueryString["nonce"]; Logger.Debug("signature:" + signature); Logger.Debug("timestamp:" + timestamp); Logger.Debug("nonce:" + nonce); Logger.Debug("echostr:" + echostr); //验证 return echostr; }
コードを表示
json
などを追加せずに直接返すだけです。このアドレスは何のためにあるのでしょうか?Wifi设备和蓝牙设备是不同的,蓝牙使用Airsync协议和微信通信,而wifi设备的话,我们在自己的服务器上调用微信提供的openApi获取或设置设备状态,微信服务器就会把数据以json格式post到我们上面设置的那个地址。硬件方面wifi设备可以使用微信提供的直连SDK来控制设备。
添加完设备,设置好服务器,你还需要硬件的同学打开设备,帮定你的微信。从微信的设置-->设备-->选择设备-->打开面板。你就可以看到设备并进行控制了。
三、调用openApi
说了这么多前提工作,终于进入调用api环节。可以先看一下openApi的官方文档:iot.weixin.qq.com/wiki/doc/hardwarecloud/openapi.pdf
文档里面主要讲了三个方法,一个是查询设备状态,一个是设置设备状态,一个是接受设备状态变化的消息,然后是一些错误信息等。但观察api就会发现我们还需要两个重要的参数,一个是access_token,一个是用户的openid。还说明一点,网页是Asp.net mvc。
1.获取access_token
官方有一个接口调试页面:mp.weixin.qq.com/debug/ ,获取access_token需要appid和secret。
而这两个值,是在公众号后台的基本配置中查看,secret是个很重要的参数,所以请保密好。
查看密钥还需要扫二维码得到管理员的确认... 拿到这两个参数了,我们就可以生成token了。注意返回的json是一个token字符串再加一个超时时间。定义一个TokenResult:
public class TokenResult { public string access_token { get; set; } public int expires_in { get; set; } }
要注意的一点是,token两小时后会过期。所以在我们的代码里面需要检查是否超时,然后自动重新获取。
public const string AccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
getAccessToken方法定义在一个服务类中,比如WxDeviceService
using SendHelp= Senparc.Weixin.CommonAPIs.CommonJsonSend;public TokenResult GetAccessToken() { var url = string.Format(WxDeviceConfig.AccessTokenUrl, WxDeviceConfig.AppId, WxDeviceConfig.APPSECRET); var res = SendHelp.Send<TokenResult>(null, url, null, CommonJsonSendType.GET); return res; }
使用Senparc.Weixin框架封装好的api来处理请求。
2.获取openid
这个参数在查询和设置设备状态的时候会用到,对应user参数名。获取openid需要三个参数,access_token已经有了,然后需要device_type和device_id
public const string GetOpenid ="https://api.weixin.qq.com/device/get_openid?access_token={0}&device_type={1}&device_id={2}";
而type和id是前端页面传过来的,当用户微信中打开控制面板的时候,微信会自动将这两个参数追加到url后面。而这个url的返回值结构是这样:
{"open_id":["oxa1otw5sk-Azgd8mx1bmBqoM2_E","oxa1ot8-j9j5bYUJJyAexe9d41_Y","oxa1ot5QTdxn0xNQ0DmYzoN0tUp1"],"resp_msg":{"ret_code":0,"error_info":"ok"}}
openid部分是一个数组,实际使用的是第三个(我目前也不知道前面两个id是干啥的),定义一个openidResult:
List<> List<> { _openId??(_openId= List<> { _openId = resp_msg resp_msg { ;
service中:
public string GetOpenId(string accessToken,string deviceType,string deviceId) { var url = string.Format(WxDeviceConfig.GetOpenid, accessToken, deviceType, deviceId); var res = SendHelp.Send<OpenIdResult>(accessToken, url, null, CommonJsonSendType.GET); return res.GetOpenId(); }
如果你的devicetype和deviceId错误,微信会返回一个不太恰当的错误json:
对比错误代码列表,我开始以为微信服务器出错了。其实是我参数填错了。
遇到的错误,将不止官方文档公布的这几个。
3.查询设备状态
查询设备和上面的这两个方法略有不同,因为流程是这的,我们的服务器先像向微信服务器请求,微信接受到请求后马上返回一个确认json,然后微信服务器会马上把数据post我们前面设置的那个地址上。
请求url:
GetDeviceStatusUrl=
从官方文档可以看到,查询设备还需要另外一个重要的参数,它包含device_type和device_id,services,user,data。
需要说明一下的就是services,意思是指设备的能力项,也就是你要查询设备的哪些属性,这个在设置设备的时候一样用到。完成的产品能力定义请看:http://iot.weixin.qq.com/wiki/doc/intro/%E4%BA%A7%E5%93%81%E8%83%BD%E5%8A%9B%E5%AE%9A%E4%B9%89%E6%8C%87%E5%BC%95%20V1.2.pdf
因此定义一个RequestData对象以及设备对应的能力项
public class RequestData { public string device_type { get; set; } public string device_id { get; set; } public string user { get; set; } public Service services { get; set; } public object data { get; set; } }
public class Service { public lightbulb lightbulb { get; set; } public air_conditioner air_conditioner { get; set; } public power_switch power_switch { get; set; } public operation_status operation_status { get; set; } }
service包括两个部分,一个是能力部分,好比上面这个service,就包含了三种能力,灯、空调以及开关(这只是测试,不是真正产品的能力)。和一个操作状态。操作状态就是指这个设备是否开着或者关闭了。而每一个能力,又包括两部分,拿灯来说:
public class lightbulb { public int alpha { get; set; } public lightbulb_value_range value_range { get; set; } } public class lightbulb_value_range { public string alpha { get; set; } }
灯有一个亮度值,和一个范围属性。范围值中包含了最大和最小值以及单位值。
"lightbulb":{"alpha":10,"value_range":{"alpha":"0|100|1"}},"
这表示灯的亮度是10,返回是0到100,每次可以调节1个单位。
发送查询请求后,微信返回一个json,定义对象为下:
public class OpenApiResult { public int error_code { get; set; } public string error_msg { get; set; } public string msg_id { get; set; } }
WxDeviceService中:
public OpenApiResult RequestDeviceStatus(string accessToken, RequestData data) { var url = string.Format(WxDeviceConfig.GetDeviceStatusUrl, accessToken); return SendHelp.Send<OpenApiResult>(accessToken, url, data); }
4.接受消息
那么问题来了,如何接受post过来的数据,以及如何存储呢。微信post的数据格式如下:
定义了一个WxResponseData对象:
public class WxResponseData { public int asy_error_code { get; set; } public string asy_error_msg { get; set; } public string create_time { get; set; } public string msg_id { get; set; } /// <summary> /// notify 说明是设备变更 /// set_resp 说明是设置设备 /// get_resp 说明获取设备信息 /// </summary> public string msg_type { get; set; } public string device_type { get; set; } public string device_id { get; set; } public object data { get; set; } public Service services { get; set; } public string user { get; set; } }
View Code
msg_type代表着不同类型的消息, notify 说明是设备变更,set_resp 说明是设置设备 get_resp 说明获取设备信息。在WxDeviceService中增加GetDeviceStatus方法:
public T GetWxResponse<T>(HttpRequestBase request) { Stream postData = request.InputStream; StreamReader sRead = new StreamReader(postData); string postContent = sRead.ReadToEnd(); if (!string.IsNullOrEmpty(postContent)) { Logger.Debug("收到数据:"+postContent); } try { return JsonConvert.DeserializeObject<T>(postContent); } catch (Exception e) { Logger.Debug(e.Message); throw; } } public WxResponseData GetDeviceStatus(HttpRequestBase request) { return GetWxResponse<WxResponseData>(request); }
需要先读取请求中的json字符串然后转换成C#对象。然后在最初启用的ReceiveWXMsg方法中随时准备接受消息:
public string ReceiveWXMsg() { var signature = Request.QueryString["signature"]; var timestamp = Request.QueryString["timestamp"]; var echostr = Request.QueryString["echostr"]; var nonce = Request.QueryString["nonce"]; Logger.Debug("signature:" + signature); Logger.Debug("timestamp:" + timestamp); Logger.Debug("nonce:" + nonce); Logger.Debug("echostr:" + echostr); try { var userdata = getUserWxData(); var data = wxDeviceService.GetDeviceStatus(Request); userdata.ResponseData = data; setUserWxData(userdata); } catch (Exception e) { Logger.Debug(e.Message); } return echostr; }
因为读取到的数据需要及时呈现给页面,所以这里选用了缓存来存储设备信息以及用户相关信息。
UserWxData:
public class UserWxData { private WxResponseData _responseData; public UserWxData() { CreateTime = DateTime.Now; } public DateTime CreateTime { get; set; } public TokenResult AccessToken { get; set; } public WxResponseData ResponseData { get { return _responseData??(_responseData=new WxResponseData()); } set { _responseData = value; } } public string OpenId { get; set; } }
View Code
private UserWxData getUserWxData() { var target = _cacheManager.Get<UserWxData>(userKey) ?? new UserWxData(); return target; } private string userKey { get { return Session.SessionID; } } private void setUserWxData(UserWxData data) { _cacheManager.Set(userKey, data, 7200); }
View Code
缓存是Nop中的MemoryCacheManager:
using System;using System.Collections.Generic;using System.Runtime.Caching;using System.Text.RegularExpressions;namespace Niqiu.Core.Domain.Common { /// <summary> /// Represents a manager for caching between HTTP requests (long term caching) /// </summary> public partial class MemoryCacheManager : ICacheManager { protected ObjectCache Cache { get { return MemoryCache.Default; } } /// <summary> /// Gets or sets the value associated with the specified key. /// </summary> /// <typeparam name="T">Type</typeparam> /// <param name="key">The key of the value to get.</param> /// <returns>The value associated with the specified key.</returns> public virtual T Get<T>(string key) { return (T)Cache[key]; } /// <summary> /// Adds the specified key and object to the cache. /// </summary> /// <param name="key">key</param> /// <param name="data">Data</param> /// <param name="cacheTime">Cache time</param> public virtual void Set(string key, object data, int cacheTime) { if (data == null) return; var policy = new CacheItemPolicy {AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime)}; Cache.Add(new CacheItem(key, data), policy); } /// <summary> /// Gets a value indicating whether the value associated with the specified key is cached /// </summary> /// <param name="key">key</param> /// <returns>Result</returns> public virtual bool IsSet(string key) { return (Cache.Contains(key)); } /// <summary> /// Removes the value with the specified key from the cache /// </summary> /// <param name="key">/key</param> public virtual void Remove(string key) { Cache.Remove(key); } /// <summary> /// Removes items by pattern /// </summary> /// <param name="pattern">pattern</param> public virtual void RemoveByPattern(string pattern) { var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase); var keysToRemove = new List<String>(); foreach (var item in Cache) if (regex.IsMatch(item.Key)) keysToRemove.Add(item.Key); foreach (string key in keysToRemove) { Remove(key); } } /// <summary> /// Clear all cache data /// </summary> public virtual void Clear() { foreach (var item in Cache) Remove(item.Key); } } }
View Code
而为什么不是PerRequestCacheManager呢,想一想~
using System;using System.Collections;using System.Collections.Generic;using System.Text.RegularExpressions;using System.Web;namespace Niqiu.Core.Domain.Common { /// <summary> /// Represents a manager for caching during an HTTP request (short term caching) /// </summary> public partial class PerRequestCacheManager : ICacheManager { /// <summary> /// Ctor /// </summary> /// <param name="context">Context</param> //public PerRequestCacheManager(HttpContextBase context) //{ // this._context = context; //} /// <summary> /// Creates a new instance of the NopRequestCache class /// </summary> protected virtual IDictionary GetItems() { if (_context != null) return _context.Items; return null; } //不用注入 private HttpContextBase _context { get { return new HttpContextWrapper(HttpContext.Current); } } /// <summary> /// Gets or sets the value associated with the specified key. /// </summary> /// <typeparam name="T">Type</typeparam> /// <param name="key">The key of the value to get.</param> /// <returns>The value associated with the specified key.</returns> public virtual T Get<T>(string key) { var items = GetItems(); if (items == null) return default(T); return (T)items[key]; } /// <summary> /// Adds the specified key and object to the cache. /// </summary> /// <param name="key">key</param> /// <param name="data">Data</param> /// <param name="cacheTime">Cache time</param> public virtual void Set(string key, object data, int cacheTime) { var items = GetItems(); if (items == null) return; if (data != null) { if (items.Contains(key)) items[key] = data; else items.Add(key, data); } } /// <summary> /// Gets a value indicating whether the value associated with the specified key is cached /// </summary> /// <param name="key">key</param> /// <returns>Result</returns> public virtual bool IsSet(string key) { var items = GetItems(); if (items == null) return false; return (items[key] != null); } /// <summary> /// Removes the value with the specified key from the cache /// </summary> /// <param name="key">/key</param> public virtual void Remove(string key) { var items = GetItems(); if (items == null) return; items.Remove(key); } /// <summary> /// Removes items by pattern /// </summary> /// <param name="pattern">pattern</param> public virtual void RemoveByPattern(string pattern) { var items = GetItems(); if (items == null) return; var enumerator = items.GetEnumerator(); var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase); var keysToRemove = new List<String>(); while (enumerator.MoveNext()) { if (regex.IsMatch(enumerator.Key.ToString())) { keysToRemove.Add(enumerator.Key.ToString()); } } foreach (string key in keysToRemove) { items.Remove(key); } } /// <summary> /// Clear all cache data /// </summary> public virtual void Clear() { var items = GetItems(); if (items == null) return; var enumerator = items.GetEnumerator(); var keysToRemove = new List<String>(); while (enumerator.MoveNext()) { keysToRemove.Add(enumerator.Key.ToString()); } foreach (string key in keysToRemove) { items.Remove(key); } } } }
View Code
5.设置设备状态
有了前面几步,这里也好说了。url:
SetDeviceUrl =
设置设备的参数和请求是一样的,
public OpenApiResult SetDevice(string accessToken, RequestData data) { var url = string.Format(WxDeviceConfig.SetDeviceUrl, accessToken); return SendHelp.Send<OpenApiResult>(accessToken, url, data); }
View Code
调用openApi基本上就这样了,如有不完善的地方还请指正。 这个方法有权限的问题,可以用查询方法代替,同样可以改变设备状态。不知道这api是个什么鬼。
四、常见错误
如果硬件通信没有开启这个能力,去查询的会报这个错误。
刚开始看到"device not login"实在没明白什么意思,文档里也没说明这个错误。设备还需要什么登录?原来是硬件同学没有连接设备... ORZ
如果你的requestData结构不对,特别是附加的那个Data参数只能是字符串,不要写成空对象{},就会出现这个错误。
token超时
同一个设备同时被操作。
【相关推荐】
1. 微信公众号平台源码下载
2. 微信投票源码下载
以上がWeChat H5 開発は openApi を呼び出しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Xianyu の公式 WeChat ミニ プログラムが静かに開始されました。ミニ プログラムでは、プライベート メッセージを投稿して購入者/販売者とコミュニケーションしたり、個人情報や注文を表示したり、商品を検索したりすることができます。プログラム、見てみましょう。 Xianyu WeChat アプレットの名前は何ですか? 回答: Xianyu、アイドル取引、中古品販売、評価、リサイクル。 1. ミニ プログラムでは、アイドル メッセージの投稿、プライベート メッセージを介した購入者/販売者とのコミュニケーション、個人情報と注文の表示、指定された商品の検索などができます。 2. ミニ プログラム ページには、ホームページ、近くに、アイドル投稿、メッセージ投稿、私の投稿 5つの機能; 3. 使用したい場合は、購入する前に WeChat 支払いを有効にする必要があります。

WeChat アプレットが画像アップロード機能を実装 モバイル インターネットの発展に伴い、WeChat アプレットは人々の生活に欠かせないものになりました。 WeChat ミニ プログラムは、豊富なアプリケーション シナリオを提供するだけでなく、画像アップロード機能などの開発者定義の機能もサポートします。この記事では、WeChat アプレットに画像アップロード機能を実装する方法と具体的なコード例を紹介します。 1. 準備作業 コードを書き始める前に、WeChat 開発者ツールをダウンロードしてインストールし、WeChat 開発者として登録する必要があります。同時に、WeChat についても理解する必要があります。

WeChat ミニ プログラムでドロップダウン メニュー効果を実装するには、特定のコード サンプルが必要です。モバイル インターネットの普及に伴い、WeChat ミニ プログラムはインターネット開発の重要な部分となり、ますます多くの人が注目し始めています。 WeChat ミニ プログラムを使用します。 WeChat ミニ プログラムの開発は、従来の APP 開発よりも簡単かつ迅速ですが、特定の開発スキルを習得する必要もあります。 WeChat ミニ プログラムの開発では、ドロップダウン メニューが一般的な UI コンポーネントであり、より良いユーザー エクスペリエンスを実現します。この記事では、WeChat アプレットにドロップダウン メニュー効果を実装し、実用的な機能を提供する方法を詳しく紹介します。

WeChat ミニ プログラムでの画像フィルター効果の実装 ソーシャル メディア アプリケーションの人気に伴い、人々は写真にフィルター効果を適用して、写真の芸術的効果や魅力を高めることがますます好まれています。画像フィルター効果は WeChat ミニ プログラムにも実装でき、より興味深く創造的な写真編集機能をユーザーに提供します。この記事では、WeChat ミニ プログラムに画像フィルター効果を実装する方法を紹介し、具体的なコード例を示します。まず、WeChat アプレットのキャンバス コンポーネントを使用して画像を読み込み、編集する必要があります。 Canvasコンポーネントはページ上で使用できます

WeChat アプレットを使用してカルーセル スイッチング効果を実現する WeChat アプレットは、シンプルで効率的な開発と使用特性を備えた軽量のアプリケーションです。 WeChat ミニ プログラムでは、カルーセル スイッチング効果を実現することが一般的な要件です。この記事では、WeChat アプレットを使用してカルーセル切り替え効果を実現する方法と、具体的なコード例を紹介します。まず、カルーセル コンポーネントを WeChat アプレットのページ ファイルに追加します。たとえば、<swiper> タグを使用すると、カルーセルの切り替え効果を実現できます。このコンポーネントでは、 b を渡すことができます。

WeChat ミニ プログラムで画像回転効果を実装するには、特定のコード サンプルが必要です。WeChat ミニ プログラムは、ユーザーに豊富な機能と優れたユーザー エクスペリエンスを提供する軽量のアプリケーションです。ミニ プログラムでは、開発者はさまざまなコンポーネントと API を使用して、さまざまな効果を実現できます。その中で、画像回転効果は、ミニプログラムに興味と視覚効果を加えることができる一般的なアニメーション効果です。 WeChat ミニ プログラムで画像の回転効果を実現するには、ミニ プログラムが提供するアニメーション API を使用する必要があります。以下は、その方法を示す具体的なコード例です。

WeChat ミニ プログラムにスライディング削除機能を実装するには、特定のコード サンプルが必要です。WeChat ミニ プログラムの人気に伴い、開発者は開発プロセス中にいくつかの一般的な機能を実装する際に問題に遭遇することがよくあります。中でも、スライド削除機能は、よく使われる一般的な機能要件です。この記事では、WeChat アプレットにスライディング削除機能を実装する方法と具体的なコード例を詳しく紹介します。 1. 要件分析 WeChat ミニ プログラムでは、スライド削除機能の実装には次の点が含まれます。 リスト表示: スライドして削除できるリストを表示するには、各リスト項目に次の要素が含まれている必要があります。

Xianyu の公式 WeChat ミニ プログラムが静かに開始され、アイドルアイテムを簡単に公開および交換できる便利なプラットフォームをユーザーに提供します。ミニ プログラムでは、プライベート メッセージを介して購入者または販売者とコミュニケーションしたり、個人情報や注文を表示したり、欲しい商品を検索したりできます。では、WeChat ミニ プログラムでは Xianyu とはいったい何と呼ばれているのでしょうか? このチュートリアル ガイドで詳しくご紹介しますので、知りたいユーザーは、この記事に従って読み続けてください。 Xianyu WeChat アプレットの名前は何ですか? 回答: Xianyu、アイドル取引、中古品販売、評価、リサイクル。 1. ミニ プログラムでは、アイドル メッセージの投稿、プライベート メッセージを介した購入者/販売者とのコミュニケーション、個人情報と注文の表示、指定された商品の検索などができます。 2. ミニ プログラム ページには、ホームページ、近くに、アイドル投稿、メッセージ投稿、マイ投稿の5つの機能、3.
