微信JS-SDK开发过程中,使用getLocation获取坐标位置,如何将微信获取的坐标直接应用到百度地图中,显示以下效果:
说明:红色图标是从微信转换过来的位置,蓝色图标是周边位置。首先从微信开发流程讲解。
1、微信JS-SDK开发文档
首先进入官网的帮助文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=〈=zh_CN
可对文档进行详细的研读,要获取位置信息,分以下步骤:
第一步:绑定域名
进入微信公众号,找到“公众号设置”菜单,进入“功能设置”面板,
点击“设置”可设置引用js的相关域名:
第二步:引用官方js类库
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js 。
引用页面是location.aspx,如下:
<%@ Page Title=\"获取位置\" Language=\"C#\" AutoEventWireup=\"true\" MasterPageFile=\"~/wxcrm/Site.Master\" CodeFile=\"location.aspx.cs\" Inherits=\"DTcms.Web.wxcrm.location\" %> <asp:Content ID=\"Content1\" ContentPlaceHolderID=\"cphHead\" runat=\"server\"> <script src=\"http://res.wx.qq.com/open/js/jweixin-1.0.0.js\"></script> <script type=\"text/javascript\"> $(\"#mask\").show(); wx.config({ debug: false, //开启调试模式,如为true,则弹出每个js函数调用情况 appId: \'<%= ResultJsData.GetValue(\"appid\") %>\', //必填,公众号的唯一标识 timestamp: <%= ResultJsData.GetValue(\"timestamp\") %>, //必填,生成签名的时间戳 nonceStr: \'<%= ResultJsData.GetValue(\"noncestr\") %>\', //必填,生成签名的随机串 signature: \'<%= ResultJsData.GetValue(\"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.ready(function(){ wx.checkJsApi({ jsApiList: [ \'getNetworkType\', \'previewImage\', \'getLocation\' ], success: function (res) { } }); wx.getLocation({ type: \'wgs84\', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入\'gcj02\' success: function (res) { try { var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90 var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。 var speed = res.speed; // 速度,以米/每秒计 var accuracy = res.accuracy; // 位置精度 //alert(JsonUti.convertToString(res)); //wx.openLocation({ // latitude: res.latitude, // 纬度,浮点数,范围为90 ~ -90 // longitude: res.longitude, // 经度,浮点数,范围为180 ~ -180。 // name: \'当前位置\', // 位置名 // address: \'点击查看\', // 地址详情说明 // scale: 28, // 地图缩放级别,整形值,范围从1~28。默认为最大 // infoUrl: \"location1.aspx?m=Home&c=Index&a=getlocation&latitude=\"+latitude+\"&longitude=\"+longitude // 在查看位置界面底部显示的超链接,可点击跳转 //}); //alert(latitude+\"-\"+longitude); $(\"#mask\").hide(); window.location.href = \"location1.aspx?m=Home&c=Index&a=getlocation&latitude=\" + latitude + \"&longitude=\" + longitude + \"&=speed\" + speed + \"&accuracy=\" + accuracy; } catch (e) { alert(e.message); } }, cancel: function (res) { window.location.href=\"none.aspx?msg=拒绝获取地理位置&r=\" + Math.random();//拒绝 }, fail:function() { alert(\"未能获取地理位置!首先检查手机是否启用微信定位。\"); } }); }); wx.error(function(res) { // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 }); wx.fail(function(res) { }); </script> </asp:Content> <asp:Content ID=\"Content2\" ContentPlaceHolderID=\"cphTitle\" runat=\"server\"> 获取位置 </asp:Content> <asp:Content ID=\"Content3\" ContentPlaceHolderID=\"cphContainer\" runat=\"server\"> <br /> <br /> <center style=\"display: block;\"> <i class=\"weui_icon_msg weui_icon_info\"></i> <div class=\"input_errow\" style=\"width: 60%; height: 60%; text-align: center;\"> 正在获取地理位置信息... </div> </center> <div class=\"mask\" style=\"display: none;\"> <span> <img src=\"/templates/txwap/images/mask.gif\" /> </span> </div> </asp:Content>
页面效果:
注意事项:
(1)如果手机设置不允许微信获取位置信息,则提示以上信息。
(2)上图参数获取的是GPS坐标,如使用百度地图,要做一定转换,将在location1.aspx中体现。
(3)所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用。
对应location.aspx.cs实现:
using Payment.WxWebHlper; using Payment.WxWebHlper.Actions; using System; using System.Globalization; using WxJsSDK; using WxPayAPI; namespace DTcms.Web.wxcrm { public partial class location : PageBase { protected string appId { get; set; } protected string timestamp { get; set; } protected string nonceStr { get; set; } protected string signature { get; set; } public static string WxJsApiParam { get; set; } public WxJsData ResultJsData { get; set; } protected void Page_Load(object sender, EventArgs e) { JudgeCode(); var webAuthorize = new WebAuthorizeAction(); Code2TokenResult = webAuthorize.Code2Token(Request[\"code\"]); if (Code2TokenResult.HasError()) { Response.Redirect(Urls.PageOfLocation); GotoNonePage(\"获取用户凭证失败,请重新获取\"); return; } GetUserInfoResult = webAuthorize.GetUserInfo(Code2TokenResult.access_token); if (GetUserInfoResult.HasError()) { GotoNonePage(\"获取用户信息失败,请重新获取\"); } var userid = wxOperation.HasBind(GetUserInfoResult.openid); if (userid.Equals(Guid.Empty)) { Response.Redirect(Urls.Oauth2Url); GotoNonePage(\"微信用户未绑定\"); } appId = WxPayConfig.APPID; timestamp = WxPayApi.GenerateTimeStamp(); nonceStr = WxPayApi.GenerateNonceStr(); //以下实现将在3、核心代码实现 体现 var jsApi = new JsApi(this); ResultJsData = jsApi.GetJsData(); WxJsApiParam = jsApi.GetJsApiParameters();//获取H5调起JS API参数 } } }
2、将微信GPS坐标转换为百度坐标
微信获取坐标成功后,页面自动跳转到location1.aspx,处理流程如下:
微信坐标—>转换为百度地图坐标—>根据百度地图API获取位置信息—>根据百度地图API显示坐标
<%@ Page Title=\"在线签到\" Language=\"C#\" MasterPageFile=\"~/wxcrm/Site.Master\" AutoEventWireup=\"true\" CodeFile=\"location1.aspx.cs\" Inherits=\"DTcms.Web.wxcrm.location1\" %> <asp:Content ID=\"Content1\" ContentPlaceHolderID=\"cphHead\" runat=\"server\"> <meta name=\"viewport\" content=\"initial-scale=1.0, user-scalable=no\" /> <style type=\"text/css\"> #allmap { width: 100%; height: 300px; } </style> <script type=\"text/javascript\" src=\"http://api.map.baidu.com/api?v=2.0&ak=dhRLKMR9QUO4wHmnnSZTarta\"></script> <script type=\"text/javascript\"> //GPS坐标 var yy = <%= this.Request[\"longitude\"] %>; //经度,浮点数,范围为180 ~ -180。 var xx = <%= this.Request[\"latitude\"] %>; //纬度,浮点数,范围为90 ~ -90 var gpsPoint = new BMap.Point(xx,yy); var bxx = 0.0; var byy = 0.0; /* * http://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition */ var PositionUrl = \"http://api.map.baidu.com/geoconv/v1/?\"; function changePosition(){ var str = \"coords=\"+yy+\",\"+xx+\"&from=1&to=5\"; var url = PositionUrl + str; $(\"#positionUrl\").html(url+\"&ak=dhRLKMR9QUO4wHmnnSZTartg\"); var script = document.createElement(\'script\'); script.src = url + \'&ak=dhRLKMR9QUO4wHmnnSZTarta&callback=dealResult\'; document.getElementsByTagName(\"head\")[0].appendChild(script); } function dealResult(msg){ if(msg.status != 0){ alert(\"无正确的返回结果。\"); $(\"#mask\").hide(); return; } //JsonUti.convertToString(msg); bxx = msg.result[0].x; byy = msg.result[0].y; doOptions(); } function getBaiduPosition() { var url =\"http://api.map.baidu.com/geoconv/v1/?coords=\"+yy+\",\"+xx+\"&from=1&to=5&ak=dhRLKMR9QUO4wHmnnSZTarta\"; $.ajax({ url: url, success: function(data,status,xhr) { alert(status); alert(data.status); }, dataType: json }); } var ADVANCED_POST = \'\'; var advancedOptions = \'\'; var address; var map; function renderOption(response) { var html = \'\'; if (response.status ) { $(\"#mask\").hide(); var text = \"无正确的返回结果!\"; alert(text); return; } var result = response.result; var location = response.result.location; var uri = \'http://api.map.baidu.com/marker?location=\'+ location.lat+\',\'+location.lng +\'&title=\'+response.result.level+\'&content=\'+address+\'&output=html\'; var staticimageUrl = \"http://api.map.baidu.com/staticimage?center=\" + location.lng+\',\'+location.lat + \"&markers=\" + location.lng+\',\'+location.lat; html = \'<p>坐标:纬度: \' + location.lat + \" 经度: \" + location.lng+\'<br />\'; html += \'精度: \'+response.result.precise+\'<br />\' ; html += \'可信度: \'+response.result.confidence +\'<br />\'; html += \'地址类型: \'+response.result.level+\'</p>\' ; html += \'<p><img src=\"\' + staticimageUrl + \'\" /></p>\' ; html += \'<p>分享该点: <a href=\"\' + uri + \'\" target=\"_blank\">\' + uri + \'</a></p>\'; //将该链接设置成可单击 // 百度地图API功能 map = new BMap.Map(\"allmap\"); var point = new BMap.Point(bxx, byy); var marker = new BMap.Marker(point); // 创建标注 map.addOverlay(marker); // 将标注添加到地图中 map.centerAndZoom(point, 100); var opts = { width: 200, // 信息窗口宽度 height: 100, // 信息窗口高度 title: \"我的位置\", // 信息窗口标题 enableMessage: true,//设置允许信息窗发送短息 message: result.formatted_address } $(\"#divPo\").html(\"当前位置:\" + result.formatted_address); var infoWindow = new BMap.InfoWindow(result.formatted_address, opts); // 创建信息窗口对象 marker.addEventListener(\"click\", function () { map.openInfoWindow(infoWindow, point); //开启信息窗口 }); var myIcon = new BMap.Icon(\"http://api.map.baidu.com/img/markers.png\", new BMap.Size(23, 25), { offset: new BMap.Size(10, 25), // 指定定位位置 imageOffset: new BMap.Size(0, 0 - 10 * 25) // 设置图片偏移 }); var pois = result.pois; for(var i=0;i<pois.length;i++){ var marker = new BMap.Marker(new BMap.Point(pois[i].point.x,pois[i].point.y),{icon:myIcon}); // 创建标注 var name = pois[i].name; var addr = pois[i].addr; map.addOverlay(marker); // 将标注添加到地图中 addClickHandler(name,addr,marker); } $(\"#mask\").hide(); $(\"#btnSign\").show(); return; } function addClickHandler(name,addr,marker){ marker.addEventListener(\"click\",function(e){ openInfo(name,addr,e)} ); } function openInfo(name,addr,e){ var p = e.target; var point = new BMap.Point(p.getPosition().lng, p.getPosition().lat); var opts = { width: 200, // 信息窗口宽度 height: 100, // 信息窗口高度 title: name, // 信息窗口标题 enableMessage: true,//设置允许信息窗发送短息 message: addr } var infoWindow = new BMap.InfoWindow(addr,opts); // 创建信息窗口对象 map.openInfoWindow(infoWindow,point); //开启信息窗口 } function doOptions() { var script = document.createElement(\'script\'); script.type = \'text/javascript\'; ADVANCED_POST =\"http://api.map.baidu.com/geocoder/v2/?ak=dhRLKMR9QUO4wHmnnSZTartg&callback=renderOption&location=\" + byy + \",\"+bxx+ \"&output=json&pois=2\"; script.src = ADVANCED_POST; document.body.appendChild(script); }; $(function () { $(\"#mask\").show(); $(\"#btnSign\").hide(); changePosition(); }); </script> </asp:Content> <asp:Content ID=\"Content2\" ContentPlaceHolderID=\"cphTitle\" runat=\"server\"> 在线签到 </asp:Content> <asp:Content ID=\"Content3\" ContentPlaceHolderID=\"cphContainer\" runat=\"server\"> <form id=\"frmLocation\" runat=\"server\"> <div class=\"box mb50\"> <div class=\"hd\"><span>位置信息</span></div> <div class=\"bd\" style=\"padding-left: 0\"> <ul class=\"stipx\" style=\"height: 300px;\"> <div id=\"allmap\"></div> </ul> </div> <div class=\"bd\" style=\"padding-left: 0\"> <ul class=\"stipx\"> <div id=\"divPo\"></div> </ul> </div> </div> <div class=\"next_btn\" style=\"text-align: center; margin-top: -50px;\"> <input id=\"btnSign\" type=\"button\" value=\"我要签到\" style=\"cursor: pointer; width: 210px; height: 50px; border-radius: 15px; background-color: #00CD00; border: 0px #FE6714 solid; cursor: pointer; color: white; font-size: 16px;\" /> </div> <div class=\"mask\" style=\"display: none;\"> <span> <img src=\"/templates/txwap/images/mask.gif\" /> </span> </div> </form> </asp:Content>
本页面主要涉及到百度地图开放平台,要申请百度地图ag。否则调用js则提示:APP不存在,AK有误请重新检查在重试。
(1)百度地图技术一:坐标转换API
官网地址:http://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition
API服务地址:http://api.map.baidu.com/geoconv/v1/?
文档有详细的说明,不再赘述哦。
(2)百度地图技术二:根据坐标获取位置
官网网址:http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding
Geocoding API包括地址解析和逆地址解析功能:
地理编码:即地址解析,由详细到街道的结构化地址得到百度经纬度信息,例如:“北京市海淀区中关村南大街27号”地址解析的结果是“lng:116.31985,lat:39.959836”。同时,地理编码也支持名胜古迹、标志性建筑名称直接解析返回百度经纬度,例如:“百度大厦”地址解析的结果是“lng:116.30815,lat:40.056885” ,通用的POI检索需求,建议使用Place API。
逆地理编码:即逆地址解析,由百度经纬度信息得到结构化地址信息,例如:“lat:31.325152,lng:120.558957”逆地址解析的结果是“江苏省苏州市虎丘区塔园路318号”。
API服务地址:http://api.map.baidu.com/geocoder/v2/
具体参数可查看官方文档。
示例:http://api.map.baidu.com/geocoder/v2/?ak=申请的百度KEY&location=34.79563,114.23075222912&callback=showLocation&output=xml&pois=1
注意事项:
(1)百度开发者key申请
(2)百度地图坐标系统与微信的坐标系统不同
(3)api调用地址及参数说明
(4)api回调函数意义
(5)理解json与jsonp的含义
3、微信JS-SDK核心代码
(1)JsAPI.cs生成相关JS-SDK配置参数
using System; using System.Globalization; using System.Linq; using System.Web.Security; using System.Web.UI; using WxPayAPI; namespace WxJsSDK { public class JsApi { /// <summary> /// 保存页面对象,因为要在类的方法中使用Page的Request对象 /// </summary> private Page page { get; set; } public WxJsData ResultJsData { get; set; } /// <summary> /// /// </summary> /// <param name=\"page\"></param> public JsApi(Page page) { this.page = page; } public WxJsData GetJsData() { var data = new WxJsData(); data.SetValue(\"appid\", WxPayConfig.APPID);//公众账号ID data.SetValue(\"timestamp\", WxPayApi.GenerateTimeStamp()); data.SetValue(\"noncestr\", WxPayApi.GenerateNonceStr());//随机字符串 var url = GetUrl(); data.SetValue(\"url\", url); var jsToken = GetJsApiTicket(); data.SetValue(\"jsapi_ticket\", jsToken); var signature = MakeSignature(jsToken, data.GetValue(\"noncestr\").ToString(), data.GetValue(\"timestamp\").ToString(), url); data.SetValue(\"signature\", signature); ResultJsData = data; return data; } private string MakeSignature(string jsapiTicket, string noncestr, string timestamp, string url) { string[] arrayList = { \"jsapi_ticket=\" + jsapiTicket, \"timestamp=\" + timestamp, \"noncestr=\" + noncestr, \"url=\" + url }; Array.Sort(arrayList); var signature = string.Join(\"&\", arrayList); signature = FormsAuthentication.HashPasswordForStoringInConfigFile(signature, \"SHA1\").ToLower(); return signature; } private string GetJsApiTicket() { var jsAuth = new JsAuthorizeAction(); var token = jsAuth.GetToken(); var nd = DateTime.Now - token.CreateDate; Log.Error(this.GetType().ToString(), token.access_token); Log.Error(this.GetType().ToString(), token.IsValid().ToString()); if (token.IsValid()) return jsAuth.GetJsApiTicket(token.access_token).ticket; return \"\"; } private string GetUrl() { string host = page.Request.Url.Host; string path = page.Request.Path; string queryString = page.Request.Url.Query; //这个地方要注意,参与签名的是网页授权获取用户信息时微信后台回传的完整url string url = \"http://\" + host + path + queryString; return url; } public string GetJsApiParameters() { Log.Debug(this.GetType().ToString(), \"JsApi ::GetJsApiParam is processing...\"); string parameters = ResultJsData.ToJson(); Log.Debug(this.GetType().ToString(), \"Get JsApi : \" + parameters); return parameters; } } }
(2)JsAuthorizeAction.cs微信JS-SDK相关API调用函数
using Payment.WxWebHlper; using Payment.WxWebHlper.Results; using System; using WxPayAPI; namespace WxJsSDK { public class JsAuthorizeAction { private static TokenResult Token = new TokenResult() { errcode = -1 }; private static JsApiTicketResult JsApiTicket = new JsApiTicketResult() { errcode = -1 }; public TokenResult GetToken() { Log.Error(this.GetType().ToString(), \"GetToken\"); if (!Token.IsValid()) { Token = GeTokenResult(); Log.Error(this.GetType().ToString(), Token.ToString()); } return Token; } /// <summary> /// /// </summary> /// <returns></returns> public TokenResult GeTokenResult() { var result = new TokenResult(); try { var webUtils = new WebUtils(); var url = string.Format(\"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}\", WxPayConfig.APPID, WxPayConfig.APPSECRET); var strRtn = webUtils.Get(url); result = Tools.JsonStringToObj<TokenResult>(strRtn); } catch (Exception ex) { Log.Error(this.GetType().ToString(), ex.Message); result = new TokenResult() { errcode = -1086 }; } return result; } /// <summary> /// /// </summary> /// <param name=\"token\"></param> /// <returns></returns> public JsApiTicketResult GetJsApiTicket(string token) { Log.Error(this.GetType().ToString(), \"GetJsApiTicket传入token:\" + token); if (!JsApiTicket.IsValid()) { JsApiTicket = GetJsApiTicketResult(token); } return JsApiTicket; } /// <summary> /// /// </summary> /// <param name=\"token\"></param> /// <returns></returns> public JsApiTicketResult GetJsApiTicketResult(string token) { JsApiTicketResult result; try { var webUtils = new WebUtils(); var url = string.Format(\"https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi\", token); var strRtn = webUtils.Get(url); result = Tools.JsonStringToObj<JsApiTicketResult>(strRtn); } catch (Exception ex) { Log.Error(this.GetType().ToString(), ex.Message); result = new JsApiTicketResult() { errcode = -1086 }; } return result; } } public class JsApiTicketResult : ReturnResult { /// <summary> /// 构造函数 /// </summary> public JsApiTicketResult() { CreateDate = DateTime.Now; } /// <summary> /// /// </summary> public string ticket { get; set; } /// <summary> /// access_token接口调用凭证超时时间,单位(秒) /// </summary> public int expires_in { get; set; } /// <summary> /// 创建时间 /// </summary> public DateTime CreateDate { get; set; } /// <summary> /// 判断是否有效 /// </summary> /// <returns></returns> public bool IsValid() { if (this.errcode != 0) return false; var nd = DateTime.Now - CreateDate; return nd.Seconds < 7200; } } public class TokenResult : ReturnResult { /// <summary> /// 构造函数 /// </summary> public TokenResult() { CreateDate = DateTime.Now; } /// <summary> /// 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 /// </summary> public string access_token { get; set; } /// <summary> /// access_token接口调用凭证超时时间,单位(秒) /// </summary> public int expires_in { get; set; } /// <summary> /// 创建时间 /// </summary> public DateTime CreateDate { get; set; } /// <summary> /// 判断是否有效 /// </summary> /// <returns></returns> public bool IsValid() { if (this.errcode != 0) return false; var nd = DateTime.Now - CreateDate; return nd.Seconds < 7200; } } }
(3)WxJsData.cs微信JS-SDK参数类
using LitJson; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; using System.Xml; using WxPayAPI; namespace WxJsSDK { public class WxJsData { private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>(); /** * 设置某个字段的值 * @param key 字段名 * @param value 字段值 */ public void SetValue(string key, object value) { m_values[key] = value; } /** * 根据字段名获取某个字段的值 * @param key 字段名 * @return key对应的字段值 */ public object GetValue(string key) { object o = null; m_values.TryGetValue(key, out o); return o; } /** * 判断某个字段是否已设置 * @param key 字段名 * @return 若字段key已被设置,则返回true,否则返回false */ public bool IsSet(string key) { object o = null; m_values.TryGetValue(key, out o); if (null != o) return true; return false; } /** * @将Dictionary转成xml * @return 经转换得到的xml串 * @throws WxPayException **/ public string ToXml() { //数据为空时不能转化为xml格式 if (0 == m_values.Count) { Log.Error(this.GetType().ToString(), \"WxPayData数据为空!\"); throw new WxPayException(\"WxPayData数据为空!\"); } string xml = \"<xml>\"; foreach (KeyValuePair<string, object> pair in m_values) { //字段值不能为null,会影响后续流程 if (pair.Value == null) { Log.Error(this.GetType().ToString(), \"WxPayData内部含有值为null的字段!\"); throw new WxPayException(\"WxPayData内部含有值为null的字段!\"); } if (pair.Value.GetType() == typeof(int) || pair.Value.GetType() == typeof(decimal)) { xml += \"<\" + pair.Key + \">\" + pair.Value.ToString() + \"</\" + pair.Key + \">\"; } else if (pair.Value.GetType() == typeof(string)) { xml += \"<\" + pair.Key + \">\" + \"<![CDATA[\" + pair.Value + \"]]></\" + pair.Key + \">\"; } else//除了string和int类型不能含有其他数据类型 { Log.Error(this.GetType().ToString(), \"WxPayData字段数据类型错误!\"); throw new WxPayException(\"WxPayData字段数据类型错误!\"); } } xml += \"</xml>\"; return xml; } /** * @将xml转为WxPayData对象并返回对象内部的数据 * @param string 待转换的xml串 * @return 经转换得到的Dictionary * @throws WxPayException */ public SortedDictionary<string, object> FromXml(string xml) { if (string.IsNullOrEmpty(xml)) { Log.Error(this.GetType().ToString(), \"将空的xml串转换为WxPayData不合法!\"); throw new WxPayException(\"将空的xml串转换为WxPayData不合法!\"); } XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xml); XmlNode xmlNode = xmlDoc.FirstChild;//获取到根节点<xml> XmlNodeList nodes = xmlNode.ChildNodes; foreach (XmlNode xn in nodes) { XmlElement xe = (XmlElement)xn; m_values[xe.Name] = xe.InnerText;//获取xml的键值对到WxPayData内部的数据中 } try { //2015-06-29 错误是没有签名 if (m_values[\"return_code\"] != \"SUCCESS\") { return m_values; } CheckSign();//验证签名,不通过会抛异常 } catch (WxPayException ex) { throw new WxPayException(ex.Message); } return m_values; } /** * @Dictionary格式转化成url参数格式 * @ return url格式串, 该串不包含sign字段值 */ public string ToUrl() { string buff = \"\"; foreach (KeyValuePair<string, object> pair in m_values) { if (pair.Value == null) { Log.Error(this.GetType().ToString(), \"WxPayData内部含有值为null的字段!\"); throw new WxPayException(\"WxPayData内部含有值为null的字段!\"); } if (pair.Key != \"sign\" && pair.Value.ToString() != \"\") { buff += pair.Key + \"=\" + pair.Value + \"&\"; } } buff = buff.Trim(\'&\'); return buff; } /** * @Dictionary格式化成Json * @return json串数据 */ public string ToJson() { string jsonStr = JsonMapper.ToJson(m_values); return jsonStr; } /** * @values格式化成能在Web页面上显示的结果(因为web页面上不能直接输出xml格式的字符串) */ public string ToPrintStr() { string str = \"\"; foreach (KeyValuePair<string, object> pair in m_values) { if (pair.Value == null) { Log.Error(this.GetType().ToString(), \"WxPayData内部含有值为null的字段!\"); throw new WxPayException(\"WxPayData内部含有值为null的字段!\"); } str += string.Format(\"{0}={1}<br>\", pair.Key, pair.Value.ToString()); } Log.Debug(this.GetType().ToString(), \"Print in Web Page : \" + str); return str; } /** * @生成签名,详见签名生成算法 * @return 签名, sign字段不参加签名 */ public string MakeSign() { //转url格式 string str = ToUrl(); //在string后加入API KEY str += \"&key=\" + WxPayConfig.KEY; //MD5加密 var md5 = MD5.Create(); var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str)); var sb = new StringBuilder(); foreach (byte b in bs) { sb.Append(b.ToString(\"x2\")); } //所有字符转为大写 string result = sb.ToString().ToUpper(); return result; } public string MakeAppSign() { //转url格式 string str = ToUrl(); //在string后加入API KEY str += \"&key=\" + WxPayConfig.KEYofAPP; //MD5加密 var md5 = MD5.Create(); var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str)); var sb = new StringBuilder(); foreach (byte b in bs) { sb.Append(b.ToString(\"x2\")); } //所有字符转为大写 string result = sb.ToString().ToUpper(); return result; } /** * * 检测签名是否正确 * 正确返回true,错误抛异常 */ public bool CheckSign() { //如果没有设置签名,则跳过检测 if (!IsSet(\"sign\")) { Log.Error(this.GetType().ToString(), \"WxPayData签名存在但不合法!\"); throw new WxPayException(\"WxPayData签名存在但不合法!\"); } //如果设置了签名但是签名为空,则抛异常 if (GetValue(\"sign\") == null || GetValue(\"sign\").ToString() == \"\") { Log.Error(this.GetType().ToString(), \"WxPayData签名存在但不合法!\"); throw new WxPayException(\"WxPayData签名存在但不合法!\"); } //获取接收到的签名 string return_sign = GetValue(\"sign\").ToString(); //在本地计算新的签名 string cal_sign = MakeSign(); if (cal_sign == return_sign) { return true; } Log.Error(this.GetType().ToString(), \"WxPayData签名验证错误!\"); throw new WxPayException(\"WxPayData签名验证错误!\"); } /** * @获取Dictionary */ public SortedDictionary<string, object> GetValues() { return m_values; } } }
提示信息:相关解析思路可参考微信公众号支付官方SDK,下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=11_1。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持phpstudy。
本文地址:https://www.stayed.cn/item/21390
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我