当前位置:   article > 正文

微信小程序内嵌webView访问H5界面,在H5界面获取定位_小程序webview获取定位

小程序webview获取定位

以下为uniapp代码!!!

第一步:

微信小程序webview组件路径写花生壳映射的https://***域名。

  1. webView页面
  2. <template>
  3. <view>
  4. <web-view :src="wvUrl"></web-view>
  5. </view>
  6. </template>
  7. <script>
  8. export default {
  9. data() {
  10. return {
  11. wvUrl: `https://******/h5/index/#/pages/login/login?platformToken=123456`,
  12. }
  13. },
  14. methods: {}
  15. }
  16. </script>
  17. <style>
  18. </style>

第二步:

 花生壳配置映射,获取域名。
花生壳动态域名解析服务-贝锐官网|花生壳官网|DNS内网穿透|域名注册|向日葵远程控制|远程桌面|蒲公英路由器-贝锐官网icon-default.png?t=N7T8https://www.oray.com/

 

第三步:

uniapp获取定位。(过程全前端实现无后端)

        3.1    下载所需文件(npm install crypto-js为了SHA1加密,npm install weixin-js-sdk为了使用微信的api)
        3.2    manifest.json配置

        重要:uniapp H5端口不能使用默认80(自己踩的坑)

  1. manifest.json
  2. /* 小程序特有相关 */
  3. "mp-weixin": {
  4. "appid": "",
  5. "setting": {
  6. "urlCheck": false
  7. },
  8. "usingComponents": true,
  9. "permission": {
  10. "scope.userLocation": {
  11. "desc": "您的位置信息将用于小程序位置接口的效果展示"
  12. }
  13. },
  14. // 微信小程序使用位置相关api需要在此处注册
  15. "requiredPrivateInfos": ["getLocation"]
  16. },
  17. "h5": {
  18. "devServer": {
  19. "port": 8081,
  20. // 此处代理是为了前端获取access_token、jsapi_ticket,如果是后端获取就不必写了
  21. "disableHostCheck": true,
  22. "proxy": {
  23. "/api": {
  24. "target": "https://api.weixin.qq.com",
  25. "changeOrigin": true,
  26. "pathRewrite": {
  27. "^/api": ""
  28. }
  29. }
  30. }
  31. }
  32. }

        3.3    获取access_token、jsapi_ticket、签名,配置。(配置一次即可,其他页面只需要调用定位)
  1. App.vue
  2. <script>
  3. import wx from 'weixin-js-sdk';
  4. import {
  5. appid,
  6. secret
  7. } from "@/request/secret_appid.js";
  8. import {
  9. apiGetAccessToken,
  10. apiGetJsapi_ticket,
  11. getSignature
  12. } from '@/request/locationApi.js';
  13. export default {
  14. onLaunch: function() {
  15. let {
  16. accessToken,
  17. dateTime
  18. } = uni.getStorageSync("access_token");
  19. let {
  20. jsapiTicket
  21. } = uni.getStorageSync("jsapi_ticket");
  22. let chaTime = new Date().getTime() - dateTime;
  23. let h_2 = 2 * 60 * 60 * 1000; // 2*60*60*1000 2小时毫秒值
  24. if (!uni.getStorageSync("access_token") || chaTime >= h_2) { // 超过2小时需要重新获取accessToken
  25. console.log("重新请求token");
  26. this.gettoken();
  27. } else {
  28. console.log("直接走配置");
  29. let result = getSignature(jsapiTicket); // 传入ticket获得timestamp,nonceStr,signature
  30. this.configWx(result); // 初始化配置
  31. }
  32. },
  33. onShow: function() {},
  34. onHide: function() {},
  35. methods: {
  36. // 获取token
  37. gettoken() {
  38. apiGetAccessToken(appid, secret).then(res => {
  39. // 需要缓存token
  40. if (!res.data.errcode) {
  41. let access_token = {
  42. accessToken: res.data.access_token,
  43. dateTime: new Date().getTime(),
  44. }
  45. uni.setStorageSync("access_token", access_token);
  46. this.getJsapi_ticket(res.data.access_token); // 获取jsapi_ticket
  47. } else {
  48. uni.showToast({
  49. title: `获取accessToken失败,errcode:${res.data.errcode}`,
  50. icon: "none"
  51. })
  52. }
  53. })
  54. },
  55. // 获取jsapi_ticket
  56. getJsapi_ticket(accessToken) {
  57. apiGetJsapi_ticket(accessToken).then(res => {
  58. if (res.data.errcode == 0) {
  59. let jsapi_ticket = {
  60. jsapiTicket: res.data.ticket
  61. }
  62. uni.setStorageSync("jsapi_ticket", jsapi_ticket);
  63. let result = getSignature(res.data.ticket); // 签名获取timestamp,nonceStr,signature
  64. this.configWx(result); // 初始化配置
  65. } else {
  66. uni.showToast({
  67. title: `获取jsapi_ticket失败,errcode:${res.data.errcode}`,
  68. icon: "none"
  69. })
  70. }
  71. })
  72. },
  73. // 初始化配置
  74. configWx(result) {
  75. wx.config({
  76. debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  77. appId: appid, // 必填,公众号的唯一标识
  78. timestamp: result.timestamp, // 必填,生成签名的时间戳
  79. nonceStr: result.noncestr, // 必填,生成签名的随机串
  80. signature: result.signature, // 必填,签名
  81. jsApiList: ["getLocation"] // 必填,需要使用的JS接口列表
  82. });
  83. wx.error((err) => {
  84. uni.showToast({
  85. title: "配置失败",
  86. icon: "none"
  87. })
  88. })
  89. },
  90. }
  91. }
  92. </script>
  93. <style>
  94. </style>
        3.4    获取定位方法
  1. weixin-js-sdk_location.js
  2. import wx from 'weixin-js-sdk';
  3. // 坐标转化的方法
  4. import {
  5. gcj02tobd09
  6. } from '@/utils/coordinateTransform.js';
  7. // 获取地理坐标
  8. export function getByLocation() {
  9. return new Promise((resolve, reject) => {
  10. wx.ready(() => {
  11. wx.getLocation({
  12. type: 'gcj02', // 默认为wgs84(gcj02)的gps坐标
  13. success: function(res) {
  14. let result = gcj02tobd09(res.longitude, res.latitude);
  15. let lngLat = {
  16. code: 200,
  17. lng: result[0],
  18. lat: result[1]
  19. };
  20. resolve(lngLat)
  21. },
  22. error: function(err) {
  23. reject(err)
  24. },
  25. })
  26. })
  27. })
  28. }
        3.5    使用
  1. <template>
  2. <view></view>
  3. </template>
  4. <script>
  5. import {
  6. getByLocation
  7. } from '@/utils/weixin-js-sdk_location.js';
  8. export default {
  9. data() {
  10. return {}
  11. },
  12. onShow() {
  13. // 通过公众号sdk获取位置
  14. getByLocation().then(res => {
  15. if (res.code == 200) {
  16. alert(JSON.stringify(res))
  17. } else {
  18. uni.showToast({
  19. title: "获取经纬度失败",
  20. icon: "none"
  21. })
  22. }
  23. })
  24. },
  25. methods: {}
  26. }
  27. </script>
  28. <style>
  29. </style>

第四步:所需文件

        4.1    secret_appid.js:存储appid及secret
  1. // 测试公众号
  2. let appid = "";
  3. let secret = "";
  4. export {
  5. appid,
  6. secret
  7. }
        4.2    locationApi.js:获取accessToken、jsapi_ticket、签名等方法
  1. import CryptoJS from "crypto-js";
  2. /*
  3. 请求函数
  4. */
  5. function request({
  6. url,
  7. method,
  8. params
  9. }) {
  10. uni.showLoading({
  11. title: "加载中..."
  12. });
  13. return new Promise((resolve, reject) => {
  14. uni.request({
  15. url: url,
  16. method: method || 'GET',
  17. data: params || {},
  18. success(res) {
  19. resolve(res);
  20. },
  21. fail(err) {
  22. reject(err);
  23. },
  24. complete() {
  25. uni.hideLoading();
  26. }
  27. });
  28. });
  29. }
  30. /* 第一步:获取accessToken
  31. access_token的有效期目前为2个小时,需定时刷新
  32. 传参:
  33. appid:开发者ID(AppID)
  34. secret:开发者密码(AppSecret)
  35. */
  36. // https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${secret}
  37. function apiGetAccessToken(appid, secret) {
  38. return request({
  39. url: `/api/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${secret}`,
  40. })
  41. }
  42. /* 第二步:获取jsapi_ticket
  43. jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket)用于权限验证的签名
  44. 传参:
  45. access_token
  46. */
  47. function apiGetJsapi_ticket(access_token) {
  48. return request({
  49. url: `/api/cgi-bin/ticket/getticket?access_token=${access_token}&type=jsapi`,
  50. })
  51. }
  52. // 第三步:获取signature
  53. function getSignature(ticket) {
  54. let noncestr = getRandomString(); // 16位随机字符串
  55. let jsapi_ticket = ticket; // 此处必须得到有效的jsapi_ticket
  56. let timestamp = getTimestamp(); // 时间戳
  57. let url = getConfigUrl(); // URL
  58. let obj = {
  59. noncestr,
  60. jsapi_ticket,
  61. timestamp,
  62. url
  63. }
  64. let string1 = sort_ascii(obj);
  65. let signature = CryptoJS.SHA1(string1).toString();
  66. let result = {
  67. noncestr,
  68. timestamp,
  69. signature
  70. }
  71. return result;
  72. }
  73. /*
  74. 签名算法所需参数:
  75. noncestr:随机字符串,
  76. jsapi_ticket:有效的,
  77. timestamp:时间戳,
  78. url:(当前网页的URL,不包含#及其后面部分)
  79. 对以上四个参数整理成对象并按ascii码从小到大排序,排完序在进行sh1加密 得到signature
  80. let result = { noncestr, jsapi_ticket: ticket, timestamp, url: getConfigUrl() };
  81. sort_ascii(result)
  82. */
  83. // 生成一个随机的字符串
  84. function getRandomString(len = 16) {
  85. let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
  86. let maxPos = chars.length;
  87. let character = '';
  88. if (len) {
  89. for (let i = 0; i < len; i++) {
  90. character += chars.charAt(Math.floor(Math.random() * maxPos))
  91. }
  92. } else {
  93. for (let i = 0; i < len; i++) {
  94. character += chars.charAt(Math.floor(Math.random() * maxPos))
  95. }
  96. }
  97. return character;
  98. }
  99. // 获取时间戳
  100. function getTimestamp() {
  101. return new Date().getTime();
  102. }
  103. // 获取url
  104. function getConfigUrl() {
  105. let u = window.navigator.userAgent;
  106. let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
  107. //安卓需要使用当前URL进行微信API注册(即当场调用location.href.split('#')[0])
  108. //iOS需要使用进入页面的初始URL进行注册,(即在任何pushstate发生前,调用location.href.split('#')[0])
  109. let url = '';
  110. if (isiOS) {
  111. url = `${window.localStorage.getItem('_iosWXConfig_') || window.location.href.split('#')[0]}`; //获取初始化的url相关参数
  112. } else {
  113. url = window.location.href.split('#')[0];
  114. }
  115. return url;
  116. }
  117. // 按ascii码从小到大排序
  118. function sort_ascii(obj) {
  119. let arr = [];
  120. let num = 0;
  121. for (let i in obj) {
  122. arr[num] = i;
  123. num++;
  124. }
  125. let sortArr = arr.sort();
  126. let str = ''; //自定义排序字符串
  127. for (let i in sortArr) {
  128. str += sortArr[i] + '=' + obj[sortArr[i]] + '&';
  129. }
  130. //去除两侧字符串
  131. let char = '&';
  132. str = str.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), '');
  133. return str;
  134. }
  135. export {
  136. apiGetAccessToken,
  137. apiGetJsapi_ticket,
  138. getRandomString,
  139. getTimestamp,
  140. getConfigUrl,
  141. sort_ascii,
  142. getSignature
  143. }
        4.3    weixin-js-sdk_location.js:获取定位封装的方法
  1. import wx from 'weixin-js-sdk';
  2. import {
  3. gcj02tobd09
  4. } from '@/utils/coordinateTransform.js';
  5. // 获取地理坐标
  6. export function getByLocation() {
  7. return new Promise((resolve, reject) => {
  8. wx.ready(() => {
  9. wx.getLocation({
  10. type: 'gcj02', // 默认为wgs84(gcj02)的gps坐标
  11. success: function(res) {
  12. let result = gcj02tobd09(res.longitude, res.latitude);
  13. let lngLat = {
  14. code: 200,
  15. lng: result[0],
  16. lat: result[1]
  17. };
  18. resolve(lngLat)
  19. },
  20. error: function(err) {
  21. reject(err)
  22. },
  23. })
  24. })
  25. })
  26. }
        4.4    coordinateTransform.js:坐标转换方法
  1. // 地图坐标转换公共方法
  2. //定义一些常量
  3. const PI = 3.1415926535897932384626;
  4. const a = 6378245.0;
  5. const ee = 0.00669342162296594323;
  6. export function transformlat(lng, lat) {
  7. var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
  8. ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
  9. ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
  10. ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
  11. return ret
  12. }
  13. export function transformlng(lng, lat) {
  14. var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
  15. ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
  16. ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
  17. ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
  18. return ret
  19. }
  20. /**
  21. * 判断是否在国内,不在国内则不做偏移
  22. * @param lng
  23. * @param lat
  24. * @returns {boolean}
  25. */
  26. export function out_of_china(lng, lat) {
  27. return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
  28. }
  29. /**
  30. * WGS84转GCj02
  31. * @param lng
  32. * @param lat
  33. * @returns {*[]}
  34. */
  35. export function wgs84togcj02 (lng, lat) {
  36. if (out_of_china(lng, lat)) {
  37. return [lng, lat]
  38. } else {
  39. var dlat = transformlat(lng - 105.0, lat - 35.0);
  40. var dlng = transformlng(lng - 105.0, lat - 35.0);
  41. var radlat = lat / 180.0 * PI;
  42. var magic = Math.sin(radlat);
  43. magic = 1 - ee * magic * magic;
  44. var sqrtmagic = Math.sqrt(magic);
  45. dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
  46. dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
  47. var mglat = lat + dlat;
  48. var mglng = lng + dlng;
  49. return [mglng, mglat]
  50. }
  51. }
  52. /**
  53. * GCJ02 转换为 WGS84
  54. * @param lng
  55. * @param lat
  56. * @returns {*[]}
  57. */
  58. export function gcj02towgs84 (lng, lat) {
  59. if (out_of_china(lng, lat)) {
  60. return [lng, lat]
  61. } else {
  62. var dlat = transformlat(lng - 105.0, lat - 35.0);
  63. var dlng = transformlng(lng - 105.0, lat - 35.0);
  64. var radlat = lat / 180.0 * PI;
  65. var magic = Math.sin(radlat);
  66. magic = 1 - ee * magic * magic;
  67. var sqrtmagic = Math.sqrt(magic);
  68. dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
  69. dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
  70. let mglat = lat + dlat;
  71. let mglng = lng + dlng;
  72. return [lng * 2 - mglng, lat * 2 - mglat]
  73. }
  74. }
  75. /**
  76. * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
  77. * 即 百度 转 谷歌、高德
  78. * @param bd_lon
  79. * @param bd_lat
  80. * @returns {*[]}
  81. */
  82. export function bd09togcj02 (bd_lon, bd_lat) {
  83. var x_pi = 3.14159265358979324 * 3000.0 / 180.0;
  84. var x = bd_lon - 0.0065;
  85. var y = bd_lat - 0.006;
  86. var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
  87. var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
  88. var gg_lng = z * Math.cos(theta);
  89. var gg_lat = z * Math.sin(theta);
  90. return [gg_lng, gg_lat]
  91. }
  92. /**
  93. * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
  94. * 即谷歌、高德 转 百度
  95. * @param lng
  96. * @param lat
  97. * @returns {*[]}
  98. */
  99. export function gcj02tobd09 (lng, lat) {
  100. var x_PI = 3.14159265358979324 * 3000.0 / 180.0;
  101. var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
  102. var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
  103. var bd_lng = z * Math.cos(theta) + 0.0065;
  104. var bd_lat = z * Math.sin(theta) + 0.006;
  105. return [bd_lng, bd_lat]
  106. }
  107. /**
  108. * WGS84转BD09
  109. * @param lng
  110. * @param lat
  111. * @returns {*[]}
  112. */
  113. export function WGS84ToBD09 (lng, lat) {
  114. let gcj02 = wgs84togcj02(lng, lat);
  115. return gcj02tobd09(gcj02[0], gcj02[1]);
  116. }
  117. /**
  118. * BD09转WGS84
  119. * @param lng
  120. * @param lat
  121. * @returns {*[]}
  122. */
  123. export function BD09ToWGS84 (lng, lat) {
  124. let gcj02 = bd09togcj02(lng, lat);
  125. return gcj02towgs84(gcj02[0], gcj02[1]);
  126. }

第五步:

测试公众号(开启获取位置的权限、js接口安全域名)

微信公众平台icon-default.png?t=N7T8https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

第六步:

vebniew的src域名要和js接口安全域名一致 (不能一个写花生壳域名一个写本地ip)

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号