Juspay Developer Guide

Welcome to the Juspay Developer Guide. You'll find comprehensive guides and documentation to help you start working with Juspay Docs as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started

Android Integration

Introduction

JusPay Safe Browser (codename: Godel) aims to reduce friction in Second Factor Authentication for Cards and Netbanking.

The library provides various convenience and security features for users to be able to complete the transaction quickly. The library also provides much deeper insight into the events occurring in the payment flow. With Godel, you will be able to provide a pleasing payments experience to your Android users.

This documentation explains the steps to integrate the library into your native Android application.

Get SDK

The library can be added as a direct dependency when you use Gradle. If you don't use Gradle, we provide a downloadable SDK which you can add as a project dependency. Before you initialize the Browser SDK, please call the following function from your Checkout Activity:

JuspayBrowserFragment.openJuspayConnection(context);

Versioning

For supporting the wide variety of minSdk-targetSdk versions we have baked in the SDK versions into the library version. The final version number is a concatenation of base number and minSdk-targetSdk.

The current base version being 0.6.25.3, the final library version is in the format of 0.6.25.3.xxxx.

Version NumberminSdktargetSdk
0.6.25.3.14211421
0.6.25.3.14231423
0.6.25.3.16231623
0.6.25.3.16251625

Add the following maven repository to the build.gradle. Please make sure that you add it in the project dependency section and NOT the buildScript section.

// Add to build.gradle

repositories {
  mavenCentral()
  maven {
    url "https://s3-ap-southeast-1.amazonaws.com/godel-release/godel/"
  }
}

dependencies {
  compile 'in.juspay:godel:0.6.25.3.1423'

  // your other dependencies
  ...
  ...
}

๐Ÿ“˜

Note: Godel library is using support library version 23.4.0

๐Ÿ“˜

Brief changelog is available here

Setup Permissions

JusPay Safe browser currently supports all applications using version >= Android API version 14.

The following are the minimum set of permissions required for the library to work as expected:

<!-- File AndroidManifest.xml-->

<manifest ...>

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

  <application>

    <!-- activity declaration -->
    <activity
        android:label="Processing your payment"
        android:name="in.juspay.godel.PaymentActivity"
        android:hardwareAccelerated="true"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize"
      >
    </activity>
  </application>
</manifest>

Start the browser

Instantiate BrowserCallback

Callback which will be invoked when a user completes the payment or cancels it midway. Whenever a payment is completed (successfully or not), the aggregator/gateway will send the user back to your website. Usually, you would pass single return_url or multiple URLs to aggregator to represent success, failure or cancel.

onTransactionAborted(JSONObject paymentDetails)

Method onTransactionAborted is invoked when the user clicks back button in the payment flow. We assume that the intent of the user is to cancel the transaction. Detailed information of the session is passed in the JSONObject parameter.

endUrlReached(WebView view, JSONObject paymentDetails)

Method endUrlReached is invoked when we encounter a URL which is identified by you as a return URL or the last URL in the payment flow. The matched URL will be passed in the URL key of the JSONObject parameter.

JusPay Browser expects endUrlRegexes as an input. This variable represents an array of String which are regular expressions to match the final return URL. You can send as many URLs as you want here. If the return flow (from the gateway to merchant) uses HTTP GET, shouldOverrideUrlLoading is used to check if the URL matches the regex and in case of POST, onPageStarted method will evaluate the regex. If matched, then endUrlReached is invoked by the browser. You will now have control of the user session.

public BrowserCallback callBack = new BrowserCallback() {

  @Override
  public void onPageStarted(WebView view, String url) {
    super.onPageStarted(view, url);
  }

  @Override
  public void onTransactionAborted(JSONObject paymentDetails) {
    GodelTracker.getInstance().trackPaymentStatus(transactionId, GodelTracker.FAILURE);
    JuspaySafeBrowser.exit();

    Toast.makeText(context,  "Transaction cancelled.", Toast.LENGTH_LONG).show();

    // Payment was not completed by the user. So, let's present the retry option to the user.
    NextActivity.this.retryPayment(); 
  }

  @Override
  public void onWebViewReady(WebView webView) {
    Log.d(TAG, "onWebViewReady: url " + webView.getUrl());
  }

  @Override
  public void endUrlReached(WebView view, JSONObject sessionInfo) {
    GodelTracker.getInstance().trackPaymentStatus(transactionId, GodelTracker.SUCCESS);
    JuspaySafeBrowser.exit();

    // Required action performed
    Toast.makeText(context, "Transaction completed. Maybe failure/success.", Toast.LENGTH_LONG).show();
    // Payment step has been completed by the user. Take the user to the next step.
    NextActivity.this.startNextActivity();
  }
};

๐Ÿ“˜

If your aggregator uses HTTP GET to redirect the user to you, then the last URL will never hit your server. However, if HTTP POST is used, then the URL will hit your server (with POST parameters).

Deprecation Notice:

๐Ÿ“˜

ontransactionAborted() and endUrlReached(String url) are now deprecated in favour of the above methods

paymentDetails JSON Object

paymentDetails json object provides a list of attributes to understand session of the payment. This object is passed via the onTransactionAborted method and endUrlReached method of BrowserCallback interface.

Find below the set of parameters which will be sent:

VariableDescriptionTypeExample
inferred_payment_statusOverall payment Status inferred by Juspay SafeStringSUCCES
payment_statusesPayment status details inferred stage-wiseJSON{
"bank_payment_status":"SUCCESS",
"pg_payment_status":"SUCCESS",
"aggregator_payment_status":"SUCCESS"
}
dropout_reasonsA JSON Object that has the user dropout reasonJSON{
"dropoutReason":["User Aborted"],
"backPressed":true,
"networkStatus":"CONNECTED",
"authenticationStatus":"",
"potentialPaymentFlowError":""
}
realtimeA JSON Object that has the system metricsJSON{
"last_visited_url":"https://www.sampleurl.com/success",
"backPressed":true,
"otp_detected":"true",
"otp_approved":"auto",
"sms_permission":"true"
}
url*The url at which transaction was completed.Stringhttps://www.sampleurl.com/success

๐Ÿ“˜

  • Payment statuses (inferred_payment_status, bank_payment_status, pg_payment_status, aggregator_payment_status) can be one of: SUCCESS, FAILURE or UNKNOWN.

  • OTP Approved (in realtime) can be one of NA, auto or manual.

๐Ÿ“˜

  • The attribute url shall be passed only for endUrlReached method

Create BrowserParams Object

BrowserParams class provides an easy-to-use interface to add all the parameters that must be sent to JusPay Safe browser. Create an instance of the class to get started:

BrowserParams browserParams = new BrowserParams();
Find below the set of parameters which must be sent:

|Variable   |Description    |Type   |Required   |Default|
|---------|-------------|-----|---------|-------|
|url    |Start URL for payment  |String |Yes|   |
|postData   |POST parameters that must be passed to the URL |String |No | |
|merchantId|    Identifies the merchant. Eg. 'merchantโ€™|    String  |Yes|   |
|clientId   |ClientID defines the platform used. Eg. 'merchant_androidโ€™ |String |Yes    | |
|transactionId  |Represents the current transactionId   |String |Yes| | 
|orderId|   Represents the order number assigned by the merchant    |String|    Yes| |  
|amount |Amount of the transaction  |String |Yes    | |
|customerId |Unique identifier of the customer  |String|    No| |   
|customerEmail| Email address of the customer   |String |No | |
|customerPhoneNumber|   Mobile number of the customer   |String|    No  | |
|displayNote (Deprecated)   |Short note about transaction shown to the customer. ex. 'Paying INR 200 for Order 123456'| String| No  | |
|remarks|   Remarks about transaction. This will be automatically filled up in the netbanking page. ex. 'Pay to merchant'|  String| No  | |
|clearCookies|  If true, we will clear webView cookies whenever Juspay Webview is initialized.  |Boolean|   No| False|

See the example below:
BrowserParams browserParams = new BrowserParams();
browserParams.setMerchantId("shop");
browserParams.setClientId("shop_android");
browserParams.setOrderId("ord_111222");
browserParams.setTransactionId("txn_111222");
browserParams.setAmount("12019.50");

browserParams.setCustomerId("9988776655");
browserParams.setCustomerEmail("[email protected]");
browserParams.setCustomerPhoneNumber("9988776655");

browserParams.setRemarks("Flight MUM DEL");

browserParams.setUrl(PAYMENT_URL);
browserParams.setPostData(PAYMENT_POST_DATA);

๐Ÿ“˜

All values in postData should be URL encoded before setting browserParams.setPostData(PAYMENT_POST_DATA);. If you do not URL encode the values, then your gateway/aggregator will show error message in the browser.

๐Ÿ“˜

browserParams.setDisplayNote() is deprecated. Please use OnScreenDisplay class.

Custom Parameters

Custom parameters let you add new dimensions which can be very useful for analytics. Please make sure that the dimensions you choose are dense. It does not make sense to put the mobile number or email address as a custom parameter.

VariableDescriptionRequired
udf_:var1Custom FieldNo
udf_:var2Custom FieldNo
udf_:var3Custom FieldNo
Map<String,String> customParameters = new HashMap<String, String>();
customParameters.put("udf_category", "FLIGHT");
customParameters.put("udf_city","BANGALORE");
customParameters.put("udf_cardbrand","VISA");
browserParams.setCustomParameters(customParameters);

With the above, if you have categories such as FLIGHT, BUS, and TRAIN, then you can measure the success rate for each of these categories and compare them with each other.

Custom HTTP Headers

Sometimes you would want to pass more information as HTTP headers to the first URL. BrowserParams class accepts a Map of as custom headers. All the headers set here will be sent to WebView as HTTP headers.

Map<String, String> customHeaders = new HashMap<String, String>();
customHeaders.put("Accept-Encoding", "gzip, deflate, sdch");
customHeaders.put("Accept-Language", "en-US,en;q=0.8");
browserParams.setCustomHeaders(customHeaders);

Define endUrls

The array of Strings each of which will be interpreted as regular expressions. Every URL loaded (in onPageStarted) by the browser will be matched against each of the array items. If a match is found, then the browser stops further processing and delegates the control back to the app via BrowserCallback.

JuspaySafeBrowser.setEndUrls(new String[]{"https://shop\\.com/paymentResponse.*", 
    "https://beta\\.shop\\.com/paymentResponse.*"})

๐Ÿ“˜

Hint: Be sure to escape the dots as required. Note the final .* is deliberately not escaped.

Start the Browser

Now, start the browser and wait for it to complete. This starts the payment activity and gives the callback when aborted or successful.

JuspaySafeBrowser.start(this, browserParams, callBack);

User Logout

User should be logged out of Juspay session whenever he logs out of the Merchant App. This ends the user session with Juspay Safe.

JuspaySafeBrowser.performLogout(getApplicationContext());

UI Customisations

Styling Action Bar

Background color, background image and logo of ActionBar can be customized by setting appropriate attributes in BrowserParams. You can either pass background color or background image. If both are passed, priority will be given to the background image.

browserParams.setActionBarIcon(getResources().getDrawable(R.drawable.juspay_logo_white));
browserParams.setActionBarBackgroundColor(new ColorDrawable(0xFF0000BB));
browserParams.setActionBarBackgroundImage(getResources().getDrawable(R.drawable.abc_item_background_holo_light));

Adding Order Summary

You can give a brief order summary to the user by using the OnScreenDisplay object. This would show above the webview, just below the toolbar. Use one of the predefined views to construct a OnScreenDisplay object and pass it to the browser by calling browserFragment.showOnScreenDisplay(osd)

Travel

Onwards Journey

Create a TravelModel for onwards journey and pass it in the single-param constructor. For the best user experience set all the values as shown below.

TravelModel onwardsTravelModel = new OnScreenDisplay.TravelModelBuilder()
                        .setJourneyFromCity(new JourneyCity("Bangalore", "BLR", "8:00 AM"))
                        .setJourneyToCity(new JourneyCity("New Delhi", "DEL", "11:30 AM"))
                        .setJourneyFlightNumber("6E-522")
                        .setJourneySeatingClass("Economy")
                        .setJourneyAirlineName("Indigo")
                        .setJourneyDate("11 Sep 2016")
                        .setTravellersNameList(getTravellersList())
                        .createTravelModel();

OnScreenDisplay osd = OnScreenDisplay.Travel(onwardsTravelModel)
                        .setAmount("โ‚น 12300")
                        .build();

Return Journey

You can create two TravelModel like above pass them both in the two-params constructor.

OnScreenDisplay osd = OnScreenDisplay.Travel(onwardsTravelModel, returnTravelModel)
                        .setAmount("โ‚น 12300")
                        .build();

Multicity Journey

Create a list of TravelModel and pass it in the single list param constructor.

List<TravelModel> travelModelList = new ArrayList<TravelModel>();
traveModelList.add(firstTravelModel);
traveModelList.add(intermediateTravelModel);
traveModelList.add(lastTravelModel);

OnScreenDisplay osd = OnScreenDisplay.Travel(travelModelList)
                        .setAmount("โ‚น 12300")
                        .build();

Booking

Hotel Booking

For Hotel, booking use the constructor with the following parameters

VariableDescriptionRequired
bookingTitlePrimary title. Appears on collapsed layout and on the top of the expanded view.Yes
bookingSubTitleSecondary Tite. Usually the address of the hotel.Yes
bookingShortDesc Short description of the stay. Usually stating the number of guests and nights.Yes
hotelBookingModelModel created using HotelModelBuilderYes
OnScreenDisplay.HotelBooking("Hotel Maverick International",
        "Old Madras Road, Bangalore, Karnataka",
        "2 Guests | 3 Nights",
        new OnScreenDisplay.HotelModelBuilder()
                .setCheckInDate("23 Sept 2016")
                .setCheckInExtra("08:00 AM")
                .setCheckOutDate("25 Sept 2016")
                .setCheckOutExtra("11:00 PM")
                .setGuestList(getGuestList())
                .createHotelModel())
        .setAmount("โ‚น 12300")
        .build();

Event Booking

Event booking OSD for Movies, Events orders.

OnScreenDisplay.EventBooking(new OnScreenDisplay.EventModelBuilder()
            .setDate("24 Sep 2016")
            .setTime("7 PM")
            .setEventName("Star Wars: Force Awakens")
            .setVenue("Inox Forum")
            .setTicketCount(1)
            .setTicketDescription("Normal - G40, G41, G54")
            .createEventModel())
    .setAmount("โ‚น 12300")
    .build();

GeneralPurchase

This is a builder which can be used for E-Commerce, Recharge or Delivery.

VariableDescriptionRequired
orderTitlePrimary title. Appears on collapsed layout and on the top of the expanded view.Yes
orderSubtitleSecondary Title. Usually the product's company name.Yes
purchaseDateTime or Date of the order.Yes
sellerNameSeller nameYes
extrasList displayed at bottom of the expanded view. Eg estimated delivery time, availed offerYes
OnScreenDisplay.GeneralPurchase("Sony MDR 650-BT",
        "by Sony",
        "8:45 PM 14 Sept 2016",
        "CloudTail", extras)
        .setAmount("โ‚น 12300")
        .build();

Collapsed Only

If you don't want to show an expanded view in the OSD, you can use this OSD Type. The expansion would be disabled for this OSD type.

OnScreenDisplay.CollapsedOnly("Recharge for 9829880095")
        .setAmount("โ‚น 145")
        .build()

Generic Builder

A generic builder can be used to create the UI manually. Start by sending the order title in the OnScreenDisplay.Generic("MacBook Pro Retina") API. You can now access the following methods to build the UI:

MethodDescription
appendSingleLineAdds a single line text view
appendDoubleLineAdds a vertically stacked double line view with title and subtitle hierarchy
appendTripleLineAdds a vertically stacked triple line view with title, subtitle and a caption
appendDottedDividerA dotted line across the full width of the view
appendFullDividerA full line across the full width of the view
OnScreenDisplay.Generic("MacBook Pro")
        .appendTripleLine("Vimal Kumar", "#513, Adayar", "Chennai, 600002")
        .appendDottedDivider()
        .appendDoubleLine("Contact", "+91-9829880095")
        .appendDoubleLine("Order Id", "#1337")
        .setAmount("54,000")
        .build()

Send Payment Status

Once payment has been completed, you should inform us if the payment was successful. This is important to provide better analytics in identifying top areas of failure points. Payment status can be one of: SUCCESS, FAILURE or CANCELLED.

Among all the three techniques, sending the status from the server is the most reliable as the network between servers is much more robust.

From endUrlReached function

Since we always invoke endUrlReached method for all payment completions, you could send us the payment status at that point.

// Putting payment status
public BrowserCallback callBack = new BrowserCallback() {

  @Override
  public void onTransactionAborted(JSONObject paymentDetails) {
    GodelTracker.getInstance().trackPaymentStatus(transactionId, GodelTracker.FAILURE);
    JuspaySafeBrowser.exit();

    // Required action performed
  }

  @Override
  public void endUrlReached(WebView webView, JSONObject paymentDetails) {
    GodelTracker.getInstance().trackPaymentStatus(transactionId, GodelTracker.SUCCESS);
    JuspaySafeBrowser.exit();

    // Required action performed
  }

};
However, it may not always be possible to have the payment status at this point, especially if the aggregator uses HTTP POST for sending the payment details. In such cases, you can POST the status from the next activity or from your server.

## From the next activity
public class PaymentCompleteActivity {

  public void onCreated(Bundle savedInstanceState) {
    String transactionId = getTransactionIdOfCurrentPayment();
    String status = getPaymentStatusFromServer(transactionId);
    GodelTracker.getInstance().trackPaymentStatus(transactionId, GodelTracker.PaymentStatus.SUCCESS);
  }

}

From your Server

Payment status can also be sent from your servers. Please make sure that the following parameters are sent correctly along with the status:

  • client_id
  • merchant_id
  • order_id
  • transaction_id

Data must be sent as a properly formatted JSON. Example payload:

{
  "data":[
    {
      "merchant_id":"shop",
      "client_id":"shop_android",
      "order_id":"ord_112233",
      "transaction_id":"txn_112233",
      "payment_status":"SUCCESS"
    }
  ]
}
Payment status can be one of: SUCCESS, FAILURE or CANCELLED. Example HTTP POST to send payment status is provided below:
# Post status directly to Juspay server
curl https://logs.juspay.in/godel/analytics \
  -H 'Content-Type: application/json' \
  -d '{"data":[{"merchant_id":"shop", "client_id":"shop_android", "order_id":"ord_112233", "transaction_id": "txn_112233", "payment_status":"SUCCESS"}]}'

๐Ÿ“˜

Note: This is the preferred method for sending Status to JusPay. Please send if Failure also. Otherwise, the transactions will be categorized as unknown.

Proguard rules

Most part of JusPay's library is already compressed with ProGuard. If your application uses ProGuard as well (and we think you should if you don't already), then please do specify the following rule to avoid integration issues:

-keep class in.juspay.** {*;}

Integration checklist

  1. Ensure android:windowSoftInputMode="adjustResize" is stated for the PaymentActivity in AndroidManifest.xml. JusPay Safe browser only works in Portrait mode. So you should also fix the orientation as 'portrait'.

  2. Ensure that correct value is sent for the following:

    • merchantId
    • clientId
    • orderId
    • transactionId
    • amount
  3. Send payment_status via GodelTracker.trackPaymentStatus or POST this information to our servers directly. We would recommend server-side POST technique as it is 100% reliable.

  4. All the classes under in. juspay namespace should be kept out of ProGuard optimization.

  5. Lastly, please get your final build checked by our team. You may write to [email protected] for this.

Updated about a year ago


Android Integration


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.