Custom Checkout Integration - Android

Learn in detail about our custom checkout integration for android.

The android integration can be completed in three steps and should not take you more than 30 minutes.

Integration Flow

  • Create Order - Create an order in Cashfree Payments system from your backend.
  • Submit the form from your application's web-view as mentioned in this document.
  • Detect the URL redirection and close the web view.

📘

This integration requires your application's package name to be whitelisted by Cashfree Payments. Please check Whitelisting Process


Step 1: Create Order

Please follow the steps mentioned in this link to create an order. This will return a "payment_session_id" value which will be used later.

📘

Don't forget to provide the return URL while creating the order as this will be used to detect payment completion.


Step 2: Pay Order

String platform = "chxx-c-x-x-x-w-x-a-" + android.os.Build.VERSION.SDK_INT;
String paymentSessionID = "PAYMENT_SESSION_ID";
String env = "SANDBOX"; // or "PROD"
String formURL = env.equals("SANBOX")? "https://sandbox.cashfree.com/pg/view/sessions/checkout" : "https://api.cashfree.com/pg/view/sessions/checkout"

String htmlForm = "<html>\n" +
                "\n" +
                "<body>\n" +
                "    <form id=\"redirectForm\" method=\"post\" action=\""+formURL+"\"> \n" +
                "        <input\n" +
                "            type=\"hidden\" name=\"payment_session_id\"\n" +
                "            value=\""+paymentSessionID+"\" />\n" +
                "     
                "        <input type=\"hidden\" name=\"platform\"\n" +
                "            value=\""+platform+"\" /></form>\n" +
                "    <script\n" +
                "        type=\"text/javascript\">\twindow.onload = function () { const form = document.getElementById(\"redirectForm\"); const meta = { userAgent: window.navigator.userAgent, }; const sortedMeta = Object.entries(meta).sort().reduce((o, [k, v]) => { o[k] = v; return o; }, {}); const base64Meta = btoa(JSON.stringify(sortedMeta)); FN = document.createElement('input'); FN.setAttribute('type', 'hidden'); FN.setAttribute('name', 'browser_meta'); FN.setAttribute('value', base64Meta); form.appendChild(FN); form.submit(); }  </script>\n" +
                "</body>\n" +
                "\n" +
                "</html>";

yourWebView.getSettings().setJavaScriptEnabled(true);
yourWebView.getSettings().setDomStorageEnabled(true);
loadDataWithBaseURL("", htmlForm, "text/html", Xml.Encoding.UTF_8.name(), "");

Step 3: Handle Redirection

Once the payment flow has ended, Cashfree Payments will redirect you to the URL specified while creating the order. Detect the URL redirection and close the web view appropriately.

yourWebView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //Find if the url is the return URL you gave while creating the order 
                // and close the webview
                return super.shouldOverrideUrlLoading(view, url);
            }
        });

UPI Intent from Checkout

If you are doing a custom integration of Cashfree Payments Web Checkout in Android and want to add UPI intent functionality, follow the steps below. Read more about UPI Intent functionality here.

  1. Add the queries element in AndroidManifest file.
  2. Add the JSBridge functions for the checkout page to get the list of UPI apps installed and for opening the UPI app selected by the user.
  3. Once the user comes back from the UPI app, the onActivityResult function notifies the checkout page by calling a javascript function inside the checkout page.

You need to add the following to your AndroidManifest.xml

<manifest package="com.example.game">
<queries>
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="upi" android:host="pay"/>
    </intent>
    <package android:name="com.android.chrome" />
</queries>
    ...
</manifest>

Sample Code

import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.net.Uri;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.List;

public class CFWebIntentJSInterface {
    private final CFWebIntentInterface cfWebIntentInterface;

    public CFWebIntentJSInterface(CFWebIntentInterface cfWebIntentInterface) {
        this.cfWebIntentInterface = cfWebIntentInterface;
    }

    public interface CFWebIntentInterface {
        List<ResolveInfo> getAppList(String link);

        String getAppName(ApplicationInfo pkg);

        void openApp(String appPkg, String url);

    }


    @android.webkit.JavascriptInterface
    public String getAppList(String name) {
        final List<ResolveInfo> resInfo = cfWebIntentInterface.getAppList(name);
        JSONArray packageNames = new JSONArray();
        try {
            for (ResolveInfo info : resInfo) {
                JSONObject appInfo = new JSONObject();
                appInfo.put("appName", cfWebIntentInterface.getAppName(info.activityInfo.applicationInfo));
                appInfo.put("appPackage", info.activityInfo.packageName);
                packageNames.put(appInfo);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return packageNames.toString();
    }

    @android.webkit.JavascriptInterface
    public boolean openApp(String upiClientPackage, String upiURL) {
        cfWebIntentInterface.openApp(upiClientPackage, upiURL);
        return true;
    }
}
public class YourWebViewActivity extends AppCompatActivity implements CFWebIntentJSInterface.CFWebIntentInterface {
    private boolean backEnabled = true;
    private WebView yourWebView;
    private static final int REQ_CODE_UPI = 9901;

    @SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"})
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    ...

        yourWebView.getSettings().setJavaScriptEnabled(true);
        yourWebView.getSettings().setDomStorageEnabled(true);

        CFWebIntentJSInterface wbInInterface = new CFWebIntentJSInterface(this);
        yourWebView.addJavascriptInterface(wbInInterface, "Android");

    ...

    }


    @Override
    public List<ResolveInfo> getAppList(String link) {
        ArrayList<ResolveInfo> resolveInfos = new ArrayList<>();
        Intent shareIntent = new Intent(Intent.ACTION_VIEW);
        shareIntent.setData(Uri.parse(link));
        final List<ResolveInfo> resInfos = getPackageManager().queryIntentActivities(shareIntent, 0);
        if (resInfos != null) {
            resolveInfos = new ArrayList<>(resInfos);
        }
        return resolveInfos;
    }

    @Override
    public String getAppName(ApplicationInfo pkg) {
        return (String) getPackageManager().getApplicationLabel(pkg);
    }

    @Override
    public void openApp(String appPkg, String url) {
        final Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(url));
        runOnUiThread(() -> {
            if ("others.upiapp".equals(appPkg)) {
                Intent chooser = Intent.createChooser(intent, "Pay with");
                startActivityForResult(chooser, REQ_CODE_UPI);
            } else {
                intent.setPackage(appPkg);
                startActivityForResult(intent, REQ_CODE_UPI);
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && requestCode == REQ_CODE_UPI) {
            yourWebView.evaluateJavascript("window.showVerifyUI()", (ValueCallback<String>) s -> {});
        }
    }

    @Override
    public void onBackPressed() {
        if (backEnabled)
            super.onBackPressed();
    }
}