--- title: "Pay Monthly at Checkout" slug: "pay-monthly-at-checkout-ios" updated: 2026-05-22T16:13:19Z published: 2026-05-22T16:13:19Z canonical: "developer.upgrade.com/pay-monthly-at-checkout-ios" --- > ## Documentation Index > Fetch the complete documentation index at: https://developer.upgrade.com/llms.txt > Use this file to discover all available pages before exploring further. # Pay Monthly at Checkout ### Create ULOrderManager All checkout activities go through `ULOrderManager` and it's delegate. Generally, this object should be created and managed by your `UIViewController`, but it can be done at any place that makes sense for your app. The only requirements are: 1. It cannot be created before `UpliftSDK` has completed being configured. 2. It cannot be destroyed while in use. ``` let orderManager = ULOrderManager() orderManager.delegate = self ``` ### Requesting an offer from Flex Pay To request an offer at checkout, call `setTripInfoForCheckout` with an **up-to-date** `ULPMTripInfo`. Every time the trip itinerary has changed/updated, simply call the same method with the new `ULPMTripInfo` to update the offer displayed. This method also accepts an optional parameter of a `ULPMPrice`. This is the `ULPMPrice` that corresponds to the `ULPMTripInfo` provided as the first parameter. If provided, the response passed to the delegate will include a specific payment amount. If omitted, it will still indicate if an offer is available, but will have a papyment amount of 0. The `ULOrderManager` maintains the current order. If there is need to reset and remove the existing order, call the same method with the `ULPMTripInfo` as well as a `renewOrderId` flag set to true. This will refresh the order id and restart the Pay Monthly application. For all other cases, this flag should be set to false. ``` let trip: ULPMTripInfo = your_trip_info if let error = orderManager.setTripInfoForCheckout(tripInfo, renewOrderId: false) { print("Error at setting tripInfo: \(error)") } ``` Just because a call to `setTripInfoForCheckout` did not return an error does not mean it is completely successful. It may take up to 10 seconds to get an offer or fail. Corresponding delegate methods will be called if an error occurs during this process or if an offer is available. Once the delegate receives a callback on `checkout(_ checkoutViewController: UIViewController, didReceiveOfferStatus hasOffer: Bool, payMonthlyAmount: UInt?)`, check the `hasOffer` flag to see if an offer is available. If it is true, `payMonthlyAmount` will be set. This callback will be called every time either `hasOffer` changes or the `payMonthlyAmount` changes. However, no delegate callback is guaranteed to be triggered. If `hasOffer` it is true when the last delegate callback has been received, it is safe to present the checkout flow. If it is not true, the trip does not qualify and Flex Pay's checkout flow should not be presented. Please contact your Flex Pay representative to discuss why a trip might not qualify. ### Presenting the Checkout Flow There are two ways to present the checkout flow. #### Container UIView Presenting the checkout flow in a container `UIView`. ``` let containerView: UIView = container_UIView do { let vc = try orderManager.presentCheckout( in: containerView, parentViewController: self) // Success! } catch { print("Error occurred presenting checkout: \(error)") } ``` #### Manually Presenting the checkout flow manually. In this case, it is up to the client on how to present the `UIViewController` for the checkout flow. ``` do { let vc = try orderManager.createCheckoutViewController() // Success! Present the received view controller } catch { print("Error occurred creating checkout view controller: \(error)") } ``` ### Configuration of the Checkout flow There are options to customize the checkout flow to improve the user-experience. These options can be found in the `ULCheckoutConfiguration` class. To set a configuration, set up the API's `ULConfiguration` with a `ULCheckoutConfiguration` object.