Swift 課金処理 忘備録

ポイントset 構造体を利用する

1-いろんな型のコレクションを作れるハッシュに近い。要素は重複しない。

2-順番は保証されない。

これは課金アイテムを保存するときにとても便利。2つ同じもの売ってしまうと怒られてしまう。

class funcはstatic fancの用な感じ。

インスタンス化しないでも呼び出しできる。 オーバーライドも可能。(あまり使わない) staticで呼ばれて、初めてインスタンス化されるイメージ。

    //SKProductは商品 商品が帰ってくる クロージャー型 必ずクロージャーを利用する
    private var completionForProductidentifiers : (([SKProduct]?, NSError?) -> ())?


    class func productsWithProductIdentifiers(productIdentifiers: [String]!, completion:(([SKProduct]?, NSError)-> () )?){
        
        let productManager = ProductManager()
        productManager.completionForProductidentifiers = completion as? (([SKProduct]?, NSError?) -> ())
        
        //SKProductsRequest appストアに上げた情報を取得する
        let productRequest = SKProductsRequest(productIdentifiers: Set(productIdentifiers))
        productRequest.delegate = productManager
        productRequest.start()
        productManagers.insert(productManager)
        
    }

//SKProductsRequestのデリゲートメソッド
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse){
        var error: NSError? = nil
        if response.products.count == 0{
            //エラーオブジェクトの生成
            error = NSError(domain: "ProductsRequestErrorDomain", code: 0,
                            userInfo: [NSLocalizedDescriptionKey : "プロダクトを取得できませんでした。"])
        }
        //毎回クロージャー
        completionForProductidentifiers?(response.products, error)
    }
 SKRequest デリゲートメソッド  関数定義

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error NS_AVAILABLE(10_7, 3_0);
requestは内部引数名 第一引数は、キーワードは兼ねているので
didFailWithError:(NSError *)error は第二引数のキーワード 
NS_AVAILABLE(10_7, 3_0);はマクロ 使えるバージョンが書いてある。

- (void)requestDidFinish:(SKRequest *)request NS_AVAILABLE(10_7, 3_0);

purchaseManager

/// シングルトン
private let purchaseManagerSharedManager = PurchaseManager()

class PurchaseManager : NSObject,SKPaymentTransactionObserver {
    var delegate : PurchaseManagerDelegate?
    fileprivate var productIdentifier : String?
    fileprivate var isRestore : Bool = false
    /// シングルトン 外側からsharedManagerを通して呼ばれる
    class func sharedManager() -> PurchaseManager{
        return purchaseManagerSharedManager;
    }
    /// 課金開始 SKProductをもって呼び出す 同時に課金できるものは一つだけ
    func startWithProduct(_ product : SKProduct){
        var errorCount = 0
        var errorMessage = ""
        if SKPaymentQueue.canMakePayments() == false {
            //エラーコードを生成している
            errorCount += 1
            errorMessage = "設定で購入が無効になっています。"
        }
//        同時に変えるのが1個まで
        if self.productIdentifier != nil {
            errorCount += 10
            errorMessage = "課金処理中です。"
        }
        //課金アイテム 非照合型=リストア機能が必要 iPhone変えたも無料で購入できないといけない
        if self.isRestore == true {
            errorCount += 100
            errorMessage = "リストア中です。"
        }
        //エラーがあれば終了 エラーコード作っていた
        if errorCount > 0 {
            let error = NSError(domain: "PurchaseErrorDomain", code: errorCount, userInfo: [NSLocalizedDescriptionKey:errorMessage + "(\(errorCount))"])
            self.delegate?.purchaseManager?(self, didFailWithError: error)
            return
        }