Advertisement
lcolli98

Untitled

Jan 26th, 2020
359
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 12.34 KB | None | 0 0
  1. //
  2. //  AllCoursesViewController.swift
  3. //  AeroBuddy
  4. //
  5. //  Created by Luke Collister on 01/09/2019.
  6. //  Copyright © 2019 Luke Collister. All rights reserved.
  7. //
  8.  
  9. import UIKit
  10. import StoreKit
  11.  
  12. class AllCoursesViewController: UITableViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver, CourseCellDelegate {
  13.  
  14.     // MARK: - Variable Declarations
  15.     var tempData = [Course]()
  16.  
  17.     var allCourses = [Course]()
  18.     var ownedCourses = [Course]()
  19.     var displayCourses = [Course]()
  20.     var mycourse: Course!
  21.    
  22.     let workingDG = DispatchGroup()
  23.    
  24.     var productsSet = Set<String>()
  25.  
  26.    
  27.     // MARK: - IAP Methods
  28.     var product_identifier: String?
  29.    
  30.     func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
  31.         let count: Int = response.products.count
  32.         if (count > 0) {
  33.             let validProduct: SKProduct = response.products[0] as SKProduct
  34.             if (/*validProduct.productIdentifier == self.product_identifier*/true) {
  35.                 print(validProduct.localizedTitle)
  36.                 print(validProduct.localizedDescription)
  37.                 print(validProduct.price)
  38.                 buyProduct(product: validProduct)
  39.             } else {
  40.                 print(validProduct.productIdentifier)
  41.                 print("Error 1")
  42.             }
  43.         } else {
  44.             print("nothing")
  45.         }
  46.     }
  47.    
  48.     func buyProduct(product: SKProduct) {
  49.         print("Sending the Payment Request to Apple")
  50.         let payment = SKPayment(product: product)
  51.         SKPaymentQueue.default().add(payment)
  52.     }
  53.  
  54.     func request(_ request: SKRequest, didFailWithError error: Error) {
  55.         print("Error Fetching product information")
  56.     }
  57.  
  58.     func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
  59.         print("Received Payment Transaction Response from Apple")
  60.        
  61.         print("Transactions: ", transactions)
  62.  
  63.         for transaction: AnyObject in transactions {
  64.             if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction {
  65.                 switch trans.transactionState {
  66.                 case .purchased:
  67.                     print("Product Purchased")
  68.                     SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
  69.                     // Handle the purchase
  70.                     UserDefaults.standard.set(true , forKey: "purchased")
  71.                     // Get the receipt if it's available
  72.                     if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL, FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
  73.  
  74.                         do {
  75.                             let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
  76.                             print("RECEIPT DATA: ", receiptData)
  77.  
  78.                             let receiptString = receiptData.base64EncodedString(options: [])
  79.                             print("RECEIPT STRING: ", receiptString)
  80.  
  81.                             // Read receiptData
  82.                             // Create POST request
  83.                             let url = URL(string: "http://fe01.kilosierracharlie.me/verifypayment")!
  84.                             var request = URLRequest(url: url)
  85.                             request.httpMethod = "POST"
  86.                             request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
  87.                             let parameters: [String: Any] = [
  88.                                 "receipt": receiptString
  89.                             ]
  90.                             request.httpBody = parameters.percentEncoded()
  91.  
  92.                             // Send the data
  93.                             URLSession.shared.dataTask(with: request) { data, response, error in
  94.                                 guard let data = data, error == nil else {
  95.                                     print(error?.localizedDescription ?? "No data")
  96.                                     print("No data could be sent to the server. Please contact us.")
  97.                                     return
  98.                                 }
  99.                                 /*let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
  100.                                 if let responseJSON = responseJSON as? [String: Any] {
  101.                                     print(responseJSON)
  102.                                 }
  103.                                 */
  104.                                 print("DATA: ", data)
  105.                             }
  106.                         }
  107.                         catch {
  108.                             print("Couldn't read receipt data with error: " + error.localizedDescription)
  109.                         }
  110.                     }
  111.                     break;
  112.                    
  113.                 case .failed:
  114.                     print("Purchased Failed")
  115.                     SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
  116.                     break;
  117.  
  118.                 case .restored:
  119.                     print("Already Purchased")
  120.                     SKPaymentQueue.default().restoreCompletedTransactions()
  121.  
  122.                     // Handle the purchase
  123.                     UserDefaults.standard.set(true , forKey: "purchased")
  124.                     //adView.hidden = true
  125.                     break;
  126.                 default:
  127.                     break;
  128.                 }
  129.             }
  130.         }
  131.     }
  132.    
  133.    
  134.    
  135.     // MARK: - Default Methods
  136.     override func viewDidLoad() {
  137.         super.viewDidLoad()
  138.        
  139.         // Set Activity Indicator and show
  140.         let activityIndicator = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.large)
  141.         activityIndicator.color = UIColor.red
  142.         activityIndicator.center = view.center
  143.         activityIndicator.hidesWhenStopped = true
  144.         activityIndicator.startAnimating()
  145.         view.addSubview(activityIndicator)
  146.        
  147.         // Provide an empty backBarButton to hide the 'Back' text present by default in the back button.
  148.         self.navigationItem.setHidesBackButton(true, animated:true)
  149.        
  150.         // IAP Code
  151.         product_identifier = "ppl.a.full.collection"
  152.         SKPaymentQueue.default().add(self)
  153.            
  154.         // Display the content
  155.         DispatchQueue.global(qos: .background).async {
  156.             self.workingDG.enter()
  157.             self.getAllCourses(endpoint: "courses")
  158.             self.workingDG.enter()
  159.             self.getAllCourses(endpoint: "courses/my")
  160.            
  161.             self.workingDG.notify(queue: .main) {
  162.                 for i in 0 ..< self.ownedCourses.count {
  163.                     self.ownedCourses[i].owned = true
  164.                 }
  165.  
  166.                 var idArray = [Int]()
  167.                 for course in self.ownedCourses {
  168.                     idArray.append(course.id)
  169.                 }
  170.                 for course in self.allCourses {
  171.                     course.owned = idArray.contains(course.id)
  172.                     self.displayCourses.append(course)
  173.                 }
  174.                 self.tableView.reloadData()
  175.  
  176.                 // Stop the activity indicator
  177.                 DispatchQueue.main.async {
  178.                     activityIndicator.stopAnimating()
  179.                 }
  180.             }
  181.         }
  182.     }
  183.  
  184.    
  185.     // MARK: - JSON Methods
  186.     func getAllCourses(endpoint: String) {
  187.         let url = URL(string: "\(ServHandler.connectProtocol)://\(ServHandler.baseURL)/\(endpoint)")
  188.         let task = URLSession.shared.dataTask(with: url!) {(data, response, error) in
  189.             guard error == nil else {
  190.                 print("Error!")
  191.                 return
  192.             }
  193.             guard let content = data else {
  194.                 print("There is no data!")
  195.                 return
  196.             }
  197.  
  198.             let decoder = JSONDecoder()
  199.             do {
  200.                 for course in try decoder.decode([Course].self, from: content) {
  201.                     if (endpoint == "courses") {
  202.                         //course.product_identifier = "com.aerobuddy.course.\(course.id)"
  203.                         course.product_identifier = "com.aerobuddy.course.6"
  204.                         self.allCourses.append(course)
  205.                     }
  206.                     else {
  207.                         self.ownedCourses.append(course)
  208.                     }
  209.                 }
  210.                 self.workingDG.leave()
  211.                 return
  212.             }
  213.             catch {
  214.                 print(error.localizedDescription)
  215.                 print(error)
  216.                 return
  217.             }
  218.         }
  219.         task.resume()
  220.     }
  221.  
  222.    
  223.     // MARK: - UITableViewMethods
  224.     override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  225.         return self.displayCourses.count
  226.     }
  227.    
  228.    
  229.     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  230.         let cell = tableView.dequeueReusableCell(withIdentifier: "CourseCell", for: indexPath) as! CourseCell
  231.         cell.course = displayCourses[indexPath.row]
  232.         cell.delegate = self
  233.         return cell
  234.     }
  235.  
  236.  
  237.     // When the cell is pressed
  238.     override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  239.         // Determine which Course was selected
  240.         let selectedCourse = displayCourses[indexPath.row]
  241.         mycourse = selectedCourse
  242.         print("Selected course: ", displayCourses[indexPath.row])
  243.        
  244.         // Load the subjects for this course
  245.         performSegue(withIdentifier: "courseToSubjectSegue", sender: self)
  246.     }
  247.    
  248.    
  249.     func cellButtonTapped(cell: CourseCell) {
  250.         // Trigger an alert to buy the course
  251.         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)
  252.  
  253.         // Add the course product identifier to the set
  254.         productsSet.insert(mycourse.product_identifier!)
  255.  
  256.         // Yes option
  257.         alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { action in
  258.            // IAP Code Here
  259.            if (SKPaymentQueue.canMakePayments())
  260.            {
  261.                //let productID:NSSet = NSSet(object: self.product_identifier!)
  262.                // let productID: NSSet = NSSet(object: self.productsSet)
  263.                // let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>)
  264.                let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: self.productsSet)
  265.                productsRequest.delegate = self
  266.                productsRequest.start()
  267.                print("Fetching Products")
  268.            } else {
  269.                print("Can't make purchases")
  270.            }
  271.         }))
  272.         // No option
  273.         alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: nil))
  274.  
  275.         self.present(alert, animated: true)
  276.         print("The course with product identifier ", mycourse.product_identifier!, " was selected!")
  277.     }
  278.    
  279.    
  280.     // MARK: - Segue Methods
  281.     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  282.         if segue.identifier == "courseToSubjectSegue" {
  283.             if let destinationVC = segue.destination as? SubjectsViewController {
  284.                 destinationVC.courseVar = mycourse
  285.             }
  286.         }
  287.     }
  288. }
  289.  
  290. extension Dictionary {
  291.     func percentEncoded() -> Data? {
  292.         return map { key, value in
  293.             let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
  294.             let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
  295.             return escapedKey + "=" + escapedValue
  296.         }
  297.         .joined(separator: "&")
  298.         .data(using: .utf8)
  299.     }
  300. }
  301. extension CharacterSet {
  302.     static let urlQueryValueAllowed: CharacterSet = {
  303.         let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
  304.         let subDelimitersToEncode = "!$&'()*+,;="
  305.  
  306.         var allowed = CharacterSet.urlQueryAllowed
  307.         allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
  308.         return allowed
  309.     }()
  310. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement