最近在开发支付宝小程序,现将其中的一些经验和坑记录下来,防止以后忘记。
支付宝小程序 开放平台 地址:https://docs.alipay.com/mini/framework/app
注意:在获取用户信息 调试 时(如显示用户头像时),一定要使用真机预览。因为有时候在 蚂蚁开发者工具 上没有问题,用户信息都能获取到,而在真机上就是undefined。
通过 用户授权 接口可以获取授权码,可以选择 auth_user(主动授权) / auth_base(静默授权)/ auth_zhima(芝麻信用),都可以获取到授权码。
*但是,使用后两种是无法获取到用户信息的。即上面提到的情况,工具上正常,真机上获取不到。
所以一定记住:使用主动授权方式且授权成功之后才可以获取到用户信息。
在和服务器交互的时候,是必须要用到authCode授权码的,而用户信息往往只是展示效果不是必须的。我认为比较可行的做法是:在app.js中使用静默授权的方式获取到authCode(传给服务器),在需要显示用户信息的地方再使用主动授权获取用户信息(这样如果用户拒绝了授权也不会影响程序的继续执行),然后将用户信息存储起来(可以存储为全局数据,也可以存储在本地缓存中)。
使用支付宝小程序的地图接口,在创建并使用返回的 map 上下文对象,来加载地图,显示地图控件(controls)和地图标记(marker)的时候。地图控件和地图标记所用的图标的地址必须要用绝对路径,否则在真机上是不显示的(在IDE模拟上可以显示)。
实现代码如下:(分别为 .acss / .axml / .js 中的代码片)
.h1 { margin: 0.2rem 0.25rem 0; font-size: 16px }
.uploadImgBtn { width: 4rem; border: none; background-color: #0c9; color: #fff; margin: 0.4rem auto 0; border-radius: 1rem }
.allImgBox { width: 740rpx; margin-top: 30rpx }
.imgBox, .addImgBox { display: inline-block; width: 140rpx; height: 140rpx; position: relative; margin: 0 22rpx 35rpx; vertical-align: middle }
.imgBox image,
.addImgBox text { width: 140rpx; height: 140rpx; border: 2rpx dotted #aaa }
.imgBox .delImg { position: absolute; top: -20rpx; right: -20rpx; height: 18px; overflow: visible }
.addImgBox text { display: inline-block; line-height: 140rpx; text-align: center; font-size: 24rpx; color: #aaa }
.photo-attention { color: #333333; font-size: 0.3rem; line-height: 0.5rem; padding: 0 25rpx }
<view class="h1">上传图片view>
<view class="allImgBox">
<block a:for="{{imgUrls}}" a:key="{{item}}" a:index="{{index}}" name="{{file}}" id="{{file}}">
<view class="imgBox">
<image src="{{item}}">image>
<view data-index="{{index}}" onTap="delImg" class="delImg">
<icon type="cancel" color="red" size="18" />
view>
view>
block>
<view class="addImgBox" onTap="addImg" a:if="{{canAddImg}}"><text>{{addImgText}}text>view>
view>
<view class="photo-attention">
<view>照片要求:view>
<view>1. 最多六张view>
<view>2. XXXXXXXXXXX XXXXXXXXXXXview>
view>
<button type="default" onTap="toUploadImg" class="uploadImgBtn"> 提交 button>
Page({
data: {
imgUrls: [],
addImgText: "拍照/相册",
canAddImg: true,
maxAddImgNum: 6,
i: 0,
imgArr: []
},
addImg: function () { // 上传照片
var that = this;
my.chooseImage({
count: that.data.maxAddImgNum,
success: (res) => {
that.setData({i: 0, imgArr: res.apFilePaths});
that.uploadImg();
},
});
},
toUploadImg: function(){},
uploadImg: function() {
var that = this;
var ii = that.data.i;
if(ii < that.data.imgArr.length){
// my.uploadFile({
// url: "", //自己服务器接口地址
// fileType: 'image',
// fileName: 'file',
// filePath: that.data.imgArr[that.data.i],
// formData: { //这里写自己服务器接口需要的额外参数
// session: my.getStorageSync({key:'session'}).data
// },
// success: (res) => {
var res = {data:'{"data":{"image_url":'+JSON.stringify(that.data.imgArr[that.data.i])+'},"code":0,"msg":"\u6210\u529f"}', errMsg:"uploadFile:ok", statusCode:200};
//res是自己服务器接口返回的数据(image_url的值为服务器上的图片链接),这里用假数据模拟
var _imgUrls = that.data.imgUrls;
_imgUrls.push(JSON.parse(res.data).data.image_url); //取到包含所有图片的数组
that.setData({imgUrls: _imgUrls});
_imgUrls.length == 0 && that.set_data(that,_imgUrls,"拍照/相册",true);
(_imgUrls.length > 0 && _imgUrls.length < that.data.maxAddImgNum) && that.set_data(that,_imgUrls,"+",true);
_imgUrls.length >= that.data.maxAddImgNum && that.set_data(that,_imgUrls.splice(0,that.data.maxAddImgNum),"+",false);
that.setData({i: ii+1});
that.uploadImg();
// },
// });
}
},
delImg: function (e) { // 删除照片
var index = e.target.dataset.index;
var _imgUrls = this.data.imgUrls;
_imgUrls.splice(index, 1);
_imgUrls.length == 0 && this.set_data(this,_imgUrls,"拍照/相册",true);
(_imgUrls.length > 0 && _imgUrls.length < this.data.maxAddImgNum) && this.set_data(this,_imgUrls,"+",true);
},
set_data: function(that,imgUrls,addImgText,canAddImg) {
that.setData({
imgUrls: imgUrls,
addImgText: addImgText,
canAddImg: canAddImg
});
}
});
这里有一点需要着重说明一下,也许有的人已经注意到了,这个demo是在用户每一次选择图片之后都进行上传操作,这样有利也有弊。
坏处:如果用户进行多次选择图片操作,选择后删除再选择又删除……,这样的话每一次选择的图片都会被上传到服务器上,而用户的删除操作不会将服务器上的清除,比较耗费服务器资源。
好处:在每一次选择图片之后进行上传,这样每一次等待的时间不会太长。而如果有很多要上传的图片,用户在多次选择完成,点击按钮(如提交按钮)后统一上传的话,可以想到,这么多的图片会上传很长时间,体验不好。
综合考虑,在上传图片数量多于5张的情况下,可以用上面demo的方式,每选择一次就将图片上传。小于5张图片的话,可以在提交的时候统一将选好的图片上传,这种方式的js代码如下:
Page({
data: {
imgUrls: [],
addImgText: "拍照/相册",
canAddImg: true,
maxAddImgNum: 6,
i: 0
},
addImg: function () { // 上传照片
var that = this;
my.chooseImage({
count: that.data.maxAddImgNum,
success: (res) => {
var _imgUrls = this.data.imgUrls;
_imgUrls = _imgUrls.concat(res.apFilePaths);
_imgUrls.length == 0 && that.set_data(that,_imgUrls,"拍照/相册",true);
(_imgUrls.length > 0 && _imgUrls.length < that.data.maxAddImgNum) && that.set_data(that,_imgUrls,"+",true);
_imgUrls.length >= that.data.maxAddImgNum && that.set_data(that,_imgUrls.splice(0,that.data.maxAddImgNum),"+",false);
},
});
},
toUploadImg: function(){
this.uploadImg();
},
uploadImg: function() {
var that = this;
var ii = that.data.i;
if(ii < that.data.imgUrls.length){
// my.uploadFile({
// url: "", //自己服务器接口地址
// fileType: 'image',
// fileName: 'file',
// filePath: that.data.imgUrls[that.data.i],
// formData: { //这里写自己服务器接口需要的额外参数
// session: my.getStorageSync({key:'session'}).data
// },
// success: (res) => {
var res = {data:'{"data":{"image_url":"xxxxxx"},"code":0,"msg":"\u6210\u529f"}', errMsg:"uploadFile:ok", statusCode:200};
//res是自己服务器接口返回的数据(image_url的值为服务器上的图片链接),这里用假数据模拟
if(JSON.parse(res.data).code == 0){
console.log('上传成功' + that.data.i);
}
that.setData({i: ii+1});
that.uploadImg();
// },
// });
}else{
that.setData({i:0})
}
},
delImg: function (e) { // 删除照片
var index = e.target.dataset.index;
var _imgUrls = this.data.imgUrls;
_imgUrls.splice(index, 1);
_imgUrls.length == 0 && this.set_data(this,_imgUrls,"拍照/相册",true);
(_imgUrls.length > 0 && _imgUrls.length < this.data.maxAddImgNum) && this.set_data(this,_imgUrls,"+",true);
},
set_data: function(that,imgUrls,addImgText,canAddImg) {
that.setData({
imgUrls: imgUrls,
addImgText: addImgText,
canAddImg: canAddImg
});
}
});