Overview of Paytm payment integration using all-in-one SDK
In this blog, we will learn how to implement Paytm payment integration using an all-in-one SDK. Before starting the Paytm Standard Checkout provides a secure and PCI-compliant way to accept payments on both website and App through different payment sources like Credit/Debit Card, Net-Banking, UPI, and Paytm Wallet from the customers.
The customers can easily pay online for their Website orders using Paytm. They are redirected to the Paytm Webpage for making secure payments.
The payment process starts at the click of the pay button on the merchant order summary page. On this click, you need to:
Add Dependencies for All-in-One SDK
a.) Add the line below to the ‘repositories’ section of your project-level build. Gradle file.
1 2 3 |
maven { url "https://artifactory.paytm.in/libs-release-local" } |
b.) Add the line below to the ‘dependencies’ section of your app build. Gradle
1 |
implementation 'com.paytm.appinvokesdk:appinvokesdk:1.5.3' |
Paytm provides MID as a unique identifier to each merchant. For your staging MID, click here. You get the production MID post the account activation.
1.) At the very start, you need to create an order on the app and then generate a transaction token by using the below-mentioned API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
private fun getPaytmTransaction(paytmDetails: PaytmDetails, orderId: String) { (mFragmentContext.context as CheckoutActivity).mContentViewBinding.loading = true var host = "" if (paytmDetails.environment == "Staging") { IS_PATM_STAGIN = true host = "https://securegw-stage.paytm.in/" } else { IS_PATM_STAGIN = false host = "https://securegw.paytm.in/" } var myCompositeDisposable: CompositeDisposable? = CompositeDisposable() val requestInterface = Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build().create(PaytmTransactionResponseModel::class.java) myCompositeDisposable?.add(requestInterface.getData( paytmDetails.merchant_id!!, paytmDetails.amount!!, paytmDetails.currency!!, paytmDetails.website!!, orderId) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ paytmTransactionResponseModel -> handleResponse(paytmTransactionResponseModel,paytmDetails,orderId) }, { error -> Toast.makeText(mFragmentContext.context,error.message,Toast.LENGTH_SHORT) } ) } |
1 2 3 4 5 6 |
private fun handleResponse(paytmTransactionResponseModel: PaytmTransactionResponseModel, paytmDetails: PaytmDetails, orderId: String) { if (paytmTransactionResponseModel.success && !orderId.isNullOrEmpty()) { paytmPlaceOrder(paytmDetails, orderId, paytmTransactionResponseModel) } } |
After calling the paytmTransaction API, we receive the “transaction tokens” and “callback URL”
2.) Here’s the completed interface:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import io.reactivex.Observable import retrofit2.http.GET interface GetData { //Describe the request type and the relative URL// @FormUrlEncoded @POST("paytmTransaction") fun paytmTransaction(@Field("merchant_id") merchant_id: String, @Field("amount") amount: String, @Field("currency") currency: String, @Field("websiteName") websiteName: String, @Field("orderId") orderId: String): Observable<PaytmTransactionResponseModel> } |
3.) After that do launch Paytm All-in-One SDK with the transaction token received before
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
private fun paytmPlaceOrder(paytmDetails: PaytmDetails, orderId: String, paytmTransactionResponseModel: PaytmTransactionResponseModel) { if (!paytmTransactionResponseModel.response.body.txnToken.isNullOrEmpty()) transactionToken = paytmTransactionResponseModel.response.body.txnToken if (!paytmDetails.callbackUrl.isNullOrEmpty()) callBackUrl = paytmDetails.callbackUrl.toString() if (!transactionToken.isNullOrEmpty() && !callBackUrl.isNullOrEmpty() && !paytmDetails.merchant_id.isNullOrEmpty()) { setStatus(R.string.msg_redirecting_to_paytm) val paytmOrder = PaytmOrder(orderId, paytmDetails.merchant_id, transactionToken, paytmDetails.amount, callBackUrl) val transactionManager = TransactionManager(paytmOrder, object : PaytmPaymentTransactionCallback { override fun onTransactionResponse(bundle: Bundle) { Log.d("Paytm", "PayTM Transaction Response: %s$bundle") val orderId = bundle.getString("ORDERID") val status = bundle.getString("STATUS") val message = bundle.getString("RESPMSG") val txnDate = bundle.getString("TXNDATE") val mid = bundle.getString("MID") val txnId = bundle.getString("TXNID") if (!orderId.isNullOrEmpty() && !status.isNullOrEmpty() && !txnDate.isNullOrEmpty()) { checkPaymentStatus(orderId, status, txnDate) } else { Toast.makeText(mFragmentContext.context as CheckoutActivity, baseModel.message, Toast.LENGTH_LONG).show() (mFragmentContext.context as CheckoutActivity).finish() } } override fun networkNotAvailable() { Log.d("Paytm", "networkNotAvailable") } override fun onErrorProceed(s: String) { Log.d("Paytm", "onErrorProceed: %s$s") Toast.makeText(mFragmentContext.context as CheckoutActivity, s, Toast.LENGTH_LONG).show() if (!(mFragmentContext.context as CheckoutActivity).isFinishing) { (mFragmentContext.context as CheckoutActivity).finish() } } override fun clientAuthenticationFailed(s: String) { Log.d("Paytm", "clientAuthenticationFailed: %s$s") Toast.makeText(mFragmentContext.context as CheckoutActivity, s, Toast.LENGTH_LONG).show() if (!(mFragmentContext.context as CheckoutActivity).isFinishing) { (mFragmentContext.context as CheckoutActivity).finish() } } override fun someUIErrorOccurred(s: String) { Log.d("Paytm", "someUIErrorOccurred: %s$s") Toast.makeText(mFragmentContext.context as CheckoutActivity, s, Toast.LENGTH_LONG).show() if (!(mFragmentContext.context as CheckoutActivity).isFinishing) { (mFragmentContext.context as CheckoutActivity).finish() } } override fun onErrorLoadingWebPage(i: Int, s: String, s1: String) { Log.d("Paytm", "onErrorLoadingWebPage: %s$s $s1") Toast.makeText(mFragmentContext.context as CheckoutActivity, "onErrorLoadingWebPage: %s$s $s1", Toast.LENGTH_LONG).show() if (!(mFragmentContext.context as CheckoutActivity).isFinishing) { (mFragmentContext.context as CheckoutActivity).finish() } } override fun onBackPressedCancelTransaction() { Toast.makeText(mFragmentContext.context as CheckoutActivity, "onBackPressedCancelTransaction", Toast.LENGTH_LONG).show() if (!(mFragmentContext.context as CheckoutActivity).isFinishing) { (mFragmentContext.context as CheckoutActivity).finish() } } override fun onTransactionCancel(s: String, bundle: Bundle) { Log.d("Paytm", "onErrorLoadingWebPage: %s$s") Toast.makeText(mFragmentContext.context as CheckoutActivity, s, Toast.LENGTH_LONG).show() if (!(mFragmentContext.context as CheckoutActivity).isFinishing) { (mFragmentContext.context as CheckoutActivity).finish() } } }) transactionManager.setShowPaymentUrl("${host}theia/api/v1/showPaymentPage") transactionManager.startTransaction(mFragmentContext.context as CheckoutActivity?, ActivityRequestCode) } } |
After calling the Paytm All-in-one-SDK API we receive the TXN_SUCCESS status.
4.) After getting the status callback “TXN_SUCCESS” we will call the order status API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
private fun checkPaymentStatus(orderId: String, status: String, createdTime: String) { (mFragmentContext.context as CheckoutActivity).mContentViewBinding.loading = true ApiConnection.changeOrderStatus(mFragmentContext.context as CheckoutActivity, mSaveOrderResponseModel.incrementId.toString(), getConfirmResponseData(orderId, status, createdTime)) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .subscribe(object : ApiCustomCallback<BaseModel>(mFragmentContext.context as CheckoutActivity, true) { override fun onNext(baseModel: BaseModel) { super.onNext(baseModel) (context as CheckoutActivity).mContentViewBinding.loading = false if (baseModel.success) { val intent = Intent(mFragmentContext.context as CheckoutActivity, OrderPlacedActivity::class.java) intent.putExtra(BUNDLE_KEY_SAVE_ORDER_RESPONSE, mSaveOrderResponseModel) (mFragmentContext.context as CheckoutActivity).startActivity(intent) (mFragmentContext.context as CheckoutActivity).finish() } else { Toast.makeText(mFragmentContext.context as CheckoutActivity, baseModel.message, Toast.LENGTH_LONG).show() (mFragmentContext.context as CheckoutActivity).finish() } } override fun onError(e: Throwable) { super.onError(e) (context as CheckoutActivity).mContentViewBinding.loading = false onErrorResponse(e) } }) } private fun setStatus(message: Int) { Toast.makeText(mFragmentContext.context as CheckoutActivity, message, Toast.LENGTH_LONG).show() } |
5.) After Paytm processes the transaction with the user’s bank and returns the transaction response to your app.
6.) Notify the payment status to the user and proceed with the order/service fulfillment
For more understanding please can go through these links:
https://developer.paytm.com/docs/all-in-one-sdk/sdk-based-integration/
You can also check this link:
https://mobikul.com/paytm-checkout/
https://mobikul.com/paytm-integration-android/