前端时间在家,朋友介绍开发一个移动应用,即在公众号里面增加一个菜单,然后链接页面通过查询某个银行的附近网点和全部网点。这里有个关键是,在查询附近网点的同时,能够查询出与用户当前的距离,并且能通过百度导航,从当前用户所在地导航到网点。
在这里有两个关键点:
1、如何通过微信的JSSDK,获取当前用户所在的经纬度。
2、如何通过百度地图的API,查询出附近的网点,并获取到网点的经纬度,然后进行导航。
关键点解决方案
1、在微信的JSSDK已经给出相关的API,获取当前用户所在的经纬度。
2、在百度地图的WEBAPI中,也已经给出API,通过查询获取相关数据。
难点和经验
难点1、关于微信JSSDK的验证,微信的验证的难度超过预计,特别是在使用和调试上,经常让人无所适从。
这里吐槽一下:我们看一下JSSDK的说明,简单看一下:
2)、需要配置验证参数:
wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: appId, // 必填,公众号的唯一标识 timestamp: timestamp, // 必填,生成签名的时间戳 nonceStr: nonceStr, // 必填,生成签名的随机串 signature: signature,// 必填,签名,见附录1 jsApiList: ['getLocation'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 });
appId很容易理解,申请的公众号ID。timestamp时间戳怎么来没说,nonceStr签名的随机串怎么生成没说明,signature有说明,通过timestamp、nonceStr、JsapiTicket(7200秒有效)和访问页面Url使用Sha1加密算出signature签名。
微信官方给出PHP的例子,本人使用C#,没用过PHP,还是不知道怎么验证。最后百度了一下,还好已经有人做过了,已经在网上说明。
3)、timestamp产生,(不同语言自己写算法实现,官方有PHP代码)自己写算法实现,生成时间戳 从 1970 年 1 月 1 日 00:00:00 至今的秒数,即当前的时间,且最终需要转换为字符串形式。代码如下:
public static string getTimestamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); }
4)、nonceStr产生,(不同语言自己写算法实现,官方有PHP代码)生成签名的随机串,使用MD5签名结果
public static string getNoncestr() { Random random = new Random(); return GetMD5(random.Next(1000).ToString(), "GBK"); } /** 获取大写的MD5签名结果 */ public static string GetMD5(string encypStr, string charset) { string retStr; MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider(); //创建md5对象 byte[] inputBye; byte[] outputBye; //使用GB2312编码方式把字符串转化为字节数组. try { inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr); } catch (Exception ex) { inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr); } outputBye = m5.ComputeHash(inputBye); retStr = System.BitConverter.ToString(outputBye); retStr = retStr.Replace("-", "").ToUpper(); return retStr; }
5)、signature产生,这个复杂了,微信官方真的没说清楚,这里分三步走。
*、首先通过APPID和AppSecret,产生Token票据,通过下面链接获取参数:”https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=” + appid + “&secret=” + secret。(7200秒有效)
*、通过Token票据获取JsapiTicket(7200秒有效),通过下面链接获取参数:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=” + accesstoken + “&type=jsapi
*、通过timestamp、nonceStr、JsapiTicket(7200秒有效)和访问页面Url使用Sha1加密算出signature签名。这里感谢网上高手,我这里给出参考
http://www.cnblogs.com/ysyn/p/4665897.html,但是Sha1加密,少了一步排序,参考开源组件:
最后代码如下:
/// <summary> /// 获取JS-SDK权限验证的签名Signature /// </summary> /// <param name="ticket"></param> /// <param name="noncestr"></param> /// <param name="timestamp"></param> /// <param name="url"></param> /// <returns></returns> public static string GetSignature(string ticket, string noncestr, string timestamp, string url) { var parameters = new Hashtable(); parameters.Add("jsapi_ticket", ticket); parameters.Add("noncestr", noncestr); parameters.Add("timestamp", timestamp); parameters.Add("url", url); return CreateSha1(parameters); } /// <summary> /// sha1加密 /// </summary> /// <returns></returns> private static string CreateSha1(Hashtable parameters) { var sb = new StringBuilder(); var akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (var k in akeys) { if (parameters[k] != null) { var v = (string)parameters[k]; if (sb.Length == 0) { sb.Append(k + "=" + v); } else { sb.Append("&" + k + "=" + v); } } } return getSha1(sb.ToString()).ToString().ToLower(); } public static String getSha1(String str) { //建立SHA1对象 SHA1 sha = new SHA1CryptoServiceProvider(); //将mystr转换成byte[] ASCIIEncoding enc = new ASCIIEncoding(); byte[] dataToHash = enc.GetBytes(str); //Hash运算 byte[] dataHashed = sha.ComputeHash(dataToHash); //将运算结果转换成string string hash = BitConverter.ToString(dataHashed).Replace("-", ""); return hash; }
这里有几个关键点,请大家注意,不要走弯路:
- 返回结果的反序列化,可直接用JsonConvert.DeserializeObject实现
- 四个参数大小写不能错,特别是Url的大小写,不能错,这个看网上很多走了弯路,可使用location.href.split(‘#’)[0]
- 参数的验证地址:有两个要分别验证的(????),为什么微信不一个验证就给人调试验证,让人难以理解。建议微信在增加一个验证调试接口。验证接口http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign,这里验证比较麻烦,通常需要不少时间。
- innvalid url domain当前页面所在域名与使用的appid没有绑定,请确认正确填写绑定的域名,如果使用了端口号,则配置的绑定域名也要加上端口号,注意按照域名,填写qq.com
- 难点2、百度地图WebApi的调用,相对来说就简单多了,只需要BaiduKey就行了,可直接使用http://developer.baidu.com/map/index.php?title=webapi。