- 同一个广告位ID可以多个小程序使用吗?
同一个广告位ID可以多个小程序使用吗?
2022-12-10 - 小程序内嵌H5页面跳转至小程序页面,再返回到H5页面不刷新问题解决方案
需求:类似常见的电商页面,从首页跳转至H5页面,在H5页面展示商品列表,点击某个商品进入小程序商品详情页 1.小程序->2.h5->3.小程序 问题是从3返回到2时,H5页面自带的监听页面可见的函数无效,如图所示: [代码]//监听页面显示隐藏 document.addEventListener(visibilitychange, this.isShow); [代码] 无法触发此类函数,类似的还有pageshow等等。 想在页面解决该问题,不通过即时通信的话,就只有两种方案 刷新webview所在的小程序页面,在onshow时更新webview 触发H5显示隐藏的监听 由于尝试了各种监听事件均无效,因此放弃了方案2,如果有什么好办法欢迎留言。 方案一具体实现: 回退可以触发onshow函数,定义一个变量,如时间戳,加在webview的url后边,url发生改变,H5页面重新加载,可以达到更新页面的目的。 [代码]onShow() { this.version = (new Date()).valueOf(); this.url = www.baidu.com+this.version; } [代码] 但是这种做法有个很严重的问题,改变url 会增加webview的history,在webview所在页面,点击后退,会返回之前的H5页面,用户可以多次点击才能回到首页。 [图片] [图片] 因此想到了在这个页面onhide的时候,移除webview组件,页面重新显示后,再增加改组件,这样就解决了这个问题。
2019-07-17 - 腾讯地图使用和选点连线计算距离
序言 最近练习了下腾讯地图的使用,包含地图展示、定位、自定义标注和气泡、点聚合、拖动地图选点、逆地址解析、地图连线计算距离,标注编辑和删除,具体可扫码或在demo查看。 效果图 [图片] [图片] [图片] [图片] 实现方式 地图展示 地图使用的是腾讯地图[代码]Map[代码]组件。官方文档 逆地址解析 逆地址解析使用的是腾讯位置服务,可以通过拿到的经纬度获取到位置的一些信息 地图选点 地图选点有两种实现方式 一种是使用小程序API wx.chooseLocation 另一种通过小程序地图选点插件 根据经纬度计算距离 计算距离有两种实现方式 一种是使用腾讯位置服务的距离算法 一种根据经纬度计算地球两个经纬度的距离(haversine公式) 注: 腾讯位置服务需要注册,使用时需要在后台配置,需要下载对应js库文件,有调用频率限制 小程序插件需要在小程序后台和小程序代码配置 经纬度计算距离 [代码]//给定的经度1,纬度1;经度2,纬度2. 计算2个经纬度之间的距离。 //<returns>距离 (单位:米)</returns> //util的方法是通过读取类文件,然后通过映射获取的,所以需要在使用的page中加入 //var util = require('../../../utils/util.js');相当于一个导入的过程。 function distance(p1, p2) { //用haversine公式计算球面两点间的距离。 //经纬度转换成弧度 var lat1 = p1.latitude * Math.PI / 180; var lon1 = p1.longitude * Math.PI / 180; var lat2 = p2.latitude * Math.PI / 180; var lon2 = p2.longitude * Math.PI / 180; //差值 var vLon = Math.abs(lon1 - lon2); var vLat = Math.abs(lat1 - lat2); //h is the great circle distance in radians, great circle就是一个球体上的切面,它的圆心即是球心的一个周长最大的圆。 var v = Math.sin(vLat / 2); var v1 = Math.sin(vLon / 2); var h = v * v + Math.cos(lat1) * Math.cos(lat2) * v1 * v1; // 地球半径 平均值,米 var distance = 2 * 6371000 * Math.asin(Math.sqrt(h)); return distance; } module.exports = {//用于映射函数 distance: distance, } [代码] 地图展示和逆地址解析实现代码 wxml [代码]<!-- <map id="myMap" style="width: 100%; height: 70vh;" latitude="40.040415" longitude="116.273511" scale="17"></map> --> <view class="map-container"> <map id="myMap" class="map" latitude="{{latitude}}" longitude="{{longitude}}" show-location="{{isShowPosition}}" show-compass="{{isShowCompass}}" show-scale="{{isShowScale}}" markers="{{markers}}" scale="{{scale}}" bindregionchange="onMapChange" bindtap="onMapTap" bindmarkertap="onMapMarkTap" bindcallouttap="onMapCalloutTap"> <!-- <cover-image class="centerImg" src="./images/ic_mark2.png" /> --> <!-- 带动画 --> <cover-image class="centerImg {{animation ? 'locationpicker-animation' : ''}}" src="./images/ic_mark2.png" bindanimationend="onMarkerAnimationend" /> <cover-view class="locationBg" catchtap='onClickLocation'> <cover-image class="locationIcon" src="./images/ic_location.png" /> </cover-view> </map> </view> <van-cell-group title="拖动地图选中的位置"> <van-cell title="地址描述" label="{{address}}" /> <van-cell title="位置描述" label="{{recommend}}" /> <van-cell title="大致位置" label="{{rough}}" /> </van-cell-group> <view style="padding-top: 50px;"></view> [代码] js [代码]var QQMapWX = require('./lib/qqmap-wx-jssdk1.2/qqmap-wx-jssdk.min.js'); var qqmapsdk; const INIT_CALLOUT = { content: '天安门广场', padding: 10, display: 'ALWAYS', anchorY: -30, bgColor: '#ffffff', anchorY: -30, fontSize: 14, textAlign: 'center', // borderWidth: 2, }; const INIT_MARKER = { id: 2, latitude: 39.903734, longitude: 116.397845, iconPath: './images/Marker3_Activated@3x.png', width: '34px', height: '34px', rotate: 0, alpha: 1, callout: INIT_CALLOUT, }; Page({ /** * 页面的初始数据 */ data: { latitude: 40.040415, // 纬度 longitude: 116.273511, // 经度 scale: 3, //默认16 isShowScale: true, isShowCompass: true, isShowPosition: true, markers: [ // 我的位置 // { // id: 0, // iconPath: "./images/ic_mark1.png", // latitude: 40.040415, // longitude: 116.273511, // width: 30, // height: 30, // title: '我的位置' //点击时显示,callout存在时将被忽略 // }, // 其它 { ...INIT_MARKER }, { id: 3, latitude: 40.040415, longitude: 116.273511, iconPath: './images/Marker1_Activated@3x.png', width: 30, height: 30, callout: { content: '腾讯总部大楼', padding: 10, borderRadius: 5, display: 'ALWAYS', }, // 地图标记文字 label: { content: '标记文字', color: '#f00', textAlign: 'center' } } ], animation: false, address: '', recommend: '', rough: '', }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { // 实例化API核心类 // 开发文档:https://lbs.qq.com/miniProgram/jsSdk/jsSdkGuide/jsSdkOverview qqmapsdk = new QQMapWX({ key: '4M5BZ-ALKLU-BVXVL-B2HCC-DJSUS-WGFBH' }); this.mapCtx = wx.createMapContext('myMap') // this.mapCtx.moveToLocation() // this.getCurrentLocation() // this.getCenterLngLat() // //更换定位图标。这个图标支持网络图片。 // this.mapCtx.setLocMarkerIcon({ // iconPath: "./images/ic_mark1.png", // }) }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, // 获取当前位置 getCurrentLocation() { var that = this const lat = "markers[0].latitude"; const log = "markers[0].longitude"; // wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标 wx.getLocation({ type: 'gcj02', success: (res) => { console.log('当前位置'); console.log(res); that.setData({ latitude: res.latitude, longitude: res.longitude, [lat]: res.latitude, [log]: res.longitude }); }, fail: (err) => { // wx.showToast({ // title: '为了不影响您的使用,请授权定位', // icon: 'none' // }) } }); }, // 点击定位按钮 onClickLocation() { var that = this this.setData({ scale: 16, }) setTimeout(() => { that.mapCtx.moveToLocation() }, 500); }, // 视野发生变化时触发 // 监听拖动地图,拖动结束根据中心点更新页面 onMapChange(e) { if (e.type == 'end' && (e.causedBy == 'scale' || e.causedBy == 'drag')) { this.getCenterLngLat() this.setData({ animation: true, }); } }, // 点击地图 onMapTap(e) { console.log('点击地图'); console.log(e); wx.showToast({ title: '点击地图', icon: 'none' }) }, // 点击标记点时触发,e.detail = {markerId} onMapMarkTap(e) { console.log('点击标记点'); console.log(e); console.log(e.detail.markerId); wx.showToast({ title: '点击标记点', icon: 'none' }) }, // 点击标记点对应的气泡时触发e.detail = {markerId} onMapCalloutTap(e) { console.log('点击气泡'); console.log(e); console.log(e.detail.markerId); wx.showToast({ title: '点击标记点对应的气泡', icon: 'none' }) }, onMarkerAnimationend() { this.setData({ animation: false }); }, // 获取地图中心点的经纬度 getCenterLngLat: function () { var that = this this.mapCtx.getCenterLocation({ success: function (res) { console.log('获取中间点'); console.log(res); that.reverseGeocoder(res.latitude, res.longitude) } }) }, // 逆地址解析 reverseGeocoder(latitude, longitude) { var that = this qqmapsdk.reverseGeocoder({ location: { latitude: latitude, longitude: longitude }, success: function (res) { console.log('逆地址解析结果'); console.log(res) var result = res.result console.log(result) // 地址描述 let address = result.address // 位置描述 let formatted_addresses = result.formatted_addresses // 经过腾讯地图优化过的描述方式, 更具人性化特点 let recommend = formatted_addresses.recommend // 大致位置, 可用于对位置的粗略描述 let rough = formatted_addresses.rough console.log(address) console.log(recommend) console.log(rough) that.setData({ address: address, recommend: recommend, rough: rough, }) }, }); } }) [代码] 地图标点连线计算距离实现代码 wxml [代码]<view class="map-container"> <map id="myMap" class="map" latitude="{{latitude}}" longitude="{{longitude}}" show-location="{{isShowPosition}}" show-compass="{{isShowCompass}}" show-scale="{{isShowScale}}" markers="{{markers}}" scale="{{scale}}" polygons="{{polygons}}" polyline="{{polyline}}" include-points="{{includePoints}}" enable-zoom bindregionchange="onMapChange" bindtap="onMapTap" bindmarkertap="onMapMarkTap" bindcallouttap="onMapCalloutTap"> <!-- <cover-image class="centerImg" src="./images/ic_mark2.png" /> --> <cover-view class="center-bg" catchtap="onClickAddMarkerBtn"> <cover-view class="center-top">确定打标</cover-view> <cover-view class="center-bottom"></cover-view> </cover-view> <!-- 定位按钮 --> <cover-view class="locationBg" catchtap='onClickLocation'> <cover-image class="locationIcon" src="./images/ic_location.png" /> </cover-view> <!-- 大头针中间文字 --> <cover-view slot="callout"> <cover-view wx:for="{{markers}}" wx:key='index' marker-id="{{item.id}}"> <cover-view> {{ (item.id + 1) }}</cover-view> </cover-view> </cover-view> </map> </view> [代码] js [代码]const util = require('./util') Page({ /** * 页面的初始数据 */ data: { latitude: 40.040415, longitude: 116.273511, scale: 16, //默认16 isShowScale: true, isShowCompass: true, isShowPosition: true, markers: [ // 我的位置 // { // id: 0, // iconPath: "./images/ic_mark1.png", // latitude: 40.040415, // longitude: 116.273511, // width: 30, // height: 30, // title: '我的位置' //点击时显示,callout存在时将被忽略 // }, // 其它 // { // id: 3, // latitude: 40.040415, // longitude: 116.273511, // iconPath: './images/Marker1_Activated@3x.png', // width: 30, // height: 30, // callout: { // content: '腾讯总部大楼', // padding: 10, // borderRadius: 5, // display: 'ALWAYS', // }, // label: { // content: '标记文字', // color: '#f00', // textAlign: 'center' // } // } ], curPoints: [], polyline: '', // 路线 polygons: '', // 多边形 includePoints: '', // 缩放视野以包含所有给定的坐标点 isSelectMarker: false, selectMarkerId: '', }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.mapCtx = wx.createMapContext('myMap') // this.mapCtx.moveToLocation() // this.getCurrentLocation() // this.getCenterLngLat() // //更换定位图标。这个图标支持网络图片。 // this.mapCtx.setLocMarkerIcon({ // iconPath: "./images/ic_mark1.png", // }) }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, // 获取当前位置 getCurrentLocation() { var that = this const lat = "markers[0].latitude"; const log = "markers[0].longitude"; // wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标 wx.getLocation({ type: 'gcj02', success: (res) => { console.log('当前位置'); console.log(res); that.setData({ latitude: res.latitude, longitude: res.longitude, [lat]: res.latitude, [log]: res.longitude }); }, fail: (err) => { // wx.showToast({ // title: '为了不影响您的使用,请授权定位', // icon: 'none' // }) } }); }, // 点击定位按钮 onClickLocation() { this.setData({ scale: 17 }); setTimeout(() => { this.mapCtx.moveToLocation() }, 200); }, // 视野发生变化时触发 // 监听拖动地图,拖动结束根据中心点更新页面 onMapChange(e) { if (e.type == 'end' && (e.causedBy == 'scale' || e.causedBy == 'drag')) { this.getCenterLngLat() if (this.data.isSelectMarker) { setTimeout(() => { this.moveMarker(this.data.selectMarkerId, this.data.latitude, this.data.longitude) }, 500); } } }, // 点击地图 onMapTap(e) { console.log('点击地图'); console.log(e); }, // 点击标记点时触发,e.detail = {markerId} onMapMarkTap(e) { console.log('点击标记点'); console.log(e.detail.markerId); this.selectMarker(e.detail.markerId) }, // 点击标记点对应的气泡时触发e.detail = {markerId} onMapCalloutTap(e) { console.log('点击气泡'); console.log(e.detail.markerId); this.selectMarker(e.detail.markerId) }, onClickAddMarkerBtn() { this.addMarker(this.data.latitude, this.data.longitude) }, // 获取地图中心点的经纬度 getCenterLngLat: function () { var that = this this.mapCtx.getCenterLocation({ success: function (res) { console.log('获取中间点'); console.log(res); that.setData({ latitude: res.latitude, longitude: res.longitude, }); } }) }, // 编辑或删除选中标记 selectMarker(markerId) { let tempMarkers = this.data.markers tempMarkers.forEach(function (item, index) { item.iconPath = "./images/ic_mark1.png" item.isSelect = false if (index == markerId) { item.isSelect = !item.isSelect item.iconPath = item.isSelect ? './images/Marker1_Activated@3x.png' : "./images/ic_mark1.png" } }); let marker = this.data.markers[markerId] this.setData({ latitude: marker.latitude, longitude: marker.longitude, markers: tempMarkers, isSelectMarker: true, selectMarkerId: markerId, }); var that = this wx.showModal({ title: '是否删除该标记点?', content: '确认将删除,取消可拖动地图更新标记点位置', success(res) { if (res.confirm) { console.log('用户点击确定') that.deleteMarker(markerId) } else if (res.cancel) { console.log('用户点击取消') } } }) }, cancelMarker() { let tempMarkers = this.data.markers tempMarkers.forEach(function (item, index) { item.iconPath = "./images/ic_mark1.png" item.isSelect = false }); this.setData({ markers: tempMarkers, isSelectMarker: false, selectMarkerId: "", }); }, // 添加一个标记点 addMarker(latitude, longitude) { // 判断是否存在,相同经纬度不再添加 let isExist = false this.data.markers.forEach(item => { if (item.latitude == latitude && item.longitude == longitude) { console.log('已存在,相同经纬度不再添加'); isExist = true return } }); if (isExist == true) { return } // 不存在。新增 var mark = new Object(); //声明一个mark对象 mark.id = this.data.markers.length; mark.longitude = longitude; //经度 mark.latitude = latitude; mark.iconPath = "./images/ic_mark1.png"; mark.width = 40; mark.height = 40; // mark.label = { // fontSize: 14, // anchorX: 0, // anchorY: -35, // content: mark.id + '', // textAlign: 'center', // color: '#000000', // } // mark.callout = { // content: '腾讯总部大楼', // padding: 10, // borderRadius: 5, // display: 'ALWAYS', // } // 自定义气泡窗口 mark.customCallout = { anchorX: 0, anchorY: 25, display: 'ALWAYS', } mark.isSelect = false this.data.markers.push(mark) this.setData({ markers: this.data.markers }) // 在data中声明一个curPoints 来记录点击所有的点,在完成绘制的时候清空点。 this.data.curPoints.push({ longitude: longitude, latitude: latitude }) // 添加线上的超过一个的点,每次把距离叠加上去 if (this.data.curPoints.length > 1) { // console.log(this.data.curPoints) // 地图上用的polyline是一个线集合对象,如果只放一条线是无法看见的。 var pl = [{ points: this.data.curPoints, color: "#0066FF", width: 2, dottedLine: false, }]; //更改界面数据 this.setData({ polyline: pl }) } // 计算距离 this.calculateDistance() }, // 编辑标记点(移动位置) moveMarker(markerId, latitude, longitude) { console.log('编辑标记点(移动位置)'); this.mapCtx.translateMarker({ // 要平移的marker的id markerId: markerId, // 移动过程中是否自动旋转 marker autoRotate: false, // 动画持续时长,平移与旋转分别计算 duration: 10, // 平移到的目的地,参数为经纬度 destination: { latitude: latitude, longitude: longitude, }, //平移动画后的回调函数 animationEnd() {} }) let tempMarkers = this.data.markers let marker = this.data.markers[markerId] let curPoints = this.data.curPoints curPoints.forEach(function (item, index) { if (item.latitude == marker.latitude && item.longitude == marker.longitude) { curPoints.splice(index, 1, { longitude: longitude, latitude: latitude }) } }); tempMarkers[markerId].latitude = latitude tempMarkers[markerId].longitude = longitude // 地图上用的polyline是一个线集合对象,如果只放一条线是无法看见的。 var pl = [{ points: curPoints, color: "#0066FF", width: 2, dottedLine: false, }]; this.setData({ polyline: curPoints.length > 1 ? pl : '', curPoints: curPoints, markers: tempMarkers, }) // 计算距离 this.calculateDistance() // 移动结束取消选中 this.cancelMarker() }, // 删除一个标记点 deleteMarker(markerId) { let tempMarkers = this.data.markers let delMarker = tempMarkers[markerId] // console.log(delMarker); if (tempMarkers.length > markerId) { // 删除 tempMarkers.splice(markerId, 1) // 重新排序,设置顺序 tempMarkers.forEach(function (item, index) { item.id = index }); let curPoints = this.data.curPoints curPoints.forEach(function (item, index) { if (item.latitude == delMarker.latitude && item.longitude == delMarker.longitude) { curPoints.splice(index, 1) } }); // 地图上用的polyline是一个线集合对象,如果只放一条线是无法看见的。 var pl = [{ points: curPoints, color: "#0066FF", width: 2, dottedLine: false, }]; this.setData({ polyline: curPoints.length > 1 ? pl : '', curPoints: curPoints, markers: tempMarkers }) // 计算距离 this.calculateDistance() } }, // 每次更新markers之后重新计算距离 calculateDistance() { // this.calculateEachDistance() this.calculateAllDistance() }, // 计算两个点之间的距离,个数大于1每个点下都显示距离,不显示总距离 calculateEachDistance() { let curPoints = this.data.curPoints if (curPoints.length > 1) { var p2 = curPoints[curPoints.length - 1] var p1 = curPoints[curPoints.length - 2] // console.log(p1); // console.log(p2); let dis = 0 dis += util.distance(p1, p2); let datas = Number(dis); //转为字符串 let datas2 = datas.toFixed(2) + "米"; //保留两位小数 var x = -(datas2.length * 1) //设置文字向左偏移 let label = { fontSize: 14, anchorX: x, anchorY: 0, content: datas2, textAlign: 'center', color: '#000000', } let last = "markers[" + (this.data.markers.length - 1) + "].label"; this.setData({ [last]: label }) } else if (curPoints.length == 1) { let label = { fontSize: 14, anchorX: x, anchorY: 0, content: '', textAlign: 'center', color: '#000000', } this.setData({ ['markers[0].label']: label }) } }, // 计算所有点之间的总距离,按添加顺序依次计算两点之间距离,并在最后一个点上显示总距离 calculateAllDistance() { // 添加线上的超过一个的点,每次把距离叠加上去 let curPoints = this.data.curPoints if (curPoints.length > 1) { let dis = 0 curPoints.forEach(function (item, index) { if (index < (curPoints.length - 1)) { var p1 = curPoints[index] var p2 = curPoints[index + 1] dis += util.distance(p1, p2); } }); let datas = Number(dis); //转为字符串 let datas2 = datas.toFixed(2) + "米"; //保留两位小数 var x = -(datas2.length * 1) //设置文字向左偏移 let label = { fontSize: 14, anchorX: x, anchorY: 0, content: datas2, textAlign: 'center', color: '#000000', } let last2 = "markers[" + (this.data.markers.length - 2) + "].label"; let last = "markers[" + (this.data.markers.length - 1) + "].label"; this.setData({ [last2]: {}, [last]: label }) } else if (curPoints.length == 1) { let label = { fontSize: 14, anchorX: x, anchorY: 0, content: '', textAlign: 'center', color: '#000000', } this.setData({ ['markers[0].label']: label }) } } }) [代码] GitHub Demo 地址: [代码]jh-weapp-demo[代码] 实现一些常用效果、封装通用组件和工具类 小程序码 [图片]
2022-04-20 - wx.login请求服务器返回数据data: "null[B@c35210c"是openid吗?
小程序端代码: wx.login({ success: res => { if (res.code) { //let URL = 'https://api.weixin.qq.com/sns/jscode2session?appid=aaaaaaaa&secret=aaaaaaaaaaaaaaaa&js_code='+res.code+'&grant_type=authorization_code' // 这个url在服务器端代码调用 //http://10.221.129.198:8080/request?type=100 let URL = 'http://10.221.129.198:8080/request?login_code='+res.code console.log(URL) wx.request({ url: URL , timeout: 100000, success:function(res){ //res.data中有openid console.log(res) console.log('login request success') fail: function (res) { console.log(res) console.log('login request failed') fail: function (res) { console.log('login failed') console.log(res) 服务器端代码: @Controller public class ServerController { @RequestMapping(value = "/request") public @ResponseBody String request(@RequestParam(value="login_code") String code) { String res = null; if ( !code.equals(' ') ) { // 向微信申请获取用户id信息 // https://api.weixin.qq.com/sns/jscode2session? // appid=aaaaaaaaaaaaaaaa&secret=aaaaaaaaaaaaaaaa // js_code=code // &grant_type=authorization_code String str_url = "https://api.weixin.qq.com/sns/jscode2session?appid=aaaaaaaaaaaaa&secret=bbbbbbbbbbbbbb&js_code='+code+'&grant_type=authorization_code"; InputStream in = null; OutputStream out = null; try { URL url = new URL(str_url); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestProperty("User-Agent","Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); in = new BufferedInputStream(connection.getInputStream()); out = new BufferedOutputStream(new FileOutputStream("/home/lys/package-app-NewHomeService/login.txt", true)); byte[] bytes = new byte[1024]; int len = 0; if((len = in.read(bytes)) != -1) { res = bytes.toString(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); // HttpServletRequest request = null; // HttpServletResponse response = null; } else { res = "request value error!"; return res; 小程序端返回的res最后打印出来的数据:和服务器端断点看到的url返回值一样 {data: "null[B@c35210c", header: {…}, statusCode: 200, cookies: Array(0), errMsg: "request:ok"}cookies: [] data: "null[B@c35210c" errMsg: "request:ok" header: Connection: "keep-alive"Content-Length: "14"Content-Type: "text/plain;charset=UTF-8"Date: "Thu, 23 Feb 2023 09:39:00 GMT"Keep-Alive: "timeout=60" __proto__: ObjectstatusCode: 200__proto__: Object login request success login调用期间,小程序没用弹出确认登陆的弹窗,感觉很奇怪 请问下各位login成功的同学们,你们返回值是这样的吗
2023-02-23 - wx.login请求服务器返回数据data,获取session_key和openid
小程序端代码: wx.login({ success: res => { if (res.code) { //let URL = 'https://api.weixin.qq.com/sns/jscode2session?appid=aaaaaaaa&secret=aaaaaaaaaaaaaaaa&js_code='+res.code+'&grant_type=authorization_code' // 这个url在服务器端代码调用 //http://10.221.129.198:8080/request?type=100 let URL = 'http://10.221.129.198:8080/request?login_code='+res.code console.log(URL) wx.request({ url: URL , timeout: 100000, success:function(res){ //res.data中有openid console.log(res) console.log('login request success') fail: function (res) { console.log(res) console.log('login request failed') fail: function (res) { console.log('login failed') console.log(res) 服务器端代码: @Controller public class ServerController { @RequestMapping(value = "/request") public @ResponseBody String request(@RequestParam(value="login_code") String code) { String res = null; if ( !code.equals(' ') ) { // 向微信申请获取用户id信息 // https://api.weixin.qq.com/sns/jscode2session? // appid=aaaaaaaaaaaaaaaa&secret=aaaaaaaaaaaaaaaa // js_code=code // &grant_type=authorization_code String str_url = "https://api.weixin.qq.com/sns/jscode2session?appid=aaaaaaaaaaaaa&secret=bbbbbbbbbbbbbb&js_code='+code+'&grant_type=authorization_code"; InputStream in = null; OutputStream out = null; try { URL url = new URL(str_url); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestProperty("User-Agent","Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); in = new BufferedInputStream(connection.getInputStream()); out = new BufferedOutputStream(new FileOutputStream("/home/lys/package-app-NewHomeService/login.txt", true)); byte[] bytes = new byte[1024]; int len = 0; if((len = in.read(bytes)) != -1) { res = bytes.toString(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); // HttpServletRequest request = null; // HttpServletResponse response = null; } else { res = "request value error!"; return res; 小程序端返回的res最后打印出来的数据:和服务器端断点看到的url返回值一样 {data: "null[B@c35210c", header: {…}, statusCode: 200, cookies: Array(0), errMsg: "request:ok"}cookies: [] data: "null[B@c35210c" errMsg: "request:ok" header: Connection: "keep-alive"Content-Length: "14"Content-Type: "text/plain;charset=UTF-8"Date: "Thu, 23 Feb 2023 09:39:00 GMT"Keep-Alive: "timeout=60" __proto__: ObjectstatusCode: 200__proto__: Object login request success login调用期间,小程序没用弹出确认登陆的弹窗,data: "null[B@c35210c"是乱码。 ---------------------------------------- 以上代码需要修改,修改如下: (看到有人说:服务端curl证书验证关闭就好了 true=>false,没试,感觉配置ssl还挺麻烦的,目测应该是不需要) 上文的url错误,="+code+"会被直接拼接到字符串,要改成 String string = "https://api.weixin.qq.com/sns/jscode2session?appid=xxx&secret=xxx&js_code="+code+"&grant_type=authorization_code"; URL url = new URL(string); 用户通过login()方法获取code,然后把code传给开发后台,后台通过code 以及appid以及密钥获取openid和sessionkey 进行登陆,然后返回一个token给前端, 目前直接在浏览器访问网页,肉眼可见返回值是json,{"session_key":"R+DEI9Q9xxxxxaMS\/gdnQ==","openid":"o4LDU5Rbyxxxxxmp6JVbuZg"}这样子,或者{"errcode":40163,"errmsg":"code been used, rid: 63f7638f-5cfd2279-5802ec1a"} 小程序端console输出res是data: "null[B@c35210c",应该是正确的返回值,但是数据格式转换有问题。 但是我用idea搭建的服务器没用jsonobject,只有jsonpobject,没办法直接转成json数据,就很迷现在,等解决了再来改评论 63f7638f-5cfd2279-5802ec1a和c35210c每次重新刷新网页或重新申请都会变,应该也是临时数据吧 ---- byte[] request(@RequestParam(value="login_code") String code) { byte[] res = null; ..... byte[] bytes = new byte[1024]; if ((len = in.read(bytes)) != -1) { 断点调试打印byte[] bytes,发现为ascii码数组,对照ascii转换后发现是session_key和openid // bytes = 123 34 115s 101e 115s 115s 105i 111o 110n 95_ 107k 101e 121y... == {"sessi..... // ascii: {"session_key":"lV+hmiQWeFYzOl\/WspCamw==","openid":"o4LDU5Rbyoz6HvMpIyNmp6JVbuZg"} res = bytes; return res; 前端不能正确获取数据,是因为服务器不能直接将字符数组转换成字符串,bytes.toString()是有问题的,所以将服务端请求返回值类型改成字符数组,直接返回给前端处理,由前端将字符数组类型转换为json类型 [图片] 至此,前端可以成功拿到session_key和openid
2023-02-24 - wx.login() “曲线救国”获取openid的方法
经热心网友指出昨日之方法上正式小程序版本时行不通,现修改如下: 小程序端: wx.login({ success: res => { if (res.code) { wx.request({ url: 'https://我的服务器网址/getopenid.php' , data:{code:res.code}, success:function(res){ console.log(res.data) } }) } } }) 服务器端: <?php $code=$_GET["code"]; $url = "https://api.weixin.qq.com/sns/jscode2session?js_code=$code"; //经试验这个js_code=$code写不到下面POST参数中去 $result = curl_get_https($url); var_dump($result); function curl_get_https($url) { $curl = curl_init(); //如果需要参数,设置POST参数 $post_string = array('appid'=>'###############','secret'=>'********************'); //小程序ID和密钥 curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post_string)); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 跳过检查 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 跳过检查 $tmpInfo = curl_exec($curl); curl_close($curl); return $tmpInfo; //返回json对象 } ?> 经试验,没问题,小程序端可得到结果:string(82) "{"session_key":"XgAJf3mWSIhs8zDB72Xacw==","openid":"************************"}"
2022-10-30