Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // AllCoursesViewController.swift
- // AeroBuddy
- //
- // Created by Luke Collister on 01/09/2019.
- // Copyright © 2019 Luke Collister. All rights reserved.
- //
- import UIKit
- import StoreKit
- class AllCoursesViewController: UITableViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver, CourseCellDelegate {
- // MARK: - Variable Declarations
- var tempData = [Course]()
- var allCourses = [Course]()
- var ownedCourses = [Course]()
- var displayCourses = [Course]()
- var products = [String: SKProduct]()
- var mycourse: Course!
- var hasFinishedLoading = true
- let workingDG = DispatchGroup()
- var productsSet = Set<String>()
- // MARK: - IAP Methods
- var product_identifier: String?
- func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
- for validProduct in response.products{
- products[validProduct.productIdentifier] = validProduct
- for course in displayCourses {
- if( course.product_identifier! == validProduct.productIdentifier ){
- course.price = validProduct.regularPrice
- }
- }
- }
- DispatchQueue.main.async {
- self.tableView.reloadData()
- }
- }
- func buyProduct(product: SKProduct) {
- let payment = SKPayment(product: product)
- SKPaymentQueue.default().add(payment)
- }
- func request(_ request: SKRequest, didFailWithError error: Error) {
- print("Error Fetching product information")
- }
- func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
- for transaction: AnyObject in transactions {
- if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction {
- switch trans.transactionState {
- case .purchased:
- SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
- // Handle the purchase
- UserDefaults.standard.set(true , forKey: "purchased")
- // Get the receipt if it's available
- if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL, FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
- do {
- let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
- let receiptString = receiptData.base64EncodedString(options: [])
- // Read receiptData
- // Create POST request
- let url = URL(string: "http://fe01.kilosierracharlie.me/verifypayment")!
- var request = URLRequest(url: url)
- request.httpMethod = "POST"
- request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
- let parameters: [String: Any] = [
- "receipt": receiptString
- ]
- request.httpBody = parameters.percentEncoded()
- // Send the data
- let task = URLSession.shared.dataTask(with: request) { data, response, error in
- guard let data = data, error == nil else {
- print(error?.localizedDescription ?? "No data")
- print("No data could be sent to the server. Please contact us.")
- return
- }
- let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
- if (responseJSON as? [String: Any]) != nil {
- //TO DO: Refresh if error false, else throw error
- }
- }
- task.resume()
- }
- catch {
- print("Couldn't read receipt data with error: " + error.localizedDescription)
- }
- }
- break;
- case .failed:
- print("Purchased Failed")
- SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
- print( transaction.error.debugDescription )
- break;
- case .restored:
- SKPaymentQueue.default().restoreCompletedTransactions()
- // Handle the purchase
- UserDefaults.standard.set(true , forKey: "purchased")
- //adView.hidden = true
- break;
- default:
- break;
- }
- }
- }
- }
- @objc func userActReload(){
- if( hasFinishedLoading ){
- hasFinishedLoading = false
- displayCourses.removeAll()
- ownedCourses.removeAll()
- allCourses.removeAll()
- self.tableView.reloadData()
- let activityIndicator = MyIndicator(frame: CGRect(x: UIScreen.main.bounds.size.width/2 - 75, y: UIScreen.main.bounds.size.height/2 - 150, width: 150, height: 150), image: UIImage(named: "LOADING.png")!)
- view.addSubview(activityIndicator)
- activityIndicator.startAnimating()
- DispatchQueue.global(qos: .background).async {
- APIHandler.load( endpoint: .AllCourses, completion: {( data ) in
- for e in data {
- let tc : Course = e as! Course
- self.productsSet.insert( tc.product_identifier! )
- forOwned:
- for sub in tc.subjects! {
- if (sub.owned ?? false) {
- tc.partOwned = true
- break
- }
- for top in sub.topics! {
- if (top.owned ?? false) {
- tc.partOwned = true
- break forOwned
- }
- }
- }
- self.displayCourses.append( tc )
- }
- APIHandler.load( endpoint: .OwnedCourses, completion: {( data ) in
- for e in data {
- let tc : Course = e as! Course
- for o in self.displayCourses {
- if o.id == tc.id {
- o.owned = true
- }
- }
- }
- let productsRequest: SKProductsRequest = SKProductsRequest(productIdentifiers: self.productsSet)
- productsRequest.delegate = self
- productsRequest.start()
- DispatchQueue.main.async {
- self.tableView.reloadData()
- activityIndicator.stopAnimating()
- self.hasFinishedLoading = true
- }
- })
- })
- }
- }
- }
- // MARK: - Default Methods
- override func viewDidLoad() {
- super.viewDidLoad()
- // Provide an empty backBarButton to hide the 'Back' text present by default in the back button.
- self.navigationItem.setHidesBackButton(true, animated:true)
- // Add a right navigation bar button to allow refreshing of JSON
- navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "arrow.clockwise"), style: .plain, target: self, action: #selector( userActReload ) )
- // IAP Code
- SKPaymentQueue.default().add(self)
- userActReload()
- }
- // MARK: - UITableViewMethods
- override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- return self.displayCourses.count
- }
- override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- let cell = tableView.dequeueReusableCell(withIdentifier: "CourseCell", for: indexPath) as! CourseCell
- cell.course = displayCourses[indexPath.row]
- if (cell.course?.owned == false) {
- cell.backgroundColor = UIColor(red: 90/255, green: 90/255, blue: 90/255, alpha: 1)
- } else {
- //cell.backgroundColor = default
- }
- cell.delegate = self
- return cell
- }
- // When the cell is pressed
- override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- // Determine which Course was selected
- let selectedCourse = displayCourses[indexPath.row]
- mycourse = selectedCourse
- // Load the subjects for this course
- performSegue(withIdentifier: "courseToSubjectSegue", sender: self)
- }
- func cellButtonTapped(cell: CourseCell) {
- // Trigger an alert to buy the course
- let alert = UIAlertController(title: "Purchase Course?", message: "You do not own this course. Do you wish to purchase it? Pressing \"Yes\" will purchase *all* subjects and topics within the course.", preferredStyle: .alert)
- // Add the course product identifier to the set
- let buttonPosition: CGPoint = cell.convert(CGPoint.zero, to: self.tableView)
- let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
- // Yes option
- alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { action in
- // IAP Code Here
- if (SKPaymentQueue.canMakePayments()) {
- self.buyProduct(product: self.products[ self.displayCourses[indexPath!.row].product_identifier! ]! )
- } else {
- print("Can't make purchases")
- }
- }))
- // No option
- alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: { action in
- self.productsSet.removeAll()
- }))
- self.present(alert, animated: true)
- }
- // MARK: - Segue Methods
- override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
- if segue.identifier == "courseToSubjectSegue" {
- if let destinationVC = segue.destination as? SubjectsViewController {
- destinationVC.courseVar = mycourse
- }
- }
- }
- }
- // MARK: - Extensions
- extension Dictionary {
- func percentEncoded() -> Data? {
- return map { key, value in
- let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
- let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
- return escapedKey + "=" + escapedValue
- }
- .joined(separator: "&")
- .data(using: .utf8)
- }
- }
- extension CharacterSet {
- static let urlQueryValueAllowed: CharacterSet = {
- let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
- let subDelimitersToEncode = "!$&'()*+,;="
- var allowed = CharacterSet.urlQueryAllowed
- allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
- return allowed
- }()
- }
- extension SKProduct {
- /// - returns: The cost of the product formatted in the local currency.
- var regularPrice: String? {
- let formatter = NumberFormatter()
- formatter.numberStyle = .currency
- formatter.locale = self.priceLocale
- return formatter.string(from: self.price)
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement