<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Shivam Maggu</title>
    <description>The latest articles on Forem by Shivam Maggu (@shivammaggu).</description>
    <link>https://forem.com/shivammaggu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1025585%2Ff43668de-3821-43b8-98a6-12f238e23d1d.jpg</url>
      <title>Forem: Shivam Maggu</title>
      <link>https://forem.com/shivammaggu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shivammaggu"/>
    <language>en</language>
    <item>
      <title>Working with UserDefaults in iOS</title>
      <dc:creator>Shivam Maggu</dc:creator>
      <pubDate>Fri, 22 Dec 2023 12:20:21 +0000</pubDate>
      <link>https://forem.com/shivammaggu/working-with-userdefaults-in-ios-46dg</link>
      <guid>https://forem.com/shivammaggu/working-with-userdefaults-in-ios-46dg</guid>
      <description>&lt;p&gt;UserDefaults provides a database to store data and it is available as long as the app is installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Features&lt;/li&gt;
&lt;li&gt;
Usage

&lt;ul&gt;
&lt;li&gt;Utilising the default shared instance of UserDefaults.&lt;/li&gt;
&lt;li&gt;Creating a UserDefaults that can be shared with multiple apps and extensions.&lt;/li&gt;
&lt;li&gt;Storing custom objects in UserDefaults.&lt;/li&gt;
&lt;li&gt;Using UserDefaults as a Property Wrapper&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The UserDefaults class provides access to the user's defaults database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It stores data persistently across the app launches as long as the app is installed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access to the data is private to the app unless shared through App Groups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access to this database is thread-safe.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is a key-value store that works through a property list (plist) file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supported data types include String, Bool, Date, Array, Dictionary, Data and Numbers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Custom objects can be stored by encoding them as data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can use this to store non-sensitive data such as user preferences.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Utilising the default shared instance of UserDefaults.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Foundation
// Set a key value in UserDefaults
UserDefaults.standard.set("Shivam", forKey: "firstname")
// Get a key value from User
DefaultsUserDefaults.standard.value(forKey: "firstname")
// Empty User
DefaultsUserDefaults.standard.removeObject(forKey: "firstname")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Creating a UserDefaults that can be shared with multiple apps and extensions.
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Foundation
// User Defaults with Suite.
// Useful for sharing data with other apps
// or extensions with app groups.
let defaults = UserDefaults(suiteName: "group.com.organisation.appname")!
// Set a key value in User Defaults
defaults.set("Shivam", forKey: "firstname")
// Get a key value from User Defaults
defaults.value(forKey: "firstname")
// Empty User Defaults
defaults.removeObject(forKey: "firstname")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Storing custom objects in UserDefaults.
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Foundation

// Custom model to be stored in UserDefaults
struct Student: Codable {
    let firstname: String
    let lastname: String
    let grade: Int
    let subjects: Array&amp;lt;String&amp;gt;
    let teachers: [String: String]
    let profileImage: Data
    let dateModified: Date
}

// Student Object
let student = Student(firstname: "John",
                      lastname: "Doe",
                      grade: 2,
                      subjects: ["Hindi", "English", "Maths"],
                      teachers: ["Hindi": "Teacher A", "English": "Teacher b", "Maths": "Teacher X"],
                      profileImage: Data(),
                      dateModified: Date())

// Encode custom object to data and store it in UserDefaults
let encoder = JSONEncoder()
do {
    let data = try encoder.encode(student)
    UserDefaults.standard.setValue(data, forKey: "StudentData")
} catch {
    throw error
}

// Retrieve data from UserDefaults and decode it to custom object
let decoder = JSONDecoder()
if let data = UserDefaults.standard.value(forKey: "StudentData") as? Data {
    do {
        let object = try decoder.decode(Student.self, from: data)
        print(object)
    } catch {
        throw error
    }
} else {
    print("No data in Defaults.")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Using UserDefaults as a Property Wrapper
&lt;/h3&gt;

&lt;p&gt;Check out this &lt;a href="https://gist.github.com/shivammaggu/451e06aafc8b25ba8ca9479a8f9ab175"&gt;gist to use UserDefaults with Property Wrapper&lt;/a&gt;. This is a more generalized way to use in Projects.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



</description>
      <category>userdefaults</category>
      <category>swift</category>
      <category>ios</category>
      <category>storage</category>
    </item>
    <item>
      <title>Offline Persistent Storage in iOS Applications</title>
      <dc:creator>Shivam Maggu</dc:creator>
      <pubDate>Thu, 21 Dec 2023 18:35:18 +0000</pubDate>
      <link>https://forem.com/shivammaggu/offline-persistent-storage-in-ios-applications-30gk</link>
      <guid>https://forem.com/shivammaggu/offline-persistent-storage-in-ios-applications-30gk</guid>
      <description>&lt;p&gt;In this article, we will discuss the various kinds of persistent storage options provided by Apple for iOS applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is offline storage?&lt;/li&gt;
&lt;li&gt;Why do we need it?&lt;/li&gt;
&lt;li&gt;When should we use it?&lt;/li&gt;
&lt;li&gt;How should we use it?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is offline storage?
&lt;/h2&gt;

&lt;p&gt;It is a kind of storage not on a network but on a physical device. In regards to an iOS application, it means that the data generated or displayed by an app is not stored on or retrieved from a network. Instead, it resides locally in the user's device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we need it?
&lt;/h2&gt;

&lt;p&gt;It makes the app more accessible to the users. They are not dependent on the internet to use the app's functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should we use it?
&lt;/h2&gt;

&lt;p&gt;Let's take examples of some popular apps that do not hinder user functionality when offline.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Chat apps such as Telegram and WhatsApp can store your messages when offline and deliver them when the connection is restored.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automation apps like Automate store users flow offline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Offline dictionaries store the words and their definitions on the device.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;E-book reading apps store the books offline so users can read anytime and anywhere.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mail apps like Gmail and Outlook queue your recently sent emails in Outbox and send them once online.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Contacts and SMS apps store phone numbers and text messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OTT apps provide download features to store your favourite TV Shows and Movies locally and watch offline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Todo lists, reminders, calendars, sketching and fitness tracker apps store data offline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;YouTube and Spotify can download our favourite songs to local storage.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We should use offline persistent storage when an app calls for such use cases. We can also use offline storage to cache data models fetched from the REST APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  How should we use it?
&lt;/h2&gt;

&lt;p&gt;If your app architecture calls for offline storage there are various ways to achieve this in iOS. Mentioned below are some examples provided directly by Apple.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;UserDefaults&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KeyChain&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Property List&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;FileManager&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URLCache&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Core Data&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll be adding a separate article discussing the features, implementation and use case for each storage technique.&lt;/p&gt;

</description>
      <category>storage</category>
      <category>swift</category>
      <category>coredata</category>
      <category>userdefaults</category>
    </item>
    <item>
      <title>Understanding SwiftUI - Why are Views in SwiftUI Struct and not Class?</title>
      <dc:creator>Shivam Maggu</dc:creator>
      <pubDate>Sun, 26 Feb 2023 00:52:46 +0000</pubDate>
      <link>https://forem.com/shivammaggu/understanding-swiftui-why-are-views-in-swiftui-struct-and-not-class-3528</link>
      <guid>https://forem.com/shivammaggu/understanding-swiftui-why-are-views-in-swiftui-struct-and-not-class-3528</guid>
      <description>&lt;p&gt;In this 2nd article on Understanding SwiftUI, let's discuss how views work in SwiftUI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Why SwiftUI prefers Struct over Class?&lt;/li&gt;
&lt;li&gt;SwiftUI Views versus UIKit Views&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why SwiftUI prefers Struct over Class?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SwiftUI Views are structs instead of classes. This avoids having multiple inherited properties, keeps them lightweight and improves performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SwiftUI Views are passed by value. This avoids retain cycles and reference counting, leading to fewer memory leaks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SwiftUI is based on the core principle of maintaining a &lt;strong&gt;Single Source of Truth.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View rendering depends on properties like the &lt;code&gt;@State&lt;/code&gt;, &lt;code&gt;@ObservableObject&lt;/code&gt; and so on. These are known as a Source of truth.&lt;/li&gt;
&lt;li&gt;When the value of these properties changes, the SwiftUI framework asks the view body to render the UI with the updated values.&lt;/li&gt;
&lt;li&gt;With UIKit, developers manage not only the state of the data but also the view changes based on that data. Whenever a view reads a piece of data, it creates a dependency between them. On data change, views should be updated to reflect the new value. When it fails to do so, then it becomes a bug. There can be multiple states in our app and multiple functions reacting to those state changes. If we do not maintain a source of truth for the current app state, UI bugs tend to creep in due to human error.&lt;/li&gt;
&lt;li&gt;SwiftUI tends to overcome this issue by making &lt;code&gt;body&lt;/code&gt; the only entry point. Despite the numerous states an app might find itself in, there is only one possible way to update the UI which is by rendering the view body. Views react to state changes by informing the framework. The framework then recomputes the derived values and generates the body with updated derived values.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  SwiftUI Views versus UIKit Views
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Serial No.&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;SwiftUI Views&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;UIKit Views&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1.&lt;/td&gt;
&lt;td&gt;Views alone are the fundamental building blocks.&lt;/td&gt;
&lt;td&gt;Views and Controllers work together to form the building blocks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.&lt;/td&gt;
&lt;td&gt;Views are data-driven.&lt;/td&gt;
&lt;td&gt;Views and Controllers are event-driven.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3.&lt;/td&gt;
&lt;td&gt;Views are a struct that conforms to the &lt;code&gt;View&lt;/code&gt; protocol.&lt;/td&gt;
&lt;td&gt;Views are a class that conforms to the &lt;code&gt;UIView&lt;/code&gt; class.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4.&lt;/td&gt;
&lt;td&gt;Views are passed by value.&lt;/td&gt;
&lt;td&gt;Views are passed by reference.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5.&lt;/td&gt;
&lt;td&gt;Views stacked one on top of another are allocated on a stack.&lt;/td&gt;
&lt;td&gt;Views are allocated their own designated space in memory.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6.&lt;/td&gt;
&lt;td&gt;Views do not inherit any stored properties.&lt;/td&gt;
&lt;td&gt;Views inherit stored properties from the parent class.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7.&lt;/td&gt;
&lt;td&gt;SwiftUI makes use of multiple single-purpose views.&lt;/td&gt;
&lt;td&gt;UIKit views are multipurpose and can be moulded as per our requirements.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.&lt;/td&gt;
&lt;td&gt;Views have only one entry point, the &lt;code&gt;body&lt;/code&gt;. View maintains a state (source of truth), computes derived values based on the state and updates the body.&lt;/td&gt;
&lt;td&gt;Views can have multiple entry points for updating their UI. If the happy path of the flow and possible edge cases (unhappy path) are not accounted for, it can lead to UI bugs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.&lt;/td&gt;
&lt;td&gt;Views are independent and isolated until they are bonded to other views by a single source of truth.&lt;/td&gt;
&lt;td&gt;View properties can be altered from anywhere within the code, making it difficult to maintain the state and leaving the code prone to UI bugs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.&lt;/td&gt;
&lt;td&gt;Views are lightweight as they only store properties that are declared in them. No additional allocation or reference counting is required.&lt;/td&gt;
&lt;td&gt;Views can become complex as they store not only the properties that we declare but also the properties of their parent. So, there is an additional allocation that we might not require. Reference counting is required as properties might hold a reference to other classes.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>swiftui</category>
      <category>class</category>
      <category>struct</category>
      <category>sourceoftruth</category>
    </item>
    <item>
      <title>Understanding SwiftUI - What is SwiftUI? 🧐</title>
      <dc:creator>Shivam Maggu</dc:creator>
      <pubDate>Mon, 20 Feb 2023 21:27:21 +0000</pubDate>
      <link>https://forem.com/shivammaggu/understanding-swiftui-what-is-swiftui-in9</link>
      <guid>https://forem.com/shivammaggu/understanding-swiftui-what-is-swiftui-in9</guid>
      <description>&lt;p&gt;In this concise and no-nonsense article, let's postulate what SwiftUI is and why it is all the hype within the iOS developer community.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Requirements&lt;/li&gt;
&lt;li&gt;The basics&lt;/li&gt;
&lt;li&gt;Pros&lt;/li&gt;
&lt;li&gt;Cons&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;minimum deployment target version is iOS 13&lt;/strong&gt; and above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SwiftUI development is supported by &lt;strong&gt;Xcode version 11&lt;/strong&gt; and above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The basics
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SwiftUI is a &lt;strong&gt;UI Design Framework&lt;/strong&gt; just like its predecessor, the UIKit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It uses the &lt;strong&gt;Declarative&lt;/strong&gt; programming approach as opposed to Imperative programming.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In simple words, we inform the framework of &lt;strong&gt;what&lt;/strong&gt; should be done based on a state change and it handles the rest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Whereas in the Imperative approach, we keep track of the state and instruct the framework on &lt;strong&gt;how&lt;/strong&gt; to change the UI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SwiftUI uses &lt;strong&gt;struct&lt;/strong&gt; to create views &lt;strong&gt;instead of class&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pros
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SwiftUI helps developers write &lt;strong&gt;simple, clean and less code&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It &lt;strong&gt;manages the state better&lt;/strong&gt; than the Imperative approach of UIKit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports &lt;strong&gt;cross-platform development for iOS/iPadOS, macOS, tvOS and watchOS&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It uses &lt;strong&gt;Live Previews&lt;/strong&gt; instead of building the project to view UI changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are &lt;strong&gt;no auto layout issues&lt;/strong&gt; as it always generates satisfiable layouts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;People working in teams &lt;strong&gt;no&lt;/strong&gt; longer have to suffer &lt;strong&gt;merge conflicts in storyboards&lt;/strong&gt;. 😜&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It can be used &lt;strong&gt;alongside UIKit using UIHostingController&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It supports &lt;strong&gt;reactive programming using ObjectBinding, BindableObject and the Combine Framework&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Users with iOS version 12 and below will not be able to use apps developed with SwiftUI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Team development might take more time as others might not be familiar with SwiftUI.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swiftui</category>
      <category>swift</category>
      <category>ios</category>
      <category>declarativeprogramming</category>
    </item>
    <item>
      <title>Processing payments using Stripe SDK iOS</title>
      <dc:creator>Shivam Maggu</dc:creator>
      <pubDate>Wed, 08 Feb 2023 22:10:33 +0000</pubDate>
      <link>https://forem.com/shivammaggu/processing-payments-using-stripe-sdk-ios-2978</link>
      <guid>https://forem.com/shivammaggu/processing-payments-using-stripe-sdk-ios-2978</guid>
      <description>&lt;p&gt;This guide explains how to install and set up Stripe SDK on your iOS application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Aim&lt;/li&gt;
&lt;li&gt;Minimum iOS Deployment Version&lt;/li&gt;
&lt;li&gt;Stripe Frameworks&lt;/li&gt;
&lt;li&gt;Requirements&lt;/li&gt;
&lt;li&gt;Proof of Concept&lt;/li&gt;
&lt;li&gt;
Setup

&lt;ul&gt;
&lt;li&gt;Adding the Stripe dependency&lt;/li&gt;
&lt;li&gt;Getting started with Stripe Developers Dashboard&lt;/li&gt;
&lt;li&gt;Setup Stripe in your iOS App&lt;/li&gt;
&lt;li&gt;Address collection&lt;/li&gt;
&lt;li&gt;Enable card scanning&lt;/li&gt;
&lt;li&gt;Process payments using Apple Pay&lt;/li&gt;
&lt;li&gt;Return to the app automatically after external authentication&lt;/li&gt;
&lt;li&gt;Clear cookies on logout&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;FAQ&lt;/li&gt;

&lt;li&gt;Resources&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Aim
&lt;/h2&gt;

&lt;p&gt;Open the inbuilt Address and Payment Sheet of Stripe and start accepting payments from your customer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimum iOS Deployment Version
&lt;/h2&gt;

&lt;p&gt;12.0&lt;/p&gt;

&lt;h2&gt;
  
  
  Stripe Frameworks
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Stripe (22.8.4)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;StripeApplePay (22.8.4)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;StripeCore (22.8.4)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;StripeUICore (22.8.4)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;MacBook / MacOS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CocoaPods installed on your system&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Xcode&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Terminal&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Proof of Concept
&lt;/h2&gt;

&lt;p&gt;iOS project and test backend for processing payments with Stripe SDK.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/shivammaggu" rel="noopener noreferrer"&gt;
        shivammaggu
      &lt;/a&gt; / &lt;a href="https://github.com/shivammaggu/payments-using-stripe" rel="noopener noreferrer"&gt;
        payments-using-stripe
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Start accepting payments from your customers through your iOS app using Stripe SDK
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;payments-using-stripe&lt;/h1&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Checkout this article for recreating or setting up this demo project&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://shivammaggu.hashnode.dev/processing-payments-using-stripe-sdk-ios" rel="nofollow noopener noreferrer"&gt;Hashnode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Simulator Screen Recording of the Project&lt;/h2&gt;

&lt;/div&gt;

  
    
    

    &lt;span class="m-1"&gt;Simulator.Screen.Recording.-.iPhone.14.Pro.-.2023-02-03.at.07.40.52.mp4&lt;/span&gt;
    
  

  

  


&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/shivammaggu/payments-using-stripe" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Adding the Stripe dependency
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Open &lt;strong&gt;Terminal&lt;/strong&gt; in the project directory and do &lt;code&gt;pod init&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the newly created &lt;code&gt;Podfile&lt;/code&gt; and set the iOS version to &lt;em&gt;12.0.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 # Uncomment the next line to define a global platform for your project
 platform :ios, '12.0'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add the &lt;strong&gt;Stripe&lt;/strong&gt; dependency to the &lt;code&gt;Podfile&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 target 'payments with stripe' do
   # Comment the next line if you don't want to use dynamic frameworks
   use_frameworks!

   # Pods for payments with stripe

   pod 'Stripe'

 end

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Save the &lt;code&gt;Podfile&lt;/code&gt; and do a &lt;code&gt;pod install&lt;/code&gt; on the &lt;strong&gt;Terminal&lt;/strong&gt;. The following dependencies showed be installed.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
pod install

Analyzing dependencies
Downloading dependencies
Installing Stripe (22.8.4)
Installing StripeApplePay (22.8.4)
Installing StripeCore (22.8.4)
Installing StripeUICore (22.8.4)
Generating Pods project
Integrating client project

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Close the &lt;code&gt;payments with stripe.xcodeproj&lt;/code&gt; and open &lt;code&gt;payments with stripe.xcworkspace&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select a simulator and run the project. The project should run successfully with a blank screen.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Getting started with Stripe Developers Dashboard
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;This process should be done once. All the teams will use the same Dashboard. (Backend, iOS, Android etc.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;a href="http://stripe.com" rel="noopener noreferrer"&gt;stripe.com&lt;/a&gt; and click on &lt;strong&gt;start now&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Follow the steps as directed by the website to complete the registration process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Complete the email verification and set up your business details for which payments will be accepted by Stripe.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On the &lt;a href="https://dashboard.stripe.com/apikeys" rel="noopener noreferrer"&gt;Stripe Dashboard&lt;/a&gt;, you should be able to see your Publishable key and Secret key for both test mode and live mode.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;em&gt;publishable key&lt;/em&gt; is used on the client side such as in iOS, android or web apps.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;secret key&lt;/em&gt; is used on the server side. &lt;strong&gt;(Secret key should not be stored on client-facing apps.)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setup Stripe in your iOS App
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;code&gt;AppDelegate.swift&lt;/code&gt; and add the &lt;strong&gt;Publishable key&lt;/strong&gt; inside the &lt;code&gt;didFinishLaunchingWithOptions&lt;/code&gt; method. The publishable key can be retrieved from the Stripe Developers Dashboard.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  StripeAPI.defaultPublishableKey = "Insert your key here"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Use the test mode keys during the testing and development phase, and the live mode keys when publishing the app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;We need to hit a POST API to create the payment intent and in return receive the following data. This data is used to initialize the &lt;code&gt;customer&lt;/code&gt;, Stripe SDK and the &lt;code&gt;PaymentSheet&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;customerId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ephemeralKey&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;paymentIntent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;publishableKey&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Refer to &lt;code&gt;CourseCheckoutViewModel&lt;/code&gt; in the Proof of Concept example on GitHub.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Creates a payment intent for the customer and fetches the important keys and id's for processing a payment

func fetchPaymentIntent(completion: @escaping ((Bool, String?) -&amp;gt; Void)) {

    // This could be the details for the item that the customer wants to buy

    let cartContent: [String: Any] = ["items": [["id": UUID().uuidString]]]

    self.apiClient.createPaymentIntent(cartContent: cartContent) { [weak self] (data, error) in

        guard let self = self else { return }

        guard error == nil else {
            print(error.debugDescription)
            completion(false, error.debugDescription)
            return
        }

        guard
            let customerId = data?.customerId as? String,
            let customerEphemeralKeySecret = data?.ephemeralKey as? String,
            let paymentIntentClientSecret = data?.paymentIntent as? String,
            let publishableKey = data?.publishableKey as? String
        else {
            let error = "Error fetching required data"
            print(error)
            completion(false, error)
            return
        }

        print("Created Payment Intent")

        self.setPublishableKey(publishableKey: publishableKey)
        self.paymentIntentClientSecret = paymentIntentClientSecret
        self.customer = .init(id: customerId,
                              ephemeralKeySecret: customerEphemeralKeySecret)
        completion(true, nil)
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Setup the &lt;code&gt;PaymentSheet&lt;/code&gt; in your View Controller. Refer to &lt;code&gt;CourseCheckoutViewController&lt;/code&gt; in the Proof of Concept example on GitHub.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// Create and configure the payment sheet

private func createPaymentSheet() {
    var configuration = PaymentSheet.Configuration()

    // Autofills the shipping details with the one we collected from user through AddressViewController

    configuration.shippingDetails = { [weak self] in
        return self?.address
    }

    // Configure button for Apple Pay in PaymentSheet

    configuration.applePay = .init(merchantId: "com.example.appname",
                                    merchantCountryCode: "US")

    // Provides checkbox for saving card details

    configuration.savePaymentMethodOptInBehavior = .requiresOptIn

    // Sets the return url. Used when user needs to go outside the app for authentication

    configuration.returnURL = "payments-with-stripe://stripe-redirect"

    // Configures the color of the pay button

    configuration.primaryButtonColor = .blue

    // Shows the name of the company collecting the payment

    configuration.merchantDisplayName = "Dummy Corp Inc"

    // Allows payments which requires some time to confirm

    configuration.allowsDelayedPaymentMethods = true

    // Adds default billing details for user to the payment object

    configuration.defaultBillingDetails.email = "dummy@corp.com"
    configuration.defaultBillingDetails.name = self.address?.name
    configuration.defaultBillingDetails.phone = self.address?.phone
    configuration.defaultBillingDetails.address.country = self.address?.address.country
    configuration.defaultBillingDetails.address.city = self.address?.address.city
    configuration.defaultBillingDetails.address.line1 = self.address?.address.line1
    configuration.defaultBillingDetails.address.line2 = self.address?.address.line2
    configuration.defaultBillingDetails.address.state = self.address?.address.state
    configuration.defaultBillingDetails.address.postalCode = self.address?.address.postalCode

    // Sets customer object to payment object

    if let customer = self.viewModel.getCustomer() {
        configuration.customer = customer
    }

    // Initiaises the PaymentSheet with the above config and client secret received from payment intent API

    if let paymentIntentClientSecret = self.viewModel.getPaymentIntentClientSecret() {
        self.paymentSheet = PaymentSheet(paymentIntentClientSecret: paymentIntentClientSecret,
                                        configuration: configuration)
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Handle the conditions after the payment. The following three scenarios can happen during/after the payment.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// Present user with the payment sheet and handles the various payment scenarios

private func presentPaymentSheet() {
    guard let paymentSheet = paymentSheet else { return }

    DispatchQueue.main.async {
        paymentSheet.present(from: self) { [weak self] (paymentResult) in

            guard let self = self else { return }

            switch paymentResult {
            case .completed:
                self.displayAlert(title: "Payment complete!")
            case .canceled:
                self.displayAlert(title: "Payment canceled!")
            case .failed(let error):
                self.displayAlert(title: "Payment failed", message: error.localizedDescription)
            }
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;On tap of the pay now button, present the payment sheet, add the payment details and click on pay.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Either the payment will be completed or it will fail if there are issues with the payment method. We can debug the failure reasons in the following &lt;a href="https://stripe.com/docs/error-codes" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Payment can also result in cancellation if the user dismisses the &lt;code&gt;PaymentSheet&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Address collection
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We can set up the &lt;code&gt;AddressViewController&lt;/code&gt; to display a form for collecting names, addresses, cities, countries, postal codes and phone numbers.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 // Setup and display the address sheet

 private func presentAddressCollectionController(_ controller: CourseCheckoutViewController) {
     let addressConfiguration = AddressViewController.Configuration(additionalFields: .init(name: .required,
                                                                                            phone: .required),
                                                                     allowedCountries: [],
                                                                     title: "Billing Address")
     let addressViewController = AddressViewController(configuration: addressConfiguration,
                                                       delegate: controller)

     let navigationController = UINavigationController(rootViewController: addressViewController)
     self.rootViewController.present(navigationController, animated: true)
 }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Set up the delegate method to get the address details filled in by the customer.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 extension CourseCheckoutViewController: AddressViewControllerDelegate {

     func addressViewControllerDidFinish(_ addressViewController: Stripe.AddressViewController, with address: Stripe.AddressViewController.AddressDetails?) {
         addressViewController.dismiss(animated: true) {
             debugPrint(address as Any)

             self.address = address
         }
     }
 }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The address details collected from the user should be passed to &lt;code&gt;PaymentSheet&lt;/code&gt; &lt;code&gt;Configuration&lt;/code&gt;. This will auto-fill the details in the &lt;code&gt;PaymentSheet&lt;/code&gt; and also send the customer details to Stripe Dashboard.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Collecting these details is essential if the Stripe account is registered in India but the users are paying in international currency. More on this &lt;a href="https://stripe.com/docs/india-accept-international-payments" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 var configuration = PaymentSheet.Configuration()

 configuration.shippingDetails = { [weak self] in
     return self?.address
 }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enable card scanning
&lt;/h3&gt;

&lt;p&gt;To enable the option for scanning debit/credit cards, add the following key to the &lt;code&gt;info.plist&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  &amp;lt;key&amp;gt;NSCameraUsageDescription&amp;lt;/key&amp;gt;
  &amp;lt;string&amp;gt;Allow the app to scan cards.&amp;lt;/string&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This feature is available on iOS 13.0 and above.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Process payments using Apple Pay
&lt;/h3&gt;

&lt;p&gt;Steps for integrating Apple Pay are well documented in the links below.&lt;/p&gt;

&lt;p&gt;Please check out this tutorial for adding Apple Pay as a payment option to your app.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/payments/accept-a-payment?platform=ios&amp;amp;ui=payment-sheet#ios-apple-pay" rel="noopener noreferrer"&gt;Apple Pay with Payment Sheet&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/apple-pay" rel="noopener noreferrer"&gt;Setup Apple Pay button&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Add an Apple pay button on your &lt;code&gt;PaymentSheet&lt;/code&gt; by editing the configuration as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var configuration = PaymentSheet.Configuration()
configuration.applePay = .init(merchantId: "merchant.com.your_app_name",
                               merchantCountryCode: "US")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Return to the app automatically after external authentication
&lt;/h3&gt;

&lt;p&gt;A customer may go out of your app for authentication purposes, for example, in Safari or their banking app to complete payment.&lt;/p&gt;

&lt;p&gt;To allow them to automatically return to your app after authenticating, &lt;a href="https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app" rel="noopener noreferrer"&gt;configure a custom URL scheme&lt;/a&gt; or &lt;a href="https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content" rel="noopener noreferrer"&gt;universal link&lt;/a&gt; and set up your app delegate/scene delegate&lt;/p&gt;

&lt;p&gt;(If using scene delegate for iOS 13 and above) to forward the URL to the SDK.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AppDelegate.swift&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  // This method handles opening custom URL schemes
  // (for example, "your-app://stripe-redirect")

  func application(_ app: UIApplication,
                    open url: URL, 
                    options: [UIApplication.OpenURLOptionsKey : Any] = [:]
  ) -&amp;gt; Bool {

      let stripeHandled = StripeAPI.handleURLCallback(with: url)

      if !stripeHandled {

          /*
            This was not a stripe url, do whatever url handling your app
            normally does, if any.
            */
      }

      return true
  }

  // This method handles opening universal link URLs
  // (for example, "https://example.com/stripe_ios_callback")

  func application(_ application: UIApplication,
                    continue userActivity: NSUserActivity,
                    restorationHandler: @escaping ([UIUserActivityRestoring]?) -&amp;gt; Void
  ) -&amp;gt; Bool  {

      if userActivity.activityType == NSUserActivityTypeBrowsingWeb {

          if let url = userActivity.webpageURL {

              let stripeHandled = StripeAPI.handleURLCallback(with: url)

              guard !stripeHandled else { return true }

              /*
                This was not a stripe url, do whatever url handling your app
                normally does, if any.
                */
          }
      }

      return false
  }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SceneDelegate.swift&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  func scene(_ scene: UIScene,
              openURLContexts URLContexts: Set&amp;lt;UIOpenURLContext&amp;gt;) {

      if let urlContext = URLContexts.first {

          let url = urlContext.url
          let stripeHandled = StripeAPI.handleURLCallback(with: url)

          if !stripeHandled {
              // This was not a stripe url, do whatever url handling your app
              // normally does, if any.
          }
      }
  }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, a &lt;code&gt;returnURL&lt;/code&gt; should be configured in the &lt;code&gt;PaymentSheet.Configuration&lt;/code&gt; object to the URL for your app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var configuration = PaymentSheet.Configuration()
configuration.returnURL = "payments-with-stripe://stripe-redirect"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Clear cookies on logout
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;PaymentSheet&lt;/code&gt; related cookies and other authentication data should be cleared when a user logs out of the app. Add the following code to your logout function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import Stripe

// Resets all payment and user related cache
// Should be called when user logs out of the app

func logout() {

    /*
      Perform all other logout related steps here
      */

    PaymentSheet.resetCustomer()
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Stripe SDK can be installed using CocoaPods, Carthage, and Swift Package Manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The latest version &lt;a href="https://github.com/stripe/stripe-ios/tree/23.3.2" rel="noopener noreferrer"&gt;v23.3.2&lt;/a&gt; or above of Stripe iOS SDK requires Xcode 13.2.1 or later and is compatible with apps targeting iOS 13 or above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For iOS 12 support use &lt;a href="https://github.com/stripe/stripe-ios/tree/22.8.4" rel="noopener noreferrer"&gt;v22.8.4&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For iOS 11 support use &lt;a href="https://github.com/stripe/stripe-ios/tree/21.13.0" rel="noopener noreferrer"&gt;v21.13.0&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For iOS 10 support use &lt;a href="https://github.com/stripe/stripe-ios/tree/v19.4.0" rel="noopener noreferrer"&gt;v19.4.0&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For iOS 9 support use &lt;a href="https://github.com/stripe/stripe-ios/tree/v17.0.2" rel="noopener noreferrer"&gt;v17.0.2&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why was my card declined when trying to make a payment? Check the reason for your &lt;a href="https://stripe.com/docs/declines/codes" rel="noopener noreferrer"&gt;decline code&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Got an error message while processing your payment? Check the reason in this &lt;a href="https://stripe.com/docs/error-codes" rel="noopener noreferrer"&gt;article&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://cocoapods.org/pods/Stripe" rel="noopener noreferrer"&gt;Stripe SDK on CocoaPods&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/stripe/stripe-ios" rel="noopener noreferrer"&gt;Stripe SDK on GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/api" rel="noopener noreferrer"&gt;Stripe API Reference&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs" rel="noopener noreferrer"&gt;Stripe Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.dev/stripe-ios/documentation/stripe/" rel="noopener noreferrer"&gt;Stripe iOS SDK Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/libraries/ios" rel="noopener noreferrer"&gt;Installing Stripe SDK using CocoaPods&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/keys#obtain-api-keys" rel="noopener noreferrer"&gt;About API Keys&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/keys#test-live-modes" rel="noopener noreferrer"&gt;Test mode and Live mode&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/payments/accept-a-payment" rel="noopener noreferrer"&gt;Accepting Payments with Stripe&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/elements/address-element/collect-addresses" rel="noopener noreferrer"&gt;Collecting User's Address&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/testing" rel="noopener noreferrer"&gt;Dummy Credentials for testing payments&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/india-accept-international-payments" rel="noopener noreferrer"&gt;Accept payment from regions outside of India&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/payments/payment-methods/integration-options#payment-method-product-support" rel="noopener noreferrer"&gt;Adding multiple payment methods&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/declines/codes" rel="noopener noreferrer"&gt;Debug card Decline Codes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/error-codes" rel="noopener noreferrer"&gt;Understanding payment Error Codes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stripe.com/docs/payments/checkout/phone-numbers" rel="noopener noreferrer"&gt;Collecting user phone numbers through the backend&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Adding additional articles on security when processing payments using Stripe:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://stripe.com/docs/strong-customer-authentication" rel="noopener noreferrer"&gt;Strong Customer Authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stripe.com/docs/strong-customer-authentication" rel="noopener noreferrer"&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stripe.com/docs/strong-customer-authentication" rel="noopener noreferrer"&gt;3-D Secure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stripe.com/docs/strong-customer-authentication" rel="noopener noreferrer"&gt;Privacy Details for iOS&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>stripe</category>
      <category>swift</category>
      <category>ios</category>
      <category>paymentgateway</category>
    </item>
  </channel>
</rss>
