iOS

A Swift Tutorial for Stripe: Taking Credit Card Payments in iOS Apps


In this tutorial we will talk about Stripe integration. Stripe provides one of the most powerful libraries for accepting payments online and mobile apps. If you are planning to sell products in your iOS apps and searching for a payment solution, Stripe should be on the top of your list.

I get asked a lot about why iOS developers need to use Stripe rather than In-App Purchase. According to Apple, you’re required to use In-App Purchase to sell digital content such as extra game levels for your game, and bonus content for your apps. For physical goods like clothing, you’re allowed to use other payment solutions such as Stripe. So, in this tutorial, I will give you a brief introduction of Stripe, explain how it works and show you how to build a demo app using Stripe’s API for accepting credit card payments.

What is Stripe?

Stripe is built for developers. It provides friendly APIs that instantly enables businesses to accept and manage mobile payments. You do not have to worry about opening a merchant account or setting up a credit card gateway. With Stripe, you can easily enable your app to take a payment from credit cards and even make recurring payments.

Stripe wants to make online/mobile transactions as easy as possible. As you will soon see, on top of the easy-to-use APIs, it even streamlines the registration process. The integration process is just so straightforward. This is one of the reasons why this company expands so quickly and has made its name in the startup world.

Take a Look at Our App

To save you time from building the app from scratch and focus on learning Stripe, I have created the project template for you. First, download the project and have a trial run.

In this tutorial, we will create a Demo app called “Donate” to demonstrate how to accept credit card payment using Stripe.

iOS Simulator Screen Shot Jun 9, 2015, 5.35.27 PM
Editor’s note: The app is for demo purpose. According to App Store Review Guidelines, if your app supports donation, it should be free and the collection of charitable donations must be done via a web site in Safari or an SMS.

Donate App Cycle and How Stripe Works

Before we dive into the implementation, let’s first see how the app will communicate with Stripe and process the transaction. In brief, here is how the app works when the customer sends a payment:

  1. The app first collects payment information including email, credit card number, expiration date, CVC, and payment amount from the payment form. It then sends the credit card data to Stripe backend by calling its API.
  2. If the payment information is valid, Stripe will return you a token. At this point, the credit card is not charged yet. Later, you’ll use the token to perform the actual transaction.
  3. Now that your app gets the token. The next step is to send it to your own server to complete the charging process. For security reasons, Stripe requires you to perform the actual charging process through a server instead of the mobile device itself. No worries. Stripe has provided us with server code to implement the charging process easily. We’ll talk about that in later section.
  4. Your web application sends the token to Stripe to perform the actual charging. No matter the transaction succeeds or not, Stripe will return you the result.
  5. Lastly, the server side sends a response back to the app about the transaction result.
stripe-flow

Note: The response returned is in JSON format, so if you are not familiar with JSON parsing, please check out this tutorial to learn more about it.

Creating a Stripe Test Account

Creating a test account on Stripe is pretty straightforward and can be done within a few seconds. Stripe simplifies the whole registration process and allows developers to sign up an account without filling in any information. I really like this streamlined process. This can be really useful if you are developing an app for a client or you just want to explore the APIs of Stripe.

The first step is to go to Stripe and click the sign up button:

Signup Stripe

You’ll be directed to the signup page to create a new account. Here, you can fill in your personal information. But as I mentioned before, Stripe streamlines the registration process. Here you can simply click “skip this step” to proceed. You’ll then be able to access the Stripe dashboard through a temporary account for testing purpose.

Screen Shot 2015-06-09 at 9.05.20 PM

Once done, Stripe will present you the dashboard:

stripe-dashboard

Next, go to “Your Account” menu and press “Account Settings”, then click the “API keys” tab to reveal the keys for our app development.

Screen Shot 2015-06-10 at 12.05.31 AM

That’s it for Stripe configuration. From now on, you can use the Stripe APIs to test transaction. Later you’ll come back to the dashboard to check if the transactions are successfully processed.

Adding the Stripe Library Using Cocoapods

Before using Stripe in our Xcode project, we have to bundle the library as a dependency. There are a couple of ways to do that. In the demo, we will use Cocoapods, which is a well-known dependency manager for Swift projects. Like this demo, many projects rely on third-party libraries to work. Cocoapods is a tool that helps developers manage the dependency of the required libraries and ensures they’re up to date.

If you do not have Cocoapods installed, executing the following command in Terminal to install it:

Just be patient, you may need to wait for a couple of minutes before the installation finishes. When it’s done, you should see something like “gems installed.”

Screen Shot 2015-06-10 at 4.09.48 PM

Next, create an empty file named “Podfile” at the root folder of the Xcode project directory. Open it with your favorite text editor and paste the following line in it:

The Podfile tells Cocoapods which libraries we want to use. In this case, the libraries we need are Stripe version 4.0 and AFNetworking version 2.5.4.

Now, quit Xcode and open Terminal. Change to the root directory of the Xcode project. The root directory is the one containing “Podfile”. Next, type this in Terminal:

CocoaPods will look for “Podfile” and attempt to install the dependencies we configure. The download and installation process can take several minutes. When it completes, the result should look like this:

Screen Shot 2015-06-10 at 4.28.31 PM

CocoaPods has downloaded, and bundled the Stripe & AFNetworking libraries in your Xcode project. However, from now on, we won’t be using the original app project. CocoaPods has generated another workspace called Donate.xcworkspace for you. This workspace contains both our original project and the CocoaPods project.

Now open the new Workspace (i.e. Donate.xcworkspace) in Xcode. You should note that there are two projects: Pods and Donate.

cocoapod-projects

Using Objective-C in Swift Project

Stripe’s library is written in Objective-C, and our project is written in Swift. These two don’t work together without a proper configuration. Any Objective-C library, project or class can be used in a Swift project by setting up a bridging header. Technically speaking, such bridge will translate header files from Objective-C to Swift.

You can create a bridging header by following these procedures:

  1. Add a new header file to the Donate directory by right-clicking the Donate directory in the project navigator, followed by clicking “New File…”.
  2. Select iOS -> Source category, choose the “Header File” template and click Next.
  3. Name the class “Donate-Bridging-Header.h”, then press continue to proceed and save the file.
  4. Next, go to “Build Settings”, and search for “Objective-C Bridging Header”. Set the value to “Donate/Donate-Bridging-Header.h”.
Screen Shot 2015-06-10 at 4.37.23 PM

Once done, open the Donate-Bridging-Header.h file and write the following code:

Great! We’ve finally completed the project configuration. Now we are ready to dive into the implementation of our demo app.

Configure API Keys

The very first thing you have to do is configure your Stripe API key. You can find your key in the Stripe dashboard by selecting “Account Settings” -> “API keys”. For now, we will use just the test keys so you can test our transactions without using a real credit card.

Open AppDelegate.swift and insert a line of code (highlighted in yellow):

Here we configure Stripe with our test publishable API key. Note that you have to change it to yours.

Note: Later when you roll out your app to production, you can update the publishable key to a live one.

Collecting Credit Card Information

To perform a transaction, your app should have a mean to collect the user’s information. Stripe suggests three ways to collect the payment information:

  • through Apple Pay to access your users’ stored payment information
  • by using Stripe’s built-in payment form component, PaymentKit
  • by building our own payment form

In this tutorial, we’ll opt for the third option and build our own payment form. Stripe requires us to collect at least the card number and expiration date. But I also recommend to secure CVC in order to prevent fraudulent transactions and gain a trust from users. The other thing you may want to obtain is email address, so you can keep a record of the person who makes the donation for later communication.

If you’re using the project template, I have already built the payment interface for collecting customers’ payment details. All the text fields are associated with the corresponding outlets in the ViewController.swift file.

donate-app-storyboard

Now, open ViewController.swift and update the donate method like this:

When the user taps the Donate button, this action method will be triggered. We first initialize a STPCard object and assemble the data into it.

Next, add the following code to the same method:

The STPCard class comes with very handy method called validateCardReturningError that saves us from implementing our own validation logic. The class sends the collected card info to its server, and return an error if the card information is invalid.

Again, add the code below to the same method as we did previously:

Once we confirm the credit card is valid, we invoke the createTokenWithCard method of the STPAPIClient class to send off the credit card data via a secure HTTPS request. Stripe will return you a token if the request is successful.

At this point, the customer’s credit card is not charged. Stripe only gives you an one-time token. Later you’ll send this token to your own server and perform the actual charging.

In case it fails to retrieve the token, the app will simply display an error to the user. Insert the following method in the ViewController class:

In the same file, add the following code:

Setting Up Your Local Server

As mentioned at the very beginning of the tutorial, the charging of the customer’s credit card actually happens on our own server. For security reasons, Stripe doesn’t charge the credit card which is sent directly from an app. It only generates you a token. Your app will then pass this token to your backend to follow up with the actual charging.

So before moving onto the implementation of the app, let’s stop for a minute and setup our server in order to process the payment. To create our backend, we will use PHP as the primary language and make use of the library provided by Stripe. No worries. You don’t need to be an expert in web development. Just go ahead and follow the steps as described, and you will be able to configure the required backend for processing the Stripe payment.

First, download XAMPP (for OS X) v5.6.8 (or up), and install it onto your Mac. Next, download this zipped file and unzip it. After that, go to the folder where XAMPP is installed. Normally it is installed under the “Applications” folder. Open the folder “Applications/XAMPP/htdocs”, then copy the folder that you just unzipped to here.

xampp-donate-htdoc

Once done, go back to the XAMPP folder and open “manager-osx”. When launched, hit the button “Start All” under the “Manage Server” tab as shown below:

xampp-manager

The next step is to go to “Applications/XAMPP/htdocs/donate”. Open the file “payment.php” with any text editor you are comfortable with.

Replace the API key with your Test Secret key, that was demonstrated earlier in this tutorial:

That’s it! You’ve just completed the configuration of your backend. Isn’t it easy?

Sending the Token to the Backend for Payment Processing

Now that our backend is ready to process the payment, let’s switch back to Xcode and start sending the token to our backend by making a HTTP POST request. Open ViewController.swift and insert the following code:

As we are hosting our backend locally, the URL is set to http://localhost/donate/payment.php. If you host the script in a remote server, please change it accordingly.

To perform the actual charge, Stripe requires us to submit the token, plus the payment amount, currency, and description. You can use the description field as a payment note. In the example, we simply use the field to store the customer’s email.

Once the parameters are configured, we submit an asynchronous POST request using AFHTTPRequestOperationManager, an API provided by AFNetworking. If the request succeeds, we display the payment response to the user.

That’s it! You can now run the app and perform a test transaction. For testing purpose, you can use the credit card number 4242 4242 4242 4242, along with any future expiration date (e.g 07/2019) and CVC (e.g. 222), to simulate a transaction:

donate-stripe-success-300

To further verify if the payment succeeds, you can check out Stripe’s dashboard:

Screen Shot 2015-06-11 at 5.09.01 PM

Summary

In this tutorial, I have walked you the basics of Stripe. You should know how to integrate Stripe in your app to accept credit card payment. For further information, I encourage you to check out the official documentation. Stripe provide many ways to accomplish payments through its APIs, you can go to its documentation for further information.

For reference, you can download the entire Donate project file here. Please use Xcode 6.3 (or up) to run the project. Note that you have to change the Secret key in the AppDelegate.swift file. I hope you guys enjoy this tutorial and as always leave us comments below.

iOS
Building Your First Blockchain App in Swift
iOS
Introducing Firebase with Swift 3: Login and Sign Up
iOS
iOS Programming Tutorial: Create a Simple Table View App
  • Eddwin Paz

    Eddwin PazEddwin Paz

    Author Reply

    I’ve made an app and integrated Stripe and Apple rejects it. It now forces users to use Apple Pay


    • Wiraj

      WirajWiraj

      Author Reply

      Are you sure about that? In a few weeks I will have to create a “buy feature” for the first time and I would like to know If I will have to use Apple Pay or there are other options to do something like this. Thanks.


  • Dmytro Bohachevskyy

    hi, Thanks for great tutorial!
    Can you check link for downloading server backend? Dropbox said that link not found.


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      The problem is fixed. Please try to download the file again.


  • Isuru Nanayakkara

    Thanks for the tutorial. Mobile payment is something I always wanted to learn.

    btw you don’t have to use bridging headers anymore. CocoaPods fully support Swift libraries now. You simply have to add use_frameworks! flag in the Podfile. Here’s a blog post I wrote about it.

    Also I added AFNetworking’s Swift cousin, Alamofire instead.


  • Chris Kong

    Chris KongChris Kong

    Author Reply

    Good stuffs. Silly question. How come I can’t use other email address, CC numbers, etc. to test out the payment info?


    • Chris Kong

      Chris KongChris Kong

      Author Reply

      Never mind the question. I got several failed transactions and couldn’t figure out the problem. Some of the errors include Optionals found nil related to the Amount Text Field.


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      You can use any email address. For CC numbers, you can refer to the test cards here:

      https://stripe.com/docs/testing


  • harsh shrivastava

    Great post! I have followed every step in this tutorial but I am still getting this error.
    No such module ‘Stripe’
    can you help?


  • Shah

    ShahShah

    Author Reply

    In a real world app, where are we supposed to keep the back end files (PHP Payment Processing etc)?


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      You can just put it on your own web server. If you don’t have one, you can host it on Webfaction, Digital Ocean, etc.


  • Yogesh Jadhav

    hey nice post..thanks for this tutorial..please make video tutorials on iOS..Thanks…


  • Simon Ng

    Simon NgSimon Ng

    Author Reply

    Congratulations! The game looks really nice 🙂


  • Huong Tran

    Huong TranHuong Tran

    Author Reply

    Hi.can you tell me how to pay from a user to another user in my app?


  • Rajan

    RajanRajan

    Author Reply

    How can I remember credits card details?


  • Will

    WillWill

    Author Reply

    Any way we could get this tutorial using Parse as the server and Object C language?


  • Daisy Ramos

    I am getting a wrapping error at

    “amount”: self.amountTextField.text.toInt()!

    has anyone else came across this issue?


    • Marko Žél

      Yeah, in Swift 2.0 you have to use Int(self.amountTextField.text!), but that too gives an error. Not sure what the problem is.


      • venkatin

        venkatinvenkatin

        Author Reply

        In Swift 2.0, you have to use let intamount: Int = Int(self.amountTextField.text!)! – note the ! after )

        This works for me.


  • somish

    somishsomish

    Author Reply

  • Joao Paulo

    Joao PauloJoao Paulo

    Author Reply

    Great Post, it has helped me a lot. Three quick questions. I’ve been trying to use it with Objective-C and when I try to use validateCardReturningError, it says it is deprecated. Would it be an issue? or Is it also deprecated in Swift? If yes, what would be the best way to validate?


  • Coração Tricolor

    Neither the template or the final project have Core Data modeled instead I believe its created on the fly by AppDelegate.. Could it be substituted? What would the entity look like? Or is it a Stripe requirement? Thanks for the tut but would like to know these details..


  • George

    GeorgeGeorge

    Author Reply

    I have : the resource could not be loaded because the app transport security…. Helppp


  • Vivek Goswami

    i got an error @property (weak, nonatomic, readonly, stp_nonnull) STPCheckoutViewController *checkoutController; Property attributes ‘nonnull’ and weak are mutually exclusive..so what should i do?


    • Dip Kasyap

      Dip KasyapDip Kasyap

      Author Reply

      use latest stripe version
      use
      pod ‘Stripe’,~>’5.0′
      it will help !


  • Kris Tobiasson

    I’m getting the following error, ‘&’ used with non-inout argument of type ‘()’, for the following code, on the second line down.

    var underlyingError: NSError?
    stripeCardParams.validateCardReturningError(&underlyingError)
    if underlyingError != nil {
    //self.spinner.stopAnimating()
    //self.handleError(underlyingError!)
    return
    }

    Can anyone point me in the right direction?


    • Kris Tobiasson

      The reason for this was because Swift has changed error handling since version 2.0. I had to change a lot of things because of Stripe deprecating methods in new versions as well. Got it working though. Great tutorial Ziad, thanks..


  • pavel

    pavelpavel

    Author Reply

    //This for fix the problem
    do{

    try stripCard.validateCardReturningError()

    } catch let underlyingError as NSError? {

    self.spinner.stopAnimating()

    self.handleError(underlyingError!)

    return

    }
    //this is problem
    /*var underlyingError: NSError?

    stripCard.validateCardReturningError(&underlyingError)

    if underlyingError != nil {

    self.spinner.stopAnimating()

    self.handleError(underlyingError!)

    return

    }*/


  • Aneena Susan Thomas

    Showing error as “Server could not be loaded” while i running the sample app


  • John Hubler

    Any chance this tutorial could be upgraded to accommodate Swift 3?


  • Aseem

    AseemAseem

    Author Reply

    If I I have a Parse Server setup to handle logging in and signing up, can I still use this local backend in the tutorial to handle the Stripe api? Thanks!


  • Mahender

    MahenderMahender

    Author Reply

    Hi Gabriel ,
    I Integrated payment process with PayPal SDK , It is working good but client requires auto payment from papal account.It is always navigating to the paypal , he wants auto payment in our application is there any way to do this.
    Thanks in advance.



  • Pavithra G J

    I have followed the every step in this tutorial but I am getting server error , I installed server on local machine.

    “Error Domain=NSCocoaErrorDomain Code=3840 “JSON text did not start with array or object and option to allow fragments not set.” UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}”

    Can anyone help me in resolving this?.


  • Salman Ali

    Salman AliSalman Ali

    Author Reply

    Hi i followed the tutorial and every step as you did and the code and the backend works fine as long as i host it on the local server like Apache or something like that. But when i upload the backend code to the web server it does not process the request. I generate the token and manually check the API Call in the web browser and it says unable to handle this request. Can you help me sort out this problem please.


  • Luis Puentes

    Hi there,

    I’m having trouble with instantiating the STPCard. I get an error saying, ”init()’ is unavailable: You cannot directly instantiate an STPCard. You should only use one that has been returned from an STPAPIClient callback.”

    I’ve tried doing some research and cannot quite find the right way to go about this. Can someone please help or point me in the right direction?


  • Ankit Saini

    How can we save the cards for later use and what is the procedure to retrieve them again some other time?


Shares