C#開發(fā)微信門戶及應(yīng)用(28)--微信“搖一搖·周邊”功能的使用和接口的實(shí)現(xiàn)
”搖一搖周邊“是微信提供的一種新的基于位置的連接方式。用戶通過“搖一搖”的“周邊”頁(yè)卡,可以與線下商戶進(jìn)行互動(dòng),獲得商戶提供的個(gè)性化的服務(wù)。微信4月份有一個(gè)贈(zèng)送搖一搖設(shè)備的活動(dòng),我們有幸獲得贈(zèng)送資格,取得一個(gè)搖一搖的設(shè)備用來(lái)測(cè)試這個(gè)新增的、很有潛力的功能?!睋u一搖周邊“是微信基于低功耗藍(lán)牙技術(shù)的 O2O 入口級(jí)應(yīng)用,與微信的其他線下連接能力一道,加速促成了微信 O2O 閉環(huán)的實(shí)現(xiàn)。本文主要介紹一搖設(shè)備的配置使用,以及如何在開發(fā)層面上,定義及實(shí)現(xiàn)微信搖一搖的功能接口。
1、IBeacon基礎(chǔ)知識(shí)介紹
搖一搖周邊是基于IBeacon來(lái)實(shí)現(xiàn)的。IBeacon是蘋果公司開發(fā)的一種通過低功耗藍(lán)牙技術(shù)進(jìn)行一個(gè)十分精確的微定位技術(shù)。IBeacon設(shè)備通過藍(lán)牙信號(hào)廣播設(shè)備id, 手機(jī)等終端進(jìn)入IBeacon設(shè)備的信號(hào)范圍,可以收到該設(shè)備的id.
實(shí)現(xiàn)分如下四個(gè)步驟:
?????? 第一步. 服務(wù)提供者向微信后臺(tái)申請(qǐng)服務(wù),微信后臺(tái)生成一個(gè)IBeaconId,并將其映射到服務(wù)提供者提供的服務(wù),再將IBeaconId告訴服務(wù)提供者;
?????? 第二步. 服務(wù)提供者把第一步拿到的IBeaconId設(shè)置到IBeacon設(shè)備上,讓IBeacon設(shè)備廣播該IBeaconId;
?????? 第三步. 用戶在該IBeacon設(shè)備的信號(hào)范圍內(nèi)打開微信搖一搖周邊,微信App拿到該IBeaconId;
?????? 第四步. 微信通過第三步拿到的IBeaconId,向微信后臺(tái)拉取相應(yīng)的服務(wù),展示在搖出來(lái)的結(jié)果上。
?????? 第五步. 用戶點(diǎn)擊搖出來(lái)結(jié)果,在微信內(nèi)嵌的瀏覽器上,會(huì)帶上用戶信息跳轉(zhuǎn)到服務(wù)提供者在第一步申請(qǐng)服務(wù)時(shí)填的url,進(jìn)入應(yīng)用頁(yè)面
應(yīng)用場(chǎng)景:
2、搖一搖設(shè)備的使用
搖一搖的beacon設(shè)備很小,底座可以用贈(zèng)送的雙面膠粘貼在墻面上,底面還可以貼一個(gè)微信的提示標(biāo)簽,挺有意思的效果。
同時(shí)可以下載這個(gè)beacon設(shè)備的App軟件RealKit進(jìn)行設(shè)置設(shè)備,設(shè)備界面管理界面如下所示。
根據(jù)官方搖一搖(https://zb.weixin.qq.com/)的配置說(shuō)明,我們擁有設(shè)備后,需要配置設(shè)備響應(yīng)的頁(yè)面,流程如下所示。
?
由于是微信贈(zèng)送的設(shè)備,默認(rèn)情況下,微信后臺(tái)已經(jīng)給我們添加贈(zèng)送的搖一搖設(shè)備記錄了;
如果是自己購(gòu)買這種搖一搖的設(shè)備,那么需要自己手工添加設(shè)備記錄,并輸入相關(guān)的參數(shù)即可。
添加設(shè)備后,我們需要配置搖一搖的頁(yè)面,頁(yè)面就是在搖動(dòng)微信的時(shí)候,顯示給微信用戶的一個(gè)界面,頁(yè)面管理界面如下所示。
最終配置完成后,我們就來(lái)試一下這個(gè)神秘的設(shè)備了,看看效果如何。這個(gè)設(shè)備的信號(hào)穿透力還是很不錯(cuò),隔了10米,兩堵墻搖一搖還是很快出來(lái)界面的。
這個(gè)搖一搖周邊的功能,我在IPhone4S里面始終無(wú)法出現(xiàn)周邊這個(gè)模塊,在5、6plus里面倒是很正常的出現(xiàn)并響應(yīng)處理,而IPAD則是在搖一搖后出現(xiàn)頁(yè)面的,但是頁(yè)面無(wú)法響應(yīng)。
?
3、基于C#的微信搖一搖接口的實(shí)現(xiàn)
搖一搖和功能界面相呼應(yīng),提供了設(shè)備管理、頁(yè)面管理、素材管理、關(guān)聯(lián)關(guān)系綁定、設(shè)備及用戶信息、數(shù)據(jù)統(tǒng)計(jì)等功能接口,如下所示。
1)設(shè)備管理
而其中設(shè)備管理部分,又分為了好幾個(gè)API的處理。
1 申請(qǐng)?jiān)O(shè)備ID
2 編輯設(shè)備信息
3 配置設(shè)備與門店的關(guān)聯(lián)關(guān)系
4 查詢?cè)O(shè)備列表
申請(qǐng)?jiān)O(shè)備ID
接口說(shuō)明?申請(qǐng)配置設(shè)備所需的UUID、Major、Minor。申請(qǐng)成功后返回批次ID,可用返回的批次ID用“查詢?cè)O(shè)備列表”接口拉取本次申請(qǐng)的設(shè)備ID。單次新增設(shè)備超過500個(gè),需走人工審核流程,大概需要三個(gè)工作日;單次新增設(shè)備不超過500個(gè)的,當(dāng)日可返回申請(qǐng)的設(shè)備ID。一個(gè)公眾賬號(hào)最多可申請(qǐng)99999個(gè)設(shè)備ID,如需申請(qǐng)的設(shè)備ID數(shù)超過最大限額,請(qǐng)郵件至zhoubian@tencent.com,郵件格式如下: 標(biāo)題:申請(qǐng)?zhí)嵘O(shè)備ID額度 內(nèi)容:1、公眾賬號(hào)名稱及appid(wx開頭的字符串,在mp平臺(tái)可查看) 2、用途 3、預(yù)估需要多少設(shè)備ID。
接口調(diào)用說(shuō)明
http請(qǐng)求方式: POST(請(qǐng)使用https協(xié)議) https://api.weixin.qq.com/shakearound/device/applyid?access_token=ACCESS_TOKEN POST數(shù)據(jù)格式:json POST數(shù)據(jù)例子: { "quantity":3, "apply_reason":"測(cè)試", "comment":"測(cè)試專用", "poi_id":1234 }
參數(shù)說(shuō)明
參數(shù) | 是否必須 | 說(shuō)明 |
---|---|---|
access_token | 是 | 調(diào)用接口憑證 |
quantity | 是 | 申請(qǐng)的設(shè)備ID的數(shù)量,單次新增設(shè)備超過500個(gè),需走人工審核流程 |
apply_reason | 是 | 申請(qǐng)理由,不超過100個(gè)字 |
comment | 否 | 備注,不超過15個(gè)漢字或30個(gè)英文字母 |
poi_id | 否 | 設(shè)備關(guān)聯(lián)的門店ID,關(guān)聯(lián)門店后,在門店1KM的范圍內(nèi)有優(yōu)先搖出信息的機(jī)會(huì)。門店相關(guān)信息具體可查看門店相關(guān)的接口文檔 |
返回說(shuō)明?正常時(shí)的返回JSON數(shù)據(jù)包示例:
當(dāng)申請(qǐng)個(gè)數(shù)小于等于500時(shí), { "data": { "apply_id": 123, "device_identifiers":[ { "device_id":10100, "uuid":"FDA50693-A4E2-4FB1-AFCF-C6EB07647825", "major":10001, "minor":10002 } ] }, "errcode": 0, "errmsg": "success." } 當(dāng)申請(qǐng)個(gè)數(shù)大于500時(shí), { "data": { "apply_id": 123, "audit_status": 0, "audit_comment": "審核未通過" }, "errcode": 0, "errmsg": "success." }
參數(shù)說(shuō)明
?
參數(shù) | 說(shuō)明 |
---|---|
device_identifiers | 指定的設(shè)備ID列表 |
device_id | 設(shè)備編號(hào) |
UUID、major、minor | UUID、major、minor |
audit_status | 審核狀態(tài)。0:審核未通過、1:審核中、2:審核已通過;審核會(huì)在三個(gè)工作日內(nèi)完成 |
audit_comment | 審核備注,包括審核不通過的原因 |
apply_id | 申請(qǐng)的批次ID,可用在“查詢?cè)O(shè)備列表”接口按批次查詢本次申請(qǐng)成功的設(shè)備ID。 |
根據(jù)這些接口定義,我們可以創(chuàng)建一個(gè)搖一搖專用的接口類IShakeAround。
/// <summary> /// 搖一搖周邊的接口定義 /// </summary> public interface IShakeAround { #region 設(shè)備管理 /// <summary> /// 申請(qǐng)?jiān)O(shè)備ID。 /// 接口說(shuō)明 申請(qǐng)配置設(shè)備所需的UUID、Major、Minor。 /// 若激活率小于50%,不能新增設(shè)備。單次新增設(shè)備超過500個(gè),需走人工審核流程。審核通過后,可用返回的批次ID用“查詢?cè)O(shè)備列表”接口拉取本次申請(qǐng)的設(shè)備ID。 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="applyInfo">設(shè)備申請(qǐng)信息</param> ShakeDeviceApplyJson ApplyDevice(string accessToken, ShakeDeviceAddJson applyInfo); /// <summary> /// 編輯設(shè)備信息。 /// 接口說(shuō)明 編輯設(shè)備的備注信息。可用設(shè)備ID或完整的UUID、Major、Minor指定設(shè)備,二者選其一。 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="info">設(shè)備信息</param> /// <param name="comment">設(shè)備的備注信息,不超過15個(gè)漢字或30個(gè)英文字母。</param> /// <returns></returns> CommonResult UpdateDevice(string accessToken, ShakeDeviceIdentifier info, string comment); /// <summary> /// 配置設(shè)備與門店的關(guān)聯(lián)關(guān)系。接口說(shuō)明 修改設(shè)備關(guān)聯(lián)的門店ID、設(shè)備的備注信息??捎迷O(shè)備ID或完整的UUID、Major、Minor指定設(shè)備,二者選其一。 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="info">設(shè)備信息</param> /// <param name="poi_id">待關(guān)聯(lián)的門店ID</param> /// <returns></returns> CommonResult BindDevice(string accessToken, ShakeDeviceIdentifier info, int poi_id); /// <summary> /// 查詢?cè)O(shè)備列表. /// 接口說(shuō)明 查詢已有的設(shè)備ID、UUID、Major、Minor、激活狀態(tài)、備注信息、關(guān)聯(lián)門店、關(guān)聯(lián)頁(yè)面等信息??芍付ㄔO(shè)備ID或完整的UUID、Major、Minor查詢,也可批量拉取設(shè)備信息列表。 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="device_identifiers">設(shè)備列表信息</param> /// <returns></returns> ShakeDeviceSearchList SearchDevice(string accessToken, List<ShakeDeviceIdentifier> device_identifiers); /// <summary> /// 查詢?cè)O(shè)備列表. /// 接口說(shuō)明 查詢已有的設(shè)備ID、UUID、Major、Minor、激活狀態(tài)、備注信息、關(guān)聯(lián)門店、關(guān)聯(lián)頁(yè)面等信息??芍付ㄔO(shè)備ID或完整的UUID、Major、Minor查詢,也可批量拉取設(shè)備信息列表。 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="data">分頁(yè)查詢條件。apply_id為批次ID,如果指定則以批次進(jìn)行查詢,否則以指定范圍查詢。</param> /// <returns></returns> ShakeDeviceSearchList SearchDevice(string accessToken, ShakeDeviceSearchPaging data); #endregion
接口定義好,我們?cè)黾訉?duì)應(yīng)的類實(shí)現(xiàn)即可,如下是申請(qǐng)?jiān)O(shè)備的接口具體實(shí)現(xiàn)函數(shù),其他遵循同樣的規(guī)則就不再贅述。
/// <summary> /// 申請(qǐng)?jiān)O(shè)備ID。 /// 接口說(shuō)明 申請(qǐng)配置設(shè)備所需的UUID、Major、Minor。 /// 若激活率小于50%,不能新增設(shè)備。單次新增設(shè)備超過500個(gè),需走人工審核流程。審核通過后,可用返回的批次ID用“查詢?cè)O(shè)備列表”接口拉取本次申請(qǐng)的設(shè)備ID。 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="applyInfo">設(shè)備申請(qǐng)信息</param> public ShakeDeviceApplyJson ApplyDevice(string accessToken, ShakeDeviceAddJson applyInfo) { var url = string.Format("https://api.weixin.qq.com/shakearound/device/applyid?access_token={0}", accessToken); string postData = applyInfo.ToJson(); ShakeDeviceApplyJson data = null; ShakeDeviceApplyResult result = JsonHelper<ShakeDeviceApplyResult>.ConvertJson(url, postData); if (result != null) { data = result.data; } return data; }
?
2)頁(yè)面管理
同樣頁(yè)面管理也包含了幾個(gè)不同的方法,用來(lái)創(chuàng)建、編輯、刪除頁(yè)面等處理操作
1 新增頁(yè)面
2 編輯頁(yè)面信息
3 查詢頁(yè)面列表
4 刪除頁(yè)面
新增頁(yè)面
新增搖一搖出來(lái)的頁(yè)面信息,包括在搖一搖頁(yè)面出現(xiàn)的主標(biāo)題、副標(biāo)題、圖片和點(diǎn)擊進(jìn)去的超鏈接。其中,圖片必須為用素材管理接口上傳至微信側(cè)服務(wù)器后返回的鏈接。
接口調(diào)用說(shuō)明
http請(qǐng)求方式: POST(請(qǐng)使用https協(xié)議) https://api.weixin.qq.com/shakearound/page/add?access_token=ACCESS_TOKEN POST數(shù)據(jù)格式:json POST數(shù)據(jù)例子: { "title":"主標(biāo)題", "description":"副標(biāo)題", "page_url":" https://zb.weixin.qq.com ", "comment":"數(shù)據(jù)示例", "icon_url":"http://3gimg.qq.com/shake_nearby/dy/icon " }
根據(jù)這些接口定義,同樣我們可以為IShakeAround接口類增加對(duì)應(yīng)的接口定義了。
#region 頁(yè)面管理 /// <summary> /// 新增頁(yè)面。 /// 新增搖一搖出來(lái)的頁(yè)面信息,包括在搖一搖頁(yè)面出現(xiàn)的主標(biāo)題、副標(biāo)題、圖片和點(diǎn)擊進(jìn)去的超鏈接。 /// 其中,圖片必須為用素材管理接口上傳至微信側(cè)服務(wù)器后返回的鏈接。 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="info">新增頁(yè)面POST數(shù)據(jù)對(duì)象</param> /// <returns></returns> ShakePageResult AddPage(string accessToken, ShakePageJson info); /// <summary> /// 編輯頁(yè)面信息。 /// 編輯搖一搖出來(lái)的頁(yè)面信息,包括在搖一搖頁(yè)面出現(xiàn)的主標(biāo)題、副標(biāo)題、圖片和點(diǎn)擊進(jìn)去的超鏈接。 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="info">編輯頁(yè)面POST數(shù)據(jù)對(duì)象</param> /// <returns></returns> ShakePageResult UpdatePage(string accessToken, ShakePageJson info); /// <summary> /// 查詢頁(yè)面列表。 /// 查詢已有的頁(yè)面,包括在搖一搖頁(yè)面出現(xiàn)的主標(biāo)題、副標(biāo)題、圖片和點(diǎn)擊進(jìn)去的超鏈接。 /// 提供詢方式:指定頁(yè)面ID查詢。 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="begin">頁(yè)面列表的起始索引值</param> /// <param name="count">待查詢的頁(yè)面?zhèn)€數(shù)</param> /// <returns></returns> ShakePageSearchJson SearchPage(string accessToken, int begin, int count); /// <summary> /// 查詢頁(yè)面列表。 /// 查詢已有的頁(yè)面,包括在搖一搖頁(yè)面出現(xiàn)的主標(biāo)題、副標(biāo)題、圖片和點(diǎn)擊進(jìn)去的超鏈接。 /// 提供詢方式:批量拉取頁(yè)面列表 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="page_ids">指定頁(yè)面的id列表</param> /// <returns></returns> ShakePageSearchJson SearchPage(string accessToken, List<int> page_ids); /// <summary> /// 查詢頁(yè)面列表。 /// 查詢已有的頁(yè)面,包括在搖一搖頁(yè)面出現(xiàn)的主標(biāo)題、副標(biāo)題、圖片和點(diǎn)擊進(jìn)去的超鏈接。 /// 提供兩種查詢方式,可指定頁(yè)面ID查詢,也可批量拉取頁(yè)面列表。 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="info"></param> /// <returns></returns> ShakePageSearchJson SearchPage(string accessToken, ShakePageSearchPaging info); /// <summary> /// 刪除頁(yè)面。 /// 刪除已有的頁(yè)面,包括在搖一搖頁(yè)面出現(xiàn)的主標(biāo)題、副標(biāo)題、圖片和點(diǎn)擊進(jìn)去的超鏈接。 /// 只有頁(yè)面與設(shè)備沒有關(guān)聯(lián)關(guān)系時(shí),才可被刪除。 /// </summary> /// <param name="accessToken">調(diào)用接口憑證</param> /// <param name="page_ids">指定頁(yè)面的id列表</param> /// <returns></returns> CommonResult DeletePage(string accessToken, List<int> page_ids); #endregion 頁(yè)面管理
3)其他管理
當(dāng)然除了上面設(shè)備、頁(yè)面的管理,還有一些如
上傳圖片素材、配置設(shè)備與頁(yè)面的關(guān)聯(lián)關(guān)系、以設(shè)備為維度的數(shù)據(jù)統(tǒng)計(jì)接口、以頁(yè)面為維度的數(shù)據(jù)統(tǒng)計(jì)接口等方法接口用來(lái)實(shí)現(xiàn),根據(jù)上面的處理方式定義即可。
4)測(cè)試代碼
增加相關(guān)的接口定義,以及完成對(duì)應(yīng)的接口實(shí)現(xiàn),我們就需要編寫一些測(cè)試類來(lái)對(duì)我們的接口進(jìn)行測(cè)試的,這些對(duì)設(shè)備、頁(yè)面的測(cè)試代碼如下所示。
/// <summary> /// 搖一搖設(shè)備的申請(qǐng)、修改、綁定處理操作測(cè)試 /// </summary> private void btnDevice_Click(object sender, EventArgs e) { try { int poi_id = 275961135; ShakeDeviceApplyJson result = api.ApplyDevice(this.token, new ShakeDeviceAddJson() { quantity = 1, apply_reason = "測(cè)試", comment = "測(cè)試備注", poi_id = poi_id }); if (result != null) { Console.WriteLine(result.ToJson()); if (result.device_identifiers != null) { ShakeDeviceIdentifier device = result.device_identifiers[0]; if (device != null) { int device_id = device.device_id; //465123; Console.WriteLine(device_id); string comment = "修改的備注"; ShakeDeviceIdentifier info = new ShakeDeviceIdentifier(device.device_id, device.uuid, device.major, device.minor); CommonResult comResult = api.UpdateDevice(this.token, info, comment); MessageUtil.ShowTips(comResult.Success ? "操作成功" : "修改設(shè)備失敗:" + comResult.ErrorMessage); comResult = api.BindDevice(this.token, info, poi_id); MessageUtil.ShowTips(comResult.Success ? "操作成功" : "修改設(shè)備失敗:" + comResult.ErrorMessage); } } } } catch(Exception ex) { Console.WriteLine(ex); } }
?
/// <summary> /// 增加搖一搖素材、增加頁(yè)面、修改頁(yè)面、刪除頁(yè)面的操作示例代碼 /// </summary> private void btnPage_Click(object sender, EventArgs e) { string file = FileDialogHelper.OpenImage(false); if(string.IsNullOrEmpty(file)) { return; } ShakeMaterialJson mediaJson = api.AddMaterail(this.token, file); if (mediaJson != null) { ShakePageJson json = new ShakePageJson() { title = "主標(biāo)題", description = "副標(biāo)題", comment = "備注說(shuō)明", page_url = "https://www.iqidi.com", icon_url = mediaJson.pic_url }; ShakePageResult result = api.AddPage(this.token, json); if (result != null) { Console.WriteLine(result.ToJson()); if (result.data != null) { json.page_id = result.data.page_id; json.comment = "修改備注信息"; result = api.UpdatePage(this.token, json); if (result != null) { Console.WriteLine("修改頁(yè)面"); Console.WriteLine(result.ToJson()); } CommonResult comResult = api.DeletePage(this.token, new List<int>() { json.page_id.Value }); MessageUtil.ShowTips(comResult.Success ? "刪除頁(yè)面操作成功" : "刪除頁(yè)面失敗:" + comResult.ErrorMessage); } } } }
個(gè)人認(rèn)為,搖一搖設(shè)備,開啟了一個(gè)更廣闊的應(yīng)用空間,隨著越來(lái)越多設(shè)備商的支持,微信接口的完善和增加,可以迸發(fā)出更多有意思、實(shí)用的應(yīng)用場(chǎng)景。
專注于Winform開發(fā)框架/混合式開發(fā)框架、Web開發(fā)框架、Bootstrap開發(fā)框架、微信門戶開發(fā)框架的研究及應(yīng)用。
??轉(zhuǎn)載請(qǐng)注明出處:
撰寫人:伍華聰??http://www.iqidi.com?
????
本文摘自 :https://blog.51cto.com/w