微信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 相关文章推荐
javascript中substr,substring,slice.splice的区别说明
Nov 25 Javascript
在父页面调用子页面的JS方法
Sep 29 Javascript
tangram框架响应式加载图片方法
Nov 21 Javascript
javascript使用onclick事件改变选中行的颜色
Dec 30 Javascript
node.js中的console.dir方法使用说明
Dec 10 Javascript
js实现透明度渐变效果的方法
Apr 10 Javascript
jquery实现删除一个元素后面的所有元素功能
Dec 21 Javascript
JS获取子窗口中返回的数据实现方法
May 28 Javascript
Vuejs第十三篇之组件——杂项
Sep 09 Javascript
详解JS: reduce方法实现 webpack多文件入口
Feb 14 Javascript
JavaScript之json_动力节点Java学院整理
Jun 29 Javascript
Vue结合SignalR实现前后端实时消息同步
Sep 19 Javascript
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
漫威DC御用漫画家去世 他的表情包曾走红网络
2020/04/09 欧美动漫
php数组函数序列之array_unshift() 在数组开头插入一个或多个元素
2011/11/07 PHP
thinkphp配置连接数据库技巧
2014/12/02 PHP
全面解析PHP操作Memcache基本函数
2016/07/14 PHP
Laravel接收前端ajax传来的数据的实例代码
2017/07/20 PHP
PHP实现统计所有字符在字符串中出现次数的方法
2017/10/17 PHP
PHP ADODB实现事务处理功能示例
2018/05/25 PHP
jQuery Ajax之load()方法
2009/10/12 Javascript
jQuery 学习入门篇附实例代码
2010/03/16 Javascript
Extjs实现进度条的两种便捷方式
2013/09/26 Javascript
判断iframe里的页面是否加载完成
2014/06/06 Javascript
JavaScript 开发工具webstrom使用指南
2014/12/09 Javascript
javacript获取当前屏幕大小
2016/06/04 Javascript
jQuery Mobile 触摸事件实例
2016/06/04 Javascript
很棒的一组js图片轮播特效
2017/01/12 Javascript
详解nodejs中的process进程
2017/03/19 NodeJs
Angularjs的启动过程分析
2017/07/18 Javascript
Vue中的vue-resource示例详解
2018/11/02 Javascript
vue.js实现左边导航切换右边内容
2019/10/21 Javascript
[01:53]DOTA2超级联赛专访Zhou 五年职业青春成长
2013/05/29 DOTA
[03:06]2018年度CS GO最具人气解说-完美盛典
2018/12/16 DOTA
python 匹配url中是否存在IP地址的方法
2018/06/04 Python
python对离散变量的one-hot编码方法
2018/07/11 Python
python中将正则过滤的内容输出写入到文件中的实例
2018/10/21 Python
女士时装鞋:Chinese Laundry
2018/08/29 全球购物
意大利在线眼镜精品店:Ottica Lipari
2019/11/11 全球购物
SQL Server的固定数据库角色都有哪些?对应的服务器权限有哪些?
2013/05/18 面试题
垃圾回收的优点和原理
2014/05/16 面试题
优秀村官事迹材料
2014/01/10 职场文书
优秀幼教自荐信
2014/02/03 职场文书
交通安全寄语大全
2014/04/08 职场文书
关于运动会的广播稿50字
2014/10/17 职场文书
物业接待员岗位职责
2015/04/15 职场文书
论文致谢词范文
2015/05/14 职场文书
Nginx tp3.2.3 404问题解决方案
2021/03/31 Servers
CSS实现鼠标悬浮动画特效
2023/05/07 HTML / CSS