Add payments to your Android app with Paytm SDK

Paytm Android SDK is a secure, PCI-compliant way to accept Debit/Credit card, Net-Banking, UPI and Paytm wallet payments from your customers in your Android app.

Demo of Paytm checkout flow in your app -



Overview of payment processing via Paytm Android SDK


  1. At click of the pay button by customer, order related payload is passed to your server by the app
  2. This order payload is used to generate checksumhash by our server side utility and merchant key on your server. Checksumhash is a signature used by Paytm to ensure that request has not been tampered. Utility to generate checksumhash is available here
  3. Your server passes the payload and checksumhash back to the app which hands over these details to Paytm SDK
  4. SDK verifies payload and displays payment Paytm checkout page
  5. Customer fills the payment details and completes the payment authentication. Once the payment is complete, response is posted back to your app via callback
  6. Verify checksumhash received in response on your server side. Utility to verify checksumhash is available here
  7. Lastly, verify transaction status with Transaction Status API via server to server call. This protects you from scenarios where your account credentials are compromised or request/response has been tampered

Find the detailed interaction of each system component in the flow chart below


Steps to start accepting payments via Paytm Android SDK


Step 1: SDK Installation and Setup

Install SDK

Install Paytm Android SDK using Android Studio and IntelliJ. To add the SDK to your app, add the following dependency in your build.gradle:

dependencies {
	compile('com.paytm:pgplussdk:1.2.3') {
		transitive = true; 
	}
}

SMS Permission

To allow SDK to autoread the OTP sent by bank during account verification, you need static and at runtime permissions

Add the following code to your AndroidManifest.xml to get static permission

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>  

Using the code below, you can get runtime permissions needed from user to auto-read the OTP

if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {
	ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_SMS, Manifest.permission.RECEIVE_SMS}, 101);
}

Proguard Rules

If you're using proguard for your build, you need to add the following lines to your proguard file (proguard-rules.pro):

-keepclassmembers class com.paytm.pgsdk.PaytmWebView$PaytmJavaScriptInterface {
   public *;
}

Step 2: Initialization

To initialize the Paytm SDK, use below classes:

Object: Service

Service object is used to used to access PG services like initiating transaction, getting transaction callbacks etc. This is different for staging and production and created with following snippet:

For Staging environment:

PaytmPGService Service = PaytmPGService.getStagingService();

For Production environment:

PaytmPGService Service = PaytmPGService.getProductionService();

Object: Order

Stores all order related information which are required to be passed by you to Paytm. Order object is created by following code snippet -

Map<String, String> paramMap = new HashMap<String,String>();
paramMap.put( "MID" , "rxazcv89315285244163");
// Key in your staging and production MID available in your dashboard
paramMap.put( "ORDER_ID" , "order1");
paramMap.put( "CUST_ID" , "cust123");
paramMap.put( "MOBILE_NO" , "7777777777");
paramMap.put( "EMAIL" , "username@emailprovider.com");
paramMap.put( "CHANNEL_ID" , "WAP");
paramMap.put( "TXN_AMOUNT" , "100.12");
paramMap.put( "WEBSITE" , "WEBSTAGING");
// This is the staging value. Production value is available in your dashboard
paramMap.put( "INDUSTRY_TYPE_ID" , "Retail");
// This is the staging value. Production value is available in your dashboard
paramMap.put( "CALLBACK_URL", "https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=order1");
paramMap.put( "CHECKSUMHASH" , "w2QDRMgp1234567JEAPCIOmNgQvsi+BhpqijfM9KvFfRiPmGSt3Ddzw+oTaGCLneJwxFFq5mqTMwJXdQE2EzK4px2xruDqKZjHupz9yXev4=")
PaytmOrder Order = new PaytmOrder(paramMap);

Description of parameters used in hashmap object:

Parameter NameDescription
MID String(20) MandatoryThis is a unique identifier provided to every merchant by Paytm. MID is part of your account credentials and is different on staging and production environment. Your staging MID is available here and production MID will be available once your activation is complete
ORDER_ID String(50) MandatoryUnique reference ID for a transaction which is generated by merchant Special characters allowed in Order ID are: “@” “-” “_” “.”.
CUST_ID String(64) MandatoryUnique reference ID for every customer which is generated by merchant Special characters allowed in Cust_ID are @, ! ,_ $
TXN_AMOUNT String(10) MandatoryAmount in INR payable by customer. Should contain digits up to two decimal points. The amount should not include any separator like (“,”)
CHANNEL_ID String(3) MandatoryThis parameter is used to control the theme of the payment page. Based on the channel passed, Paytm will render the layout suitable for that specific platform
For App, the value is WAP
WEBSITE String(30) MandatoryFor staging environment: WEBSTAGING
For production environment: Will be available here once your activation is complete
INDUSTRY_TYPE_ID String(20) MandatoryFor staging environment: "Retail"
For production environment: Will be available here once your activation is complete
CHECKSUMHASH String(108) MandatorySecurity parameter to avoid tampering. Generated using server side checksum utility provided by Paytm. Merchant has to ensure that this always gets generated on server. Utilities to generate checksumhash is available here
MOBILE_NO Optional String(15) MandatoryCustomer mobile number. Passing this enables faster login for customer into his/her Paytm account
EMAIL Optional String(50) MandatoryCustomer's email ID. Passing this enables faster login for customer into his/her mobile wallet.
CALLBACK_URL String(255) MandatoryStaging Environment:
"https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=<order_id>"
Production Environment:
"https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=<order_id>"

Object: Certificate (optional)

Certificate object stores client-side SSL certificate related information and ensures secured handshake between your app and Paytm. Use this code snippet to create certificate object:

PaytmClientCertificate Certificate = new PaytmClientCertificate(String inPassword, String inFileName);
// inPassword is the password for client side certificate 
//inFileName is the file name of client side certificate

Note:

  • Client certificate must be present in “raw” folder
  • Pass filename without extension. For e.g if filename is “clientCert.cert” then pass only “clientCert”.

Step 3: Initiate Payment

Initialize Service

Parameters required to invoke initialize method are Order and Certificate objects:

Service.initialize(Order, Certificate);

In case you do not wish to pass the certificate, pass NULL:

Service.initialize(Order, null);

Call start transaction method using service object:

 Service.startPaymentTransaction(this, true, true, new PaytmPaymentTransactionCallback() {
	/*Call Backs*/
                       public void someUIErrorOccurred(String inErrorMessage) {}
                       public void onTransactionResponse(Bundle inResponse) {}
                       public void networkNotAvailable() {}
                       public void clientAuthenticationFailed(String inErrorMessage) {}
                       public void onErrorLoadingWebPage(int iniErrorCode, String inErrorMessage, String inFailingUrl) {}
                       public void onBackPressedCancelTransaction() {}
                       public void onTransactionCancel(String inErrorMessage, Bundle inResponse) {}
     });

Parameters used in startPaymentTransaction in order are -

  • contextofyourActivity is the activity context in where this method is called
  • A boolean variable (true/false) to hide or show header bar.
  • A boolean variable (true/false) to determine whether to send all checksum response parameters to PG server or not
  • inPaymentTransactionCallback is a PaytmPaymentTransactionCallback instance to send callback messages back to your application. Details and description provided in next section

Step 4: Handling callback from Paytm

You need to implement callback methods to handle payment response. This will provide the payment status and reason for transaction failures. Based on the reasons for failures, handling can be built at your end. Transaction callbacks can be listened via overriding methods of PaytmPaymentTransactionCallback

After transaction is complete:

Once the transaction is complete, you will get a JSON response. Note that completion of transaction does not imply that payment is successful. Payment can be in successful or failed state which needs to be derived from JSON.

public void onTransactionResponse(Bundle inResponse) {
	/*Display the message as below */
	Toast.makeText(getApplicationContext(), "Payment Transaction response " + inResponse.toString(), Toast.LENGTH_LONG).show();
}

User interface error:

This is caused when SDK is unable to load the payment page. This might happen in case SDK is not able to parse the transaction payload received from the app

public void someUIErrorOccurred(String inErrorMessage) {
	/*Display the error message as below */
	Toast.makeText(getApplicationContext(), "UI Error " + inErrorMessage , Toast.LENGTH_LONG).show();
}

Network Error:

Due to weak or no internet connectivity on customer's device.

public void networkNotAvailable() {
	/*Display the message as below */
	Toast.makeText(getApplicationContext(), "Network connection error: Check your internet connectivity", Toast.LENGTH_LONG).show();
}

Client authentication failure:

This can happen due to multiple reason -

  1. Paytm services are not available due to a downtime
  2. Server unable to generate checksum or checksum response is not in proper format
  3. Server failed to authenticate the client. That is value of payt_STATUS is 2. // payt_STATUS hasn't been defined anywhere
public void clientAuthenticationFailed(String inErrorMessage)  {
        /*Display the message as below */
        Toast.makeText(getApplicationContext(), "Authentication failed: Server error" + inResponse.toString(), Toast.LENGTH_LONG).show();
}

Error in loading web page:

This is caused when SDK is unable to load the payment page. This might happen due to server unavailability at Paytm's end or due to handshaking error with Paytm gateway

public void onErrorLoadingWebPage(int iniErrorCode, String inErrorMessage, String inFailingUrl)  {
	/*Display the message as below */
	Toast.makeText(getApplicationContext(), "Unable to load webpage " + inResponse.toString(), Toast.LENGTH_LONG).show();
}

On press of back button

This is caused when user presses a back button on the payment page. Followed by pressing the back button, there is a reconfirmation taken from the customer to leave the payment page

public void onBackPressedCancelTransaction(){
	/*Display the message as below */
	Toast.makeText(getApplicationContext(), "Transaction cancelled" , Toast.LENGTH_LONG).show();
}

On transaction cancelled:

This is caused when a transaction gets cancelled. In case user presses a back or cancel button and confirms to leave the page, this callback is triggered

public void onTransactionCancel(String inErrorMessage, Bundle inResponse)
	/*Display the message as below */
	Toast.makeText(getApplicationContext(), "Transaction Cancelled" + inResponse.toString(), Toast.LENGTH_LONG).show();
}

Step 5: Checksum Generation and Verification

Checksumhash Generation

All requests sent to Paytm via SDK needs to have a checksumhash. Checksumhash is signature used by Paytm to ensure that transaction request has not been tampered. All the request parameters needs to be sent to the server where merchant key is available. Server will use our server side utility and merchant key to generate checksumhash. Code snippet and Checksum generation library are provided below

String merchantMid = "rxazcv89315285244163";
// Key in your staging and production MID available in your dashboard
String merchantKey = "gKpu7IKaLSbkchFS";
// Key in your staging and production MID available in your dashboard
String orderId = "order1";
String channelId = "WAP";
String custId = "cust123";
String mobileNo = "7777777777";
String email = "username@emailprovider.com";
String txnAmount = "100.12";
String website = "WEBSTAGING";
// This is the staging value. Production value is available in your dashboard
String industryTypeId = "Retail";
// This is the staging value. Production value is available in your dashboard
String callbackUrl = "https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=order1";
TreeMap<String, String> paytmParams = new TreeMap<String, String>();
paytmParams.put("MID",merchantMid);
paytmParams.put("ORDER_ID",orderId);
paytmParams.put("CHANNEL_ID",channelId);
paytmParams.put("CUST_ID",custId);
paytmParams.put("MOBILE_NO",mobileNo);
paytmParams.put("EMAIL",email);
paytmParams.put("TXN_AMOUNT",txnAmount);
paytmParams.put("WEBSITE",website);
paytmParams.put("INDUSTRY_TYPE_ID",industryTypeId);
paytmParams.put("CALLBACK_URL", callbackUrl);
String paytmChecksum = CheckSumServiceHelper.getCheckSumServiceHelper().genrateCheckSum(merchantKey, paytmParams);
Endpoints:-
Staging: https://securegw-stage.paytm.in/theia/processTransaction
Production: https://securegw.paytm.in/theia/processTransaction

Checksumhash Verification

All responses sent by Paytm consists checksumhash. This checksumhash needs to be verified to ensure that response have not been tampered. Checksum verification is done using our server side utility. Code snippets and Github links for the utility in your language of choice are provided below.

private final String merchantKey = "gKpu7IKaLSbkchFS";
private String paytmChecksum = null;
// Create a tree map from the form post param
TreeMap<String, String> paytmParams = new TreeMap<String, String>();
// Request is HttpServletRequest
for (Entry<String, String[]> requestParamsEntry : request.getParameterMap().entrySet()) {
    if ("CHECKSUMHASH".equalsIgnoreCase(requestParamsEntry.getKey())){
        paytmChecksum = requestParamsEntry.getValue()[0];
    } else {
        paytmParams.put(requestParamsEntry.getKey(), requestParamsEntry.getValue()[0]);
    }
}
// Call the method for verification
boolean isValidChecksum = CheckSumServiceHelper.getCheckSumServiceHelper().verifycheckSum(merchantKey, paytmParams, paytmChecksum);
// If isValidChecksum is false, then checksum is not valid
if(isValidChecksum){
    System.out.append("Checksum Matched");
}else{
    System.out.append("Checksum MisMatch");
}

Get the sample code for a language of your choice -

On completion of your integration -


Post completion of integration on your staging environment, do a complete transaction from order summary page on your website or mobile app

  1. Attempt a test transaction using test paymodes credentials
  2. Ensure you re-verify transaction response with Transaction Status API via server to server call in payment flow and not separately as a one time activity
  3. See the transaction details in “Test Data” mode on your dashboard

Once the test transaction is complete, move your code to live environment with production account details. Note that production accounts details are available after you have activated your account on the dashboard

Lastly, it's recommended that you read about Managing Refunds and late payment notifications

In case of any issues, please search or post your query on our Developer Forum or send your queries to devsupport@paytm.com