ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

swift5 接入内购全流程

2021-07-05 14:04:29  阅读:782  来源: 互联网

标签:内购 SKPaymentQueue default self print 接入 let swift5 data


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

填写苹果协议

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

标签:内购,SKPaymentQueue,default,self,print,接入,let,swift5,data
来源: https://blog.csdn.net/xo19882011/article/details/118487884

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有