微信JS-SDK坐标位置如何转换为百度地图坐标


Posted in Javascript onJuly 04, 2016

微信JS-SDK开发过程中,使用getLocation获取坐标位置,如何将微信获取的坐标直接应用到百度地图中,显示以下效果:

微信JS-SDK坐标位置如何转换为百度地图坐标

说明:红色图标是从微信转换过来的位置,蓝色图标是周边位置。首先从微信开发流程讲解。

1、微信JS-SDK开发文档

首先进入官网的帮助文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN

可对文档进行详细的研读,要获取位置信息,分以下步骤:

第一步:绑定域名

进入微信公众号,找到“公众号设置”菜单,进入“功能设置”面板,

微信JS-SDK坐标位置如何转换为百度地图坐标

点击“设置”可设置引用js的相关域名:

微信JS-SDK坐标位置如何转换为百度地图坐标

第二步:引用官方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>

页面效果:

微信JS-SDK坐标位置如何转换为百度地图坐标微信JS-SDK坐标位置如何转换为百度地图坐标

注意事项:

(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/?

微信JS-SDK坐标位置如何转换为百度地图坐标

文档有详细的说明,不再赘述哦。

(2)百度地图技术二:根据坐标获取位置

官网网址:http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding

微信JS-SDK坐标位置如何转换为百度地图坐标

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

微信JS-SDK坐标位置如何转换为百度地图坐标

注意事项:

(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。

微信JS-SDK坐标位置如何转换为百度地图坐标

本文已被整理到了《JavaScript微信开发技巧汇总》,欢迎大家学习阅读。

为大家推荐现在关注度比较高的微信小程序教程一篇:《微信小程序开发教程》小编为大家精心整理的,希望喜欢。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
使用jquery实现select添加实现后台权限添加的效果
May 28 Javascript
JavaScript call apply使用 JavaScript对象的方法绑定到DOM事件后this指向问题
Sep 28 Javascript
Jquery刷新页面背景图片随机变换的实现方法
Mar 15 Javascript
Javascript定义类(class)的三种方法详解
Mar 13 Javascript
fullCalendar中文API官方文档
Feb 07 Javascript
纯JS实现弹性导航条效果
Mar 06 Javascript
js弹出窗口简单实现代码
Mar 22 Javascript
vue使用混入定义全局变量、函数、筛选器的实例代码
Jul 29 Javascript
vue.config.js常用配置详解
Nov 14 Javascript
浅谈Vue 函数式组件的使用技巧
Jun 16 Javascript
ES11屡试不爽的新特性,你用上了几个
Oct 21 Javascript
Vue3配置axios跨域实现过程解析
Nov 25 Vue.js
Bootstrap实现水平排列的表单
Jul 04 #Javascript
JSONP跨域请求实例详解
Jul 04 #Javascript
Bootstrap表单布局样式源代码
Jul 04 #Javascript
JS JSOP跨域请求实例详解
Jul 04 #Javascript
json格式的javascript对象用法分析
Jul 04 #Javascript
jQuery简单动画变换效果实例分析
Jul 04 #Javascript
Node.js Streams文件读写操作详解
Jul 04 #Javascript
You might like
随机头像PHP版
2006/10/09 PHP
PHP分页显示制作详细讲解
2008/11/19 PHP
PHP 5.3.0 安装分析心得
2009/08/07 PHP
教你如何使用php session
2013/10/28 PHP
php中文字符串截取方法实例总结
2014/09/30 PHP
关于laravel后台模板laravel-admin select框的使用详解
2019/10/03 PHP
php中yar框架实例用法讲解
2020/12/27 PHP
js中将具有数字属性名的对象转换为数组
2011/03/06 Javascript
jQuery UI Dialog 创建友好的弹出对话框实现代码
2012/04/12 Javascript
JavaScript中操作字符串之localeCompare()方法的使用
2015/06/06 Javascript
javascript伸缩菜单栏实现代码分享
2015/11/12 Javascript
BootStrap Table对前台页面表格的支持实例讲解
2016/12/22 Javascript
Bootstrap轮播图学习使用
2017/02/10 Javascript
bootstrap表单按回车会自动刷新页面的解决办法
2017/03/08 Javascript
详解vue2父组件传递props异步数据到子组件的问题
2017/06/29 Javascript
vue在使用ECharts时的异步更新和数据加载详解
2017/11/22 Javascript
vue+vuex+axios+echarts画一个动态更新的中国地图的方法
2017/12/19 Javascript
Vue指令v-for遍历输出JavaScript数组及json对象的常见方式小结
2019/02/11 Javascript
基于jQuery实现挂号平台首页源码
2020/01/06 jQuery
[47:43]完美世界DOTA2联赛PWL S3 Magama vs GXR 第二场 12.19
2020/12/24 DOTA
python中解析json格式文件的方法示例
2017/05/03 Python
Python内置函数 next的具体使用方法
2017/11/24 Python
Python(TensorFlow框架)实现手写数字识别系统的方法
2018/05/29 Python
Python Web版语音合成实例详解
2019/07/16 Python
使用pyshp包进行shapefile文件修改的例子
2019/12/06 Python
pytorch实现MNIST手写体识别
2020/02/14 Python
HTML5之SVG 2D入门4—笔画与填充
2013/01/30 HTML / CSS
PHP面试题及答案二
2015/05/23 面试题
命名空间(namespace)和程序集(Assembly)有什么区别
2015/09/25 面试题
党员承诺书内容
2014/03/26 职场文书
个人承诺书格式
2014/06/03 职场文书
自我介绍演讲稿范文
2014/08/21 职场文书
珠宝的促销活动方案
2014/08/31 职场文书
群众路线个人自我剖析材料
2014/10/07 职场文书
解除租房协议书
2014/12/03 职场文书
地方课程教学计划
2015/01/19 职场文书