Advertisement
lcolli98

Untitled

Jan 26th, 2020
370
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 12.18 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) {
  35.                 print(validProduct.localizedTitle)
  36.                 print(validProduct.localizedDescription)
  37.                 print(validProduct.price)
  38.                 buyProduct(product: validProduct)
  39.             } else {
  40.                 print(validProduct.productIdentifier)
  41.             }
  42.         } else {
  43.             print("nothing")
  44.         }
  45.     }
  46.    
  47.     func buyProduct(product: SKProduct) {
  48.         print("Sending the Payment Request to Apple")
  49.         let payment = SKPayment(product: product)
  50.         SKPaymentQueue.default().add(payment)
  51.     }
  52.  
  53.     func request(_ request: SKRequest, didFailWithError error: Error) {
  54.         print("Error Fetching product information")
  55.     }
  56.  
  57.     func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
  58.         print("Received Payment Transaction Response from Apple")
  59.  
  60.         for transaction:AnyObject in transactions {
  61.             if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction {
  62.                 switch trans.transactionState {
  63.                 case .purchased:
  64.                     print("Product Purchased")
  65.                     SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
  66.                     // Handle the purchase
  67.                     UserDefaults.standard.set(true , forKey: "purchased")
  68.                     // Get the receipt if it's available
  69.                     if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
  70.                         FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
  71.  
  72.                         do {
  73.                             let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
  74.                             print(receiptData)
  75.  
  76.                             let receiptString = receiptData.base64EncodedString(options: [])
  77.  
  78.                             // Read receiptData
  79.                             // Encode data as JSON
  80.                             let jsonData = try? JSONSerialization.data(withJSONObject: receiptString)
  81.  
  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": receiptData
  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)
  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.                         self.allCourses.append(course)
  204.                     }
  205.                     else {
  206.                         self.ownedCourses.append(course)
  207.                     }
  208.                 }
  209.                 self.workingDG.leave()
  210.                 return
  211.             }
  212.             catch {
  213.                 print(error.localizedDescription)
  214.                 print(error)
  215.                 return
  216.             }
  217.         }
  218.         task.resume()
  219.     }
  220.  
  221.    
  222.     // MARK: - UITableViewMethods
  223.     override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  224.         return self.displayCourses.count
  225.     }
  226.    
  227.    
  228.     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  229.         let cell = tableView.dequeueReusableCell(withIdentifier: "CourseCell", for: indexPath) as! CourseCell
  230.         cell.course = displayCourses[indexPath.row]
  231.         cell.delegate = self
  232.         return cell
  233.     }
  234.  
  235.  
  236.     // When the cell is pressed
  237.     override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  238.         // Determine which Course was selected
  239.         let selectedCourse = displayCourses[indexPath.row]
  240.         mycourse = selectedCourse
  241.        
  242.         // Load the subjects for this course
  243.         performSegue(withIdentifier: "courseToSubjectSegue", sender: self)
  244.     }
  245.    
  246.    
  247.     func cellButtonTapped(cell: CourseCell) {
  248.         // Trigger an alert to buy the course
  249.         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)
  250.  
  251.         // Add the course product identifier to the set
  252.         productsSet.insert(mycourse.product_identifier!)
  253.  
  254.         // Yes option
  255.         alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { action in
  256.            // IAP Code Here
  257.            if (SKPaymentQueue.canMakePayments())
  258.            {
  259.                //let productID:NSSet = NSSet(object: self.product_identifier!)
  260.                // let productID: NSSet = NSSet(object: self.productsSet)
  261.                // let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>)
  262.                let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: self.productsSet)
  263.                productsRequest.delegate = self
  264.                productsRequest.start()
  265.                print("Fetching Products")
  266.            } else {
  267.                print("Can't make purchases")
  268.            }
  269.         }))
  270.         // No option
  271.         alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: nil))
  272.  
  273.         self.present(alert, animated: true)
  274.         print("The course with product identifier ", mycourse.product_identifier!, " was selected!")
  275.     }
  276.    
  277.    
  278.     // MARK: - Segue Methods
  279.     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  280.         if segue.identifier == "courseToSubjectSegue" {
  281.             if let destinationVC = segue.destination as? SubjectsViewController {
  282.                 destinationVC.courseVar = mycourse
  283.             }
  284.         }
  285.     }
  286. }
  287.  
  288. extension Dictionary {
  289.     func percentEncoded() -> Data? {
  290.         return map { key, value in
  291.             let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
  292.             let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
  293.             return escapedKey + "=" + escapedValue
  294.         }
  295.         .joined(separator: "&")
  296.         .data(using: .utf8)
  297.     }
  298. }
  299. extension CharacterSet {
  300.     static let urlQueryValueAllowed: CharacterSet = {
  301.         let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
  302.         let subDelimitersToEncode = "!$&'()*+,;="
  303.  
  304.         var allowed = CharacterSet.urlQueryAllowed
  305.         allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
  306.         return allowed
  307.     }()
  308. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement