Skip to main content

Android Native SDK: PortOne'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 jwt token with your client key and secret key.
internal fun getJwtToken(clientKey:String,secretKey:String): String {
val cur = Calendar.getInstance().time
val generationTime: Long = cur.time / 1000
val expirationTime: Long = generationTime + 100
val jwt = Jwts.builder()
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "HS256")
.claim("iss", "CHAIPAY")
.claim("sub", clientKey)
.claim("iat", generationTime)
.claim("exp", expirationTime)
.signWith(SignatureAlgorithm.HS256,
secretKey.toByteArray(
StandardCharsets.UTF_8
)
)
.compact()
return jwt
}

Recomanded Library for generating jwt Token on frontend:

implementation 'io.jsonwebtoken:jjwt:0.9.1'

Authentication | PortOne

  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. To checkout using webview, the following method has to be invoked with the required request body
val checkoutDetails = CheckoutPaymentDto.CheckoutUsingWebRequest()
portone.checkoutUsingWeb(
token = getJwtToken(clientKey,secretKey),
clientKey = clientKey,
request = checkoutDetails
)
  1. 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