Orders

I have an app similar to Uber. The problem I am having is that I want it so that when you click on the apple pay button and pay for the ride the order is saved on my orders view controller. Just let me know what code you need and I will provide it.

Accepted Reply

So, you can use a delegate.


Define a protocol:

- in Orders, before class declaration


protocol PayRequestDelegate {

    func sendRequest(items: [PKPaymentSummaryItem])
}


- in Orders, declare that the class conforms to protocol


class Orders: UIViewController, PayRequestDelegate  {
}


- in Orders, in the class, implement the protocol


    func sendRequest(items: [PKPaymentSummaryItem]) {
     
        // Display the elements you get in the appropriate labels or var
    }


- in Orders, in the prepare to go to priceView, set the delegate that you will declare in PriceView


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destination = segue.destination as? PriceView {
            destination.delegate = self
        }
    }


- in PriceView, declare a delegate

var delegate : PayRequestDelegate?


- in PriceView, when request is completed, use the delegate to send to Orders

            let tshirt = PKPaymentSummaryItem(label: "T-shirt", amount: NSDecimalNumber(decimal:1.00), type: .final)
            let shipping = PKPaymentSummaryItem(label: "Shipping", amount: NSDecimalNumber(decimal:1.00), type: .final)
            let tax = PKPaymentSummaryItem(label: "Tax", amount: NSDecimalNumber(decimal:1.00), type: .final)
            let total = PKPaymentSummaryItem(label: "Total", amount: NSDecimalNumber(decimal:3.00), type: .final)
            request.paymentSummaryItems = [tshirt, shipping, tax, total]
  
            delegate?.sendRequest(items: request.paymentSummaryItems])

Replies

Show how you create your payment request.


And describe exactly what is the problem:

- getting the information ?

- sending them to the view controller ?

- Is the pay button on the same view than orders view controller ? : I understand not, so the solution is likely to use delegation.

The pay button is not on the same view as the orders. Here is the code for my price view:


import UIKit
import Stripe

class RidePriceView: UIViewController, PKPaymentAuthorizationViewControllerDelegate{
    var price : Float?
    var category : RideType?
    var length: rideLength?
    var dateOfRide: Date?
    
    
    
    @IBOutlet weak var ridePriceTotalConstraint: NSLayoutConstraint!
    @IBOutlet weak var rideTypePrice: UILabel!
    @IBOutlet weak var rideLengthPrice: UILabel!
    @IBOutlet weak var ridePriceTotal: UILabel!
    @IBOutlet weak var rideDate: UILabel!
    @IBOutlet weak var currentDateLabel: UILabel!
    

    override func viewDidLoad() {
        print("viewDidLoad starts")
        if price != nil { ridePriceTotal.text = String(format: "$" + "%.2f", price!) }
        print("price is", ridePriceTotal.text!, price!)
        if category != nil {rideTypePrice.text = category!.description() }
        print("category is", rideeTypePrice.text!, category!.description())
        if length != nil { rideLengthPrice.text = length!.description() }
        print("length is", rideLengthPrice.text!, length!.description())
        if dateOfride != nil {
            let formatter = DateFormatter()
            formatter.dateFormat = "MM/dd/yyyy hh:mm a"
            massageDate.text = formatter.string(from: dateOfMassage!)
        }
        currentDateLabel.text = DateFormatter.localizedString(from: Date(), dateStyle: .long, timeStyle: .none)
        addApplePayPaymentButtonToView()
    }
    
    private func addApplePayPaymentButtonToView() {
        let paymentButton = PKPaymentButton(paymentButtonType: .buy, paymentButtonStyle: .black)
        paymentButton.translatesAutoresizingMaskIntoConstraints = false
        paymentButton.addTarget(self, action: #selector(applePayButtonTapped(sender:)), for: .touchUpInside)
        view.addSubview(paymentButton)
        
        view.addConstraint(NSLayoutConstraint(item: paymentButton, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1, constant: 0))
        view.addConstraint(NSLayoutConstraint(item: paymentButton, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: -25))
    }
    
    @objc private func applePayButtonTapped(sender: UIButton) {
        let paymentNetworks:[PKPaymentNetwork] = [.amex, .masterCard, .visa, .discover]
        
        if PKPaymentAuthorizationViewController.canMakePayments(usingNetworks: paymentNetworks) {
            let request = PKPaymentRequest()
            
            request.merchantIdentifier = "merchant.com.shiningdevelopers"
            request.countryCode = "CA"
            request.currencyCode = "CAD"
            request.supportedNetworks = paymentNetworks
            request.requiredShippingContactFields = [.name, .postalAddress]
            // This is based on using Stripe
            request.merchantCapabilities = .capability3DS
            
            let tshirt = PKPaymentSummaryItem(label: "T-shirt", amount: NSDecimalNumber(decimal:1.00), type: .final)
            let shipping = PKPaymentSummaryItem(label: "Shipping", amount: NSDecimalNumber(decimal:1.00), type: .final)
            let tax = PKPaymentSummaryItem(label: "Tax", amount: NSDecimalNumber(decimal:1.00), type: .final)
            let total = PKPaymentSummaryItem(label: "Total", amount: NSDecimalNumber(decimal:3.00), type: .final)
            request.paymentSummaryItems = [tshirt, shipping, tax, total]
            
            let authorizationViewController = PKPaymentAuthorizationViewController(paymentRequest: request)
            
            if let viewController = authorizationViewController {
                viewController.delegate = self
                
                present(viewController, animated: true, completion: nil)
            }
        }
    }
    
    func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) {
        // Let the Operating System know that the payment was accepted successfully
        completion(PKPaymentAuthorizationResult(status: .success, errors: nil))
    }
    
    func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) {
        // Dismiss the Apple Pay UI
        dismiss(animated: true, completion: nil)
    }
}



Is this the code you are looking for?

Yes, partly.


But,

what is the problem exactly:

- getting the information ?

- sending the information to the orders view controller ?


What information do you need to send ?

request.merchantIdentifier = "merchant.com.shiningdevelopers"

request.countryCode = "CA"

request.currencyCode = "CAD"

request.supportedNetworks = paymentNetworks

request.requiredShippingContactFields = [.name, .postalAddress]

request.paymentSummaryItems = [tshirt, shipping, tax, total]

I want to send the price and the items they ordered to my orders view controller. I already have the information in the price view controller.

So, you can use a delegate.


Define a protocol:

- in Orders, before class declaration


protocol PayRequestDelegate {

    func sendRequest(items: [PKPaymentSummaryItem])
}


- in Orders, declare that the class conforms to protocol


class Orders: UIViewController, PayRequestDelegate  {
}


- in Orders, in the class, implement the protocol


    func sendRequest(items: [PKPaymentSummaryItem]) {
     
        // Display the elements you get in the appropriate labels or var
    }


- in Orders, in the prepare to go to priceView, set the delegate that you will declare in PriceView


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destination = segue.destination as? PriceView {
            destination.delegate = self
        }
    }


- in PriceView, declare a delegate

var delegate : PayRequestDelegate?


- in PriceView, when request is completed, use the delegate to send to Orders

            let tshirt = PKPaymentSummaryItem(label: "T-shirt", amount: NSDecimalNumber(decimal:1.00), type: .final)
            let shipping = PKPaymentSummaryItem(label: "Shipping", amount: NSDecimalNumber(decimal:1.00), type: .final)
            let tax = PKPaymentSummaryItem(label: "Tax", amount: NSDecimalNumber(decimal:1.00), type: .final)
            let total = PKPaymentSummaryItem(label: "Total", amount: NSDecimalNumber(decimal:3.00), type: .final)
            request.paymentSummaryItems = [tshirt, shipping, tax, total]
  
            delegate?.sendRequest(items: request.paymentSummaryItems])

I am getting this message Use of undeclared type 'PKPaymentSummaryItem' when I define the protocol.

Did you import PassKit in the Orders file ?


Note: May be you need to import Stripe in Oders file, if that is the package you use.