---
page_title: 5. Making a Payment
product: EC Headless
platform: iOS
page_source: https://juspay.io/in/docs/ec-headless/ios/base-sdk-integration/making-a-payment
llms_txt: https://juspay.io/in/docs/llms.txt
product_llms_txt: https://juspay.io/in/docs/ec-headless/llms.txt
---


## 5. Making a Payment



Once the checkout page is rendered, your users may proceed with payments. Payment initiation has two steps to it:

1. [Order Creation](https://docs.juspay.in/ec-headless/ios/base-sdk-integration/making-a-payment#5.1.-Order-Creation)
2. [Transaction Initiation](https://docs.juspay.in/ec-headless/ios/base-sdk-integration/making-a-payment#5.2.-Transaction-Initiation)

Following sections describe how to complete the steps above -


### 5.1. Order Creation



Create an order that is a representation of your shopping cart. The order contains important information like amount, customer details, shipping address, billing address, etc. Only after an order is created at Juspay end, the payment can be initiated.To create an order follow the step below -


### Step 5.1.a. Call Create Order API


Call [Create Order API](https://docs.juspay.in/ec-headless/ios/base-sdk-integration/create-order-api) to create an order_id at Juspay end and get the corresponding client_auth_token

> **Warning**
> client_auth_token is valid only for 15 mins and is used for frontend authentication of SDK/client side calls.






### 5.2. Transaction Initiation



Transaction initiation involves a `process` SDK call from the merchant application with a process payload based on the payment method selected by your user. To inititate a transaction, follow the steps below -


### Step 5.2.a. Process SDK Call for Transaction Initiation


A process SDK call is to be made with a process payload based on the payment method selected by the user. For sample request and response payloads for different process SDK calls, please refer to the [payload samples](https://docs.juspay.in/ec-headless/ios/payloads/payload-samples) page and use the dropdown menus to select the appropriate category and flows.

> **Warning**
> Process SDK call is to be made on the same instance of HyperService using which initiate API was triggered. It should not be called on an HyperSDK instance which has not been initiated.





#### Code Snippets: -

#### Swift Code Snippet:

```swift
if hyperInstance?.isInitialised() ?? false {
     hyperInstance.process(processPayload)               
    }
```

#### ObjectiveC Code Snippet:

```objectivec
if ([hyperInstance isInitialised]) {
          [hyperInstance process:processPayload];       
    }
```



### Step 5.2.b. Consume Process SDK Response


Upon receiving the process call, the SDK internally initiates a transaction request to Juspay servers. Process response is returned as an SDK callback to the merchant application post payment completion.



---

## Complete Code Reference

The following code files are referenced in the steps above:

### ViewController.swift

```
//
//  ViewController.swift
//  juspay-sdk-integration-swift
//
//
import UIKit

// Importing Hyper SDK
// block:start:import-hyper-sdk

import HyperSDK
// block:end:import-hyper-sdk


class ViewController: UIViewController {

    // Creating an object of HyperServices class.
    // block:start:create-hyper-services-instance

    let hyperInstance = HyperServices();
    // block:end:create-hyper-services-instance

    
    override func viewDidLoad() {
        super.viewDidLoad()
    }


    // Creating initiate payload JSON object
    // block:start:create-initiate-payload

    func createInitiatePayload() -> [String: Any] {
        let innerPayload : [String: Any] = [
            "action": "initiate",
            "merchantId": "<MERCHANT_ID>",
            "clientId": "<CLIENT_ID>",
            "customerId": "<CUSTOMER_ID>",
            "xRoutingId": "<X_ROUTING_ID>",
            "environment": "prod"
        ];

        let sdkPayload : [String: Any] = [
            "requestId": UUID().uuidString,
            "service": "in.juspay.hyperapi",
            "payload": innerPayload
        ]

        return sdkPayload
    }
    // block:end:create-initiate-payload

    // Creating HyperPaymentsCallbackAdapter
    // This callback will get all events from hyperService instance
    // block:start:create-hyper-callback

    func hyperCallbackHandler(response : (Optional<Dictionary<String, Any>>)) {
        if let data = response, let event = data["event"] as? String {
            if (event == "hide_loader") {
                // hide loader
            }
            // Handle Process Result
            // block:start:handle-process-result
            else if (event == "process_result") {
                let error = data["error"] as! Bool

                let innerPayload = data["payload"] as! [ String: Any ]
                let status = innerPayload["status"] as! String
                let pi = innerPayload["paymentInstrument"] as? String
                let pig = innerPayload["paymentInstrumentGroup"] as? String

                if (!error) {
                    // txn success, status should be "charged"
                    // process data -- show pi and pig in UI maybe also?
                    // example -- pi: "PAYTM", pig: "WALLET"
                    // call orderStatus once to verify (false positives)
                } else {

                    let errorCode = data["errorCode"] as! String
                    let errorMessage = data["errorMessage"] as! String
                    switch (status) {
                        case "backpressed":
                            // user back-pressed from checkout screen without initiating any txn
                            break;
                        case "user_aborted":
                            // user initiated a txn and pressed back
                            // poll order status
                            break;
                        case "pending_vbv", "authorizing":
                            // txn in pending state
                            // poll order status until backend says fail or success
                            break;
                        case "authorization_failed", "authentication_failed", "api_failure":
                            // txn failed
                            // poll orderStatus to verify (false negatives)
                            break;
                        case "new":
                            // order created but txn failed
                            // also failure
                            // poll order status
                            break;
                        default:
                            // unknown status, this is also failure
                            // poll order status
                            break;
                    }
                }
            }
            // block:end:handle-process-result
        }

    }
    // block:end:create-hyper-callback

    
    @IBAction func initiatePayments(_ sender: Any) {
        // Calling initiate on hyperService instance to boot up payment engine.
        // block:start:initiate-sdk
        
        hyperInstance.initiate(
            self,
            payload: createInitiatePayload(),
            callback: hyperCallbackHandler
        )
        // block:end:initiate-sdk
    }


    // Creating process payload JSON object
    // block:start:process-sdk-call

    if hyperInstance?.isInitialised() ?? false {
     hyperInstance.process(processPayload)               
    }
    // block:end:process-sdk-call
    
}


```

### ViewController.m

```
//
//  ViewController.swift
//  juspay-sdk-integration-swift
//
//
import UIKit

// Importing Hyper SDK
// block:start:import-hyper-sdk

#import <HyperSDK/HyperSDK.h>
// block:end:import-hyper-sdk


class ViewController: UIViewController {

    // Creating an object of HyperServices class.
    // block:start:create-hyper-services-instance

    self.hyperInstance = [[HyperServices alloc] init];
    // block:end:create-hyper-services-instance

    
    override func viewDidLoad() {
        super.viewDidLoad()
    }


    // Creating initiate payload JSON object
    // block:start:create-initiate-payload

    - (NSDictionary *)createInitiatePayload {
        NSDictionary *innerPayload = @{
            @"action": @"initiate",
            @"merchantId": @"<MERCHANT_ID>",
            @"clientId": @"<CLIENT_ID>",
            @"customerId": @"<CUSTOMER_ID>",
            @"xRoutingId": @"<X_ROUTING_ID>",
            @"environment": @"prod"
        };

        NSDictionary *sdkPayload = @{
            @"requestId": @"12398b5571d74c3388a74004bc24370c",
            @"service": @"in.juspay.hyperapi",
            @"payload": innerPayload
        };

        return sdkPayload;
    }
    // block:end:create-initiate-payload

    // Creating HyperPaymentsCallbackAdapter
    // This callback will get all events from hyperService instance
      //block:start:create-hyper-callback

    self.hyperCallbackHandler = ^(NSDictionary<NSString *,id> * _Nullable response) {
        NSDictionary *data = response;
        NSString *event = data[@"event"];

        if ([event isEqualToString:@"hide_loader"]) {
            // hide loader
        }
        // Handle Process Result
        // block:start:handle-process-result

        else if ([event isEqualToString:@"process_result"]) {
            BOOL error = [data[@"error"] boolValue];

            NSDictionary *innerPayload = data[@"payload"];
            NSString *status = innerPayload[@"status"];
            NSString *pi = innerPayload[@"paymentInstrument"];
            NSString *pig = innerPayload[@"paymentInstrumentGroup"];

            if (!error) {
                // txn success, status should be "charged"
                // process data -- show pi and pig in UI maybe also?
                // example -- pi: "PAYTM", pig: "WALLET"
                // call orderStatus once to verify (false positives)
            } else {

                NSString *errorCode = data[@"errorCode"];
                NSString *errorMessage = data[@"errorMessage"];
                if([status isEqualToString:@"backpressed"]) {
                    // user back-pressed from checkout screen without initiating any txn
                }
                else if ([status isEqualToString:@"backpressed"]) {
                    // user initiated a txn and pressed back
                    // poll order status
                } else if ([status isEqualToString:@"pending_vbv"] || [status isEqualToString:@"authorizing"]) {
                    // txn in pending state
                    // poll order status until backend says fail or success
                } else if ([status isEqualToString:@"authorization_failed"] || [status isEqualToString:@"authentication_failed"] || [status isEqualToString:@"api_failure"]) {
                    // txn failed
                    // poll orderStatus to verify (false negatives)
                } else if([status isEqualToString:@"new"]) {
                    // order created but txn failed
                    // also failure
                    // poll order status
                } else {
                    // unknown status, this is also failure
                    // poll order status
                }
            }
        }
        // block:end:handle-process-result
    };
    //block:end:create-hyper-callback


    
    @IBAction func initiatePayments(_ sender: Any) {
        // Calling initiate on hyperService instance to boot up payment engine.
        // block:start:initiate-sdk
        
        NSDictionary *initPayload = [self createInitiatePayload];
        [self.hyperInstance initiate:self payload:initPayload callback:self.hyperCallbackHandler];
        // block:end:initiate-sdk
    }


    // Creating process payload JSON object
    // block:start:process-sdk-call

    if ([hyperInstance isInitialised]) {
          [hyperInstance process:processPayload];       
    }
    // block:end:process-sdk-call
    
}


```


---

## See Also

- [4. Rendering the Checkout Screen](https://juspay.io/in/docs/ec-headless/ios/base-sdk-integration/rendering-the-checkout-screen)
- [6. Handling Payment Response](https://juspay.io/in/docs/ec-headless/ios/base-sdk-integration/handling-payment-response)
