Commit 5df2c27c authored by Seatel's avatar Seatel

implement acleda service

parent 8e495f6c
Pipeline #97 failed with stages
package com.seatel.mobilehall.ui.home.activity
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import com.seatel.mobilehall.R
import com.seatel.mobilehall.ui.base.activity.BaseActivity
import com.seatel.mobilehall.util.Constant
import com.seatel.mobilehall.util.SeatelAlertDialog
import com.seatel.mobilehall.util.customview.ErrorHandleView
import androidx.core.net.toUri
import com.seatel.mobilehall.databinding.ActivityAcledaBinding
class AcledaActivity : BaseActivity<ActivityAcledaBinding>() {
private lateinit var mUrlPay: String
private var mAmount: Double = 0.0
private var mPhoneNumber: String? = null
private var isAbleBack: Boolean = false
private var isShowValentineDayPromotion = false
private val mWebViewClient = object : WebViewClient() {
// override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
// println("===>>> WebView onPageStarted: $url")
// super.onPageStarted(view, url, favicon)
// }
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
showHideLoading(false)
}
override fun onReceivedError(
view: WebView, request: WebResourceRequest, error: WebResourceError
) {
super.onReceivedError(view, request, error)
//closeWingPaymentWithError()
closeAcledaPaymentWithError()
}
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
val url = request?.url.toString()
val uri = request?.url.toString()
val host = request?.url?.host ?: ""
Log.d("TAG::>>>", "shouldOverrideUrlLoading: url=$url host=$host")
println("===> URI: $uri")
// SUCCESS
if (url.contains("_paymentresult=SUCCESS")) {
TopUpSuccessActivity.lunch(
this@AcledaActivity,
Constant.TOPUP_SUCCESS,
mAmount.toString(),
mPhoneNumber ?: ""
)
finish()
return true
}
// CANCEL / SESSION EXPIRED
if (url.contains("cancel")) {
val uri = url.toUri()
val resultMsg = uri.getQueryParameter("_resultmsg") ?: "Payment failed"
exitAcledaPayment(false)
return true
}
val allowedHosts = listOf(
"yes.com.kh",
"dev.yes.com.kh",
"api.yes.com.kh",
"acleda.com.kh",
"api-dev.yes.com.kh"
)
println("===> allowedHosts: $allowedHosts")
if (allowedHosts.any { host.contains(it) }) return false
println("===> host return : $host")
startActivity(Intent(Intent.ACTION_VIEW, url.toUri()))
return true
}
}
private fun closeAcledaPaymentWithError() {
showHideLoading(false)/* SeatelAlertDialog.with(this, getString(R.string.message_wing_error)).setCancelable(true)
.setPositiveButton(getString(R.string.yes)) { _, _ ->
exitWingPayment(false)
}.show()*/
}
private fun closePaymentProcress() {
if (binding.webViewAcleda.canGoBack()) {
binding.webViewAcleda.goBack()
} else {
showHideLoading(false)
SeatelAlertDialog.with(this, getString(R.string.cancel_process_payment))
.setCancelable(true).setPositiveButton(getString(R.string.yes)) { _, _ ->
exitAcledaPayment(false)
}.setNegativeButton(getString(R.string.cancel)) { dailog, _ ->
dailog.dismiss()
}.show()
}
}
override fun isDisplayBackgroundBlur(): Boolean {
return false
}
override fun isDisplayToolbar(): Boolean {
return false
}
override fun isStatusBarColorDark(): Boolean {
return true
}
override fun getViewBinding(): ActivityAcledaBinding {
return ActivityAcledaBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
println("===> OnCreateAcledaCalled")
activityEnterFadeInAnimation()
showHideLoading(true)
init()
}
private fun showHideLoading(isShow: Boolean) {
if (isShow) {
binding.errorView.visibility = View.VISIBLE
binding.errorView.setViewMode(ErrorHandleView.Mode.LOADING)
} else {
binding.errorView.visibility = View.GONE
}
}
@SuppressLint("SetJavaScriptEnabled")
private fun init() {
mUrlPay = intent.getStringExtra("payment_url") ?: ""
println("===> Payment URL: $mUrlPay")
// Log.d("TAG::>>>", "acledaUrl: $mUrlPay")
// if (mUrlPay.isEmpty()) {
// closeAcledaPaymentWithError()
// return
// }
isShowValentineDayPromotion = intent.getBooleanExtra("show_valentine_promotion", false)
isAbleBack = intent.getBooleanExtra("is_able_back", false)
mAmount = intent.getDoubleExtra("top_amount", 0.0)
mPhoneNumber = intent.getStringExtra(Constant.PHONE_NUMBER)
binding.webViewAcleda.settings.javaScriptEnabled = true
binding.webViewAcleda.webViewClient = mWebViewClient
binding.webViewAcleda.loadUrl(mUrlPay)
}
private fun exitAcledaPayment(isSuccess: Boolean) {
showHideLoading(false)
if (isSuccess) {
val intent = Intent(this, PaymentActivity::class.java)
intent.putExtra("show_valentine_promotion", isShowValentineDayPromotion)
setResult(Activity.RESULT_OK, intent)
}
activityExitLeftAnimation()
finish()
}
override fun onBackPressed() {
super.onBackPressed()
closePaymentProcress()
}
override fun onPause() {
super.onPause()
binding.webViewAcleda.onPause()
}
override fun onResume() {
super.onResume()
binding.webViewAcleda.onResume()
}
companion object {
fun lunch(
context: Context,
url: String,
amount: Double,
isAbleBackPress: Boolean = false,
showValentineDayPromotion: Boolean = false,
phoneNumber: String,
) {
val i = Intent(context, AcledaActivity::class.java)
i.putExtra("payment_url", url)
i.putExtra("top_amount", amount)
i.putExtra("is_able_back", isAbleBackPress)
// i.putExtra("show_valentine_promotion", showValentineDayPromotion)
i.putExtra(Constant.PHONE_NUMBER, phoneNumber)
(context as Activity).startActivityForResult(i, Constant.REQUEST_ACLEDA)
}
}
}
\ No newline at end of file
package com.seatel.mobilehall.ui.home.activity
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
......@@ -10,6 +11,9 @@ import android.text.TextUtils
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.net.toUri
import androidx.recyclerview.widget.GridLayoutManager
import com.android.volley.NoConnectionError
import com.android.volley.Request
......@@ -59,6 +63,11 @@ class PaymentActivity : BaseActivity<ActivityPaymentBinding>(), TopupTransaction
private var isWingInstalled = 0
private val WING_SCHEME_DEV = "com.wingmoney.wingpay.uat"
private val WING_SCHEME_PRO = "com.wingmoney.wingpay"
//private var acledaRemark: Int = 0
private var acledaRemark: String? = null
private var selectedPaymentIndex: Int = -1
private var paymentTokenId: String = ""
//Topup
private lateinit var mTopupTransactionPresenter: TopupTransactionPresenter
......@@ -207,7 +216,67 @@ class PaymentActivity : BaseActivity<ActivityPaymentBinding>(), TopupTransaction
mAmountTopup,
paymentType
)
} else {
}
else if (paymentType.equals("acleda", ignoreCase = true)) {
val myRemark = remark
acledaRemark = myRemark
openAcledaDeeplink(myRemark)
}
else if (paymentType.equals("acleda-khqr", ignoreCase = true)) {
val khqrRemark = acledaRemark ?: remark
object : SeatelJSONObjectRequest(this) {
override fun getFunctionName() = "v2/payment-methods/acleda/open-session"
override fun getMethod() = Request.Method.POST
override fun onGetBodyRequest(): String {
val body = JSONObject().apply {
put("remark", khqrRemark)
put("paymentType", "khqr")
}
println("===> Body Request : $body")
return body.toString()
}
}.execute { response ->
hideProgress()
val jsonResponse = response as JSONObject
val payment_url = jsonResponse.optString("link")
println("===> Acleda KHQR Link: $payment_url")
if (payment_url.isNotEmpty()) {
try {
AcledaActivity.lunch(
context = this,
url = payment_url,
amount = mAmountTopup,
isAbleBackPress = true,
showValentineDayPromotion = false,
phoneNumber = mPhoneNumber,
)
} catch (
e: Exception
) {
println(
"===> Error: ${e.message}"
)
}
// if (!acledaLink.isNullOrEmpty()) {
// AcledaActivity.lunch(
// context = this@PaymentActivity,
// url = acledaLink,
// amount = mAmountTopup,
// phoneNumber = mPhoneNumber,
// isAbleBackPress = true,
// showValentineDayPromotion = false
// )
// } else {
// println("===> Error: acledaLink is empty")
// }
}
}
}else {
if (TextUtils.equals(mTopupStatus.lowercase(Locale.getDefault()), "success")) {
checkCallBack = false
TopUpSuccessActivity.lunch(
......@@ -267,6 +336,12 @@ class PaymentActivity : BaseActivity<ActivityPaymentBinding>(), TopupTransaction
this, Constant.TOPUP_SUCCESS, originalAmount.toString(), mPhoneNumber.toString()
)
}
else if (resultCode == Constant.REQUEST_ACLEDA) {
println("===> Acleda Payment Success")
TopUpSuccessActivity.lunch(
this, Constant.TOPUP_SUCCESS, originalAmount.toString(), mPhoneNumber.toString()
)
}
}
private fun startUnionPayProcess() {
......@@ -276,6 +351,8 @@ class PaymentActivity : BaseActivity<ActivityPaymentBinding>(), TopupTransaction
private fun checkTopupPaymentTypeProcess(index: Int) {
selectedPaymentIndex = index // ✅ store for later use
println("===> checkTopupPaymentTypeProcess called with index: $index, mPaymentType: $mPaymentType")
if (handlerRefresh == null) handlerRefresh = Handler()
if (handlerRefresh != null) handlerRefresh?.postDelayed({
mAdapterPayActivity?.notifyItemChanged(index)
......@@ -283,7 +360,8 @@ class PaymentActivity : BaseActivity<ActivityPaymentBinding>(), TopupTransaction
handlerRefresh = null
}, 100)
when (mPaymentType) {/* "unionpay" -> {
when (mPaymentType) {
/* "unionpay" -> {
startUnionPayProcess()
FirebaseAnalyticsUtil.getInstance(this).logCustomEvent(Constant.SeaTelAnalytics.Value.UNION_PAY)
}*/
......@@ -310,6 +388,12 @@ class PaymentActivity : BaseActivity<ActivityPaymentBinding>(), TopupTransaction
Constant.ABA_CARD -> {
startPaymentProcess("aba-card")
}
Constant.ACLEDA -> {
startPaymentProcess("acleda")
}
Constant.ACLEDA_KHQR -> {
startPaymentProcess("acleda-khqr")
}
else -> {
SeatelAlertDialog.with(this, getString(R.string.choose_payment_option)).show()
......@@ -472,21 +556,36 @@ class PaymentActivity : BaseActivity<ActivityPaymentBinding>(), TopupTransaction
mAdapterPayActivity?.notifyDataSetChanged()
showHideLoading(false)
if (checkCallBack) getAbaCallBack()
println("===> Check Transaction By PaymentTokenId : $paymentTokenId")
if (checkCallBack) {
showProgress()
getAcledaCallBack()
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
println("===> ONNEWINTENT")
val appLinkAction: String? = intent.action
val appLinkData: Uri? = intent.data
Log.d(TAG, "onNewIntent: ${appLinkData.toString()} $appLinkAction")
println("===> appDeepData Acldeda========================: $appLinkData")
if (appLinkData.toString().contains("transaction_status=true")) {
TopUpSuccessActivity.lunch(
this, Constant.TOPUP_SUCCESS, originalAmount.toString(), mPhoneNumber
)
finish()
}
val acledaAction: String? = intent.action
val acledaLinkData: Uri? = intent.data
val link = intent.data?.toString() ?: ""
println("===> ACLEDAACTION: $acledaAction")
println("===> ACLEDALINKDATA: $acledaLinkData")
println("===> LINK CALLBACK: $link")
if (acledaLinkData != null) {
showProgress()
checkVerify()
}
}
......@@ -501,4 +600,110 @@ class PaymentActivity : BaseActivity<ActivityPaymentBinding>(), TopupTransaction
context.startActivity(intent)
}
}
private fun openAcledaDeeplink(remark: String) {
object : SeatelJSONObjectRequest(this) {
override fun getFunctionName() = "v2/payment-methods/acleda/open-session"
override fun getMethod() = Request.Method.POST
override fun onGetBodyRequest(): String {
val body = JSONObject().apply {
put("remark", remark)
put("paymentType", "deeplink")
}
println("===> Body Deeplink : $body")
return body.toString()
}
}.execute { response ->
hideProgress()
checkCallBack = true
val link = (response as JSONObject).optString("link")
val paymentTokenId = response.optString("paymentTokenId")
this.paymentTokenId = paymentTokenId
try {
val intent = Intent(Intent.ACTION_VIEW, link.toUri())
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
} catch (e: ActivityNotFoundException) {
SeatelAlertDialog.with(this, "ACLEDA app not installed").show()
installAcledaApp(this)
}
}
}
private fun installAcledaApp(context: Context) {
val packageName = "com.domain.acledabankqr"
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=$packageName"))
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
// Play Store not installed, open in browser instead
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse("https://play.google.com/store/apps/details?id=$packageName")
)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
}
}
private fun checkVerify(){
object : SeatelJSONObjectRequest(this) {
override fun getFunctionName() = "acleda/transaction"
override fun getMethod() = Request.Method.POST
override fun onGetBodyRequest(): String {
val body = JSONObject().apply {
put("paymentTokenId", paymentTokenId)
}
println("===> Body Request : $body")
return body.toString()
}
}.execute { response ->
hideProgress()
val json = JSONObject(response.toString())
val result = json.optJSONObject("result")
if (result != null) {
if (result.optString("errorDetails") == "SUCCESS") {
TopUpSuccessActivity.lunch(
this, Constant.TOPUP_SUCCESS, originalAmount.toString(), mPhoneNumber
)
}
finish()
}
}
}
private fun getAcledaCallBack(){
object : SeatelJSONObjectRequest(this) {
override fun getFunctionName(): String {
return "acleda/transaction"
}
override fun onGetBodyRequest(): String {
val obj = JSONObject()
obj.put("paymentTokenId" , paymentTokenId)
return obj.toString()
}
override fun getMethod(): Int {
return Request.Method.POST
}
}.setOnErrorListener {
SeatelAlertDialog.with(this, SeatelSuperRequest.getErrorMessageFrom(it)).show()
}.execute {
hideProgress()
val json = JSONObject(it.toString())
val result = json.optJSONObject("result")
if (result != null) {
if (result.optString("errorDetails") == "SUCCESS") {
TopUpSuccessActivity.lunch(
this, Constant.TOPUP_SUCCESS, originalAmount.toString(), mPhoneNumber
)
}else{
SeatelAlertDialog.with(this, "Acleda Payment Failed").show()
}
}
//finish()
}
}
}
......@@ -85,6 +85,7 @@ object Constant {
const val SMS_PERMISSION_CODE = 108
const val PHONE_PERMISSION = 109
const val REQUEST_WING = 99
const val REQUEST_ACLEDA = 200
const val PICK_UP_YES_HUB_LOCATION = 98
const val DEVICE_OPTION = 96
const val CART_DEVICE_DETAIL = 95
......@@ -115,6 +116,8 @@ object Constant {
var ALI_PAY = "alipay"
var ABA = "aba"
var ABA_CARD = "aba-card"
var ACLEDA = "acleda"
var ACLEDA_KHQR: String = "acleda-khqr"
/**
* Request
......
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBgWhiteGray"
android:fillViewport="true"
android:fitsSystemWindows="true"
android:scrollbars="vertical">
<View
android:id="@+id/viewSpace"
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="@android:color/transparent" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/viewSpace"
android:background="@color/colorBgWhiteGray"
android:fillViewport="true"
android:scrollbars="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBgWhiteGray">
<WebView
android:id="@+id/web_view_acleda"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarStyle="insideOverlay"
android:scrollbars="vertical" />
<com.seatel.mobilehall.util.customview.ErrorHandleView
android:id="@+id/error_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
</RelativeLayout>
</ScrollView>
</RelativeLayout>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment