In App Subscription Testing

PHOTO EMBED

Mon Oct 23 2023 06:41:18 GMT+0000 (Coordinated Universal Time)

Saved by @hasnat #ios #swift #inapp #subscription #purchase #appstore

// you need apple developer account for this
// Start by watching these CodeWithChris videos and skip Revenue cat. Link: https://youtu.be/Ecxucvej1Dc
// i have to add code for in app subscription later *.

//Log in to your Apple connect account //https://appstoreconnect.apple.com/.

//Access Users and Access:

//In iTunes Connect, navigate to "Users and Access."
//Click on "Sandbox Testers" under the "People" section.
//Add a New Sandbox Tester:

//Click the "+" button to add a new sandbox tester.
//Fill in the tester's details, such as first name, last name, and dummy email address.


import Foundation
import StoreKit


protocol SubscriptionManagerDelegate: AnyObject {
    func transactionDidUpdate(state: SKPaymentTransactionState)
}

class SubscriptionManager: NSObject, SKProductsRequestDelegate, SKPaymentTransactionObserver {
    
     var delegate: SubscriptionManagerDelegate?
    
    static let shared = SubscriptionManager()
    
    private var productIdentifier = "com.InAppSubscription.Demo.MonthlySubscription"
    private var product: SKProduct?
    private var completionBlock: ((SKProduct?) -> Void)?
    
    override init() {
        super.init()
        SKPaymentQueue.default().add(self)
    }
    
    func requestProductInfo1(myProductIentifier : String, completion: @escaping (SKProduct?) -> Void) {
        productIdentifier = myProductIentifier
        let productIdentifiers: Set<String> = [productIdentifier]
        let request = SKProductsRequest(productIdentifiers: productIdentifiers)
        request.delegate = self
        request.start()
        
        self.completionBlock = completion
    }
    
    func purchaseProduct() {
        if SKPaymentQueue.canMakePayments() {
            if let product = self.product {
                let payment = SKPayment(product: product)
                SKPaymentQueue.default().add(payment)
            } else {
                print("Product not available")
            }
        }
    }
    
    func restorePurchases() {
        SKPaymentQueue.default().restoreCompletedTransactions()
    }
    
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        if let product = response.products.first {
            self.product = product
            
            completionBlock?(product)
        }
    }
    
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for transaction in transactions {
            switch transaction.transactionState {
            case .purchased:
                delegate?.transactionDidUpdate(state: .purchased)
                SKPaymentQueue.default().finishTransaction(transaction)
            case .failed:
                delegate?.transactionDidUpdate(state: .failed)
                SKPaymentQueue.default().finishTransaction(transaction)
            case .restored:
                delegate?.transactionDidUpdate(state: .restored)
                SKPaymentQueue.default().finishTransaction(transaction)
                
                
                let dateFormatter = DateFormatter()
                dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
                
                if let date = transaction.transactionDate {
                    
                    let formattedDate = dateFormatter.string(from: date)
                    print("Status Check: Restored: \(transaction.payment.productIdentifier), \(formattedDate)")
                }
                
            default:
                break
            }
        }
    }
}


import UIKit
import StoreKit

class SubscriptionViewController: UIViewController, SubscriptionManagerDelegate {
    let productInfoLabel = UILabel()
    let transactionStatusLabel = UILabel()

    var product: SKProduct?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        SubscriptionManager.shared.delegate = self
        requestProductInfo()
    }

        func setupUI() {
            // Product Info Label
            productInfoLabel.text = "Product Information:\nLine 1 of product info\nLine 2 of product info"
            productInfoLabel.numberOfLines = 0 // 0 means unlimited lines
            productInfoLabel.frame = CGRect(x: 20, y: 100, width: 300, height: 100)
            view.addSubview(productInfoLabel)
    
            // Transaction Status Label
            transactionStatusLabel.text = "Transaction Status: "
            transactionStatusLabel.frame = CGRect(x: 20, y: 210, width: 300, height: 30)
            view.addSubview(transactionStatusLabel)
    
            // Request Product Button
            let requestProductButton = UIButton(type: .system)
            requestProductButton.setTitle("Request Product Info", for: .normal)
            requestProductButton.contentHorizontalAlignment = .left
            requestProductButton.frame = CGRect(x: 20, y: 280, width: 200, height: 30)
            requestProductButton.addTarget(self, action: #selector(requestProductInfo), for: .touchUpInside)
            view.addSubview(requestProductButton)
    
            // Purchase Button
            let purchaseButton = UIButton(type: .system)
            purchaseButton.setTitle("Purchase", for: .normal)
            purchaseButton.contentHorizontalAlignment = .left
            purchaseButton.frame = CGRect(x: 20, y: 320, width: 200, height: 30)
            purchaseButton.addTarget(self, action: #selector(purchaseProduct), for: .touchUpInside)
            view.addSubview(purchaseButton)
    
            // Restore Purchases Button
            let restorePurchasesButton = UIButton(type: .system)
            restorePurchasesButton.setTitle("Restore Purchases", for: .normal)
            restorePurchasesButton.contentHorizontalAlignment = .left
            restorePurchasesButton.frame = CGRect(x: 20, y: 350, width: 200, height: 30)
            restorePurchasesButton.addTarget(self, action: #selector(restorePurchases), for: .touchUpInside)
            view.addSubview(restorePurchasesButton)
        }

    @objc func requestProductInfo() {
        SubscriptionManager.shared.requestProductInfo1(myProductIentifier: "com.InAppSubscription.Demo.MonthlySubscription") { [weak self] product in
            if let product = product {
                self?.setValue("Product Information: \(product.localizedTitle), Price: \(product.price)")
            } else {
                self?.productInfoLabel.text = "Product Information not available."
            }
        }
    }

    @objc func purchaseProduct() {
        SubscriptionManager.shared.purchaseProduct()
    }

    @objc func restorePurchases() {
        SubscriptionManager.shared.restorePurchases()
    }
    
    @IBAction func showStatus(_ sender: Any) {
        SubscriptionManager.shared.restorePurchases()
    }
    
    func setValue(_ value : String) {
           DispatchQueue.main.async {
               self.productInfoLabel.text = value
           }
       }
    
    func transactionDidUpdate(state: SKPaymentTransactionState) {
          DispatchQueue.main.async {
              switch state {
              case .purchased:
                  self.transactionStatusLabel.text = "Transaction Status: Purchased"
              case .failed:
                  self.transactionStatusLabel.text = "Transaction Status: Failed"
              case .restored:
                  self.transactionStatusLabel.text = "Transaction Status: Restored"
              default:
                  print("Transaction state Empty")
                  break
              }
          }
      }
}
content_copyCOPY