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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Swift 5 中,您可以使用 Network.framework 库来创建和管理 TCP 连接。在 iOS 14 及更高版本中,默认情况下禁用了对不安的连接的支持,因此您需要在应用的 Info.plist 文件中添加网络连接权限键并将其设置为 true,才能允许您的应用连接到任何网络资源。 以下是如何在 Info.plist 文件中添加网络连接权限键的步骤: 1. 打开您的应用的 Info.plist 文件。 2. 单击右键,选择“Add Row”。 3. 在新行中输入“App Transport Security Settings”。 4. 将此行展开,并在下面添加一个新的键值对。 5. 设置键的名称为“Allow Arbitrary Loads”。 6. 将键的类型设置为布尔值,并将其值设置为“YES”。 7. 保存 Info.plist 文件。 现在,您可以使用 Network.framework 库中的 NWConnection 类创建和管理 TCP 连接。在创建连接之前,您需要创建一个连接参数对象,并设置所需的参数,例如远程主机的 IP 地址和端口号等。 以下是一个简单的示例代码片段,演示如何使用 Network.framework 库创建 TCP 连接: ``` import Network let connection = NWConnection(host: "example.com", port: 80, using: .tcp) connection.stateUpdateHandler = { (newState) in switch (newState) { case .ready: // 连接已准备就绪,可以开始发送和接收数据 break case .failed(let error): // 连接失败,处理错误 break default: break } } connection.start(queue: .main) ``` 请注意,此代码片段仅用于演示目的,并且需要根据您的应用的需要进行修改和调整。您应该确保在使用 Network.framework 库时进行正确的错误处理和异常情况处理,以避免可能的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xyccstudio

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值