swift5 接入内购全流程

公司需要对接内购,顺便记录一下过程。

填写苹果协议

app store connect 协议

填写其中的付费 App,填写点公司名称、公司简介、公司帐号、公司之类的。
由于已经填写过了无法截图,可以去搜搜其他人的分享。
银行账户: 填的的时候注意银行帐号选择中国之后就是国内银行的代码了,选择每个地区下边的银行代码都是会变的。另外银行的受益人需要填写 英文 这个比较坑,名在前姓在后。
报税表: 参照别人的截图勾选一下就行,就是本着能不填就不填的原则,稍微写了点。另外那个报税表不需要下载填写就行。

联系信息: 这个联系人都是新建就可以了,同现有系统中的用户没有半点关系。

新建沙盒测试员

app store connect 用户和访问

在沙盒里边的测试员中新建沙盒ID,这个ID比较坑的是添加成功了如果删除,再添加同样的帐号就过不去了。。。还是记好了密码比较好。

新建商品

app store connect

进入到需要增加内购的app中,在App内购买项目里边的管理中新建商品,根据需求把商品的详情都填好,如果报元数据缺失就是还没填全,最后的审核图片必须要上传一个,按照要求随便上传一个,然后状态变成准备提交就搞定了。记下其中的商品ID

上代码~

其中需要特别关注的是,开发使用的bundleID必须同app store connect中应用的bundleID一致,不然无法获取到商品。

//
//  WSPay.swift
//  WiseTV-HD
//
//  Created by wangyu on 7/5/21.
//

import Foundation
import UIKit
import StoreKit
import SnapKit

class WSPayManager: NSObject, SKPaymentTransactionObserver, SKProductsRequestDelegate {
    
    static var `default`:WSPayManager = WSPayManager()
    private var proId:String!
    
    //沙盒验证地址
    let url_receipt_sandbox = "https://sandbox.itunes.apple.com/verifyReceipt"
    //生产环境验证地址
    let url_receipt_itunes = "https://buy.itunes.apple.com/verifyReceipt"
    
    //21008表示生产换使用  21007表示测试环境使用
    var state = 21008
    var resultBlock:(_ result:String)->Void = { (_ result:String)->Void in
        print("交易结果:", result)
    }
    
    func doPay() {
        if SKPaymentQueue.canMakePayments() == false {
            return
        }
        
        SKPaymentQueue.default().add(self)
        self.proId = "xiaogangzhu"
        let set = Set<String>.init([self.proId])
        
        let request = SKProductsRequest.init(productIdentifiers: set)
        request.delegate = self
        request.start()
    }
    
    //MARK:购买成功验证凭证
    func completePay(transaction:SKPaymentTransaction) {
        print(transaction)
        //获取交易凭证
        let recepitUrl = Bundle.main.appStoreReceiptURL
        let data = try! Data.init(contentsOf: recepitUrl!)
        if recepitUrl == nil {
            self.resultBlock("交易凭证为空")
            print("交易凭证为空")
            return
        }

        //客户端验证
        verify(data: data,transaction: transaction)

        //注销交易
        SKPaymentQueue.default().finishTransaction(transaction)
    }
    
    // SKProductsRequestDelegate
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        let productArray = response.products
        if productArray.count == 0 {
            print("此商品id没有对应的商品")
            return
        }
        var product:SKProduct!
        for pro in productArray {
            if pro.productIdentifier == proId {
                product = pro
                break
            }
        }
        print(product.description)
        print(product.localizedTitle)
        print(product.localizedDescription)
        print(product.price)
        print(product.productIdentifier)
        let payment = SKMutablePayment.init(product: product)
        payment.quantity = 1
        SKPaymentQueue.default().add(payment)
    }
    
    //MARK:客户端验证
    func verify(data:Data,transaction:SKPaymentTransaction)  {
        let base64Str = data.base64EncodedString(options: .endLineWithLineFeed)
        let params = NSMutableDictionary()
        params["receipt-data"] = base64Str
        let body = try! JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
        var request = URLRequest.init(url: URL.init(string: state == 21008 ? url_receipt_itunes : url_receipt_sandbox)!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 20)
        request.httpMethod = "POST"
        request.httpBody = body
        let session = URLSession.shared
        let task = session.dataTask(with: request) { (data, response, error) in
            let dict = try! JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
            print(dict)
            SKPaymentQueue.default().finishTransaction(transaction)
            let status = dict["status"] as! Int
            switch(status){
            case 0:
                self.resultBlock("购买成功")
                break
            case 21007:
                self.state = 21007
                self.verify(data: data!, transaction: transaction)
                break
            default:
                self.resultBlock("验证失败")
                break
            }
            //移除监听
            SKPaymentQueue.default().remove(self)
        }
        task.resume()
    }
    
    // MARK: SKPaymentTransactionObserver
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for tran in transactions {
            switch tran.transactionState {
            case .purchased://购买完成
                SKPaymentQueue.default().finishTransaction(tran)
                completePay(transaction: tran)
                break
            case.purchasing://商品添加进列表
                break
            case.restored://已经购买过该商品
                SKPaymentQueue.default().finishTransaction(tran)
                break
            case.failed://购买失败
                SKPaymentQueue.default().finishTransaction(tran)
                break
            default:
                break
            }
        }
    }
}

let WSPayManagerInstance = WSPayManager.default


参考:
https://blog.csdn.net/weixin_39339407/article/details/112647323
https://www.jianshu.com/p/b58525b71798

上一篇:swift5.x for-in, switch语句


下一篇:【学习】重学Swift5-函数和闭包