微信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,如下:
<%@ 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。
本文已被整理到了《JavaScript微信開發技巧匯總》,歡迎大家學習閱讀。
為大家推薦現在關注度比較高的微信小程序教程一篇:《微信小程序開發教程》小編為大家精心整理的,希望喜歡。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持。