分享微信开发中的一些经验
一、微信html5小游戏的一些“坑”
现如今微信为各种移动Web的小应用提供了肥沃的土壤,于是乎形形色色的应用孕育而出。人人都可以做开发,但不是每个人都能开发出好的应用,在开发过程中开发者会应注意哪些“坑”呢?本文转自深海的博客,他分享了在具体开发实现过程中基于微信的Html5 WebApp需要注意的细节以及如何用代码实现。
全文如下:
不同于传统的手游商店下载模式,HTML5 手机网页游戏是可以直接运行在微信内置的浏览器里。
这段时间团队一直在做微信端的一些产品设计和开发,当然也包含一定的运营工作。做过的东西也不少,微名片、微抢票、微活动、微招聘等一些小case。
今天想说的是我们在微信中被玩的最活跃的轻游戏--微刮奖,这东西可以被用来刮书、刮门票、刮套餐,还有客户要用来刮电话费。
先上图,感知一下具体样子:
而我想分享的是我们在具体开发实现过程中,基于微信的Html5 WebApp需要去克服的一些坑:这个小游戏的基本规则是:限定用户每天刮书次数是2次 (自由刮一次和分享后再刮一次),每天都可刮奖为此,我们希望实现的思路首先是限定在只能使用微信中玩,实现代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
if (!HttpContext.Current.Request.Browser.IsMobileDevice) { var result = new RedirectResult("url", true); filterContext.Result = result; return; } if (string.IsNullOrEmpty(HttpContext.Current.Request.UserAgent)) { var result = new RedirectResult("url", true); filterContext.Result = result; return; } if (HttpContext.Current.Request.UserAgent.IndexOf("MicroMessenger") == -1) { var result = new RedirectResult("url", true); filterContext.Result = result; return; } |
这招通过UserAgent的判断思路貌似网上大家也用的比较多,不用却依然存在挺多坑:
1. 初级问题:iOS和主流Android机器没问题,但碰到Windows Phone,就直接在微信中跳出去无法玩。原因是微信中默认的UserAgent是MicroMessenger,在这些机器的微信版本中不存在,所以为了解决Windows Phone,我们加入了如下代码:
|
1
2
3
4
5
6
|
var useragent = HttpContext.Current.Request.UserAgent.ToLower(); if (useragent.IndexOf("Windows Phone".ToLower()) != -1) { base.OnActionExecuting(filterContext); return; } |
2. 高级问题:有高人直接使用一些插件工具,伪造MicroMessenger的UserAgent,这样理论上就可以在任何可以打开网页的浏览器中玩了,解决此问题,我们利用的是微信的sdk中接口:仅当用户在微信中使用时执行控件初始化刮奖操作,否则其他终端浏览就会一直处于loading状态。
|
1
2
3
|
dataForWeixin.callback = function () { //一些初始化的操作 } |
关于微信的接口大家直接阅读原文,这边不直接贴代码出来了,不然贴不下。
上面的思路做了很多事,但对我们的业务规则来说还有一个很致命的bug没有解决。
这个bug就是只要用户手动清除微信中的cookie和缓存信息,然后重新进入活动,就能无限次刮奖,理论上是百分百中奖了。这是由于我的规则将判断当前微信用户是否刮过奖的判断依据放在了cookie中,貌似除此以外也没有其他办法。想利用openid,但我们的微信订阅号,如果从朋友圈过来的话都无法获取openid,还是依然存在上诉问题。
为了解决这个问题,最后我们终于找到了一条思路,借用微信服务号的授权接口,基本思路如下:
用户进入页面loading=》程序调用我们另外一个微信服务号的授权接口,返回openid=》将openid存入cookie(若不存在或过期,则重新执行前面步骤)=》根据openid从数据库判断本期活动刮了几次,同时,这个过程会自动判断用户是否在微信中玩游戏,否则回调将一直处于loading状态。整个过程使用下来,还比较流畅。这边贴一下授权相关的代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#region 微信授权 public ActionResult WeixinLogin(string CurrentUrl) { string url = WeixinOAuth2.Authorize(Server.UrlEncode(CurrentUrl)); return RedirectPermanent(url); } public ActionResult WeixinCallback() { if (!string.IsNullOrEmpty(Request["code"])) { // 获取AccessToken参数 var param = WeixinOAuth2.GetAccessToken(Request["code"]); string url = string.Format("{0}#access_token={1}&openid={2}&expires_in={3}&state={4}", ConfigHelper.GetValue("Weixin_Callback"), param.access_token,param.openid,param.expires_in, Server.UrlDecode(Request.QueryString["state"])); //重新跳转到回调页面,保持腾讯登录相同风格 return Redirect(url); } return View(); } /// <summary> /// 授权请求页面 /// </summary> /// <param name="flag">0为获取微信基本信息 1为获取微信openid接口</param> /// <returns></returns> public static string Authorize(string ReturnUrl) { string url=string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_base&state={2}#wechat_redirect", Weixin_AppKey, Weixin_GetOpenIDCallback, ReturnUrl); return url; } #endregion |
至此,在微信中解决如何判断当前用户的唯一性问题,基本上完全可以搞定。针对这套方案唯一存在的风险就是微信的接口的通畅性和稳定性。
当然,在整个开发过程中还有很多其他问题需要一一克服,比如,微信分享后回调的实现,相应很多朋友都要用,还比如这种小游戏我们甚至需要支持grps下流程访问,不可能那些很大的游戏框架,这怎么搞等等问题,这些打算后面再慢慢写些文章分享,今天的东西够多了,先歇歇去。
二、微信分享内容的修改
var imgUrl = "图片地址"; var lineLink = "网址"; var descContent = '内容'; var shareTitle = '标题'; var appid = ''; function shareFriend() { WeixinJSBridge.invoke('sendAppMessage',{ "appid": appid, "img_url": imgUrl, "img_width": "200", "img_height": "200", "link": lineLink, "desc": descContent, "title": shareTitle }, function(res) { //_report('send_msg', res.err_msg); }) } function shareTimeline() { WeixinJSBridge.invoke('shareTimeline',{ "img_url": imgUrl, "img_width": "200", "img_height": "200", "link": lineLink, "desc": descContent, "title": shareTitle }, function(res) { //_report('timeline', res.err_msg); }); } function shareWeibo() { WeixinJSBridge.invoke('shareWeibo',{ "content": descContent, "url": lineLink, }, function(res) { //_report('weibo', res.err_msg); }); } // 当微信内置浏览器完成内部初始化后会触发WeixinJSBridgeReady事件。 document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() { // 发送给好友 WeixinJSBridge.on('menu:share:appmessage', function(argv){ shareFriend(); }); // 分享到朋友圈 WeixinJSBridge.on('menu:share:timeline', function(argv){ shareTimeline(); }); // 分享到微博 WeixinJSBridge.on('menu:share:weibo', function(argv){ shareWeibo(); }); }, false);
三、微信开发之移动手机WEB页面(HTML5)Javascript实现一键拨号及短信发送功能
在做一个微信的微网站中的一个便民服务电话功能的应用,用到移动web页面中列出的电话号码,点击需要实现调用通讯录,网页一键拨号的拨打电话功能。
如果需要在移动浏览器中实现拨打电话,发送email,美国服务器,调用sns等功能,移动手机WEB页面(HTML5)Javascript提供的接口是一个好办法。
采用url链接的方式,实现在Safari ios,香港服务器,Android 浏览器,webos 浏览器,塞班浏览器,IE,Operamini等主流浏览器,进行拨打电话功能。
1.最常用WEB页面JS实现一键拨号的电话拨打功能:
<a href="tel:13764567708">移动WEB页面JS一键拨打号码咨询功能</a>
帅哥,美女,请注意,要把这个号码换成你的真实号码
在拨号界面,显示号码,并提示拨打。
支持大部分的浏览器,但是在QQ浏览器上支持不好。
微信现在出现屏蔽常规拨号功能,具体解决办法见《微信开发实现一键拨号出现屏蔽问题的解决方案》
2.最常用WEB页面JS实现一键发送短信功能:
<a href="sms:13764567708">移动WEB页面JS一键发送短信咨询功能</a>
在信息录入界面,显示发送号码,并提示录入信息。
支持大部分的浏览器,但是在QQ浏览器上支持不好。
3、移动web页面自动探测电话号码
<meta name="format-detection" content="telephone=no">
<meta http-equiv="x-rim-auto-match" content="none">
4.使用wtai协议进行拨打电话。
代码如下所示:
实例:
<a href="wtai://wp//mc;13764567708">拨打10086 </a>
<a href="wtai://wp/ap;13764567708;">将10086存储至电话簿 </a>
建议采用这个方式。
5、不太灵验的方式:
<a href="dc:13764567708">移动WEB页面JS一键拨打号码咨询功能</a>
经过测试,大部分浏览器都不支持了。
在测试中发现iPad上的Safari总会把长串数字识别为电话号码,文字变成蓝色,点击还会弹出菜单添加到通讯录。
别的地方倒也罢了,如果在用户名中出现数字(手机注册新浪微博的话用户名就是“手机用户xxxxxxxx”),版式会很恶心。
经过测试在a标签中的长串数字不会识别为电话,于是给出现用户名但没有链接的地方嵌套一个无动作的a标签,临时解决了这个问题。
但是这样增加了额外的标签,代码的语义性变得很差,而且对大段文字不能用这个方法。
今天无意中撞进Safari的官网,发现了safari有个私有meta属性可以解决这个问题:
<meta name="format-detection" content="telephone=no" />
四、微信浏览器判断
/**
* 判断当前浏览器是否为微信浏览器
* */
var isOpenInWechat = function (){
var ua = navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i)=="micromessenger") {
return true;
} else {
return false;
}
}
五、添加背景音乐
var board_sound = function () {
var board_audio = $('#board_audio');
var data_url = board_audio.attr('data_src');
board_audio.attr('src', data_url);
document.addEventListener('WeixinJSBridgeReady', function () {
WeixinJSBridge.invoke('getNetworkType', {}, function () {
board_audio[0].play();
board_audio.on('ended', function () {
setTimeout(function () {
board_audio.attr('src', data_url);
board_audio[0].play();
}, 200)
}, false)
});
}, false);
};
安卓机子只会播放一次,没有循环功能,所以需要做以上处理,页面html:
<div id="audio_btn">
<div class="play_yinfu"></div>
<div class="off">
<audio loop="loop" data_src="../../../music/bg-music.mp3" id="board_audio" autoplay="autoplay" preload="preload"></audio>
</div>
</div>

浙公网安备 33010602011771号