Accepting credit cards in iOS with Stripe
Far from setting up payment gateways, Stripe integration is a solution that helps developers enable payment through their web or mobile apps with a set of friendly easy-to-use APIs. Stripe provides a fairly good documentation that enables developers to get started. It provides React ui components and prebuilt native ui elements, notifications management, refunds and declines management and much more .
We are adding this tutorial to our iOS ones, in which we will see a simple integration of Stripe for iOS, how to use the prebuilt ui elements, how to accept a valid credit card and how to perform a payment operation. Below is an illustration of what we’ll do by end of this tutorial :
Setting up Stripe and the sample code
In order to save your time and focus to Stripe controllers and method calls, I provided the source code for the sample app here. Start by cloning it, setting up a Stripe account and getting a test API key to run the demo, then we’ll go through the code together .
Go to stripe.com and create your account . Then go to Developers API –> Keys to get your test API keys .
You will be requested to verify your account first, then you’ll be able to see a test secret and test publishable API keys for your account which you will use later in the app .
⚠ For this tutorial and any testing purpose you will be using the test API keys and never the live keys .
To run the demo go to Constants.swift and change publishableKey value with the your key . Build and run the app to be able to get the final popup after payment.
Before jumping into coding, let’s first understand the flow and how things happened in the app you just run. In order to charge a card the following have to happen :
In steps 1 and 2 your app will send the credit card information (card number and expiration month and year. CVC is not required but is highly recommended for better security) to Stripe API using a secure HTTPS POST request . Stripe then returns a one-time token to your app.
In steps 3 and 4 your app must post the one-time token to your backend server which will call Stripe API again to request whatever operation you’ll perform on the card. The API then returns your operation result, be it success or failure to the server. Once notified, your backend will notify your client app as well with the result .
In the rest of the tutorial we will see how we coded each of these steps . But before starting, you have one more setup task : if you havent updated the publishableKey value in Constants.swift to build and run the app as mentionned in the steps above, update it now. Then go to your AppDelegate.swift and setup the STPPaymentConfiguration.shared().publishableKey value to the key value defined in Constants.swift as follows :
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { STPPaymentConfiguration.shared().publishableKey = Constants.publishableKey return true }
Accepeting credit cards
To make the sample code simple we will not get our data from remote servers or from APIs. I wrote a simple bouquet json object presenting the items we’ll sell, and populated the main uis lists with it .The two first tabs and the single item ui have basic code for listviews and item details which I will not go through here for sure . The DetailsViewController have basic and easy to get code to add the item to selected items list, which adds its price value to be charged from the card in next steps .
In next ” Checkout ui ” we’ll see the total amount we have to pay and click on Continue to open the credit card details collection ui , which is a built in ui provided by the API :
@IBAction func continueDidTap(_ sender: Any) { // ... let addCardViewController = STPAddCardViewController() addCardViewController.delegate = self navigationController?.pushViewController(addCardViewController, animated: true) } }
STPAddCarViewController is a view controller class provided by the API to handle collecting and tokenizing the user’s payment information. Once presented, the user will see a screen to input the credit card details like the number, expiration date and CVC as follows :
Since CheckoutViewController has been set as a delegate of the STPAddViewController we will have to implement the rest of the methods in CheckoutViewController. We will first add the two methods for cancelling adding a card and successfully adding a card and receiving a token.
extension CheckoutViewController: STPAddCardViewControllerDelegate { func addCardViewControllerDidCancel(_ addCardViewController: STPAddCardViewController) { navigationController?.popViewController(animated: true) } func addCardViewController(_ addCardViewController: STPAddCardViewController, didCreateToken token: STPToken, completion: @escaping STPErrorBlock) { } }
the addCardViewController(_:didCreateToken:completion:) will simply call StripeClient.shared.completeCharge(with:amount:completion:) and present alerts depending on if the result is success – where entered details where accepted and the card was charged – or failure .
StripeClient.swift is our singleton class that interacts with the back end. All we have here is a network call with Alamofire to perform the card charge operation which is implemeted in our backend. Remember in the beginning we defined the flow as the server will request charging the card after getting the one-time token from the API. Through StripeClient we will ping the server with the token and wait for its response as follows :
func completeCharge(with token: STPToken, amount: Int, completion: @escaping (Result) -> Void) { let url = baseURL.appendingPathComponent("charge"). //asking to invoke the charge operation let params: [String: Any] = [. //with the following parameters "token": token.tokenId, "amount": amount, "currency": Constants.defaultCurrency, "description": Constants.defaultDescription ] Alamofire.request(url, method: .post, parameters: params) .validate(statusCode: 200..<300) .responseString { response in switch response.result { case .success: completion(Result.success) case .failure(let error): completion(Result.failure(error)) } } }
Setting up a backend
You can use NodeJS or Ruby or others to implement a backend server which call Stripe API with a certain token to invoke a certain operation (card charge in our case) and pass back the result to the client . Stripe documentation provides clear guides on how to build a NodeJS server to call the API . Or you can use the Ruby script provided with our sample repo .
Once done setting up and starting your service, you have to configure the backend URL on Constants.swift . You can now start your server and run your app to test . For testing, Stripe provides some test credit cards numbers and tokens here .
That’s all for a simple and basic introduction to using Stripe API in Swift iOS apps ! Eventually there will be more tutorials on using Stripe in the coming weeks .
Recent Comments