iOS内购(代码部分,swift)

一.创建支付类

1.创建一个类继承NSObject为内购付款类

import UIKit
class AppPayManager: NSObject {

}

2.类内引入头文件

import StoreKit

3.实现单利,方便支付结果的回调

let payManager = AppPayManager()
 class var shareInstance : AppPayManager {
            return payManager
}

二.发起购买请求

1.发起购买请求前的准备工作声明商品id String类型,声明回调闭包,以及支付结果状态码后面会用到

var proId:String!
//21008表示生产换使用  21007表示测试环境使用
var state = 21008
var resultBlock:(_ result:String)->Void = { (_ result:String)->Void in
        
}

2.声明并实现发起购买请求的方法,并在方法中添加购买结果的监听。

增加监听的协议

class AppPayManager: NSObject ,SKPaymentTransactionObserver{

实现发起购买请求,参数一商品id,参数2回调逃逸闭包(商品id,也就是在开发者网站添加商品的id,在这里可以先提供一个com.saixin.eduline6)

//MARK:发起购买请求
    func startPay(proId:String,resultBlock:@escaping ((_ result:String)->Void))  {
        self.resultBlock = resultBlock
        if !SKPaymentQueue.canMakePayments() {
            print("不可使用苹果支付")
            return
        }
        //监听购买结果
        SKPaymentQueue.default().add(self)
        self.proId = proId
        let set = Set.init([proId])
        let requst = SKProductsRequest.init(productIdentifiers: set)
        requst.delegate = self
        requst.start()
    }

3.发起请求后里面设置了一个SKProductsRequst的代理,所以需要遵循协议并实现协议方法

增加一个SKProductsRequst协议


class AppPayManager: NSObject ,SKProductsRequestDelegate,SKPaymentTransactionObserver{

实现协议方法

//MARK:发起购买请求回调代理方法
    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)
    }

三.获取购买结果

实现SKPaymentTransactionObserver的协议方法监听购买结果

//MARK:购买结果 监听回调
    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
            }
        }
    }

四.支付成功获取交易凭证

//MARK:购买成功验证凭证
    func completePay(transaction:SKPaymentTransaction) {
        //获取交易凭证
        let recepitUrl = Bundle.main.appStoreReceiptURL
        let data = try! Data.init(contentsOf: recepitUrl!)
        if recepitUrl == nil {
            self.resultBlock("交易凭证为空")
            print("交易凭证为空")
            return
        }
        
        if verify_type == 0 {//客户端验证
            verify(data: data,transaction: transaction)
        }else{//服务器端校验
            
        }
        //注销交易
        SKPaymentQueue.default().finishTransaction(transaction)
    }

五.校验支付凭证完成支付

方式一.客户端校验支付凭证

首先验证正式环境,如果返回结果为21007则表示为沙盒环境,再去校验沙盒环境,当status为0时则表示校验成功

//沙盒验证地址
let url_receipt_sandbox = "https://sandbox.itunes.apple.com/verifyReceipt"
//生产环境验证地址
let url_receipt_itunes = "https://buy.itunes.apple.com/verifyReceipt"
//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()
    }

方式二.服务器端校验

一般来讲是将获取到的支付凭证转化为base64编码格式传递后台便可以,和普通接口没有区别。

六.漏单处理

一般是客户已经完成支付,但尚未来得及校验支付凭证便退出了APP。一般我们可以在用户完成支付的同时存储支付凭证到本地,校验完支付凭证之后将数据清除。每次启动应用如果支付凭证还在则表示有漏单情况,直接发起校验请求便可。

七.内购工具类连接

https://download.csdn.net/download/weixin_39339407/14240375

八.开放者账号内购配置连接

iOS 内购开(发者账号部分)_苹果内购账户人持有地址-CSDN博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值