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

打印 上一主题 下一主题

主题 936|帖子 936|积分 2808

uniapp各平台付出功能

目录


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应用才能调用开放产物的接口能力。



    点击上面设置后,在加签管理,选择公钥证书,然后下载工具生csr文件








  • 步调二、开通App付出功能,应用创建完成后,体系会主动跳转到应用详情页面。开辟者可以点击 添加能力 来添加 App 付出能力。添加功能后开辟者需要在商家中心中进行 签约,第三方应用开辟者可以 代商户签约。

    得到沙箱测试账号

步调三、 设置密钥(获取公钥、私钥)
为了包管交易双方(商户和付出宝)的身份和数据安全,商户在调用接口前,需要设置双方密钥,对交易数据进行双方校验。密钥包含应用私钥APP_PRIVATE_KEY和应用公钥 APP_PUBLIC_KEY。生成密钥后,商户需要在开放平台控制台进行密钥配,设置完成后可以获取付出宝公钥 ALIPAY_PUBLIC_KEY,设置的详细步调请参考 设置应用环境。您还可以通过 生成密钥并上传 学习密钥的设置。密钥的设置旨在对交易数据进行双方校验。
微信付出【参考】

步调一、创建应用

  • 利用微信付出功能需到微信开放平台 申请移动应用并开通付出功能 微信APP
    付出接入商户服务中心 申请应用后可以获取AppID和AppSecret值。

    步调二、开通
    开通付出功能后可获取付出业务服务器设置数据(要先交300元开辟者认证费用,个人不可)。
    PARTNER:财付通商户号
    PARTNER_KEY:财付通密钥
    PAYSIGNKEY:付出签名密钥

服务端生成付出订单接口

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

客户端请求背景服务端获取签名后的订单信息,客户端带上订单信息(字符串)请求付出接口。

微信付出业务流程图【官方参考】

客户端请求背景服务端获代替签名的付出订单信息,然后客户端带上订单信息(Object范例)请求付出接口,此中订单信息请求请参考官网文档【APP调起付出API】

HBuilderX中设置利用付出功能

从微信开放平台申请获取设置参数后(Apple应用内付出和付出宝无需设置),需要再HBuilderX中设置并提交云端打包才能生效。

勾选后会表现支持的付出模块,可根据应用需要进行选择设置
Apple应用内付出【仅支持IOS平台】


付出宝付出【支持Android及iOS平台】


微信付出【参考】

获取appid填入,去微信开放平台申请应用的AppId值,UniversalLinks:iOS平台通用链接,必须与微信开放平台设置的同等,参考iOS平台微信SDK设置通用链接(UniversalLinks)

功能实现


APP端付出宝/微信付出实现

发送请求到背景服务端,背景服务端生成订单信息,相应预付出订单信息,通过预付出订单信息请求付出接口。
  1. import api from '@/api/order.js'
  2. export default {
  3.         methods: {
  4.                 // 获取订单信息 (微信小程序支付需要openid)
  5.                 getOrderInfo(openid) {
  6.                         // 不要少了async
  7.                         return new Promise( async (resolve, reject) => {
  8.                                 let res = null
  9.                                 let data = {} // 服务接口请求参数
  10.                                 if(this.provider === 'alipay') {
  11.                                         res = await api.getOrderInfoAlipay(data)
  12.                                 }else if(this.provider === 'wxpay') {
  13.                                         res = await api.getOrderInfoWxpay(data)
  14.                                 }
  15.                                 if (res && res.code === 20000) {
  16.                                         resolve(res.data)
  17.                                 } else {
  18.                                         reject(new Error('获取支付信息失败' + res.message))
  19.                                 }
  20.                         })
  21.                 },
  22.         // 微信、支付宝等支付
  23.         async payHandler() {
  24.                 // 支付中
  25.                 this.loading = true
  26.                 // #ifdef APP-PLUS
  27.                 // 1. 发送请求到服务端,服务端生成订单信息,响应预支付订单
  28.                 let orderInfo = await this.getOrderInfo();
  29.                 if (!orderInfo) {
  30.                         uni.showModal({
  31.                                 content: '获取支付信息失败',
  32.                                 showCancel: false
  33.                         })
  34.                         return
  35.                 }
  36.                 // 2. 请求支付
  37.                 uni.requestPayment({
  38.                         provider: this.provider, // 支付渠道
  39.                         orderInfo: orderInfo,
  40.                         success: (e) => {
  41.                                 console.log("success", e);
  42.                                 uni.showToast({
  43.                                         title: "支付成功!"
  44.                                 })
  45.                         },
  46.                         fail: (e) => {
  47.                                 console.log("fail", e);
  48.                                 uni.showModal({
  49.                                         content: "支付失败!",
  50.                                         showCancel: false
  51.                                 })
  52.                         },
  53.                         complete: () => {
  54.                                 this.loading = false;
  55.                         }
  56.                 })
  57.                 // #endif
  58.         },
  59. }
复制代码

微信小程序付出功能实现

微信小程序运行在微信内里,需要付出的话,起首要知道是谁的微信内里,就需要将当前微信进行登录获取获取code,再根据code获取openid的值。
步调一、先登录微信小程序获取用户code,再请求服务端获取openid,微信小程序登录参考:

  1. // 登录微信小程序
  2. loginWeixinMp() {
  3.                 return new Promise((resolve, reject) => {
  4.                         // 1. 先使用微信登录小程序响应 code,
  5.                         uni.login({
  6.                                 provider: 'weixin',
  7.                                 success: (res) => {
  8.                                         console.log('登录', res)
  9.                                         const code = res.code
  10.                                         // 2. 请求服务端通过code获取openid
  11.                                         let openid = 'xx'
  12.                                         uni.setStorageSync('openid', openid)
  13.                                         resolve(openid)
  14.                                 },
  15.                                 fail(err) {
  16.                                         reject(err)
  17.                                 }
  18.                         })
  19.                 })
  20. },
复制代码
步调二、通过openid再获取订单预付出信息,直接在getOrderInfo写死一个模拟预付出信息即可。
  1. getOrderInfo(openid) {
  2.         return new Promise(async (resolve, reject) => {
  3.                 if (openid) {
  4.                         // 微信小程序获取订单信息,发送请求
  5.                         // let orderInfo = await api.getOrderInfoWxpayMP(openid) 如果有真实接口替换即可
  6.                         let orderInfo = {
  7.                                 "timeStamp": "1414561699",
  8.                                 "nonceStr": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS",
  9.                                 "package": "prepay_id=wx201410272009395522657a690389285100", //预支付交易会话标识( prepay_id)
  10.                                 "signType": "RSA",
  11.                                 "paySign": "oR9d8PuhnIc+YZ8cBHFCwfgpaK9gd7vaRvkYD7rthRAZ",
  12.                         }
  13.                         resolve(orderInfo)
  14.                         return
  15.                 }
  16.                 let res = null
  17.                 let data = {} // 服务接口请求参数
  18.                 if (this.provider === 'alipay') {
  19.                         res = await api.getOrderInfoAlipay(data)
  20.                 } else if (this.provider === 'wxpay') {
  21.                         res = await api.getOrderInfoWxpay(data)
  22.                 }
  23.                 if (res && res.code === 20000) {
  24.                         resolve(res.data)
  25.                 } else {
  26.                         reject(new Error('获取支付信息失败' + res.message))
  27.                 }
  28.         })
  29. },
复制代码
步调三、通过订单预付出信息,去调用付出接口
  1. // 微信小程序支付
  2. async wxPayHandler() {
  3.         this.loading = true
  4.         // 1. 先获取用户code, 再获取openid
  5.         let openid = uni.getStorageSync('openid')
  6.         if (!openid) {
  7.                 try {
  8.                         openid = await this.loginWeixinMp()
  9.                 } catch (e) {
  10.                         console.error(e)
  11.                 }
  12.                 if (!openid) {
  13.                         uni.showModal({
  14.                                 content: '获取openid失败',
  15.                                 showCancel: false
  16.                         })
  17.                         this.loading = false
  18.                         return
  19.                 }
  20.         }
  21.         // 2. 通过 openid 再获取订单信息,
  22.         let orderInfo = await this.getOrderInfo(openid)
  23.         // 3. 通过订单预支付信息,去调用支付接口
  24.         uni.requestPayment({
  25.                 ...orderInfo,
  26.                 success: (res) => {
  27.                         uni.showToast({
  28.                                 title: "支付成功!"
  29.                         })
  30.                 },
  31.                 fail: (res) => {
  32.                         uni.showModal({
  33.                                 content: "支付失败,原因为: " + res.errMsg,
  34.                                 showCancel: false
  35.                         })
  36.                 },
  37.                 complete: () => {
  38.                         this.loading = false;
  39.                 }
  40.         })
  41. }
复制代码
因为用的是模拟的假数据,会报权限不足问题,假如真实开辟中调用后端请求服务拿到商品信息,先登录微信小程序获取用户code,再请求服务端获取openid,通过openid再获取订单预付出信息,直接在getOrderInfo写死一个模拟预付出信息即可,通过订单预付出信息,去调用付出接口即可。

Apple应用内付出

苹果应用内置流程与别的三方付出平台存在差异,请单独参考iOS 平台利用Apple应用内付出文档,项目中参考付出文档最下面示例代码
流程:

在onLoad中先获取Apple付出渠道的实例。
  1. onLoad: function(option) {
  2.         // 获取支付金额
  3.         if (option.params) {
  4.                 const params = JSON.parse(option.params)
  5.                 this.price = params.price
  6.                 this.courseIds = params.courseIds
  7.         }
  8.         // 查询余额
  9.         this.loadData()
  10.         // 获取apple支付渠道实例
  11.         plus.payment.getChannels((channels) => {
  12.                 console.log("获取到channel" + JSON.stringify(channels))
  13.                 for (var i in channels) {
  14.                         var channel = channels[i];
  15.                         if (channel.id === 'appleiap') {
  16.                                 iapChannel = channel;
  17.                                 this.requestOrder();
  18.                         }
  19.                 }
  20.                 if (!iapChannel) {
  21.                         this.errorMsg()
  22.                 }
  23.         }, (error) => {
  24.                 this.errorMsg()
  25.         });
  26. },
复制代码
requestOrder环境检测方法
  1.                         requestOrder() {
  2.                                 uni.showLoading({
  3.                                         title: '检测支付环境...'
  4.                                 })
  5.                                 //必须调用此方法向Appstore请求有效的商品详情,才能进行 iap 支付,
  6.                                 iapChannel.requestOrder(this.moneyList, (orderList) => {
  7.                                         this.disabled = false;
  8.                                         console.log('requestOrder success666: ' + JSON.stringify(orderList));
  9.                                         uni.hideLoading();
  10.                                 }, (e) => {
  11.                                         console.log('requestOrder failed: ' + JSON.stringify(e));
  12.                                         uni.hideLoading();
  13.                                         this.errorMsg()
  14.                                 });
  15.                         },
复制代码
弹窗提示判断,假如环境不支持apple付出则弹窗提示
  1. errorMsg() {
  2.         uni.showModal({
  3.                 content: "暂不支持苹果 iap 支付",
  4.                 showCancel: false
  5.         })
  6. },
复制代码
假如当前环境可以付出,则利用uni.requestPayment进行apple支
  1. // Apple应用内支付
  2. iosPayHandler() {
  3.         this.loading = true;
  4.         uni.requestPayment({
  5.                 provider: 'appleiap',
  6.                 orderInfo: {
  7.                         productid: this.applePrice // 商品金额
  8.                 },
  9.                 success: (e) => {
  10.                         console.log("success", e);
  11.                         uni.showToast({
  12.                                 title: "支付成功!"
  13.                         })
  14.                         // 再进行app内部扣款
  15.                 },
  16.                 fail: (e) => {
  17.                         console.log("fail", e);
  18.                         uni.showModal({
  19.                                 content: "支付失败,原因为: " + e.errMsg,
  20.                                 showCancel: false
  21.                         })
  22.                 },
  23.                 complete: () => {
  24.                         this.loading = false;
  25.                 }
  26.         })
  27. },
复制代码
总体代码:
  1. <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[i];                                        if (channel.id === 'appleiap') {                                                iapChannel = channel;                                                this.requestOrder();                                        }                                }                                if (!iapChannel) {                                        this.errorMsg()                                }                        }, (error) => {                                this.errorMsg()                        });                },                methods: {
  2.                         requestOrder() {
  3.                                 uni.showLoading({
  4.                                         title: '检测支付环境...'
  5.                                 })
  6.                                 //必须调用此方法向Appstore请求有效的商品详情,才能进行 iap 支付,
  7.                                 iapChannel.requestOrder(this.moneyList, (orderList) => {
  8.                                         this.disabled = false;
  9.                                         console.log('requestOrder success666: ' + JSON.stringify(orderList));
  10.                                         uni.hideLoading();
  11.                                 }, (e) => {
  12.                                         console.log('requestOrder failed: ' + JSON.stringify(e));
  13.                                         uni.hideLoading();
  14.                                         this.errorMsg()
  15.                                 });
  16.                         },
  17.                         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应用付出弹窗。

Appstore审核报PGPay SDK不答应上架的问题
A:数字类产物(好比购买会员等不需要配送实物的商品),Apple规定必须利用苹果IAP应用内付出,给Apple分成30%。打包的时间不要勾选微信或付出宝等其他付出方式。假如你提交的包里包含了微信付出宝等付出的sdk,即使没利用,Appstore也会以为你有隐藏方式,以后会绕过IAP,不给Apple分成,因此拒绝你的App上线。云打包时,manifest里选上付出模块,但sdk设置里去掉微信付出和付出宝付出。很多开辟者的Android版是包含微信和付出宝付出的,此时留意分开判断。详见
H5沙箱付出功能实现实现

设置沙箱

沙箱支持产物

沙箱测试账号

带着商品信息请求后端接口,获取paymentUrl然后通过window.location.href = res.paymentUrl进行跳转


通过location.href跳转到如下页面即可利用沙箱测试账号进行登录。下图为付出宝登录页面,可能会违规。
留意: 沙箱测试付出功能一定要开启无痕浏览进行测试

利用付出宝开放平台给的沙箱测试账号进行测试:如下找到

输入沙箱账号暗码


付出成功

交易成功后,此页面会跳转到前端传递给后端的设置的跳转页面,付出成功后就会跳回到指定页面。

设置的付出成功后的跳转页面,在此页面调用后端接口,后端返回付出状态,根据付出状态再在此页面进行其他业务逻辑处理。


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企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

梦见你的名字

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表