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

前端技术 2023/09/08 JavaScript

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

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

1、微信JS-SDK开发文档

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

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

第一步:绑定域名

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

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

第二步:引用官方js类库

在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js 。

引用页面是location.aspx,如下:

<%@ Page Title=\"获取位置\" Language=\"C#\" AutoEventWireup=\"true\" MasterPageFile=\"~/wxcrm/Site.Master\" CodeFile=\"location.aspx.cs\" Inherits=\"DTcms.Web.wxcrm.location\" %>

<asp:Content ID=\"Content1\" ContentPlaceHolderID=\"cphHead\" runat=\"server\">
 <script src=\"http://res.wx.qq.com/open/js/jweixin-1.0.0.js\"></script>
 <script type=\"text/javascript\">
  $(\"#mask\").show();
  wx.config({
   debug: false, //开启调试模式,如为true,则弹出每个js函数调用情况
   appId: \'<%= ResultJsData.GetValue(\"appid\") %>\', //必填,公众号的唯一标识
   timestamp: <%= ResultJsData.GetValue(\"timestamp\") %>, //必填,生成签名的时间戳
   nonceStr: \'<%= ResultJsData.GetValue(\"noncestr\") %>\', //必填,生成签名的随机串
   signature: \'<%= ResultJsData.GetValue(\"signature\") %>\', //必填,签名
   jsApiList: [
    \'checkJsApi\',
    \'onMenuShareTimeline\',
    \'onMenuShareAppMessage\',
    \'onMenuShareQQ\',
    \'onMenuShareWeibo\',
    \'hideMenuItems\',
    \'showMenuItems\',
    \'hideAllNonBaseMenuItem\',
    \'showAllNonBaseMenuItem\',
    \'translateVoice\',
    \'startRecord\',
    \'stopRecord\',
    \'onRecordEnd\',
    \'playVoice\',
    \'pauseVoice\',
    \'stopVoice\',
    \'uploadVoice\',
    \'downloadVoice\',
    \'chooseImage\',
    \'previewImage\',
    \'uploadImage\',
    \'downloadImage\',
    \'getNetworkType\',
    \'openLocation\',
    \'getLocation\',
    \'hideOptionMenu\',
    \'showOptionMenu\',
    \'closeWindow\',
    \'scanQRCode\',
    \'chooseWXPay\',
    \'openProductSpecificView\',
    \'addCard\',
    \'chooseCard\',
    \'openCard\'
   ]
  });
  wx.ready(function(){
   wx.checkJsApi({
    jsApiList: [
     \'getNetworkType\',
     \'previewImage\',
     \'getLocation\'
    ],
    success: function (res) {
    }
   });
   wx.getLocation({
    type: \'wgs84\', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入\'gcj02\'
    success: function (res) {
     try {
      var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
      var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
      var speed = res.speed; // 速度,以米/每秒计
      var accuracy = res.accuracy; // 位置精度
      //alert(JsonUti.convertToString(res));
      //wx.openLocation({
      // latitude: res.latitude, // 纬度,浮点数,范围为90 ~ -90
      // longitude: res.longitude, // 经度,浮点数,范围为180 ~ -180。
      // name: \'当前位置\', // 位置名
      // address: \'点击查看\', // 地址详情说明
      // scale: 28, // 地图缩放级别,整形值,范围从1~28。默认为最大
      // infoUrl: \"location1.aspx?m=Home&c=Index&a=getlocation&latitude=\"+latitude+\"&longitude=\"+longitude // 在查看位置界面底部显示的超链接,可点击跳转
      //});
      //alert(latitude+\"-\"+longitude);
      $(\"#mask\").hide();
      window.location.href = \"location1.aspx?m=Home&c=Index&a=getlocation&latitude=\" +
       latitude +
       \"&longitude=\" +
       longitude +
       \"&=speed\" +
       speed +
       \"&accuracy=\" +
       accuracy;
     } catch (e) {
      alert(e.message);
     }
    },
    cancel: function (res) {
     window.location.href=\"none.aspx?msg=拒绝获取地理位置&r=\" + Math.random();//拒绝
    },
    fail:function() {
     alert(\"未能获取地理位置!首先检查手机是否启用微信定位。\");
    }
   });
  });

  wx.error(function(res) {
   // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
  });

  wx.fail(function(res) {
  });
 </script>
</asp:Content>
<asp:Content ID=\"Content2\" ContentPlaceHolderID=\"cphTitle\" runat=\"server\">
 获取位置
</asp:Content>
<asp:Content ID=\"Content3\" ContentPlaceHolderID=\"cphContainer\" runat=\"server\">
 <br />
 <br />
 <center style=\"display: block;\">

  <i class=\"weui_icon_msg weui_icon_info\"></i>

  <div class=\"input_errow\" style=\"width: 60%; height: 60%; text-align: center;\">
   正在获取地理位置信息...
  </div>
 </center>

 <div class=\"mask\" style=\"display: none;\">
  <span>
   <img src=\"/templates/txwap/images/mask.gif\" />
  </span>
 </div>
</asp:Content>

页面效果:

注意事项:

(1)如果手机设置不允许微信获取位置信息,则提示以上信息。

(2)上图参数获取的是GPS坐标,如使用百度地图,要做一定转换,将在location1.aspx中体现。

(3)所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用。

对应location.aspx.cs实现:

using Payment.WxWebHlper;
using Payment.WxWebHlper.Actions;
using System;
using System.Globalization;
using WxJsSDK;
using WxPayAPI;

namespace DTcms.Web.wxcrm
{
 public partial class location : PageBase
 {
 protected string appId { get; set; }
 protected string timestamp { get; set; }
 protected string nonceStr { get; set; }
 protected string signature { get; set; }
 public static string WxJsApiParam { get; set; }
 public WxJsData ResultJsData { get; set; }

 protected void Page_Load(object sender, EventArgs e)
 {
  JudgeCode();
  var webAuthorize = new WebAuthorizeAction();
  Code2TokenResult = webAuthorize.Code2Token(Request[\"code\"]);
  if (Code2TokenResult.HasError())
  {
  Response.Redirect(Urls.PageOfLocation);
  GotoNonePage(\"获取用户凭证失败,请重新获取\");
  return;
  }
  GetUserInfoResult = webAuthorize.GetUserInfo(Code2TokenResult.access_token);
  if (GetUserInfoResult.HasError())
  {
  GotoNonePage(\"获取用户信息失败,请重新获取\");
  }
  var userid = wxOperation.HasBind(GetUserInfoResult.openid);
  if (userid.Equals(Guid.Empty))
  {
  Response.Redirect(Urls.Oauth2Url);
  GotoNonePage(\"微信用户未绑定\");
  }

  appId = WxPayConfig.APPID;
  timestamp = WxPayApi.GenerateTimeStamp();
  nonceStr = WxPayApi.GenerateNonceStr();
  //以下实现将在3、核心代码实现 体现  var jsApi = new JsApi(this);
  ResultJsData = jsApi.GetJsData();
  WxJsApiParam = jsApi.GetJsApiParameters();//获取H5调起JS API参数
 }
 }
}

2、将微信GPS坐标转换为百度坐标

微信获取坐标成功后,页面自动跳转到location1.aspx,处理流程如下:

微信坐标—>转换为百度地图坐标—>根据百度地图API获取位置信息—>根据百度地图API显示坐标

<%@ Page Title=\"在线签到\" Language=\"C#\" MasterPageFile=\"~/wxcrm/Site.Master\" AutoEventWireup=\"true\" CodeFile=\"location1.aspx.cs\" Inherits=\"DTcms.Web.wxcrm.location1\" %>

<asp:Content ID=\"Content1\" ContentPlaceHolderID=\"cphHead\" runat=\"server\">
 <meta name=\"viewport\" content=\"initial-scale=1.0, user-scalable=no\" />
 <style type=\"text/css\">
 #allmap { width: 100%; height: 300px; }
 </style>
 <script type=\"text/javascript\" src=\"http://api.map.baidu.com/api?v=2.0&ak=dhRLKMR9QUO4wHmnnSZTarta\"></script>
 <script type=\"text/javascript\">
 //GPS坐标
 var yy = <%= this.Request[\"longitude\"] %>; //经度,浮点数,范围为180 ~ -180。
 var xx = <%= this.Request[\"latitude\"] %>; //纬度,浮点数,范围为90 ~ -90
 var gpsPoint = new BMap.Point(xx,yy);
 var bxx = 0.0;
 var byy = 0.0;

 /*
 * http://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition
 */
 var PositionUrl = \"http://api.map.baidu.com/geoconv/v1/?\";
 function changePosition(){
  var str = \"coords=\"+yy+\",\"+xx+\"&from=1&to=5\";
  var url = PositionUrl + str;
  $(\"#positionUrl\").html(url+\"&ak=dhRLKMR9QUO4wHmnnSZTartg\");
  var script = document.createElement(\'script\');
  script.src = url + \'&ak=dhRLKMR9QUO4wHmnnSZTarta&callback=dealResult\';
  document.getElementsByTagName(\"head\")[0].appendChild(script);
 }
 function dealResult(msg){
  if(msg.status != 0){
  alert(\"无正确的返回结果。\");
  $(\"#mask\").hide();
  return;
  }
  //JsonUti.convertToString(msg);
  bxx = msg.result[0].x;
  byy = msg.result[0].y;
  doOptions();
 }

 function getBaiduPosition() {
  var url =\"http://api.map.baidu.com/geoconv/v1/?coords=\"+yy+\",\"+xx+\"&from=1&to=5&ak=dhRLKMR9QUO4wHmnnSZTarta\";
  $.ajax({
  url: url,
  success: function(data,status,xhr) {
   alert(status);
   alert(data.status);
  },
  dataType: json
  });
 }

 var ADVANCED_POST = \'\';
 var advancedOptions = \'\';
 var address;
 var map;

 function renderOption(response) {
  var html = \'\';
  if (response.status ) {
  $(\"#mask\").hide();
  var text = \"无正确的返回结果!\";
  alert(text);
  return;
  }
  var result = response.result;
  var location = response.result.location;
  var uri = \'http://api.map.baidu.com/marker?location=\'+ location.lat+\',\'+location.lng +\'&title=\'+response.result.level+\'&content=\'+address+\'&output=html\';
  var staticimageUrl = \"http://api.map.baidu.com/staticimage?center=\" + location.lng+\',\'+location.lat + \"&markers=\" + location.lng+\',\'+location.lat;
  html = \'<p>坐标:纬度: \' + location.lat + \" 经度: \" + location.lng+\'<br />\';
  html += \'精度: \'+response.result.precise+\'<br />\' ;
  html += \'可信度: \'+response.result.confidence +\'<br />\';
  html += \'地址类型: \'+response.result.level+\'</p>\' ;
  html += \'<p><img src=\"\' + staticimageUrl + \'\" /></p>\' ;
  html += \'<p>分享该点: <a href=\"\' + uri + \'\" target=\"_blank\">\' + uri + \'</a></p>\'; //将该链接设置成可单击
  // 百度地图API功能
  map = new BMap.Map(\"allmap\");
  var point = new BMap.Point(bxx, byy);
  var marker = new BMap.Marker(point); // 创建标注
  map.addOverlay(marker);  // 将标注添加到地图中
  map.centerAndZoom(point, 100);
  var opts = {
  width: 200, // 信息窗口宽度
  height: 100, // 信息窗口高度
  title: \"我的位置\", // 信息窗口标题
  enableMessage: true,//设置允许信息窗发送短息
  message: result.formatted_address
  }

  $(\"#divPo\").html(\"当前位置:\" + result.formatted_address);
  var infoWindow = new BMap.InfoWindow(result.formatted_address, opts); // 创建信息窗口对象
  marker.addEventListener(\"click\", function () {
  map.openInfoWindow(infoWindow, point); //开启信息窗口
  });

  var myIcon = new BMap.Icon(\"http://api.map.baidu.com/img/markers.png\", new BMap.Size(23, 25), {
  offset: new BMap.Size(10, 25), // 指定定位位置
  imageOffset: new BMap.Size(0, 0 - 10 * 25) // 设置图片偏移
  });

  var pois = result.pois;
  for(var i=0;i<pois.length;i++){
  var marker = new BMap.Marker(new BMap.Point(pois[i].point.x,pois[i].point.y),{icon:myIcon}); // 创建标注
  var name = pois[i].name;
  var addr = pois[i].addr;
  map.addOverlay(marker);  // 将标注添加到地图中
  addClickHandler(name,addr,marker);
  }

  $(\"#mask\").hide();
  $(\"#btnSign\").show();
  return;
 }

 function addClickHandler(name,addr,marker){
  marker.addEventListener(\"click\",function(e){
  openInfo(name,addr,e)}
  );
 }

 function openInfo(name,addr,e){
  var p = e.target;
  var point = new BMap.Point(p.getPosition().lng, p.getPosition().lat);
  var opts = {
  width: 200, // 信息窗口宽度
  height: 100, // 信息窗口高度
  title: name, // 信息窗口标题
  enableMessage: true,//设置允许信息窗发送短息
  message: addr
  }
  var infoWindow = new BMap.InfoWindow(addr,opts); // 创建信息窗口对象
  map.openInfoWindow(infoWindow,point); //开启信息窗口
 }

 function doOptions() {
  var script = document.createElement(\'script\');
  script.type = \'text/javascript\';
  ADVANCED_POST =\"http://api.map.baidu.com/geocoder/v2/?ak=dhRLKMR9QUO4wHmnnSZTartg&callback=renderOption&location=\" + byy + \",\"+bxx+ \"&output=json&pois=2\";
  script.src = ADVANCED_POST;
  document.body.appendChild(script);
 };

 $(function () {
  $(\"#mask\").show();
  $(\"#btnSign\").hide();
  changePosition();
 });
 </script>
</asp:Content>
<asp:Content ID=\"Content2\" ContentPlaceHolderID=\"cphTitle\" runat=\"server\">
 在线签到
</asp:Content>
<asp:Content ID=\"Content3\" ContentPlaceHolderID=\"cphContainer\" runat=\"server\">
 <form id=\"frmLocation\" runat=\"server\">
 <div class=\"box mb50\">
  <div class=\"hd\"><span>位置信息</span></div>
  <div class=\"bd\" style=\"padding-left: 0\">
  <ul class=\"stipx\" style=\"height: 300px;\">
   <div id=\"allmap\"></div>
  </ul>
  </div>
  <div class=\"bd\" style=\"padding-left: 0\">
  <ul class=\"stipx\">
   <div id=\"divPo\"></div>
  </ul>
  </div>
 </div>
 <div class=\"next_btn\" style=\"text-align: center; margin-top: -50px;\">
  <input id=\"btnSign\" type=\"button\" value=\"我要签到\" style=\"cursor: pointer; width: 210px; height: 50px; border-radius: 15px; background-color: #00CD00; border: 0px #FE6714 solid; cursor: pointer; color: white; font-size: 16px;\" />
 </div>
 <div class=\"mask\" style=\"display: none;\">
  <span>
  <img src=\"/templates/txwap/images/mask.gif\" />
  </span>
 </div>
 </form>
</asp:Content>

本页面主要涉及到百度地图开放平台,要申请百度地图ag。否则调用js则提示:APP不存在,AK有误请重新检查在重试。

(1)百度地图技术一:坐标转换API

官网地址:http://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition

API服务地址:http://api.map.baidu.com/geoconv/v1/?

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

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

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

Geocoding API包括地址解析和逆地址解析功能:

地理编码:即地址解析,由详细到街道的结构化地址得到百度经纬度信息,例如:“北京市海淀区中关村南大街27号”地址解析的结果是“lng:116.31985,lat:39.959836”。同时,地理编码也支持名胜古迹、标志性建筑名称直接解析返回百度经纬度,例如:“百度大厦”地址解析的结果是“lng:116.30815,lat:40.056885” ,通用的POI检索需求,建议使用Place API。

逆地理编码:即逆地址解析,由百度经纬度信息得到结构化地址信息,例如:“lat:31.325152,lng:120.558957”逆地址解析的结果是“江苏省苏州市虎丘区塔园路318号”。

API服务地址:http://api.map.baidu.com/geocoder/v2/

具体参数可查看官方文档。

示例:http://api.map.baidu.com/geocoder/v2/?ak=申请的百度KEY&location=34.79563,114.23075222912&callback=showLocation&output=xml&pois=1

注意事项:

(1)百度开发者key申请

(2)百度地图坐标系统与微信的坐标系统不同

(3)api调用地址及参数说明

(4)api回调函数意义

(5)理解json与jsonp的含义

3、微信JS-SDK核心代码

(1)JsAPI.cs生成相关JS-SDK配置参数

using System;
using System.Globalization;
using System.Linq;
using System.Web.Security;
using System.Web.UI;
using WxPayAPI;

namespace WxJsSDK
{
 public class JsApi
 {
 /// <summary>
 /// 保存页面对象,因为要在类的方法中使用Page的Request对象
 /// </summary>
 private Page page { get; set; }

 public WxJsData ResultJsData { get; set; }

 /// <summary>
 ///
 /// </summary>
 /// <param name=\"page\"></param>
 public JsApi(Page page)
 {
  this.page = page;
 }

 public WxJsData GetJsData()
 {
  var data = new WxJsData();
  data.SetValue(\"appid\", WxPayConfig.APPID);//公众账号ID
  data.SetValue(\"timestamp\", WxPayApi.GenerateTimeStamp());
  data.SetValue(\"noncestr\", WxPayApi.GenerateNonceStr());//随机字符串

  var url = GetUrl();
  data.SetValue(\"url\", url);
  var jsToken = GetJsApiTicket();
  data.SetValue(\"jsapi_ticket\", jsToken);
  var signature = MakeSignature(jsToken, data.GetValue(\"noncestr\").ToString(), data.GetValue(\"timestamp\").ToString(), url);
  data.SetValue(\"signature\", signature);

  ResultJsData = data;
  return data;
 }

 private string MakeSignature(string jsapiTicket, string noncestr, string timestamp, string url)
 {
  string[] arrayList =
  {
  \"jsapi_ticket=\" + jsapiTicket,
  \"timestamp=\" + timestamp,
  \"noncestr=\" + noncestr,
  \"url=\" + url
  };
  Array.Sort(arrayList);
  var signature = string.Join(\"&\", arrayList);
  signature = FormsAuthentication.HashPasswordForStoringInConfigFile(signature, \"SHA1\").ToLower();
  return signature;
 }

 private string GetJsApiTicket()
 {
  var jsAuth = new JsAuthorizeAction();
  var token = jsAuth.GetToken();
  var nd = DateTime.Now - token.CreateDate;
  Log.Error(this.GetType().ToString(), token.access_token);
  Log.Error(this.GetType().ToString(), token.IsValid().ToString());
  if (token.IsValid())
  return jsAuth.GetJsApiTicket(token.access_token).ticket;
  return \"\";
 }

 private string GetUrl()
 {
  string host = page.Request.Url.Host;
  string path = page.Request.Path;
  string queryString = page.Request.Url.Query;
  //这个地方要注意,参与签名的是网页授权获取用户信息时微信后台回传的完整url
  string url = \"http://\" + host + path + queryString;
  return url;
 }

 public string GetJsApiParameters()
 {
  Log.Debug(this.GetType().ToString(), \"JsApi ::GetJsApiParam is processing...\");

  string parameters = ResultJsData.ToJson();

  Log.Debug(this.GetType().ToString(), \"Get JsApi : \" + parameters);
  return parameters;
 }
 }
}

(2)JsAuthorizeAction.cs微信JS-SDK相关API调用函数

using Payment.WxWebHlper;
using Payment.WxWebHlper.Results;
using System;
using WxPayAPI;

namespace WxJsSDK
{
 public class JsAuthorizeAction
 {
 private static TokenResult Token = new TokenResult() { errcode = -1 };
 private static JsApiTicketResult JsApiTicket = new JsApiTicketResult() { errcode = -1 };

 public TokenResult GetToken()
 {
  Log.Error(this.GetType().ToString(), \"GetToken\");
  if (!Token.IsValid())
  {
  Token = GeTokenResult();
  Log.Error(this.GetType().ToString(), Token.ToString());
  }
  return Token;
 }

 /// <summary>
 ///
 /// </summary>
 /// <returns></returns>
 public TokenResult GeTokenResult()
 {
  var result = new TokenResult();
  try
  {
  var webUtils = new WebUtils();
  var url = string.Format(\"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}\", WxPayConfig.APPID, WxPayConfig.APPSECRET);
  var strRtn = webUtils.Get(url);
  result = Tools.JsonStringToObj<TokenResult>(strRtn);
  }
  catch (Exception ex)
  {
  Log.Error(this.GetType().ToString(), ex.Message);
  result = new TokenResult() { errcode = -1086 };
  }
  return result;
 }

 /// <summary>
 ///
 /// </summary>
 /// <param name=\"token\"></param>
 /// <returns></returns>
 public JsApiTicketResult GetJsApiTicket(string token)
 {
  Log.Error(this.GetType().ToString(), \"GetJsApiTicket传入token:\" + token);
  if (!JsApiTicket.IsValid())
  {
  JsApiTicket = GetJsApiTicketResult(token);
  }
  return JsApiTicket;
 }

 /// <summary>
 ///
 /// </summary>
 /// <param name=\"token\"></param>
 /// <returns></returns>
 public JsApiTicketResult GetJsApiTicketResult(string token)
 {
  JsApiTicketResult result;
  try
  {
  var webUtils = new WebUtils();
  var url = string.Format(\"https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi\", token);
  var strRtn = webUtils.Get(url);
  result = Tools.JsonStringToObj<JsApiTicketResult>(strRtn);
  }
  catch (Exception ex)
  {
  Log.Error(this.GetType().ToString(), ex.Message);
  result = new JsApiTicketResult() { errcode = -1086 };
  }
  return result;
 }
 }

 public class JsApiTicketResult : ReturnResult
 {
 /// <summary>
 /// 构造函数
 /// </summary>
 public JsApiTicketResult()
 {
  CreateDate = DateTime.Now;
 }

 /// <summary>
 ///
 /// </summary>
 public string ticket { get; set; }

 /// <summary>
 /// access_token接口调用凭证超时时间,单位(秒)
 /// </summary>
 public int expires_in { get; set; }

 /// <summary>
 /// 创建时间
 /// </summary>
 public DateTime CreateDate { get; set; }

 /// <summary>
 /// 判断是否有效
 /// </summary>
 /// <returns></returns>
 public bool IsValid()
 {
  if (this.errcode != 0)
  return false;
  var nd = DateTime.Now - CreateDate;
  return nd.Seconds < 7200;
 }
 }

 public class TokenResult : ReturnResult
 {
 /// <summary>
 /// 构造函数
 /// </summary>
 public TokenResult()
 {
  CreateDate = DateTime.Now;
 }

 /// <summary>
 /// 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
 /// </summary>
 public string access_token { get; set; }

 /// <summary>
 /// access_token接口调用凭证超时时间,单位(秒)
 /// </summary>
 public int expires_in { get; set; }

 /// <summary>
 /// 创建时间
 /// </summary>
 public DateTime CreateDate { get; set; }

 /// <summary>
 /// 判断是否有效
 /// </summary>
 /// <returns></returns>
 public bool IsValid()
 {
  if (this.errcode != 0)
  return false;
  var nd = DateTime.Now - CreateDate;
  return nd.Seconds < 7200;
 }
 }
}

(3)WxJsData.cs微信JS-SDK参数类

using LitJson;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using WxPayAPI;

namespace WxJsSDK
{
 public class WxJsData
 {
 private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>();
 /**
 * 设置某个字段的值
 * @param key 字段名
 * @param value 字段值
 */

 public void SetValue(string key, object value)
 {
  m_values[key] = value;
 }

 /**
 * 根据字段名获取某个字段的值
 * @param key 字段名
  * @return key对应的字段值
 */

 public object GetValue(string key)
 {
  object o = null;
  m_values.TryGetValue(key, out o);
  return o;
 }

 /**
  * 判断某个字段是否已设置
  * @param key 字段名
  * @return 若字段key已被设置,则返回true,否则返回false
  */

 public bool IsSet(string key)
 {
  object o = null;
  m_values.TryGetValue(key, out o);
  if (null != o)
  return true;
  return false;
 }

 /**
 * @将Dictionary转成xml
 * @return 经转换得到的xml串
 * @throws WxPayException
 **/

 public string ToXml()
 {
  //数据为空时不能转化为xml格式
  if (0 == m_values.Count)
  {
  Log.Error(this.GetType().ToString(), \"WxPayData数据为空!\");
  throw new WxPayException(\"WxPayData数据为空!\");
  }

  string xml = \"<xml>\";
  foreach (KeyValuePair<string, object> pair in m_values)
  {
  //字段值不能为null,会影响后续流程
  if (pair.Value == null)
  {
   Log.Error(this.GetType().ToString(), \"WxPayData内部含有值为null的字段!\");
   throw new WxPayException(\"WxPayData内部含有值为null的字段!\");
  }

  if (pair.Value.GetType() == typeof(int) || pair.Value.GetType() == typeof(decimal))
  {
   xml += \"<\" + pair.Key + \">\" + pair.Value.ToString() + \"</\" + pair.Key + \">\";
  }
  else if (pair.Value.GetType() == typeof(string))
  {
   xml += \"<\" + pair.Key + \">\" + \"<![CDATA[\" + pair.Value + \"]]></\" + pair.Key + \">\";
  }
  else//除了string和int类型不能含有其他数据类型
  {
   Log.Error(this.GetType().ToString(), \"WxPayData字段数据类型错误!\");
   throw new WxPayException(\"WxPayData字段数据类型错误!\");
  }
  }
  xml += \"</xml>\";
  return xml;
 }

 /**
 * @将xml转为WxPayData对象并返回对象内部的数据
 * @param string 待转换的xml串
 * @return 经转换得到的Dictionary
 * @throws WxPayException
 */

 public SortedDictionary<string, object> FromXml(string xml)
 {
  if (string.IsNullOrEmpty(xml))
  {
  Log.Error(this.GetType().ToString(), \"将空的xml串转换为WxPayData不合法!\");
  throw new WxPayException(\"将空的xml串转换为WxPayData不合法!\");
  }

  XmlDocument xmlDoc = new XmlDocument();
  xmlDoc.LoadXml(xml);
  XmlNode xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
  XmlNodeList nodes = xmlNode.ChildNodes;
  foreach (XmlNode xn in nodes)
  {
  XmlElement xe = (XmlElement)xn;
  m_values[xe.Name] = xe.InnerText;//获取xml的键值对到WxPayData内部的数据中
  }

  try
  {
  //2015-06-29 错误是没有签名
  if (m_values[\"return_code\"] != \"SUCCESS\")
  {
   return m_values;
  }
  CheckSign();//验证签名,不通过会抛异常
  }
  catch (WxPayException ex)
  {
  throw new WxPayException(ex.Message);
  }

  return m_values;
 }

 /**
 * @Dictionary格式转化成url参数格式
 * @ return url格式串, 该串不包含sign字段值
 */

 public string ToUrl()
 {
  string buff = \"\";
  foreach (KeyValuePair<string, object> pair in m_values)
  {
  if (pair.Value == null)
  {
   Log.Error(this.GetType().ToString(), \"WxPayData内部含有值为null的字段!\");
   throw new WxPayException(\"WxPayData内部含有值为null的字段!\");
  }

  if (pair.Key != \"sign\" && pair.Value.ToString() != \"\")
  {
   buff += pair.Key + \"=\" + pair.Value + \"&\";
  }
  }
  buff = buff.Trim(\'&\');
  return buff;
 }

 /**
 * @Dictionary格式化成Json
  * @return json串数据
 */

 public string ToJson()
 {
  string jsonStr = JsonMapper.ToJson(m_values);
  return jsonStr;
 }

 /**
 * @values格式化成能在Web页面上显示的结果(因为web页面上不能直接输出xml格式的字符串)
 */

 public string ToPrintStr()
 {
  string str = \"\";
  foreach (KeyValuePair<string, object> pair in m_values)
  {
  if (pair.Value == null)
  {
   Log.Error(this.GetType().ToString(), \"WxPayData内部含有值为null的字段!\");
   throw new WxPayException(\"WxPayData内部含有值为null的字段!\");
  }

  str += string.Format(\"{0}={1}<br>\", pair.Key, pair.Value.ToString());
  }
  Log.Debug(this.GetType().ToString(), \"Print in Web Page : \" + str);
  return str;
 }

 /**
 * @生成签名,详见签名生成算法
 * @return 签名, sign字段不参加签名
 */

 public string MakeSign()
 {
  //转url格式
  string str = ToUrl();
  //在string后加入API KEY
  str += \"&key=\" + WxPayConfig.KEY;
  //MD5加密
  var md5 = MD5.Create();
  var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
  var sb = new StringBuilder();
  foreach (byte b in bs)
  {
  sb.Append(b.ToString(\"x2\"));
  }
  //所有字符转为大写
  string result = sb.ToString().ToUpper();
  return result;
 }

 public string MakeAppSign()
 {
  //转url格式
  string str = ToUrl();
  //在string后加入API KEY
  str += \"&key=\" + WxPayConfig.KEYofAPP;
  //MD5加密
  var md5 = MD5.Create();
  var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
  var sb = new StringBuilder();
  foreach (byte b in bs)
  {
  sb.Append(b.ToString(\"x2\"));
  }
  //所有字符转为大写
  string result = sb.ToString().ToUpper();
  return result;
 }

 /**
 *
 * 检测签名是否正确
 * 正确返回true,错误抛异常
 */

 public bool CheckSign()
 {
  //如果没有设置签名,则跳过检测
  if (!IsSet(\"sign\"))
  {
  Log.Error(this.GetType().ToString(), \"WxPayData签名存在但不合法!\");
  throw new WxPayException(\"WxPayData签名存在但不合法!\");
  }
  //如果设置了签名但是签名为空,则抛异常
  if (GetValue(\"sign\") == null || GetValue(\"sign\").ToString() == \"\")
  {
  Log.Error(this.GetType().ToString(), \"WxPayData签名存在但不合法!\");
  throw new WxPayException(\"WxPayData签名存在但不合法!\");
  }

  //获取接收到的签名
  string return_sign = GetValue(\"sign\").ToString();

  //在本地计算新的签名
  string cal_sign = MakeSign();

  if (cal_sign == return_sign)
  {
  return true;
  }

  Log.Error(this.GetType().ToString(), \"WxPayData签名验证错误!\");
  throw new WxPayException(\"WxPayData签名验证错误!\");
 }

 /**
 * @获取Dictionary
 */

 public SortedDictionary<string, object> GetValues()
 {
  return m_values;
 }
 }
}

提示信息:相关解析思路可参考微信公众号支付官方SDK,下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=11_1。

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

本文地址:https://www.stayed.cn/item/21390

转载请注明出处。

本站部分内容来源于网络,如侵犯到您的权益,请 联系我

我的博客

人生若只如初见,何事秋风悲画扇。