vonfly
vonfly
  • 发布:2024-04-17 11:53
  • 更新:2024-04-18 17:37
  • 阅读:77

【报Bug】ios端取消订阅产品后,再次购买订阅产品不会重新拉起支付,而是直接进入支付成功回调

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: windows10 v2009

HBuilderX类型: 正式

HBuilderX版本号: 3.99

手机系统: iOS

手机系统版本号: iOS 15

手机厂商: 苹果

手机机型: iPhone6s Plus

页面类型: vue

vue版本: vue2

打包方式: 云端

项目创建方式: HBuilderX

示例代码:
import {  
    Iap,  
    IapTransactionState,  
} from "@/utils/iap.js"  
export default {  
    data() {  
        return {  
            // 获取苹果真实的产品列表  
            iapProductList: [],  
            loading: false,  
            disabled: true,  
            personId: uni.getStorageSync("personId"),  
            quantity: 1,  
        }  
    },  
    methods: {  
        // 初始化支付环境  
        initPayEnv(products) {  
            this._iap = new Iap({  
                products  
            })  
            this.init();  
        },  
        async init() {  
            uni.showLoading({  
                title: '正在检测支付环境...'  
            });  

            try {  
                await this._iap.init();  
                this.iapProductList = await this._iap.getProduct();  
                this.disabled = false;  
            } catch (e) {  
                uni.showToast({  
                    icon: 'none',  
                    title: '支付环境检测失败',  
                    duration: 2000  
                });  
            } finally {  
                uni.hideLoading();  
            }  
            if (this._iap.ready) {  
                this.restore();  
            }  
        },  
        async restore() {  
            this.loading = true;  
            this.disabled = true  
            // 检查上次用户已支付且未关闭的订单,可能出现原因:首次绑卡,网络中断等异常  
            // 提示是正在检测支付环境,实际是正在检测未关闭的订单  
            uni.showLoading({  
                title: '正在检测支付环境...'  
            });  

            try {  

                // 从苹果服务器检查未关闭的订单,可选根据 username 过滤,和调用支付时透传的值一致  
                const transactions = await this._iap.restoreCompletedTransactions({  
                    username: ''  
                });  

                console.log(transactions)  

                if (!transactions.length) {  
                    return;  
                }  

                for (var i = 0; i < transactions.length; i++) {  
                    let transaction = transactions[i]  
                    switch (transaction.transactionState) {  

                        case IapTransactionState.purchased:  
                            // 用户已付款,在此处请求开发者服务器,在服务器端请求苹果服务器验证票据  
                            const username = transaction.payment.username || uni.getStorageSync(  
                                'IAP_ORDER_USERNAME');  
                            console.log('username', username)  
                            if (!username) {  
                                return await this._iap.finishTransaction(transaction);  
                            }  
                            this.validatePaymentResult(username, transaction);  
                            break;  
                        case IapTransactionState.failed:  
                            // 关闭未支付的订单  
                            await this._iap.finishTransaction(transaction);  
                            break;  
                            // case IapTransactionState.restored:  
                            //  // 关闭未支付的订单  
                            //  this.validatePaymentResult(username, transaction);  
                            //  break;  
                        default:  
                            break;  
                    }  
                }  
            } catch (e) {  
                uni.showToast({  
                    icon: 'none',  
                    title: e.message,  
                    duration: 2000  
                });  
            } finally {  
                this.loading = false  
                this.disabled = false  
                uni.hideLoading();  
            }  
        },  
        async onPayment() {  
            if (this.loading === true) {  
                return;  
            }  
            this.loading = true;  
            this.disabled = true  

            try {  

                // 从开发者服务器创建订单  
                const orderInfo = await this.$u.post('/api/finance/CreateIAPOrder', {  
                    "PersonId": this.personId,  
                    "CoinCount": this.currProductInfo.Price,  
                    "ProductId": this.currProductId  
                })  

                console.log(orderInfo)  

                if (orderInfo && orderInfo.Status) {  
                    // 本地缓存username  
                    uni.setStorageSync('IAP_ORDER_USERNAME', orderInfo.UserName);  
                } else {  
                    uni.showToast({  
                        icon: 'none',  
                        title: '订单创建失败,请联系管理员',  
                        duration: 3000  
                    });  
                    uni.hideLoading()  
                    return  
                }  

                // 请求苹果支付  
                const transaction = await this._iap.requestPayment({  
                    productid: this.currProductId,  
                    username: orderInfo.UserName,  
                    quantity: this.quantity,  
                    manualFinishTransaction: true,  
                });  

                console.log('transaction', transaction)  

                if (transaction.transactionState === IapTransactionState.purchased) {  
                    // 在此处请求开发者服务器,在服务器端请求苹果服务器验证票据  
                    const res = await this.validatePaymentResult(transaction.payment.username, transaction)  
                    if (res.ReturnCode === 1001) {  
                        // 支付成功,重新获取用户余额  
                        uni.showToast({  
                            icon: 'success',  
                            title: '支付成功',  
                            duration: 2000  
                        });  
                        // 触发统一的支付成功函数,由各个业务页面自行处理成功逻辑  
                        this.paySuccess()  
                    } else {  
                        uni.showToast({  
                            icon: 'none',  
                            title: res.MessageChinese,  
                            duration: 3000  
                        });  
                    }  
                    uni.hideLoading()  
                    this.onPaySuccessReset()  
                }  
            } catch (e) {  
                console.log(e)  
                uni.setStorageSync('IAP_ORDER_USERNAME', '');  
                if (e.errCode === 2 && e.code === 2) {  
                    uni.showToast({  
                        icon: 'none',  
                        title: '支付已取消',  
                        duration: 2000  
                    });  

                } else {  
                    uni.showToast({  
                        icon: 'none',  
                        title: e.message,  
                        duration: 2000  
                    });  
                }  
                uni.hideLoading()  
                this.onPaySuccessReset()  
            } finally {  
                // this.onPaySuccessReset()  
            }  
        },  
        // 向本地服务器验证支付结果  
        async validatePaymentResult(userName, transaction) {  
            const serverRes = await this.$u.post('/api/finance/IAPOrderVerify', {  
                "UserName": userName,  
                "TransactionReceipt": transaction.transactionReceipt,  
            })  
            console.log(serverRes)  
            if (serverRes.ReturnCode === 1001) {  
                uni.setStorageSync('IAP_ORDER_USERNAME', '');  
                // 验证成功后关闭订单  
                await this._iap.finishTransaction(transaction);  
            }  
            return serverRes  
        }  
    }  
}  

操作步骤:

ios测试环境:沙盒环境

场景一:在每次支付前不调用restoreCompletedTransactions api的情况下,订阅产品在订阅状态下,再次购买苹果系统会提示“你目前已订阅此项目”

场景二:在每次支付前调用restoreCompletedTransactions api的情况下,订阅产品在订阅状态下,再次购买会直接进入支付成功回调,无提示。

场景三:在产品订阅情况下,进入设置->App Store->沙盒账户->取消产品订阅,再进入app,在未调用restoreCompletedTransactions api后购买该订阅产品,会先执行支付成功回调,再弹出系统支付弹窗。

场景四:在产品订阅情况下,进入设置->App Store->沙盒账户->取消产品订阅,再进入app,在调用restoreCompletedTransactions api后购买该订阅产品,会直接进入支付成功回调,支付弹窗未弹出。同时,检查设置->App Store->沙盒账户->产品订阅状态还是未订阅状态

预期结果:

产品在未订阅状态下,可以订阅成功。产品在已订阅状态下,有系统提示用户。

实际结果:

无法形成订阅产品支付闭环

bug描述:

ios测试环境:沙盒环境

场景一:在每次支付前不调用restoreCompletedTransactions api的情况下,订阅产品在订阅状态下,再次购买苹果系统会提示“你目前已订阅此项目”

场景二:在每次支付前调用restoreCompletedTransactions api的情况下,订阅产品在订阅状态下,再次购买会直接进入支付成功回调。

场景三:在产品订阅情况下,进入设置->App Store->沙盒账户->取消产品订阅,再进入app,在未调用restoreCompletedTransactions api后购买该订阅产品,会先执行支付成功回调,再弹出系统支付弹窗。

场景四:在产品订阅情况下,进入设置->App Store->沙盒账户->取消产品订阅,再进入app,在调用restoreCompletedTransactions api后购买该订阅产品,会直接进入支付成功回调,支付弹窗未弹出。同时,检查设置->App Store->沙盒账户->产品订阅状态还是未订阅状态

2024-04-17 11:53 负责人:无 分享
已邀请:
vonfly

vonfly (作者) - 中端开发工程师

顶下

vonfly

vonfly (作者) - 中端开发工程师

有官方同学解答下吗?

要回复问题请先登录注册