Friday, March 10, 2017

Stripe Payment Solution on iOS platform - Using Swift

Hi Everyone,

In this blog we’ll see the integration methodology of Stripe payment API with iOS platform based application.

To start with, we required first to set-up an environment in development machine and look at some important key steps during time of the implementation. I have done this lab sample in my Mac machine i.e., the configuration spec are such as:
·      Mac OSX- 10.12.3
·      XCode – 8.2.1
·      Swift – 3.0.2
·      Getting start with the Stripe-Mobile: https://stripe.com/docs/mobile

1. First create a new project in Xcode:
Open Xcode IDE - > File -> New -> Project - > Choose ‘Single View Application’ template under iOS for creation of new project-> provide desired ‘Product Name’ and pick ‘Swift’ corresponding to ‘Language’ selection and ‘Devices’ should be ‘iPhone’ at this moment (can be considered ‘Universal’ as well for supporting iPad in addition).


E.g. – the project directory path look like: /Users/ranbijaykumar/Stripe-Sample/Stripe-iOS

2. Next, open Terminal in Mac machine:

Install the latest version of ‘Cocoapods
 
$ sudo gem install cocoapods

Once you installed the ‘Cocoapods’ in machine. Go to the directory of your project and create podfile:

$ cd /Users/ranbijaykumar/Stripe-Sample/Stripe-iOS

$ init pod (please make sure the Podfile should create in same directory of the project where .xcodeproj and .xcworkspace are already there)

$ edit pod

Open Podfile, add this line to the Podfile i.e., pod ‘Stripe’. This will be look like it:

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'Stripe-iOS' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for Stripe-iOS
     pod 'Stripe'
     pod 'CardIO'
     pod 'SVProgressHUD'
end



Save and close the Podfile. Run the following command under project directory folder in Terminal:

$ pod install (latest Stripe SDK (i.e., Stripe – 9.4.0 will be installed in your Xcode project)

* For future - to update the installed SDK version $ pod update, to do that - make sure first to remove pod.lock file from the project directory.


Run the following command in terminal under project directory in case you have closed your Xcode IDE.

$ open ./Stripe-iOS.xcworkspace

3. Open AppDelegate.swift file of your project in Xcode

import UIKit
import Stripe

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
   
    var window: UIWindow?
   
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
       
        STPPaymentConfiguration.shared().publishableKey = "pk_test_3m5KLiVZ2BsiRJVH3Xsx5ViW"
       
        return true
    }
   

To get a Test and LiveSecret and Publishable key’, user need to register over here: https://dashboard.stripe.com/register. The publishable key can be replaced in above statement or track the logs via dashboard for future transactions or any actions.

4. Under ViewController.swift: paste below code, allow users to fetch the default UIView for Stripe Payment option and getting tokenID to backend for process

//
//  ViewController.swift
//  Stripe-iOS
//
//  Created by RANBIJAY KUMAR on 03/03/17.
//  Copyright © 2017 SaturnMob. All rights reserved.
//

import UIKit
import Stripe

class ViewController: UIViewController, STPAddCardViewControllerDelegate {
   
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
   
   
    @IBAction func actionAddCardDefault(_ sender: AnyObject) {
        let addCardViewController = STPAddCardViewController()
        addCardViewController.delegate = self
        // STPAddCardViewController must be shown inside a UINavigationController.
        let navigationController = UINavigationController(rootViewController: addCardViewController)
        self.present(navigationController, animated: true, completion: nil)
    }
   
    // MARK: STPAddCardViewControllerDelegate
   
    func addCardViewControllerDidCancel(_ addCardViewController: STPAddCardViewController) {
        self.dismiss(animated: true, completion: nil)
    }
   
    func addCardViewController(_ addCardViewController: STPAddCardViewController, didCreateToken token: STPToken, completion: @escaping STPErrorBlock) {
        //Send token to backend for process
        print(token)
        self.dismiss(animated: true, completion: {
            completion(nil)
        })
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
       
}


5. Create another Swift file i.e, StripeCardVC.swift and paste the following code inside it. This view allow users to enter detail of the card manually and getting tokenID to backend for process

//
// StripeCardVC.swift
//  Stripe-iOS
//
//  Created by RANBIJAY KUMAR on 03/03/17.
//  Copyright © 2017 SaturnMob. All rights reserved.
//

import UIKit
import Stripe

class StripeCardVC: UIViewController, STPPaymentCardTextFieldDelegate {
   
    @IBOutlet weak var btnBuy: UIButton!
   
    let cardParams = STPCardParams()
   
    override func viewDidLoad() {
        super.viewDidLoad()
       
       
       
        let paymentField = STPPaymentCardTextField(frame: CGRect(x: 10, y: 100, width:self.view.frame.size.width - 20, height: 44))
        paymentField.delegate = self
        self.view.addSubview(paymentField)
        // Do any additional setup after loading the view.
       
        self.btnBuy.isEnabled = paymentField.isValid
        btnBuy.backgroundColor = UIColor.gray
    }
   
    // MARK: STPPaymentCardTextFieldDelegate
   
    func paymentCardTextFieldDidChange(_ textField: STPPaymentCardTextField) {
        print("Card number: \(textField.cardParams.number) Exp Month: \(textField.cardParams.expMonth) Exp Year: \(textField.cardParams.expYear) CVC: \(textField.cardParams.cvc)")
        self.btnBuy.isEnabled = textField.isValid
       
        if btnBuy.isEnabled {
            btnBuy.backgroundColor = UIColor.blue
            cardParams.number = textField.cardParams.number
            cardParams.expMonth = textField.cardParams.expMonth
            cardParams.expYear = textField.cardParams.expYear
            cardParams.cvc = textField.cardParams.cvc
        }
    }
   
    @IBAction func actionGetStripeToken() {
        STPAPIClient.shared().createToken(withCard: cardParams) { (token, error) in
            if let error = error {
                // show the error to the user
                print(error)
                self.showAlertButtonTapped("Error", strMessage: error.localizedDescription)
            } else if let token = token {
                //Send token to backend for process
                print(token)
                self.showAlertButtonTapped("Success", strMessage: "Got Token Successfully")
            }
        }
    }
   
   
    //MARK:- AlerViewController
    func showAlertButtonTapped(_ strTitle:String, strMessage:String) {
        // create the alert
        let alert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
        // add an action (button)
        alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
        // show the alert
        self.present(alert, animated: true, completion: nil)
    }
   
   
    @IBAction func actionBack(_ sender: AnyObject) {
        self.navigationController?.popViewController(animated: true)
    }
   
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    /*
     // MARK: - Navigation
    
     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
     // Get the new view controller using segue.destinationViewController.
     // Pass the selected object to the new view controller.
     }
     */
   
}


* Please be noted, Stripe are available for businesses in 25 countries, accept payments from anywhere in the world. Checkout the details here: https://stripe.com/global#signup-form


6. The complete working-code sample user can be fetched from Github. Please clone or download from here: https://github.com/RANBIJAY/Stripe-iOS

After downloading the project in local drive - open it in Xcode IDE. Few things need to be done before Build or Run the project:

Open ‘Build Settings’ of the project; search ‘Objective-C Bridging Header’ filed. Drag the file Stripe-iOS-Bridging-Header.hfile from Project navigator and put into the corresponding field of  Objective-C Bridging Header. It will set the path of the file and needed to avoid linking error during runtime of the project.



Once set with the above sample in machine, build or run the app – you can see the tokenID been generated – shown in below screenshot



App Screenshots of multiple screens:



That's it for this blog. 

Stay tune for next exciting blog .....! 

1 comment: