2

uni-app官网指路

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
微信图片_20200528115237.jpg

解决方案

在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.微信分享

image.png
首先需要前往微信开放平台申请应用的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链接的协议需要配置,我们后面说
微信图片_20200801152915.jpg
这个是我的中间页面,部署到服务器之后能够访问后,我们只要把打开app后跳转链接带上就行了,所以这里href大概就知道了
xxx.com?url=/pages/xxx/xxx

下一步,我们解决app内实现点击链接后页面跳转,这里还有一个问题,就是我们需要配置UrlSchemes,这个的作用就相当于我们应用的标识,
image.png
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版是包含微信和支付宝支付的,此时注意分开判断。
  • 解决办法
    首先我们需要到苹果开发者中心中创建苹果内购项目
    image.png
    创建的内购项目有四种类型:
    消耗型项目
    用户可以购买各种消耗型项目 (例如游戏中的生命或宝石) 从而进一步探索 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;
                }

以上就是苹果应用内支付的完整流程了,支付过程中可能会出现无响应,可以试试重新打包重新安装。
而且需要注意传参的数据类型错误也会导致支付无响应。


wzp123321
17 声望3 粉丝