梦见你的名字 发表于 昨天 06:09

利用UniApp实现多平台付出集成:小程序、Apple IAP、App端微信与付出宝付出

uniapp各平台付出功能

目录

https://i-blog.csdnimg.cn/direct/3c79c20ea4cc47a8ab5ce4e6c9075e20.png
APP端付出参考资料

   

[*]方式一(保举):https://uniapp.dcloud.net.cn/api/plugins/payment.html
[*]方式二(唤醒不了微信付出):https://ask.dcloud.net.cn/article/71
申请开通各平台APP付出

在利用付出前,需要向各付出平台申请开通付出功能【要有营业执照才可以开通】。
Apple应用内付出(IAP)

因为苹果应用内置流程与其他三方付出平台存在差异,需要单独参考ios平台利用Apple应用内付出文档。
留意事项:
   

[*]要成为Apple 开辟者人员,需要向Apple付出开辟人员年费。【 https://developer.apple.com】,【https://developer.apple.com/cn】
[*]iOS平台苹果审核规范要求,应用中虚拟物品交易必需利用Apple应用内付出,实物交易才能利用第三方付出(付出宝和微信付出)
HBuilder 里的调试基座默认不带IAP付出通道,假如需要调试IAP需要利用开辟证书生成一个自定义调试基座,用来实现IAP的开辟和调试。 自定义调试基座利用方法请参考文档。
付出宝付出

登录付出宝账号,创建应用接入付出宝APP付出如下步调【前提需要营业执照】付出宝官方文档App付出快速接入。


[*] 步调一、 创建应用,登录付出宝开放平台,创建应用并提交审核,审核通事后会生成应用唯一标识,APPID,并且可以申请开通开放产物利用权限,通过AppID应用才能调用开放产物的接口能力。
https://i-blog.csdnimg.cn/direct/0889e63b85154a71a4b2912c17fb3541.png
https://i-blog.csdnimg.cn/direct/6a088d15784344218fbb999d818c7360.png
https://i-blog.csdnimg.cn/direct/7183ecda1a7940658e02e4e082bccb4d.png
点击上面设置后,在加签管理,选择公钥证书,然后下载工具生csr文件
https://i-blog.csdnimg.cn/direct/a5ca2b964ed148fc8adf1dc15852d86f.png
https://i-blog.csdnimg.cn/direct/9b20975cc78e4aebafb7ec5c449c8752.png
https://i-blog.csdnimg.cn/direct/4d77dc67f20749d9b15fdb83a6d31342.png
https://i-blog.csdnimg.cn/direct/2982271810294df7ab661b0b5be39c33.png
https://i-blog.csdnimg.cn/direct/36a8474bd86e494784bc1ac16a0f9137.png
https://i-blog.csdnimg.cn/direct/aad34b8a2ae249a395867a29eabe5757.png
https://i-blog.csdnimg.cn/direct/3bee45c5fb304662b339342b3a30c9fb.png
https://i-blog.csdnimg.cn/direct/f9d1d30dcdab408fa1601fdb69e1d813.png
[*] 步调二、开通App付出功能,应用创建完成后,体系会主动跳转到应用详情页面。开辟者可以点击 添加能力 来添加 App 付出能力。添加功能后开辟者需要在商家中心中进行 签约,第三方应用开辟者可以 代商户签约。
https://i-blog.csdnimg.cn/direct/eba97dc60165415ca7d9dc6853ae63ec.png
得到沙箱测试账号
https://i-blog.csdnimg.cn/direct/f92cd4d9bbde4c7f84f2526f40b3d556.png
步调三、 设置密钥(获取公钥、私钥)
为了包管交易双方(商户和付出宝)的身份和数据安全,商户在调用接口前,需要设置双方密钥,对交易数据进行双方校验。密钥包含应用私钥APP_PRIVATE_KEY和应用公钥 APP_PUBLIC_KEY。生成密钥后,商户需要在开放平台控制台进行密钥配,设置完成后可以获取付出宝公钥 ALIPAY_PUBLIC_KEY,设置的详细步调请参考 设置应用环境。您还可以通过 生成密钥并上传 学习密钥的设置。密钥的设置旨在对交易数据进行双方校验。
微信付出【参考】

步调一、创建应用

[*]利用微信付出功能需到微信开放平台 申请移动应用并开通付出功能 微信APP
付出接入商户服务中心 申请应用后可以获取AppID和AppSecret值。
https://i-blog.csdnimg.cn/direct/3a6df55b579340d7b60c7aae30743d7d.png
步调二、开通
开通付出功能后可获取付出业务服务器设置数据(要先交300元开辟者认证费用,个人不可)。
PARTNER:财付通商户号
PARTNER_KEY:财付通密钥
PAYSIGNKEY:付出签名密钥
https://i-blog.csdnimg.cn/direct/d91076c0ac09415abdbbf563b0bd3efc.png
服务端生成付出订单接口

在App端调用付出功能时,需要先在调用服务器上生成预付出订单接口,再将预付出订单信息传递给付出接口。
付出宝业务流程图【官方参考】

客户端请求背景服务端获取签名后的订单信息,客户端带上订单信息(字符串)请求付出接口。
https://i-blog.csdnimg.cn/direct/ac0d43032d654eca971539008750c433.png
微信付出业务流程图【官方参考】

客户端请求背景服务端获代替签名的付出订单信息,然后客户端带上订单信息(Object范例)请求付出接口,此中订单信息请求请参考官网文档【APP调起付出API】
https://i-blog.csdnimg.cn/direct/48ef9f32d98c40b798b43c29992229e5.png
HBuilderX中设置利用付出功能

从微信开放平台申请获取设置参数后(Apple应用内付出和付出宝无需设置),需要再HBuilderX中设置并提交云端打包才能生效。
https://i-blog.csdnimg.cn/direct/779100c3ece34b24ad3c302694447dcb.png
勾选后会表现支持的付出模块,可根据应用需要进行选择设置
Apple应用内付出【仅支持IOS平台】

https://i-blog.csdnimg.cn/direct/09f645c1597047189dd40efb79454336.png
付出宝付出【支持Android及iOS平台】

https://i-blog.csdnimg.cn/direct/302f2ff3108b44a8834c3210b4b9f942.png
微信付出【参考】

获取appid填入,去微信开放平台申请应用的AppId值,UniversalLinks:iOS平台通用链接,必须与微信开放平台设置的同等,参考iOS平台微信SDK设置通用链接(UniversalLinks)
https://i-blog.csdnimg.cn/direct/26906cd90c2549afa6482a0c35106195.png
功能实现

https://i-blog.csdnimg.cn/direct/d472ee3aca5449f2ad6f1ab52d7daf21.png
APP端付出宝/微信付出实现

发送请求到背景服务端,背景服务端生成订单信息,相应预付出订单信息,通过预付出订单信息请求付出接口。
import api from '@/api/order.js'
export default {
        methods: {
                // 获取订单信息 (微信小程序支付需要openid)
                getOrderInfo(openid) {
                        // 不要少了async
                        return new Promise( async (resolve, reject) => {
                                let res = null
                                let data = {} // 服务接口请求参数
                                if(this.provider === 'alipay') {
                                        res = await api.getOrderInfoAlipay(data)
                                }else if(this.provider === 'wxpay') {
                                        res = await api.getOrderInfoWxpay(data)
                                }
                                if (res && res.code === 20000) {
                                        resolve(res.data)
                                } else {
                                        reject(new Error('获取支付信息失败' + res.message))
                                }
                        })
                },
        // 微信、支付宝等支付
        async payHandler() {
                // 支付中
                this.loading = true
                // #ifdef APP-PLUS
                // 1. 发送请求到服务端,服务端生成订单信息,响应预支付订单
                let orderInfo = await this.getOrderInfo();
                if (!orderInfo) {
                        uni.showModal({
                                content: '获取支付信息失败',
                                showCancel: false
                        })
                        return
                }
                // 2. 请求支付
                uni.requestPayment({
                        provider: this.provider, // 支付渠道
                        orderInfo: orderInfo,
                        success: (e) => {
                                console.log("success", e);
                                uni.showToast({
                                        title: "支付成功!"
                                })
                        },
                        fail: (e) => {
                                console.log("fail", e);
                                uni.showModal({
                                        content: "支付失败!",
                                        showCancel: false
                                })
                        },
                        complete: () => {
                                this.loading = false;
                        }
                })
                // #endif
        },
}
https://i-blog.csdnimg.cn/direct/c1129d700573422c8d2a4cdf4490bb59.gif
微信小程序付出功能实现

微信小程序运行在微信内里,需要付出的话,起首要知道是谁的微信内里,就需要将当前微信进行登录获取获取code,再根据code获取openid的值。
步调一、先登录微信小程序获取用户code,再请求服务端获取openid,微信小程序登录参考:
https://i-blog.csdnimg.cn/direct/c2f00f07434242358ccba5e3cf0e94df.png
// 登录微信小程序
loginWeixinMp() {
                return new Promise((resolve, reject) => {
                        // 1. 先使用微信登录小程序响应 code,
                        uni.login({
                                provider: 'weixin',
                                success: (res) => {
                                        console.log('登录', res)
                                        const code = res.code
                                        // 2. 请求服务端通过code获取openid
                                        let openid = 'xx'
                                        uni.setStorageSync('openid', openid)
                                        resolve(openid)
                                },
                                fail(err) {
                                        reject(err)
                                }
                        })
                })
},
步调二、通过openid再获取订单预付出信息,直接在getOrderInfo写死一个模拟预付出信息即可。

getOrderInfo(openid) {
        return new Promise(async (resolve, reject) => {
                if (openid) {
                        // 微信小程序获取订单信息,发送请求
                        // let orderInfo = await api.getOrderInfoWxpayMP(openid) 如果有真实接口替换即可
                        let orderInfo = {
                                "timeStamp": "1414561699",
                                "nonceStr": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS",
                                "package": "prepay_id=wx201410272009395522657a690389285100", //预支付交易会话标识( prepay_id)
                                "signType": "RSA",
                                "paySign": "oR9d8PuhnIc+YZ8cBHFCwfgpaK9gd7vaRvkYD7rthRAZ",
                        }
                        resolve(orderInfo)
                        return
                }
                let res = null
                let data = {} // 服务接口请求参数
                if (this.provider === 'alipay') {
                        res = await api.getOrderInfoAlipay(data)
                } else if (this.provider === 'wxpay') {
                        res = await api.getOrderInfoWxpay(data)
                }
                if (res && res.code === 20000) {
                        resolve(res.data)
                } else {
                        reject(new Error('获取支付信息失败' + res.message))
                }
        })
},
步调三、通过订单预付出信息,去调用付出接口
// 微信小程序支付
async wxPayHandler() {
        this.loading = true
        // 1. 先获取用户code, 再获取openid
        let openid = uni.getStorageSync('openid')
        if (!openid) {
                try {
                        openid = await this.loginWeixinMp()
                } catch (e) {
                        console.error(e)
                }
                if (!openid) {
                        uni.showModal({
                                content: '获取openid失败',
                                showCancel: false
                        })
                        this.loading = false
                        return
                }
        }
        // 2. 通过 openid 再获取订单信息,
        let orderInfo = await this.getOrderInfo(openid)
        // 3. 通过订单预支付信息,去调用支付接口
        uni.requestPayment({
                ...orderInfo,
                success: (res) => {
                        uni.showToast({
                                title: "支付成功!"
                        })
                },
                fail: (res) => {
                        uni.showModal({
                                content: "支付失败,原因为: " + res.errMsg,
                                showCancel: false
                        })
                },
                complete: () => {
                        this.loading = false;
                }
        })
}
因为用的是模拟的假数据,会报权限不足问题,假如真实开辟中调用后端请求服务拿到商品信息,先登录微信小程序获取用户code,再请求服务端获取openid,通过openid再获取订单预付出信息,直接在getOrderInfo写死一个模拟预付出信息即可,通过订单预付出信息,去调用付出接口即可。
https://i-blog.csdnimg.cn/direct/d6e8f4144586419ea96d2279ed189262.gif
Apple应用内付出

苹果应用内置流程与别的三方付出平台存在差异,请单独参考iOS 平台利用Apple应用内付出文档,项目中参考付出文档最下面示例代码
流程:
https://i-blog.csdnimg.cn/direct/9f16f07c482646b08e508096aea5d2c3.png
在onLoad中先获取Apple付出渠道的实例。
onLoad: function(option) {
        // 获取支付金额
        if (option.params) {
                const params = JSON.parse(option.params)
                this.price = params.price
                this.courseIds = params.courseIds
        }
        // 查询余额
        this.loadData()
        // 获取apple支付渠道实例
        plus.payment.getChannels((channels) => {
                console.log("获取到channel" + JSON.stringify(channels))
                for (var i in channels) {
                        var channel = channels;
                        if (channel.id === 'appleiap') {
                                iapChannel = channel;
                                this.requestOrder();
                        }
                }
                if (!iapChannel) {
                        this.errorMsg()
                }
        }, (error) => {
                this.errorMsg()
        });
},
requestOrder环境检测方法

                        requestOrder() {
                                uni.showLoading({
                                        title: '检测支付环境...'
                                })
                                //必须调用此方法向Appstore请求有效的商品详情,才能进行 iap 支付,
                                iapChannel.requestOrder(this.moneyList, (orderList) => {
                                        this.disabled = false;
                                        console.log('requestOrder success666: ' + JSON.stringify(orderList));
                                        uni.hideLoading();
                                }, (e) => {
                                        console.log('requestOrder failed: ' + JSON.stringify(e));
                                        uni.hideLoading();
                                        this.errorMsg()
                                });
                        },
弹窗提示判断,假如环境不支持apple付出则弹窗提示
errorMsg() {
        uni.showModal({
                content: "暂不支持苹果 iap 支付",
                showCancel: false
        })
},
假如当前环境可以付出,则利用uni.requestPayment进行apple支
// Apple应用内支付
iosPayHandler() {
        this.loading = true;
        uni.requestPayment({
                provider: 'appleiap',
                orderInfo: {
                        productid: this.applePrice // 商品金额
                },
                success: (e) => {
                        console.log("success", e);
                        uni.showToast({
                                title: "支付成功!"
                        })
                        // 再进行app内部扣款
                },
                fail: (e) => {
                        console.log("fail", e);
                        uni.showModal({
                                content: "支付失败,原因为: " + e.errMsg,
                                showCancel: false
                        })
                },
                complete: () => {
                        this.loading = false;
                }
        })
},
总体代码:
<template>        <view>                <view class="money column center">                        <text>余额:</text>                        <text>{{parseFloat(balance).toFixed(2)}}币</text>                </view>                <view class="recharge">                        <view>充值</view>                        <view class="list">                                <view v-for="(item, index) in 6" :key="index" :class="{active: activeIndex===index}"                                        @click="clickItem(index, item)">                                        <view>{{index+1}}00币</view>                                        <view>¥{{index+1}}00</view>                                </view>                        </view>                </view>                <view class="desc">                        <view>充值说明:</view>                        <view>                                1.在IOS设备的APP要进行充值后,利用虚拟币消耗。<br>                                2.充值后不能在非IOS设备利用,与安卓版和网站余额不通用。<br>                                3.充值后没有利用期限,但不可提现、退换、转让和申请发票。<br>                                4.如遇无法充值、充值失败等问题,可关注[梦学谷]公众号,接洽我们解决。<br>                        </view>                </view>                <view class="bottom center">                        <button class="btn" :loading="loading" :disabled="disabled" @click="iosPayHandler">立即充值</button>                </view>        </view></template><script>        import api from '@/api/order.js'        let iapChannel = null // 苹果内部付出渠道        export default {                data() {                        return {                                activeIndex: 0,                                loading: false, // 是否充值中                                disabled: true, //要先查抄付出环境是否iap,不付出则点击立即付出无效                                balance: 0, // 余额                                moneyList: [], // 充值列表展示金额                                price: 0, // 付出金额                                courseIds: [], // 付出的课程ids                                applePrice: 30, // ios充值金额                        }                },                onLoad: function(option) {                        // 获取付出金额                        if (option.params) {                                const params = JSON.parse(option.params)                                this.price = params.price                                this.courseIds = params.courseIds                        }                        // 查询余额                        this.loadData()                        // 获取apple付出渠道实例                        plus.payment.getChannels((channels) => {                                console.log("获取到channel" + JSON.stringify(channels))                                for (var i in channels) {                                        var channel = channels;                                        if (channel.id === 'appleiap') {                                                iapChannel = channel;                                                this.requestOrder();                                        }                                }                                if (!iapChannel) {                                        this.errorMsg()                                }                        }, (error) => {                                this.errorMsg()                        });                },                methods: {
                        requestOrder() {
                                uni.showLoading({
                                        title: '检测支付环境...'
                                })
                                //必须调用此方法向Appstore请求有效的商品详情,才能进行 iap 支付,
                                iapChannel.requestOrder(this.moneyList, (orderList) => {
                                        this.disabled = false;
                                        console.log('requestOrder success666: ' + JSON.stringify(orderList));
                                        uni.hideLoading();
                                }, (e) => {
                                        console.log('requestOrder failed: ' + JSON.stringify(e));
                                        uni.hideLoading();
                                        this.errorMsg()
                                });
                        },
                        iosPayHandler() {                                this.loading = true;                                uni.requestPayment({                                        provider: 'appleiap',                                        orderInfo: {                                                productid: this.applePrice // 商品id                                        },                                        success: (e) => {                                                console.log("success", e);                                                uni.showToast({                                                        title: "付出成功!"                                                })                                                // 调用接口,立即扣款购买商品                                        },                                        fail: (e) => {                                                console.log("fail", e);                                                uni.showModal({                                                        content: "付出失败,原因为: " + e.errMsg,                                                        showCancel: false                                                })                                        },                                        complete: () => {                                                this.loading = false;                                        }                                })                        },                        errorMsg() {                                uni.showModal({                                        content: "暂不支持苹果 iap 付出",                                        showCancel: false                                })                        },                        clickItem(index, item) {                                this.activeIndex = index                                this.applePrice = item                        },                        async loadData() {                                // 查询余额                                const {                                        data                                } = await api.getUserBalance()                                this.balance = data                                // 要进行付出,则计算还差多少金额, 则充值多少,                                if (this.price) {                                        // ios充值多少 = 余额-付款金额 < 0 : 余额不够:充足 const applePrice=this.balance - this.price // console.log('applePrice', applePrice)                                        // 取正数,向上取整 this.applePrice=Math.ceil(Math.abs(applePrice)) } // 充值列表展示金额 for(let i=0; i<6; i++) { // 6个元素,每个加30元                                        this.moneyList.push(this.applePrice + i * 30)                                }                        },                }        }</script><style lang="scss">        .money {                height: 288rpx;                background-color: $mxg-color-primary;                color: #FFFFFF;                font-size: 88rpx;                text:first-child {                        color: #e7e4e9;                        font-size: 30rpx;                }        }        .recharge {                margin: 20rpx 0 0 20rpx;                color: #999;                font-size: 30rpx;                .list {                        margin-top: 20rpx;                        text-align: center;                        >view {                                float: left;                                width: 225rpx;                                margin-right: 10rpx;                                margin-bottom: 15rpx;                                background-color: #fff;                                border-radius: 10rpx;                                padding: 20rpx 0;                                border: 1px solid $mxg-color-grey;                                flex-wrap: wrap;                                view:first-child {                                        color: $mxg-text-color-red;                                        font-size: 36rpx;                                }                        }                }        }        .active {                box-shadow: 0 0 0 .5px $mxg-text-color-red;        }        .desc {                // 扫除浮动                clear: both;                margin: 0 20rpx;                font-size: 30rpx;                line-height: 45rpx;                color: #6e6d70;                view:first-child {                        padding-top: 50rpx;                        padding-bottom: 30rpx;                        font-weight: bold;                }                view:last-child {                        padding-bottom: 120rpx;                }        }        /* 底部 */        .bottom {                position: fixed;                left: 0;                right: 0;                bottom: 0;                height: 100rpx;                background-color: #FFFFFF;                border-top: 1px solid #F1F1F1;        }        .btn {                width: 700rpx;                background-color: $mxg-color-primary;                color: #fff;                border-radius: 50rpx;                line-height: 80rpx;                font-size: 30rpx;                &::after {                        // 加载中时,隐藏边框                        border: none;                }        }</style> 效果:由于我用的是mock数据,说一检测环境就会失败判断,到了生产环境就会弹出apple应用付出弹窗。
https://i-blog.csdnimg.cn/direct/be04a5b963074148ab9ef4b79fe78e4b.jpeg
Appstore审核报PGPay SDK不答应上架的问题
A:数字类产物(好比购买会员等不需要配送实物的商品),Apple规定必须利用苹果IAP应用内付出,给Apple分成30%。打包的时间不要勾选微信或付出宝等其他付出方式。假如你提交的包里包含了微信付出宝等付出的sdk,即使没利用,Appstore也会以为你有隐藏方式,以后会绕过IAP,不给Apple分成,因此拒绝你的App上线。云打包时,manifest里选上付出模块,但sdk设置里去掉微信付出和付出宝付出。很多开辟者的Android版是包含微信和付出宝付出的,此时留意分开判断。详见
H5沙箱付出功能实现实现

设置沙箱
https://i-blog.csdnimg.cn/direct/9d281768ca874d7aa3ac217d0be70251.png
沙箱支持产物
https://i-blog.csdnimg.cn/direct/8d3d526b9da4436792b462ef510633ea.png
沙箱测试账号
https://i-blog.csdnimg.cn/direct/9f31e683f0314d4b88da6268e15392ac.png
带着商品信息请求后端接口,获取paymentUrl然后通过window.location.href = res.paymentUrl进行跳转
https://i-blog.csdnimg.cn/direct/ef703010e62a492991e3803292a83d61.png
https://i-blog.csdnimg.cn/direct/80e641e9717345858ba79818b0fa8610.png
通过location.href跳转到如下页面即可利用沙箱测试账号进行登录。下图为付出宝登录页面,可能会违规。
留意: 沙箱测试付出功能一定要开启无痕浏览进行测试。
https://i-blog.csdnimg.cn/direct/b8e897cd289d40548b4cf7c5f4157011.jpeg
利用付出宝开放平台给的沙箱测试账号进行测试:如下找到https://i-blog.csdnimg.cn/direct/057ce5b8f27440779a5b7b354a9ec546.png
输入沙箱账号暗码
https://i-blog.csdnimg.cn/direct/f3723d9b53a54a43a6e0eac51b6cbbcc.png
https://i-blog.csdnimg.cn/direct/2112d2c80cd04410a2658812af97e492.png
付出成功
https://i-blog.csdnimg.cn/direct/b9affc9ec0b14b97bf4692119bf45a70.png
交易成功后,此页面会跳转到前端传递给后端的设置的跳转页面,付出成功后就会跳回到指定页面。
https://i-blog.csdnimg.cn/direct/f38677a2858f424ba17ad8f8a1c103e5.png
设置的付出成功后的跳转页面,在此页面调用后端接口,后端返回付出状态,根据付出状态再在此页面进行其他业务逻辑处理。
https://i-blog.csdnimg.cn/direct/ce84d82847fe410d97b73ffebeeeb291.png
https://i-blog.csdnimg.cn/direct/2882e150aabb45eeb383782b633e8a87.png
H5付出第二种方法

微信付出:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_6_0.shtml
付出宝:https://opendocs.alipay.com/open/204/105297
   

[*]普通浏览器平台的付出,仍然是常规web做法。uni-app未封装。
[*]在普通浏览器里也可以调起微信进行付出,这个在微信叫做H5付出,此功能未开放给普通开辟者,需向微信 单独申请,[详见]
[*]微信内嵌浏览器运行H5版时,可通过js sdk实现微信付出,需要引入一个单独的js, [详见]
完结~,如有不足,后继补充。。。。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 利用UniApp实现多平台付出集成:小程序、Apple IAP、App端微信与付出宝付出