uni-app开发中的坑
1.无法覆盖uni-app提供的组件的样式
直接重写样式会发现并不生效
编译到H5如果要重置组件样式使用
>>> .className{
width:xxx
}
scss的话 要使用
/deep/ .uni-radio-input {
width: 32upx;
height: 32upx;
background: #fff !important;
border: 2upx solid #CCCCCC !important;
}
2.ios真机下键盘遮挡住弹框底部部分内容
rt
解决方案
在pages.json中配置
{
"path": "pages/normative-interpretation/normative-interpretation-info/normative-interpretation-info",
"style": {
"app-plus":{
"softinputMode": "adjustResize"
}
}
},
3.uni-app文件上传&多文件上传
官网文档指路:https://uniapp.dcloud.io/api/request/network-file
选择文件:
uni.chooseImage({
count: 3,
async success(e) {
const res = await handleFileButhUpload(e.tempFilePaths)
if (res) {
const imgUrls = res.data
that.imgUrls = imgUrls
}
},
fail(err) {
uni.showToast({
icon: 'none',
title: '图片选择失败,请稍后重试'
})
}
})
单文件(可附带传其他参数)
export const handleUserAvatarUpload = (id, filePath) => {
return new Promise((resolve, reject) => {
uni.uploadFile({
url: BASE_URL + '/community/xfFile/uploadHeadimage',
filePath: filePath, // uni.chooseImage函数调用后获取的本地文件路劲
name: 'file',
formData: {
id
},
success: (res) => {
resolve(res)
},
fail: (err) => {
reject(err)
}
});
})
}
多文件:
我这边后台接口是要我传files的文件对象,这东西折腾我大半天,在传参的时候碰到过传的file为{},后来我这边对选中的文件做了处理。
// 处理选中的文件
export const getFilecalculate = (data) => {
const newData = [];
data.forEach((item, index) => {
newData.push({
name: 'files',
uri: item
})
})
return newData
}
调用官方api
export const handleFileButhUpload = (filePaths) => {
const files = getFilecalculate(filePaths)
return new Promise((resolve, reject) => {
uni.uploadFile({
url: BASE_URL + '/community/xfFile/uploadImage',
files,
success: (res) => {
const newRes = JSON.parse(res.data)
resolve(newRes)
},
fail: (err) => {
reject(err)
}
});
})
}
4.微信分享
首先需要前往微信开放平台申请应用的appid
其次需要按照这个申请ios通用链接,这也是苹果iOS 13系统版本安全升级,微信SDK1.8.6版本要求支持Universal Links方式跳转,以便进行合法性校验,提升安全性。
前期准备工作都做完之后就可以开发了,官方也提供了分享的api.
传参直接按照文档来就行了
贴一下我的代码
export const handleWeixinShare = (title, imageUrl, href, summary) => {
return new Promise((resolve, reject) => {
uni.share({
provider: 'weixin',
scene: 'WXSceneSession',
type: 0,
title,
imageUrl,
href,
summary,
async success(res) {
resolve(res)
},
fail(err) {
reject(err)
}
})
})
}
到这里已经能够正常分享了,but,你试过点击链接能够调起app吗?
1.href怎么填
我们这里填的链接应该是项目里面页面的路径,大概是/pages/xxx/xxx
2.微信是有限制的,无法打开第三方应用
3.打开应用后,怎么处理页面跳转
带着这些问题,我们逐个解决
最重要的是,在微信里面点击链接怎么能够调起app!
由于微信的限制,所以我们无法直接去调起app,但是我们能够引导用户,让用户去手动调起啊,具体实现方法就是:我们新建一个h5页面,h5页面内容自定义,最主要的是能够起到引导用户去点击微信浏览器右上角按钮,在弹出框里面点击用手机自带浏览器打开,如果这一步实现了我们就能够调起app了,在浏览器打开我们需要添加一个触发a标签点击事件,href链接的协议需要配置,我们后面说
这个是我的中间页面,部署到服务器之后能够访问后,我们只要把打开app后跳转链接带上就行了,所以这里href大概就知道了
xxx.com?url=/pages/xxx/xxx
下一步,我们解决app内实现点击链接后页面跳转,这里还有一个问题,就是我们需要配置UrlSchemes,这个的作用就相当于我们应用的标识,
h5页面跳转链接
$(function () {
function getQueryString(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
var r = window.location.search.substr(1).match(reg);
if (r != null) {
return unescape(r[2]);
}
return null;
}
// {type:类型 0-规范 1-解读,url:地址}
const type = getQueryString('type') || 0
const url = getQueryString('url')
console.log('type',type)
// 根据type获取图片地址
const src = Number(type) === 0 ? './static/guifan_share.png' : './static/jiedu_share.png'
const imgEle = document.getElementsByTagName('img')[0]
imgEle.src = src;
let ele = document.createElement('a')
ele.href = "firecollegue://" + url
ele.click()
})
app内部处理分享链接
/**
* 处理分享链接进入时页面跳转
*/
handleShareNavigate() {
setTimeout(function() {
var args = plus.runtime.arguments;
if (args) {
const urls = args.split('firecollegue://')
uni.navigateTo({
url: urls[1]
})
}
}, 10);
},
这样,我们的分享就做完了,主要还是链接调起app这里有坑
5.微信支付&支付宝支付
这个没啥好说的,按照官方文档要求申请应用,重点是后端,按照微信和支付宝这块的文档进行集成,前端调用接口拿到订单信息即可。
// 支付宝支付
export const handleAliPay = (orderInfo) => {
return new Promise((resolve, reject) => {
uni.requestPayment({
provider: 'alipay',
orderInfo, //支付宝订单数据
success: function(res) {
resolve(res)
},
fail: function(err) {
reject(err)
}
});
})
}
// 微信支付
export const handleWeixinPay = (orderInfo) => {
const {
appid,
noncestr,
partnerid,
prepayid,
sign,
timestamp
} = orderInfo
const newPackage = orderInfo.package
return new Promise((resolve, reject) => {
uni.requestPayment({
provider: "wxpay",
timeStamp: timestamp,
nonceStr: noncestr,
package: newPackage,
signType: "MD5",
paySign: sign,
orderInfo: JSON.stringify(orderInfo),
success: function(res) {
resolve(res)
},
fail: function(err) {
reject(err)
}
});
})
}
6.图片下载保存到本地
需求大概是下载一个类似于小说结构的文档,其实下载没啥,主要是文档是可能会有图片,再无网络情况下我们无法访问网络地址的图片,所以只能下载到本地才能进行浏览。
思路:遍历数组拿到所有网络图片地址链接,遍历图片地址调用官方api下载图片,这里下载完也只是一个临时地址,我们还需要调用保存文件接口保存到本地,才能拿到本地真实地址,再无网络下页面渲染时替换网络地址即可。
图片下载保存:
/**
* 获取富文本内容中的图片地址 存入数组返回
*/
export const getImgList = (html) => {
var list = [];
if (!html || Object.keys(html).length === 0) {
return list
}
html.replace(/<img [^="">]*src=['"]([^'"]+)[^>]*>/g, (match, capture) => {
list.push(capture);
});
return list;
}
/**
* 图片下载保存
*/
export const getImageDownload = (url) => {
return new Promise((resolve, reject) => {
uni.downloadFile({
url,
success: (res) => {
if (res.statusCode === 200) {
uni.saveFile({
tempFilePath: res.tempFilePath,
success: function(saveRes) {
var savedFilePath = saveRes.savedFilePath;
resolve({
[url]: savedFilePath
})
},
fail(e) {
console.log('e', e)
}
});
}
},
fail: (err) => {
console.log('err', err)
}
});
})
}
/**
* 处理图片
*/
export const handlexfNormsChaptersDtoList = async (xfNormsChaptersDtoList, userInfo) => {
let normImageList = {}
let newxfNormsChaptersDtoList = [];
xfNormsChaptersDtoList.forEach(item => {
newxfNormsChaptersDtoList = [...newxfNormsChaptersDtoList, ...item.xfNormsClauseList]
})
newxfNormsChaptersDtoList = newxfNormsChaptersDtoList.filter(item => {
return JSON.stringify(item).indexOf('img') !== -1
})
let promiseAll = [];
let imgList = []
newxfNormsChaptersDtoList.forEach(item => {
imgList = [...imgList, ...getImgList(item.clauseContent), ...getImgList(item.clauseImage), ...getImgList(item.clauseInterpretation)]
})
promiseAll = imgList.map(childItem => {
return getImageDownload(childItem)
})
const resAll = await Promise.all(promiseAll)
resAll.forEach(item => {
normImageList = Object.assign(normImageList, item)
})
console.log(normImageList)
const xf_download_imageList = uni.getStorageSync('xf_download_imageList') || {}
normImageList = Object.assign(normImageList, xf_download_imageList)
uni.setStorageSync('xf_download_imageList', normImageList)
console.log(uni.getStorageSync('xf_download_imageList'))
}
我们将下载完之后的图片地址与网络地址组成的键值对存到缓存,
渲染时
if (returnContent.indexOf('img') !== -1) {
for (let key in this.imageList) {
returnContent = returnContent.replace(new RegExp(key, 'g'), this.imageList[key]);
}
}
7.苹果应用内支付
- 背景-
Appstore审核报PGPay SDK不允许上架的问题
A:数字类产品(比如购买会员等不需要配送实物的商品),Apple规定必须使用苹果IAP应用内支付,给Apple分成30%。打包的时候不要勾选微信或支付宝等其他支付方式。如果你提交的包里包含了微信支付宝等支付的sdk,即使没使用,Appstore也会认为你有隐藏方式,以后会绕过iap,不给Apple分成,因此拒绝你的App上线。云打包时,manifest里选上支付模块,但sdk配置里去掉微信支付和支付宝支付。很多开发者的Android版是包含微信和支付宝支付的,此时注意分开判断。 - 解决办法
首先我们需要到苹果开发者中心中创建苹果内购项目
创建的内购项目有四种类型:
消耗型项目
用户可以购买各种消耗型项目 (例如游戏中的生命或宝石) 从而进一步探索 app 。消耗型项目只可使用一次,使用之后即失效,可再次购买。
非消耗型项目
用户可购买非消耗型项目,解锁更多 app 内的进阶功能。非消耗型项目只需购买一次,不会过期 (例如修图 app 中的其他滤镜)。Apple 可以托管您的非消耗型产品。
自动续期订阅
用户可购买周期性持续的服务或更新的内容 (例如云存储或每周更新的杂志)。此类订阅会自动续期,除非用户选择取消。
非续期订阅
用户可购买有时限性的服务或内容 (例如线上播放内容的季度订阅)。此类的订阅不会自动续期,用户需要逐次续订。
注意:内购项目的productid是唯一的 不可重复。
- 代码实现:
首先需要在manifest.json中选择苹果支付,同时打苹果包的时候需要把微信支付和支付宝支付给勾选掉。
然后在支付页面实现支付,大致流程是:首先调用plus.payment.getChannels获取支付通道,IAP支付通道的ID为“appleiap”
调用ID为“appleiap”的PaymentChannel对象的requestOrder方法,像Appstore请求有效的商品详情。注意:需先调用requestOrder方法然后在调用payment.request方法,否则直接调用payment.request将会报错。
调用plus.payment.request方法发起支付请求,传入statement的参数为JSON对象,可以设置如下参数
productid String(必选)要支付的商品的标识(必须是调用requestOrder返回的有效的商品标识)
username String(可选)购买商品用户的用户名
quantity String (可选)购买商品的数量,如果不填写默认为1
调用后端接口校验订单信息
获取支付通道:
plus.payment.getChannels(
function(channels) {
console.log("channels-------------", channels);
for (var i in channels) {
if (channels[i].id == "appleiap") {
console.log("channels[i]-----------", channels[i]);
that.iapChannel = channels[i];
that.iapChannel.requestOrder(
IAPOrders,
function(event) {
console.log(event, event.length);
uni.hideLoading();
for (var j in event) {
console.log(event)
// that.vipList.push(
// Object.assign(event[j], {
// id: event[j].productid,
// goodsName: event[j].title,
// })
// );
// that.goodInfo = that.vipList[0];
// console.log(that.vipList);
}
},
function(errormsg) {
console.log(
"获取支付通道失败:" +
JSON.stringify(errormsg) +
"-" +
errormsg.message
);
uni.showToast({
title: '获取会员信息失败,请稍后重试'
})
uni.navigateBack()
uni.hideLoading();
}
);
}
}
},
function(e) {
console.log("获取支付通道失败:" + e.message);
}
);
获取订单信息:
uni.requestPayment({
provider: "appleiap",
orderInfo: {
productid: productid + '',
},
success: (result) => {
console.log("success--------------------", result);
this.getIapPayChecked(result);
},
fail: (e) => {
console.log('e-------------------------', e)
uni.showToast({
title: '支付失败'
})
that.loading = false;
},
complete: () => {
console.log("payment结束");
that.loading = false;
},
});
订单信息获取成功后调用服务端接口检验订单信息:
const {
payment,
transactionDate,
transactionIdentifier,
transactionReceipt,
} = result;
console.log(
payment,
transactionDate,
transactionIdentifier,
transactionReceipt
);
try {
const res = await getIapPayCheck({
productid: payment.productid,
transactionDate,
transactionIdentifier,
transactionReceipt,
});
console.log("res-----------", res);
if (res) {
/**
* {
* "code": 0000,
* "message": 验证通过,
* }
*/
uni.showToast({
icon: "success",
title: "支付成功",
});
this.loading = false;
// 返回上一级
uni.navigateBack();
} else {
uni.showToast({
title: '支付失败【' + res.message + '】'
})
this.loading = false;
}
} catch (error) {
console.log("error---------------------", error);
uni.showToast({
title: '支付失败【' + error + '】'
})
this.loading = false;
}
以上就是苹果应用内支付的完整流程了,支付过程中可能会出现无响应,可以试试重新打包重新安装。
而且需要注意传参的数据类型错误也会导致支付无响应。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。