微信JS-SDK坐标位置如何转换为百度地图坐标
说明:红色图标是从微信转换过来的位置,蓝色图标是周边位置。首先
微信JS-SDK开发过程中,使用getLocation获取坐标位置,如何将微信获取的坐标直接应用到百度地图中,显示以下效果:
说明:红色图标是从微信转换过来的位置,蓝色图标是周边位置。首先从微信开发流程讲解。
1、微信JS-SDK开发文档
首先进入官网的帮助文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
可对文档进行详细的研读,要获取位置信息,分以下步骤:
第一步:绑定域名
进入微信公众号,找到“公众号设置”菜单,进入“功能设置”面板,
点击“设置”可设置引用js的相关域名:
第二步:引用官方js类库
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js 。
引用页面是location.aspx,如下:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | <%@ 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实现:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 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显示坐标
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | <%@ 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配置参数
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | 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调用函数
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | 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参数类
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | 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。