美文网首页
苹果内购流程

苹果内购流程

作者: linggaozhen | 来源:发表于2018-10-31 18:46 被阅读0次

    苹果内购流程

    苹果现在对应用市场的审核规则越来越严格,不仅对马甲包进行大批量下架,而且对应用内的支付也有了严格的规定,凡是虚拟商品的购买都要使用苹果内购进行支付,否则应用不能被审核通过,而且苹果还要分成30%。无奈之下,只能遵循苹果的规则,毕竟是依赖它的平台进行开发的,所以苹果内购买流程是开发者必须要掌握的技能。

    一、填写协议、税务和银行业务

    登录苹果开发者中心网站,选择进入App Store Connect,然后点击 “协议、税务和银行业务”,按照流程填写一些基本信息


    协议、税务和银行业务.png

    二、添加App 内购买项目

    • 选择要添加内购项目的App


      我的App.png
    • 选择功能菜单,便可添加内购项目


      添加内购项目.png
    • 选择内购商品的类型,点击创建


      项目类型.png
    • 创建产品后,填写产品的基本信息


      A04B5140-E0D1-41EE-ADC7-EE3C61FEF2DC.png
      4FF81F75-3C39-49DC-A93C-C521CFC13B13.png
      截图,审核备注.png
    • 下面这些就是已经创建好的内购商品


      创建好的商品.png

    三、添加沙箱测试员账号,在测试的环境下方便测试人员购买

    • 点击进入


      添加沙箱测试的入口.png
    • 填写账号信息,创建成功后就可以使用账号测试购买


      填写沙箱账号的信息.png

    四、代码实现

    支付流程

    • 从公司的服务器获取商品ID,也就是我们在开发中中心添加的内购项目的ID

    • 根据商品ID,向苹果发送请求,请求所有可买的商品

    /// 获取苹果内购商品信息
        ///
        /// - Parameters:
        ///   - productId: 内购商品product_id
        ///   - completion: 内购商品SKProduct回调
        func fetchProduct(_ productId: String?, completion: @escaping CompletionResult) {
            
            guard let product_id = productId else {
                completion(Result.failure(RxSwiftMoyaError.filterError("抱歉,商品id无效")))
                return
            }
            
            // 检查用户是否允许支付
            guard SKPaymentQueue.canMakePayments() == true else {
                completion(Result.failure(RxSwiftMoyaError.filterError("检查是否允许支付功能或者该设备是否支持支付.")))
                return
            }
            
            self.completionResult = completion
            
            /// 请求商品信息
            let set: Set<String> = [product_id]
            let request = SKProductsRequest.init(productIdentifiers: set)
            request.delegate = self
            request.start()
        }
    
    • 在代理方法里面获取所有的可卖商品
    // MARK: - 获取苹果商品对象
    extension IAPService: SKProductsRequestDelegate {
        
        /// 接收苹果商品信息回调
        ///
        /// - Parameters:
        ///   - request: 请求体
        ///   - response: 返回结果
        func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
            
            let products = response.products
            guard products.count > 0, let product = products.first else {
                self.completionResult?(Result.failure(RxSwiftMoyaError.filterError("抱歉,商品信息无效!")))
                return
            }
            //将商品实体回调出去,作为发起支付时的入参
            self.completionResult?(Result.success(product))
        }
    }
    
    • 创建票据SKPayment,将票据加入到交易队列,便可发起支付
    /// 发起苹果支付
        ///
        /// - Parameter product: 苹果内购商品对象
        func purchase(_ product: SKProduct, completion: @escaping PaymentCompletionResult) {
            Logger.log(product.productIdentifier)
            
            self.paymentCompletionResult = completion
            let payment = SKPayment.init(product: product)
            SKPaymentQueue.default().add(payment)
        }
    
    • 在init方法中添加观察者,监听用户是否支付的各种状态
    override init() {
            super.init()
         
            // 监听支付事务回调
            SKPaymentQueue.default().add(self as SKPaymentTransactionObserver)
        }
    
    • 监听支付的各种事物
    // MARK: - 支付事物监听
    extension IAPService: SKPaymentTransactionObserver {
        
        /// 当事务数组发生更改时发送(添加或状态更改)。客户端应该检查事务状态,并在适当的时候完成。
        ///
        /// - Parameters:
        ///   - queue: 支付队列
        ///   - transactions: 支付事务数组
        func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
            Logger.log("")
            
            for transaction in transactions {
                Logger.log(transaction.transactionState.rawValue)
                
                switch transaction.transactionState {
                case .purchasing: // 交易事务进行中
                    break
                case .purchased: // 交易完成
                    
                    self.handlerTransaction(transaction)
                    break
                case .failed: // 交易失败
                    
                    self.handlerTransaction(transaction)
                    break
                case .restored: // 从用户的购买历史中恢复交易
                    
                    self.handlerTransaction(transaction)
                    break
                default:
                    /// 结束支付事务
                    SKPaymentQueue.default().finishTransaction(transaction)
                    break
                }
            }
            
        }
        
        /// 当事务从队列中删除时被调用
        ///
        /// - Parameters:
        ///   - queue: 支付队列
        ///   - transactions: 支付事务数组
        func paymentQueue(_ queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
            Logger.log("")
            
            for transaction in transactions {
                Logger.log("删除事务: \(transaction.payment.productIdentifier)")
                /// 结束该条支付事务: 否则出现弹框 您已购买此 App 内购买项目。此项目将免费恢复。
                SKPaymentQueue.default().finishTransaction(transaction)
            }
        }
        
        /// 当遇到错误时发送,同时从用户的购买历史中添加事务回到队列
        ///
        /// - Parameters:
        ///   - queue: 支付队列
        ///   - error: 错误
        func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
            
            Logger.log(error.localizedDescription)
        }
        
        /// 当用户的购买记录的所有事务都成功地添加到队列中时被调用
        ///
        /// - Parameter queue: 支付队列
        func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
            
            Logger.log("")
        }
        
        /// 当用户从应用程序商店发起IAP购买时发送
        ///
        /// - Parameters:
        ///   - queue: 支付队列
        ///   - payment: 支付对象
        ///   - product: 商品信息
        /// - Returns: 是否发起支付
        func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool {
            
            Logger.log(product.productIdentifier)
            return true
        }
    }
    
    • 对监听到的支付事物进行处理
    /// 自定义处理支付事务
        ///
        /// - Parameter transaction: 支付事务
        func handlerTransaction(_ transaction: SKPaymentTransaction) {
            
            let error = transaction.error as NSError?
            if error?.code == SKError.paymentCancelled.rawValue {
                
                // 用户手动取消支付
                SKPaymentQueue.default().finishTransaction(transaction)
                self.paymentCompletionResult?(Result.failure(RxSwiftMoyaError.filterError("已取消支付")))
            }else{
                
                switch transaction.transactionState {
                case .purchased, .restored:
                    
                    // 苹果订单校验
                    self.verifyReceipt(transaction)
                    break
                case .failed:
                    SKPaymentQueue.default().finishTransaction(transaction)
                    if let error = transaction.error as NSError? {
                        self.completionResult?(Result.failure(RxSwiftMoyaError.error(error)))
                    }
                    break
                default:
                    
                    SKPaymentQueue.default().finishTransaction(transaction)
                    break
                }
            }
        }
    
    • 最后支付成功后,上传支付凭证到服务器

    相关文章

      网友评论

          本文标题:苹果内购流程

          本文链接:https://www.haomeiwen.com/subject/fofztqtx.html