Skip to main content

Android Native SDK: Merchant's Checkout

Integration:#

SDK Integration prerequisites#

  1. Add PortOne SDK in dependency in build.gradle (:app)

    implementation 'com.github.iamport-intl:chaipay-android-native-sdk:V3.0.21'
  2. Add Authorization key provided by PortOne in gradle.properties

    //Auth Token will be provided by the PortOne Team
    authToken=XXXXXXXXXXXXXXXXXXXXXX
  3. Add the following snippets in build.gradle (:Project) or in settings.gradle to get access of the library.

    repositories {
    maven { url '<https://maven.google.com/>' }
    maven{
    url '<https://jitpack.io>'
    credentials { username authToken }
    }
    }
  4. Add the following snippets in build.gradle (:Project) to get access of the library.

    buildscript {
    ext.kotlin_version = "1.5.10"
    dependencies {
    classpath 'com.google.gms:google-services:3.0.0'
    }
    }
  5. Initialize the PortOne Instance in your checkout activity which will be used to access checkout methods. You will also require to pass the environment

    private lateinit var portone: PortOne
    private var environment = sandbox // For Sandbox
    private var environment = live // For Live
    portone = PortOneImpl(this, "$environment")
  6. Add the following Intent Filter to the Activity to which you want the user to be navigated after completion of payment. Default is should be Checkout Activity. In the data tag there are two parameters host and scheme whose values will be set according the redirection url.

    redirectionUrl= **portone://checkout**
    then the host will be **checkout** and the scheme will be **portone**
    <data
    android:host="checkout"
    android:scheme="portone" />
    <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data
    android:host="$host"
    android:scheme="$scheme" />
    </intent-filter>

Checkout#

  1. Generate a Signture Hash to be added in payload.
internal fun getSignatureHash(
amount: String,
currency: String,
failureUrl: String,
orderId: String,
clientKey: String,
successUrl: String
): String {
val hashMap: HashMap<String, String> = HashMap()
hashMap["amount"] = amount
hashMap["currency"] = currency
hashMap["failure_url"] = failureUrl
hashMap["merchant_order_id"] = orderId
hashMap["client_key"] = clientKey
hashMap["success_url"] = successUrl
val message = StringBuilder()
for ((key, value) in hashMap.toSortedMap().entries) {
val values = URLEncoder.encode(value, "UTF-8")
if (message.isNotEmpty()) {
message.append("&$key=$values")
} else {
message.append("$key=$values")
}
}
val sha256 = Hashing.hmacSha256(SECRET_KEY.toByteArray(StandardCharsets.UTF_8))
.hashString(message, StandardCharsets.UTF_8).asBytes()
val base64: String = Base64.encodeToString(sha256, Base64.DEFAULT)
Log.i(TAG_CHAI_PAY, "SignatureHash:base64-> $base64")
return base64.trim()
}

Payment Request | PortOne

  1. Following methods are mentioned with their use cases.

    //To get Available Payment Methods
    portone.getPaymentMethods(RequestBodies.clientKey, RequestBodies.currency, object :
    ApiCallbackInterface<PaymentDto.PaymentMethodResponse> {
    override fun onSucceed(response: PaymentDto.PaymentMethodResponse) {
    LoggerUtil.info("Successful")
    }
    override fun onFailure(
    errorCode: Int?,
    status: String?,
    errorMessage: String,
    throwable: Throwable
    ) {
    LoggerUtil.info("Failed")
    }
    })
    //To get the Otp (MobileNumber=CountryCode+Number)
    portone.getOTP($mobileNo, object :
    ApiCallbackInterface<PaymentDto.OtpResponse> {
    override fun onSucceed(response: PaymentDto.OtpResponse) {
    LoggerUtil.info("Successful")
    }
    override fun onFailure(
    errorCode: Int?,
    status: String?,
    errorMessage: String,
    throwable: Throwable
    ) {
    LoggerUtil.info("Failed")
    }
    })
    //To get the saved crads
    // Token is not a mandatory param
    portone.getSavedCards($token, RequestBodies.clientKey, $mobileNo, $otp, object :
    ApiCallbackInterface<PaymentDto.CreditCardDetailsResponse> {
    override fun onSucceed(response: PaymentDto.CreditCardDetailsResponse) {
    LoggerUtil.info("Successful")
    }
    override fun onFailure(
    errorCode: Int?,
    status: String?,
    errorMessage: String,
    throwable: Throwable
    ) {
    LoggerUtil.info("Failed")
    }
    })
    //To Initiate Checkout Without Tokenization
    val checkoutRequest= PaymentDto.CheckoutWithoutTokenizationRequest()
    portone.checkoutWithoutTokenization(checkoutRequest)
    //To Initiate Checkout Using Tokenization
    val checkoutRequest= PaymentDto.CheckoutUsingTokenizationRequest()
    portone.initiatePaymentWithTokenization(checkoutRequest)
    //To Initiate Checkout Using New Credit Card
    val checkoutRequest= PaymentDto.CheckoutUsingTokenizationRequest()
    val newCard= PaymentDto.NewCard()
    portone.checkoutUsingNewCreditCard(
    paymentDetails = checkoutRequest,
    newCard = newCard
    )
    //To Fetch the Bank List with Details
    portone.getBankList(
    RequestBodies.paymentChannel,
    RequestBodies.getBankListRequest(),
    object : ApiCallbackInterface<PaymentDto.BankListResponse> {
    override fun onSucceed(response: PaymentDto.BankListResponse) {
    LoggerUtil.info("Successful")
    }
    override fun onFailure(
    errorCode: Int?,
    status: String?,
    errorMessage: String,
    throwable: Throwable
    ) {
    LoggerUtil.info("Failed")
    }
    })
    //To fetch the direct Bank Transfer Details
    portone.getDBTDetails(RequestBodies.clientKey,
    object : ApiCallbackInterface<PaymentDto.DBTResponse> {
    override fun onSucceed(response: PaymentDto.DBTResponse) {
    LoggerUtil.info("Successful")
    }
    override fun onFailure(
    errorCode: Int?,
    status: String?,
    errorMessage: String,
    throwable: Throwable
    ) {
    LoggerUtil.info("Failed")
    }
    })
  2. After the completion of checkout, app has to receive its payment status which has to be handled using intent and the received status will be passed to the updatePaymentStatus() method

if (null != intent && null != intent.data) {
val paymentStatus = intent.data.toString()
portone.updatePaymentStatus(paymentStatus)
}
  1. The following method has to be added on the checkout activity where the checkout action has performed to receive the checkout status after checkout completion the HashMap format.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_CODE && data != null) {
when (requestCode) {
PAYOUT_REQUEST_CODE, PAYMENT_STATUS_REQUEST_CODE -> {
val paymentStatus: PaymentDto.PaymentStatus? =
(data.getSerializableExtra(PAYMENT_STATUS)
?: "Empty") as PaymentDto.PaymentStatus
}
}
}
}
  1. Things to be taken care while generating payload:
    1. Mandatory params in payload:

      price
      promo_discount (0 is also acceptable)
      shipping_charges (0 is also acceptable)
    2. If items are provided then please verify the values provided should match the total amount: sum(items price * items quantity) + shipping charge - discount = amount


Example Integration:#

https://github.com/iamport-intl/chaiport-android-sdk-merchant-demo-app