迁移支付宝小程序踩坑记录
本文记录使用 uniapp 框架,将原微信小程序项目迁移至支付宝小程序过程中的踩坑过程。项目技术栈: vite2+vue3+uniapp+vuex。
# 框架应用
# 1.使用 qqmapsdk
开始以为阿里小程序不支持腾讯系的 mapsdk,后来看了下,其实也就是一个网络请求而已。业务场景是,将获取到的经纬度通过 qqmapsdk 来获取附近的地点,交互很简单,只是请 求了一个接口。因此,该 qqmapsdk 是可以接入的,只是需要配置下服务器域名。
https://apis.map.qq.com
# 2.请求器
由于之前使用的是 flyio 请求器,因此继续沿用。但是对于支付宝小程序,需要使用ap
模块。
// #ifdef MP-WEIXIN
import Fly from 'flyio/dist/npm/wx'
// #endif
// #ifdef MP-ALIPAY
import Fly from 'flyio/dist/npm/ap'
// #endif
// #ifdef H5
import Fly from 'flyio'
// #endif
2
3
4
5
6
7
8
9
10
同时,需要额外处理后端返回的内容。
try {
res.data = JSON.parse(res.data)
} catch (error) {
// console.log('JSON.parse-error', error)
}
2
3
4
5
# 3.请求头
业务上会经常自定义请求头,比如 token,channel,发现安卓机调试时请求头没有传给后端(iOS 正常),查阅文档才发现,请求头的 key/value 都必须是 string 类型。 见文档 (opens new window)。
req.headers['appId'] = 1 // 不生效
req.headers['appId'] = '1' // 生效
2
# 4.不支持全局组件
先前的 Vue 全局组件是在 main.js 中进行注册,其他地方可以不需要引入直接使用,但是这种方式在支付宝小程序行不通。所有组件必须先引入后使用。
# 5.自定义头部
支付宝支持自定义头部,但是不能隐藏返回键。在pages.json
中设置即可自定义头部。
"globalStyle": {
"transparentTitle": "always",
}
2
3
如果页面需要原生头部,在 pages 中如下设置:
{
"style": {
"transparentTitle": "none",
"navigationBarTitleText": "登录"
}
}
2
3
4
5
6
# 组件
# 1.image 标签要么设置要么不设置 mode(不设置默认 scaleToFill),不能设置为mode=""
,否则图片显示有问题。
# 2.label 和 span 都会转为 label 元素,且原来监听的 click 事件不会生效。将其改为 text 即可。
# 3.picker 组件显示的内容必须有标签包裹。
先前的代码(微信没问题):
<picker range-key="reason_info" :range="reasonList" @change="changeReason">
{{ reason.reason_info ? reason.reason_info : '请选择退款原因' }}
</picker>
2
3
改后的代码(兼容支付宝):
<picker range-key="reason_info" :range="reasonList" @change="changeReason">
<div>{{ reason.reason_info ? reason.reason_info : '请选择退款原因' }}</div>
</picker>
2
3
# 4.rich-text 组件 nodes 属性不支持 html string 方式,仅支持直接使用节点列表。
如果原来 是 HTML string,则需自己将 HTML String 转化为 nodes 数组,可使用 html-parser (opens new window)转换。见文档 (opens new window)。
# 5.swiper 组件。
和其他组件联动时,更改的 swiperIndex 不会触发 swiperChange。此外,支付宝小程序默认所有 swiper-item 都取第一个 swiper-item 的高度,如果需要单独设置,需要修改属
性adjust-height="none"
。
例如:
<swiper class="swiper-wrap" adjust-height="none" :current="swiperIndex" :style="{ height: (swiperHeights[swiperIndex] || 1) + 'rpx' }" @change="swiperChange">
</swiper>
2
如果在其他地方更新了 swiperIndex,将不会触发 swiperChange,需要手动去调用 swiperChange()中执行的代码。
6.input 组件。
iOS 光标移动问题:购物车页面,由于商品较多,产生滚动。此时如果聚焦到底部某个 input,会发生光标错位,仅在 iOS 出现。
解决方式:设置always-system
属性,使用系统键盘即可。
# API
# 1.支付宝小程序不支持 selectorQuery.in(this)
# 2.对比微信支付和支付宝支付
微信支付接口如下:
const xx = {} // 后端返回
uni.requestPayment({
provider: 'wxpay',
timeStamp: xx.timeStamp + '',
nonceStr: xx.nonceStr,
package: xx.package,
signType: xx.signType,
paySign: xx.sign,
orderInfo: xx.orderInfo || '', // 非必传
success: () => {},
fail: () => {},
complete: () => {},
})
2
3
4
5
6
7
8
9
10
11
12
13
支付宝支付接口如下:
const xx = {} // 后端返回
uni.requestPayment({
provider: 'alipay',
orderInfo: xx.aliTradeNo,
success: () => {},
fail: () => {},
complete: () => {},
})
2
3
4
5
6
7
8
# 3.uni.uploadFile 需要多传参数 fileType
微信小程序调用方式:
uni.uploadFile({
url: 'https://www.example.com/upload',
name: 'image',
filePath: path,
formData: {
aa: 'bb',
},
header: {
Authorization: '',
},
success: (res) => {},
})
2
3
4
5
6
7
8
9
10
11
12
支付宝小程序调用方式:
uni.uploadFile({
url: 'https://www.example.com/upload',
name: 'image',
filePath: path,
fileType: 'image', // 仅支付宝小程序,且必填。
formData: {
aa: 'bb',
},
header: {
Authorization: '',
},
success: (res) => {},
})
2
3
4
5
6
7
8
9
10
11
12
13
# 4.关于用户授权
uni.openSetting()
在微信和支付宝都可以跳转到用户授权设置页- 以
uni.chooseImage()
为例,调用该 API 时,会拉起弹窗,提示【申请访问你的相册,使用你的摄像头】。- 如果直接点击拒绝,则会进入 fail 回调,且 err.message 为
用户不允许授权
。(微信小程序拒绝后就不会拉起弹窗了) - 如果先勾选不再询问,再点击拒绝,则 err.message 为
用户勾选了不允许授权选项
。 - 此时再调用 api,会直接进入 fail,不会拉起弹窗了。这时候为了优化用户体验,可以引导至授权设置页。操作方案为:调用
uni.getSetting()
判断用户是否授权,如果未授 权,则弹窗提示用户是否去授权,调用uni.openSetting()
进入授权设置页。
- 如果直接点击拒绝,则会进入 fail 回调,且 err.message 为
uni.getSetting()
返回的结果,微信和支付宝不一致。以 location 为例。
let authLocation
//#ifdef MP-WEIXIN
authLocation = 'scope.userLocation'
//#endif
//#ifdef MP-ALIPAY
authLocation = 'location'
//#endif
uni.getSetting({
success({ authSetting }) {
console.log('getSetting-ok', authSetting)
if (!authSetting[authLocation]) {
console.log('没有授权过 || 拒绝过 地理位置权限')
// 没有授权过 || 拒绝过
uni.showModal({
title: '“xx”想使用您的位置信息',
content:
'我们将通过调用位置权限的方式获取您的精准定位信息,用于提供地理位置服务功能,包括推荐附近的xxx。您可以随时通过xx小程序的设置功能,选择是否允许我们获取,以及在何种情况下获取您的地理位置信息。如果您拒绝提供地理位置信息,您将无法使用上述功能,但不影响您使用xx小程序的其他功能。',
confirmText: '去设置',
// confirmColor: '#FFB414', // 支付宝不支持设置confirmColor
success(res) {
if (res.confirm) {
// 授权并获取用户信息
getLocationInfo()
} else {
console.log('点击了取消')
}
},
})
} else {
getLocationInfo()
}
},
fail: (err) => {
console.log('getSetting-fail', err)
},
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 5.uni.createCanvasContext 唯一标识符,使用 id
其他平台是 canvas-id,见文档 (opens new window)
<canvas canvas-id="barcode" id="barcode" />
function barc(id, code, width, height) {
let canvas = uni.createCanvasContext(id)
barcode.code128(canvas, code, convert_length(width), convert_length(height))
}
barc('barcode', 'code1234', 600, 200)
2
3
4
5
# 6.uni.getSystemInfo(),安卓获取的 screenHeight 不准确,建议使用 screen.height 或者根据实际情况使用 windowHeight。
# 支付宝开发工具注意事项
- 模拟器默认在右侧,可以在【设置】-【模拟器布局】-【左侧】进行修改。
- 导入项目后,必须选择对应的应用,不像微信小程序,需要填写 appid。
- 支付宝的体验版线上只有一个,但需要手动切换,且体验版最多只能上传 20 个,超出需要手动一个个删除。
- 以下是开发者工具调用无效,而真机是正常的
- 复制到粘贴板接口:
uni.setClipboardData
。