本文实例讲述了C#实现微信结合百度api获取当前用户地理位置的方法。分享给大家供大家参考,具体如下:
操作步骤:
1. 先根据微信提供的接口文档获取到经纬度
参考文档地址:http://mp.weixin.qq.com/wiki/8/1b86529d05db9f960e48c3c7ca5be288.html
2. 由于直接使用微信获取到的经纬度,来使用百度地图api获取地址存在500~1000米的偏差,有时候定位不是很准确,所以需要转换成百度的坐标
参考文档地址:http://developer.baidu.com/map/index.php?title=webapi/guide/changeposition
3. 根据百度api实现逆地址解析,获取当前位置
参考文档地址:http://developer.baidu.com/map/index.php?title=webapi/guide/webservice-geocoding
具体实例:
该例子是mvc项目
1. WX_Location.cshtml页面:
@using System.Web.Optimization;@{ Layout = "~/Views/Shared/Master/_App.cshtml";}@section Head{}<div data-role="page"> <div data-role="header" id="header" data-position="fixed"> <h1>微信定位页面</h1> </div> <div data-role="content" class="ui-content"> <form id="add" method="post" onsubmit="return false"> <table border="0" cellpadding="0" cellspacing="0" class="register_table"> <tr class='tr_bg neiy'><td class='tdl neiy'>定位:</td><td class='tdr'><input id='txt_dw' name='dw' type='text' placeholder='正在定位' class='td_input' value='' /></td></tr> </table> <div data-role="footer" data-position="fixed" data-id="footernav"> <div data-role="navbar"> <ul> <li><a href="" style=" rel="external nofollow" font-size: 1em;">返回主页</a></li> </ul> </div> </div> @Html.AntiForgeryToken() </form> </div></div>@section scripts{ @*微信js-sdk*@ <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js" type="text/javascript"></script> <script type="text/javascript"> //微信jssdk配置 wx.config({ debug: false, appId: "", timestamp: "@Html.Raw(ViewData["timestamp"])", nonceStr: "@Html.Raw(ViewData["nonceStr"])", signature: "@Html.Raw(ViewData["signature"])", jsApiList: [ 'checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'translateVoice', 'startRecord', 'stopRecord', 'onRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'closeWindow', 'scanQRCode', 'chooseWXPay', 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard' ] }); //wx.error(function (res) { // alert("错误:" + res); //}); wx.checkJsApi({ jsApiList: [ 'getLocation', ], success: function (res) { if (res.checkResult.getLocation == false) { alert('你的微信版本太低,不支持微信JS接口,请升级到最新的微信版本!'); return; } } }); wx.ready(function () { wx.getLocation({ type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02' success: function (res) { var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90 var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。 var speed = res.speed; // 速度,以米/每秒计 var accuracy = res.accuracy; // 位置精度 //alert(latitude + "。" + longitude); //获取到经纬度之后,异步去后台加载出来真实的地理位置 $.post("/App/Common/GetLocation", { lat: latitude, lon: longitude }, function (data) { //把返回回来的地理位置显示在页面的控件里面 $("#txt_dw").val(data); }, 'html'); }, cancel: function (res) { alert('用户拒绝授权获取地理位置'); } }); }); </script>}
2.
/// <summary>/// 微信定位/// </summary>/// <returns></returns>public ActionResult WX_Location(){ #region 获取定位所需要的参数 //jssdk JS接口安全域名填写, //access_token来获取jsapi_ticket string ticket = GetTicket(); var timeStamp = TenpayUtil.getTimestamp(); var nonceStr = TenpayUtil.getNoncestr(); //设置参数 RequestHandler paySignReqHandler = new RequestHandler(System.Web.HttpContext.Current); //参数顺序。 paySignReqHandler.setParameter("jsapi_ticket", ticket); paySignReqHandler.setParameter("noncestr", nonceStr); paySignReqHandler.setParameter("timestamp", timeStamp); paySignReqHandler.setParameter("url", Request.Url.AbsoluteUri);//Url#号后不要 // LogHelper.WriteInfoLog("noncestr:" + nonceStr + "。jsapi_ticked:" + ticket + "。timestamp:" + timeStamp + "。url:"+Request.Url.AbsoluteUri + "。"); ViewData["signature"] = paySignReqHandler.createSHA1Sign(); //LogHelper.WriteInfoLog("signature:" + paySignReqHandler.createSHA1Sign()); ViewData["timestamp"] = timeStamp; ViewData["nonceStr"] = nonceStr; #endregion return View();}
3. 获取地理位置方法
#region 获取地理位置public ActionResult GetLocation(string lat, string lon){ //23.1294。113.3761 LogHelper.WriteInfoLog(lat + "。" + lon); string x = string.Empty, y = string.Empty, strReturn = string.Empty; #region 先把微信经纬度(23.12536。113.36684 )转换成百度坐标 string apiurl = "http://api.map.baidu.com/geoconv/v1/?coords=" + lon + "," + lat + "&from=1&to=5&ak=你的百度地图api密钥"; WebRequest request = WebRequest.Create(@apiurl); request.Method = "POST"; WebResponse response = request.GetResponse(); Stream stream = response.GetResponseStream(); Encoding encode = Encoding.UTF8; StreamReader reader = new StreamReader(stream, encode); string detail = reader.ReadToEnd(); var jd = JsonConvert.DeserializeObject<BaiDuCoordinates>(detail); List<bc_result> result = jd.result; foreach (var item in result) { x = item.x; y = item.y; } #endregion #region 通过得到的百度坐标进行逆地址解析获取到真实的地理位置 apiurl = "http://api.map.baidu.com/geocoder/v2/?ak=8aoCgAGfz0r4MantipNitjI0&callback=renderReverse&location=" + y + "," + x + "&output=json&pois=1"; #region 通过传入的参数得到url请求 request = WebRequest.Create(@apiurl); request.Method = "POST"; response = request.GetResponse(); stream = response.GetResponseStream(); encode = Encoding.UTF8; reader = new StreamReader(stream, encode); detail = reader.ReadToEnd(); //@"(?is)(?<=)(.∗)(?=)";//(?is) // string results = System.Text.RegularExpressions.Regex.Replace(detail, @"(?is)(?<=)(.∗)(?=)", "$2"); string results = Regex.Match(detail, @"(?is)(?<=)(.∗)(?=)").Result("$1"); JsonData jsondta = JsonMapper.ToObject(results); JsonData jdItems = jsondta["result"]; //获取结构化地址信息 strReturn = (String)jdItems["formatted_address"]; LogHelper.WriteInfoLog(strReturn); #endregion #endregion return Content(strReturn);}#endregion
涉及到的相关方法以及类:
1. 获取ticket
#region w微信JS-SDK权限签名public string GetTicket(){ #region 通过 appid + appsecert 获取公众号的 access_token(不是用户的 access_token) string apiurl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + TenpayUtil.appid + "&secret=" + TenpayUtil.appsecret; #region 通过传入的参数得到url请求 WebRequest request = WebRequest.Create(@apiurl); request.Method = "POST"; WebResponse response = request.GetResponse(); Stream stream = response.GetResponseStream(); Encoding encode = Encoding.UTF8; StreamReader reader = new StreamReader(stream, encode); string detail = reader.ReadToEnd(); var jd = JsonConvert.DeserializeObject<WX_JSSDK>(detail); String access_token = (String)jd.access_token; Session["access_token"] = access_token; #endregion #endregion #region 获取ticket apiurl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token + "&type=jsapi"; request = WebRequest.Create(@apiurl); response = request.GetResponse(); stream = response.GetResponseStream(); encode = Encoding.UTF8; reader = new StreamReader(stream, encode); detail = reader.ReadToEnd(); jd = JsonConvert.DeserializeObject<WX_JSSDK>(detail); String ticket = jd.ticket; Session["ticket"] = ticket; #endregion return ticket;}#endregion
2. TenpayUtil类
/// <summary>/// TenpayUtil 的摘要说明。/// 配置文件/// </summary>public class TenpayUtil{ public static string tenpay = "1"; //财付通商户号 public static string partner = "";/ //财付通密钥 public static string key = ""; //微信appsecret public static string appsecret = ""; //微信appid public static string appid = ""; //paysignkey(非appkey) public static string appkey = ""; //支付完成后的回调处理页面,*替换成notify_url.asp所在路径 public static string tenpay_notify = ""; public TenpayUtil() { } public static string getNoncestr() { Random random = new Random(); return MD5Util.GetMD5(random.Next(1000).ToString(), "GBK"); } public static string getTimestamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); } /** 对字符串进行URL编码 */ public static string UrlEncode(string instr, string charset) { //return instr; if (instr == null || instr.Trim() == "") return ""; else { string res; try { res = HttpUtility.UrlEncode(instr, Encoding.GetEncoding(charset)); } catch (Exception ex) { res = HttpUtility.UrlEncode(instr, Encoding.GetEncoding("GB2312")); } return res; } } /** 对字符串进行URL解码 */ public static string UrlDecode(string instr, string charset) { if (instr == null || instr.Trim() == "") return ""; else { string res; try { res = HttpUtility.UrlDecode(instr, Encoding.GetEncoding(charset)); } catch (Exception ex) { res = HttpUtility.UrlDecode(instr, Encoding.GetEncoding("GB2312")); } return res; } } /** 取时间戳生成随即数,替换交易单号中的后10位流水号 */ public static UInt32 UnixStamp() { TimeSpan ts = DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); return Convert.ToUInt32(ts.TotalSeconds); } /** 取随机数 */ public static string BuildRandomStr(int length) { Random rand = new Random(); int num = rand.Next(); string str = num.ToString(); if (str.Length > length) { str = str.Substring(0, length); } else if (str.Length < length) { int n = length - str.Length; while (n > 0) { str.Insert(0, "0"); n--; } } return str; }}
3. RequestHandler类
/**'签名工具类============================================================================/// <summary>'api说明:'init();'初始化函数,默认给一些参数赋值。'setKey(key_)'设置商户密钥'createMd5Sign(signParams);字典生成Md5签名'genPackage(packageParams);获取package包'createSHA1Sign(signParams);创建签名SHA1'parseXML();输出xml'getDebugInfo(),获取debug信息** ============================================================================*/public class RequestHandler{ public RequestHandler(HttpContext httpContext) { parameters = new Hashtable(); this.httpContext = httpContext; } /** 密钥 */ private string key; protected HttpContext httpContext; /** 请求的参数 */ protected Hashtable parameters; /** debug信息 */ private string debugInfo; /** 初始化函数 */ public virtual void init() { } /** 获取debug信息 */ public String getDebugInfo() { return debugInfo; } /** 获取密钥 */ public String getKey() { return key; } /** 设置密钥 */ public void setKey(string key) { this.key = key; } /** 设置参数值 */ public void setParameter(string parameter, string parameterValue) { if (parameter != null && parameter != "") { if (parameters.Contains(parameter)) { parameters.Remove(parameter); } parameters.Add(parameter, parameterValue); } } //获取package带参数的签名包 public string getRequestURL() { this.createSign(); StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (string k in akeys) { string v = (string)parameters[k]; if (null != v && "key".CompareTo(k) != 0) { sb.Append(k + "=" + TenpayUtil.UrlEncode(v, getCharset()) + "&"); } } //去掉最后一个& if (sb.Length > 0) { sb.Remove(sb.Length - 1, 1); } return sb.ToString(); } //创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 protected virtual void createSign() { StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (string k in akeys) { string v = (string)parameters[k]; if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) { sb.Append(k + "=" + v + "&"); } } sb.Append("key=" + this.getKey()); string sign = MD5Util.GetMD5(sb.ToString(), getCharset()).ToUpper(); this.setParameter("sign", sign); //debug信息 this.setDebugInfo(sb.ToString() + " => sign:" + sign); } //创建package签名 public virtual string CreateMd5Sign(string key, string value) { StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (string k in akeys) { string v = (string)parameters[k]; if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) { sb.Append(k + "=" + v + "&"); } } sb.Append(key + "=" + value); string sign = MD5Util.GetMD5(sb.ToString(), getCharset()).ToUpper(); return sign; } //创建sha1签名 public string createSHA1Sign() { StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (string k in akeys) { string v = (string)parameters[k]; if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) { if (sb.Length == 0) { sb.Append(k + "=" + v); } else { sb.Append("&" + k + "=" + v); } } } string paySign = SHA1Util.getSha1(sb.ToString()).ToString().ToLower(); //debug信息 this.setDebugInfo(sb.ToString() + " => sign:" + paySign); return paySign; } public string GetBizSign() { Dictionary<string, string> bizParameters = new Dictionary<string, string>(); ArrayList akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (string k in akeys) { string v = (string)parameters[k]; if (!string.IsNullOrEmpty(k)) { bizParameters.Add(k.ToLower(), v); } } if (!bizParameters.Any(p => p.Key.ToLower() == "appkey")) bizParameters.Add("appkey", TenpayUtil.appkey); string bizString = FormatBizQueryParaMap(bizParameters, false); return SHA1Util.Sha1(bizString); } public string FormatBizQueryParaMap(Dictionary<string, string> paraMap, bool urlencode) { string buff = ""; try { var result = from pair in paraMap orderby pair.Key select pair; foreach (KeyValuePair<string, string> pair in result) { if (pair.Key != "") { string key = pair.Key; string val = pair.Value; if (urlencode) { val = System.Web.HttpUtility.UrlEncode(val); } buff += key.ToLower() + "=" + val + "&"; } } if (buff.Length == 0 == false) { buff = buff.Substring(0, (buff.Length - 1) - (0)); } } catch (Exception e) { throw e; //throw new SDKRuntimeException(e.Message); } return buff; } //输出XML public string parseXML() { StringBuilder sb = new StringBuilder(); sb.Append("<xml>"); int iIsNumber = 0; foreach (string k in parameters.Keys) { string v = (string)parameters[k]; if (int.TryParse(v, out iIsNumber)) { sb.Append("<" + k + ">" + v + "</" + k + ">"); } else { sb.Append("<" + k + "><![CDATA[" + v + "]]></" + k + ">"); } } sb.Append("</xml>"); return sb.ToString(); } /** 设置debug信息 */ public void setDebugInfo(String debugInfo) { this.debugInfo = debugInfo; } public Hashtable getAllParameters() { return this.parameters; } protected virtual string getCharset() { return this.httpContext.Request.ContentEncoding.BodyName; }}
4. 实体
#region 微信sdkpublic partial class WX_JSSDK{ public string access_token { get; set; } public string ticket { get; set; }}#endregion#region 百度坐标转换public partial class BaiDuCoordinates{ public string status { get; set; } public List<bc_result> result { get; set; }}public partial class bc_result{ public string x { get; set; } public string y { get; set; }}#endregion
更多关于C#相关内容感兴趣的读者可查看本站专题:《C#常见控件用法教程》、《WinForm控件用法总结》、《C#数据结构与算法教程》、《C#面向对象程序设计入门教程》及《C#程序设计之线程使用技巧总结》
希望本文所述对大家C#程序设计有所帮助。
新闻热点
疑难解答