微信連Wi-Fi是為商家的線下場所提供一套完整和便捷的微信連Wi-Fi的方案。商家接入微信連Wi-Fi后,顧客無需輸入繁瑣的Wi-Fi密碼,通過微信掃二維碼等方式即可快速上網。微信連Wi-Fi還幫助商家打造個性化服務,如提供微信頂部常駐入口、商家主頁展示、連網后公眾號下發消息等。因此,微信連Wi-Fi既可以極大的提升用戶體驗,又可以幫助商家提供精准的近場服務。
微信連Wi-Fi具有以下特性

在這篇微信公眾平台開發教程中,我們將介紹如何實現微信連Wi-Fi的功能。
本文分為以下二個部分:
- 創建公眾賬號門店
- 添加微信連Wi-Fi設備
- 改造Portal型路由器設備
- 開發移動端Portal頁面
使用微信連Wi-Fi需要在“添加功能插件”中添加“門店管理”和“微信連Wi-Fi”兩項。
微信連Wi-Fi設備分為密碼型設備和Portal型設備,本教程介紹Portal型設備。
一、創建公眾賬號門店
登錄微信公眾平台,在左側邊欄點擊“門店管理“

點擊右上角“新建門店”按鈕,進入門店新建頁面;

手工填寫各類信息,完成后提交門店,然后進入審核流程,審核結果將會在5個工作日內反饋。
審核通過后,門店新建完成。
二、添加微信連Wi-Fi設備
在微信公眾平台,在左側邊欄點擊“微信連Wi-Fi“

在“設備管理”中點擊“添加設備”按鈕,

完成后提交,獲得門店Wi-Fi設備改造信息,包括:appId,shop_id,ssid,secretkey。

三、改造Portal型路由器設備
以下是某路由器設備支持連接SSID: A01-S001-R04時,查看到的路由狀態表,
root@OpenWrt:~# ubus call privoxy get_client
{
"client_array": [
{
"mac": "3c9157c5ccaf",
"ip": "192.168.4.25",
"last_active": "Wed Dec 16 14:29:31 2015\n",
"ref_cnt": 0,
"ssid": "A01-S001-R04",
"extra_infos": {
"browser_name": "safari",
"userAgent": "android"
},
"state_array": [
{
"name": "auth",
"duration": 0,
"mode": 1,
"created": "Wed Dec 16 12:17:24 2015\n"
}
]
},
{
"mac": "0c153969563f",
"ip": "192.168.4.73",
"last_active": "Wed Dec 16 14:31:41 2015\n",
"ref_cnt": 1,
"ssid": "A01-S001-R04"
}
]
}
root@OpenWrt:~#
該AC/AP在移動設備連接上SSID,彈出portal頁后,能夠臨時放行用戶的上網請求。
詳細實現一般由Wi-Fi硬件設備商來完成。
四、開發移動端Portal頁面
微信連Wi-Fi流程
顧客在手機上點選ssid后喚起portal頁,點擊頁面上“微信連Wi-Fi”按鈕進入連接前頁,展示公眾號logo和名稱,點擊“立即連網”按鈕后開始連WiFi,連接成功后跳轉到成功連接頁,默認勾選關注商家公眾號。
微信連Wi-Fi時序圖

1. 用戶手動選擇SSID,手機瀏覽器彈出Portal頁面

2. Portal頁面初始化時,向AC/AP請求移動端和AC/AP的MAC地址
蘋果手機需要開放 http://captive.apple.com/連接
3. 用戶點擊微信連Wi-Fi按鈕,瀏覽器請求AC/AP臨時放行
4. AC/AP臨時放行移動端所有上網請求
5. 瀏覽器生成ticket,發向微信Server
移動設備在portal頁中引用下述微信JSAPI,讓原有Wi-Fi portal頁具備呼起微信的能力:
<script type="text/javascript" src="https://wifi.weixin.qq.com/resources/js/wechatticket/wechatutil.js" ></script>
調用JSAPI觸發呼起微信客戶端:
Wechat_GotoRedirect(
appId,
extend,
timestamp,
sign,
shop_id,
authUrl,
mac,
ssid,
bssid
);
具體示例如下
<script type="text/javascript">
var appId = "wx1b7559b818e3c33e";
var secretkey = "9cf2e6e5af383b068178d313270c237a";
var extend = "fangbei"; //開發者自定義參數集合
var timestamp = new Date().getTime(); //時間戳(毫秒)
var shop_id = "8191752"; //AP設備所在門店的ID
var authUrl = "http://www.fangbei.org/wifigw/auth.xhtml?httpCode=200"; //認證服務端URL
var mac = "3c:91:57:c2:cc:af"; //用戶手機mac地址 安卓設備必需
var ssid = "A01-S001-R044"; //AP設備信號名稱,非必須
var bssid = "00:a0:b1:4c:a1:c5"; //AP設備mac地址,非必須
function callWechatBrowser(){
var sign = hex_md5(appId + extend + timestamp + shop_id + authUrl + mac + ssid + bssid + secretkey);
Wechat_GotoRedirect(appId, extend, timestamp, sign, shop_id, authUrl, mac, ssid, bssid);
}
</script>
參數說明
| 參數 | 是否必須 | 說明 |
|---|---|---|
| appId | 是 | 商家微信公眾平台賬號 |
| extend | 是 | extend里面可以放開發者需要的相關參數集合,最終將透傳給運營商認證URL。extend參數只支持英文和數字,且長度不得超過300個字符。 |
| timestamp | 是 | 時間戳使用毫秒 |
| sign | 是 | 請求參數簽名,具體計算方法見下方說明 |
| shop_id | 是 | AP設備所在門店的ID(微信公眾平台門店) |
| authUrl | 是 | 認證服務端URL,微信客戶端將把用戶微信身份信息向此URL提交並獲得認證放行 |
| mac | 安卓設備必需 | 用戶手機mac地址,格式冒號分隔,字符長度17個,並且字母小寫,例如:00:1f:7a:ad:5c:a8 |
| ssid | 否 | AP設備的信號名稱 |
| bssid | 否 | 無線網絡設備的無線mac地址,格式冒號分隔,字符長度17個,並且字母小寫,例如:00:1f:7a:ad:5c:a8 |
簽名的計算方法:
sign = MD5(appId + extend + timestamp + shop_id + authUrl + mac + ssid + bssid + secretkey); #注意這里timestamp為毫秒單位的當前時間戳
獲得簽名后,Portal將生成如下URL並發送到微信Server
https://wifi.weixin.qq.com/operator/callWechat.xhtml?appId=wx1b7559b818e3c223&extend=fangbei×tamp=1450260747171&sign=c9847fdf18209a760891b8de653fa71c&shopId=8191751&authUrl=http%3A%2F%2Fwifi.weixin.qq.com%2Fassistant%2Fwifigw%2Fauth.xhtml%3FhttpCode%3D200&mac=3c:91:57:c5:cc:af&ssid=A01-S001-R04&bssid=00:e0:61:4c:a7:c5
6. 微信服務器返回URL Scheme
微信服務器將返回如下鏈接
jsonpCallback({'success':true,'data':'weixin://connectToFreeWifi/?apKey=http%3A%2F%2Fmp.weixin.qq.com%2Fmp%2Fwifi%3Fq%3D47b33c80e2910d51&ticket=ba21685ba44144dc988fa02ec8254053'})
其中的data數據解碼如下
weixin://connectToFreeWifi/?apKey=http://mp.weixin.qq.com/mp/wifi?q=47b33c80e2910d51&ticket=ba21685ba44144dc988fa02ec8254053
此處為一個URL Scheme
weixin://connectToFreeWifi/
7. 調起微信連Wi-Fi前置頁面
該URL Scheme將調起微信APP,並向微信服務Server核對連WiFi注冊信息及獲取用戶微信身份,微信Server返回用戶身份信息(OpenId, tid),微信打開微信連Wi-Fi前置頁面

8. 連接Wi-Fi
用戶點立即連接 按鈕,微信自動向authUrl(JSAPI的傳入參數)發起請求,提交認證所需的用戶微信身份信息參數,包括extend、openId、tid。
http://www.fangbei.org/wifigw/auth.xhtml?httpCode=200&extend=fangbei&openId=oiPuduCHIBb2aHvZoqSm1t7KbXtw&tid=010002d1eb4ee298934a7d44c1ece599ed57c4c010119bb23028b8
參數說明如下
| 參數 | 說明 |
|---|---|
| extend | 為上文中調用呼起微信JSAPI時傳遞的extend參數,這里原樣回傳給商家主頁 |
| openId | 用戶的微信openId |
| tid | 為加密后的用戶手機號碼(僅作網監部門備案使用) |
雲端Auth URL 返回AC認證結果
authUrl所對應的后台認證服務器必須能識別這些參數信息,並向微信客戶端返回AC認證結果,微信客戶端將根據http返回碼,提示用戶連網成功與否。
若http返回碼為200,則認為服務認證成功,微信客戶端跳轉到成功連接頁,並默認勾選關注公眾號,用戶點擊“完成”按鈕后,將跳轉到商家主頁;若認證服務器需要轉移認證請求,請返回302和下一跳地址,微信客戶端將向下一跳地址再發起一次請求,302跳轉僅支持一次;對於非200和302,或者超過次數的302返回碼,視為認證失敗,此次連網失敗,微信客戶端跳轉到連接失敗頁。
注意:微信客戶端一次請求的等待時間為10s,請確保后台認證服務器在微信客戶端向authUrl發送請求10s之內返回AC認證結果,即http返回碼。超過10s未返回認證結果將視為認證失敗。
9. 連接成功
當http返回碼為200時,將轉入微信連WiFi連接成功頁

成功頁面中,顯示公眾賬號,並且默認勾選關注選項
10. 跳轉商家主頁
點擊““完成”,再跳轉到商家模版或自定義鏈接

11. 路由表中可以查看到放行狀態如下
root@OpenWrt:~# ubus call privoxy get_client
{
"client_array": [
{
"mac": "3c9157c5ccaf",
"ip": "192.168.4.25",
"last_active": "Wed Dec 16 14:58:13 2015\n",
"ref_cnt": 0,
"ssid": "A01-S001-R04",
"extra_infos": {
"browser_name": "safari",
"userAgent": "android"
},
"state_array": [
{
"name": "auth",
"duration": 0,
"mode": 1,
"created": "Wed Dec 16 12:17:24 2015\n"
}
]
},
{
"mac": "0c153969563f",
"ip": "192.168.4.73",
"last_active": "Wed Dec 16 15:08:18 2015\n",
"ref_cnt": 3,
"ssid": "A01-S001-R04",
"extra_infos": {
"browser_name": "safari",
"userAgent": "ios"
},
"state_array": [
{
"name": "auth",
"duration": 0,
"mode": 1,
"created": "Wed Dec 16 14:44:38 2015\n"
}
]
}
]
}
root@OpenWrt:~#
五、Portal頁面代碼
Portal頁面代碼實例
<!DOCTYPE HTML>
<html>
<head lang="zh-CN">
<meta charset="UTF-8">
<title>微信連Wi-Fi</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<script type="text/javascript">
/**
* 微信連Wi-Fi協議3.1供運營商portal呼起微信瀏覽器使用
*/
var loadIframe = null;
var noResponse = null;
var callUpTimestamp = 0;
function putNoResponse(ev){
clearTimeout(noResponse);
}
function errorJump()
{
var now = new Date().getTime();
if((now - callUpTimestamp) > 4*1000){
return;
}
alert('該瀏覽器不支持自動跳轉微信請手動打開微信\n如果已跳轉請忽略此提示');
}
myHandler = function(error) {
errorJump();
};
function createIframe(){
var iframe = document.createElement("iframe");
iframe.style.cssText = "display:none;width:0px;height:0px;";
document.body.appendChild(iframe);
loadIframe = iframe;
}
//注冊回調函數
function jsonpCallback(result){
if(result && result.success){
alert('WeChat will call up : ' + result.success + ' data:' + result.data);
var ua=navigator.userAgent;
if (ua.indexOf("iPhone") != -1 ||ua.indexOf("iPod")!=-1||ua.indexOf("iPad") != -1) { //iPhone
document.location = result.data;
}else{
if('false'=='true'){
alert('[強制]該瀏覽器不支持自動跳轉微信請手動打開微信\n如果已跳轉請忽略此提示');
return;
}
createIframe();
callUpTimestamp = new Date().getTime();
loadIframe.src=result.data;
noResponse = setTimeout(function(){
errorJump();
},3000);
}
}else if(result && !result.success){
alert(result.data);
}
}
function Wechat_GotoRedirect(appId, extend, timestamp, sign, shopId, authUrl, mac, ssid, bssid){
//將回調函數名稱帶到服務器端
var url = "https://wifi.weixin.qq.com/operator/callWechatBrowser.xhtml?appId=" + appId
+ "&extend=" + extend
+ "×tamp=" + timestamp
+ "&sign=" + sign;
//如果sign后面的參數有值,則是新3.1發起的流程
if(authUrl && shopId){
url = "https://wifi.weixin.qq.com/operator/callWechat.xhtml?appId=" + appId
+ "&extend=" + extend
+ "×tamp=" + timestamp
+ "&sign=" + sign
+ "&shopId=" + shopId
+ "&authUrl=" + encodeURIComponent(authUrl)
+ "&mac=" + mac
+ "&ssid=" + ssid
+ "&bssid=" + bssid;
}
//通過dom操作創建script節點實現異步請求
var script = document.createElement('script');
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
}
</script>
<link rel="stylesheet" href="https://wifi.weixin.qq.com/resources/css/style-simple-follow.css"/>
</head>
<body class="mod-simple-follow">
<div class="mod-simple-follow-page">
<div class="mod-simple-follow-page__banner">
<img class="mod-simple-follow-page__banner-bg" src="https://wifi.weixin.qq.com/resources/images/background.jpg" alt=""/>
<div class="mod-simple-follow-page__img-shadow"></div>
<div class="mod-simple-follow-page__logo">
<img class="mod-simple-follow-page__logo-img" src="https://wifi.weixin.qq.com/resources/images/t.weixin.logo.png" alt=""/>
<p class="mod-simple-follow-page__logo-name"></p>
<p class="mod-simple-follow-page__logo-welcome">歡迎您</p>
</div>
</div>
<div class="mod-simple-follow-page__attention">
<p class="mod-simple-follow-page__attention-txt">歡迎使用微信連Wi-Fi</p>
<a class="mod-simple-follow-page__attention-btn" onclick="callWechatBrowser()">一鍵打開微信連Wi-Fi2</a>
</div>
</div>
</body>
<script type="text/javascript" src="md5.js"></script>
<script type="text/javascript">
var appId = "wx1b7559b818e3c223";
var secretkey = "9cf2e6e5af387b068178d313270c737a";
var extend = "www.fangbei.org"; //開發者自定義參數集合
var timestamp = new Date().getTime(); //時間戳(毫秒)
var shop_id = "8191751"; //AP設備所在門店的ID
var authUrl = "http://www.fangbei.org/wifigw/auth.xhtml?httpCode=200"; //認證服務端URL
var mac = "3c:91:57:c5:cc:af"; //用戶手機mac地址 安卓設備必需
var ssid = "A01-S001-R044"; //AP設備信號名稱,非必須
var bssid = "00:e0:61:4c:a7:c5"; //AP設備mac地址,非必須
function callWechatBrowser(){
var sign = md5(appId + extend + timestamp + shop_id + authUrl + mac + ssid + bssid + secretkey);
Wechat_GotoRedirect(appId, extend, timestamp, sign, shop_id, authUrl, mac, ssid, bssid);
}
</script>
<script type="text/javascript">
document.addEventListener('visibilitychange', putNoResponse, false);
</script>
</html>
六、其他常見問題
1. 部分安卓手機的web瀏覽器無法自動呼起微信客戶端
6.2.5以上的Android版微信已經支持手動打開客戶端后繼續進行連接流程的功能,為保證此流程順暢進行,開發者需注意以下幾點:
1.保證微信客戶端版本為6.2.5以上的Android版微信; 2.參考示例demo中jsapi的寫法,在無法自動跳轉微信客戶端時彈出提示,讓用戶手動切換到微信; 3.在portal頁面中調用微信jsapi時,需保證AP設備的bssid、ssid、和手機mac這三個參數真實有效; 4.測試過程請從切換到目標ssid動作開始(例如:原來為3G或4G網絡然后手動選擇目標ssid,原來為非目標ssid的wifi信號然后手動選擇目標ssid,等等)。
2. IOS從portal頁面跳轉到微信后如何保證手機仍保持在目標ssid下?
IOS系統為了保證Wi-Fi是可用的,在用戶選擇完一個ssid后不會馬上切換過去,而是會嗅探通過該ssid是否能觸達公網上的預設服務,如果能嗅探到才真正顯示連接該ssid。在彈portal的AP環境中,這點正好被用來彈出portal頁面,如果在portal頁面上完成了認證,則在portal右上方的提示會由“取消”變為“完成”,如果在“取消”狀態下離開這個界面,那么剛剛選擇的ssid將會被斷開,回到上一個可用的連接,而如果在“完成”狀態下離開這個界面則不會斷開。
由於通過微信認證時,會由portal界面跳轉到微信,所以確保portal右上角的“完成”狀態是個前提。開發者需要注意以下幾點:
1.確保彈出portal后,臨時放行手機的所有流量; 2.臨時放行手機的所有流量后,局部或整體刷新portal頁面觸發IOS再次進行嗅探; 3.IOS嗅探可以正常觸達公網上的預設服務后“取消”變為“完成”; 4.以上動作完成后,再調用跳轉微信的JSAPI,繼而跳轉微信完成認證連接流程。
七、設備類型說明
| 密碼型設備 | portal型設備 | |
|---|---|---|
| 設備類型 |
|
|
| 注冊加入 微信連WiFi方式 |
|
有兩種方式:
|
| 可獲取的微信連WiFi能力 |
|
不同的接入方式具備的能力不同:
|
| 能力類型 | 微信連WiFi能力 | 能力說明 |
|---|---|---|
| 微信方式聯網能力 | 微信方式連WiFi | 接入微信帳號驗證體系,用戶可掃一掃或通過公眾號菜單一鍵連接WiFi,不需輸入密碼或通過手機號碼驗證。 |
| 默認關注公眾號 | 微信方式連WiFi過程與商家公眾號關聯,連WiFi后默認關注商家公眾號,幫助商家零邊際成本獲得線下顧客粉絲 | |
| 商戶品牌持續曝光 | 微信方式連WiFi過程中,會持續展示商戶品牌信息,為品牌提供更多曝光機會 | |
| 聯網后近場服務能力 | 微信頂部常駐入口 | 設備添加成功后、顧客到店連上WiFi,即可在微信首頁頂部看到歡迎光臨的商家主頁入口 |
| 連網后自定義消息推送 | 設備添加成功后、顧客到店連上WiFi,即可收到此店公眾號下發的聯網成功通知消息。此消息支持文字和卡券兩種格式。 | |
| 開放式商家主頁 | 從微信頂部常駐入口點擊可進入商家主頁,此頁面開放給商家自行定義內容、可配置商家自有網站鏈接。 |

