Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
timeout-minutes: 60
strategy:
matrix:
api-level: [ 33 ]
api-level: [ 35 ]
needs: build
steps:
- name: Free Disk Space (Ubuntu)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
timeout-minutes: 60
strategy:
matrix:
api-level: [ 33 ]
api-level: [ 35 ]
needs: build
steps:
- name: Free Disk Space (Ubuntu)
Expand Down
15 changes: 11 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-android'

android {

buildFeatures {
viewBinding true
}

defaultConfig {
namespace "co.omise.android.example"
minSdkVersion min_sdk_version
Expand Down Expand Up @@ -47,8 +51,11 @@ android {
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
}

Expand All @@ -66,4 +73,4 @@ dependencies {
}
repositories {
mavenCentral()
}
}
124 changes: 40 additions & 84 deletions app/src/kotlin/java/co/omise/android/example/CheckoutActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,11 @@ import android.os.Parcelable
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.widget.Button
import android.widget.EditText
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import co.omise.android.AuthorizingPaymentURLVerifier.Companion.EXTRA_AUTHORIZED_URLSTRING
import co.omise.android.AuthorizingPaymentURLVerifier.Companion.EXTRA_EXPECTED_RETURN_URLSTRING_PATTERNS
import co.omise.android.api.Client
import co.omise.android.api.RequestListener
import co.omise.android.config.ButtonCustomization
import co.omise.android.config.ButtonCustomizationBuilder
import co.omise.android.config.ButtonType
Expand All @@ -25,6 +20,7 @@ import co.omise.android.config.TextBoxCustomizationBuilder
import co.omise.android.config.ThemeConfig
import co.omise.android.config.ToolbarCustomizationBuilder
import co.omise.android.config.UiCustomizationBuilder
import co.omise.android.example.databinding.ActivityCheckoutBinding
import co.omise.android.models.Amount
import co.omise.android.models.CardHolderDataField
import co.omise.android.models.CardHolderDataList
Expand All @@ -38,102 +34,75 @@ import co.omise.android.ui.CreditCardActivity
import co.omise.android.ui.OmiseActivity
import co.omise.android.ui.PaymentCreatorActivity
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_checkout.amount_edit
import kotlinx.android.synthetic.main.activity_checkout.authorize_url_button
import kotlinx.android.synthetic.main.activity_checkout.choose_payment_method_button
import kotlinx.android.synthetic.main.activity_checkout.credit_card_button
import kotlinx.android.synthetic.main.activity_checkout.currency_edit

inline fun <reified T : Parcelable> Intent.parcelable(key: String?): T? = when {
// https://stackoverflow.com/questions/72571804/getserializableextra-and-getparcelableextra-are-deprecated-what-is-the-alternat/73543350#73543350
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getParcelableExtra(key, T::class.java)
else -> @Suppress("DEPRECATION") getParcelableExtra(key) as? T
}

class CheckoutActivity : AppCompatActivity() {
class CheckoutActivity : OmiseActivity() {

companion object {

private const val TAG = "CheckoutActivity"
private const val PUBLIC_KEY = "[PUBLIC_KEY]"
private const val GOOGLEPAY_MERCHANT_ID = "[GOOGLEPAY_MERCHANT_ID]"
private const val GOOGLEPAY_REQUEST_BILLING_ADDRESS = false
private const val GOOGLEPAY_REQUEST_PHONE_NUMBER = false
private val CARD_HOLDER_DATA = CardHolderDataList(arrayListOf(CardHolderDataField.EMAIL,CardHolderDataField.PHONE_NUMBER))

private val CARD_HOLDER_DATA = CardHolderDataList(arrayListOf(CardHolderDataField.EMAIL, CardHolderDataField.PHONE_NUMBER))

private const val AUTHORIZING_PAYMENT_REQUEST_CODE = 0x3D5
private const val PAYMENT_CREATOR_REQUEST_CODE = 0x3D6
private const val CREDIT_CARD_REQUEST_CODE = 0x3D7
}

private val amountEdit: EditText by lazy { amount_edit }
private val currencyEdit: EditText by lazy { currency_edit }
private val choosePaymentMethodButton: Button by lazy { choose_payment_method_button }
private val creditCardButton: Button by lazy { credit_card_button }
private val authorizeUrlButton: Button by lazy { authorize_url_button }
private val snackbar: Snackbar by lazy {
Snackbar.make(findViewById(R.id.content), "", Snackbar.LENGTH_SHORT)
}
private lateinit var binding: ActivityCheckoutBinding
private val snackbar: Snackbar by lazy { Snackbar.make(binding.content, "", Snackbar.LENGTH_SHORT) }

private lateinit var authorizingPaymentLauncher: ActivityResultLauncher<Intent>
private lateinit var paymentCreatorLauncher: ActivityResultLauncher<Intent>
private lateinit var creditCardLauncher: ActivityResultLauncher<Intent>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_checkout)
binding = ActivityCheckoutBinding.inflate(layoutInflater)
setContentView(binding.root)

supportActionBar?.title = getString(R.string.activity_checkout)
authorizingPaymentLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result: ActivityResult ->
handleActivityResult(
AUTHORIZING_PAYMENT_REQUEST_CODE,
result.resultCode,
result.data
)
}

paymentCreatorLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result: ActivityResult ->
handleActivityResult(
PAYMENT_CREATOR_REQUEST_CODE,
result.resultCode,
result.data
)
}

creditCardLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result: ActivityResult ->
handleActivityResult(
CREDIT_CARD_REQUEST_CODE,
result.resultCode,
result.data
)
}

setupActivityLaunchers()

choosePaymentMethodButton.setOnClickListener { choosePaymentMethod() }
creditCardButton.setOnClickListener { payByCreditCard() }
authorizeUrlButton.setOnClickListener {
binding.choosePaymentMethodButton.setOnClickListener { choosePaymentMethod() }
binding.creditCardButton.setOnClickListener { payByCreditCard() }
binding.authorizeUrlButton.setOnClickListener {
AuthorizingPaymentDialog.showAuthorizingPaymentDialog(this) { authorizeUrl, returnUrl ->
startAuthoringPaymentActivity(authorizeUrl, returnUrl)
}
}
}

private fun setupActivityLaunchers() {
authorizingPaymentLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
handleActivityResult(AUTHORIZING_PAYMENT_REQUEST_CODE, result.resultCode, result.data)
}

paymentCreatorLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
handleActivityResult(PAYMENT_CREATOR_REQUEST_CODE, result.resultCode, result.data)
}

creditCardLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
handleActivityResult(CREDIT_CARD_REQUEST_CODE, result.resultCode, result.data)
}
}

private fun choosePaymentMethod() {
val isUsedSpecificsPaymentMethods = PaymentSetting.isUsedSpecificsPaymentMethods(this)

val localAmount = amountEdit.text.toString().trim().toDouble()
val currency = currencyEdit.text.toString().trim().lowercase()
val localAmount = binding.amountEdit.text.toString().trim().toDouble()
val currency = binding.currencyEdit.text.toString().trim().lowercase()
val amount = Amount.fromLocalAmount(localAmount, currency)

Intent(this, PaymentCreatorActivity::class.java).run {
val intent = Intent(this, PaymentCreatorActivity::class.java).apply {
putExtra(OmiseActivity.EXTRA_PKEY, PUBLIC_KEY)
putExtra(OmiseActivity.EXTRA_AMOUNT, amount.amount)
putExtra(OmiseActivity.EXTRA_CURRENCY, amount.currency)
Expand All @@ -145,18 +114,16 @@ class CheckoutActivity : AppCompatActivity() {
if (isUsedSpecificsPaymentMethods) {
putExtra(OmiseActivity.EXTRA_CAPABILITY, PaymentSetting.createCapabilityFromPreferences(this@CheckoutActivity))
}

paymentCreatorLauncher.launch(this)
}
paymentCreatorLauncher.launch(intent)
}


private fun payByCreditCard() {
Intent(this, CreditCardActivity::class.java).run {
val intent = Intent(this, CreditCardActivity::class.java).apply {
putExtra(OmiseActivity.EXTRA_PKEY, PUBLIC_KEY)
putExtra(OmiseActivity.EXTRA_CARD_HOLDER_DATA, CARD_HOLDER_DATA)
creditCardLauncher.launch(this)
}
creditCardLauncher.launch(intent)
}

private fun startAuthoringPaymentActivity(authorizeUrl: String, returnUrl: String) {
Expand Down Expand Up @@ -202,6 +169,7 @@ class CheckoutActivity : AppCompatActivity() {
.textColor("#1A56F0")
.backgroundColor("#FFFFFF")
.build()

val buttonCustomizations: MutableMap<ButtonType, ButtonCustomization> = mutableMapOf()
buttonCustomizations[ButtonType.SUBMIT] = primaryButtonCustomization
buttonCustomizations[ButtonType.CONTINUE] = primaryButtonCustomization
Expand All @@ -211,42 +179,33 @@ class CheckoutActivity : AppCompatActivity() {
buttonCustomizations[ButtonType.RESEND] = secondaryButtonCustomization
buttonCustomizations[ButtonType.CANCEL] = secondaryButtonCustomization


val uiCustomization = UiCustomizationBuilder()
.setDefaultTheme(ThemeConfig(
labelCustomization,
toolbarCustomization,
textBoxCustomization,
buttonCustomizations
))
.setDarkTheme(ThemeConfig(
buttonCustomizations = buttonCustomizations
))
.setDarkTheme(ThemeConfig(buttonCustomizations = buttonCustomizations))
.setMonoChromeTheme(ThemeConfig())
.build()

Log.d(
TAG, """
Log.d(TAG, """
authorizeUrl=$authorizeUrl
returnUrl=$returnUrl
""".trimIndent()
)
Intent(this, AuthorizingPaymentActivity::class.java).run {
""".trimIndent())

val intent = Intent(this, AuthorizingPaymentActivity::class.java).apply {
putExtra(EXTRA_AUTHORIZED_URLSTRING, authorizeUrl)
putExtra(EXTRA_EXPECTED_RETURN_URLSTRING_PATTERNS, arrayOf(returnUrl))
putExtra(EXTRA_UI_CUSTOMIZATION, uiCustomization)
putExtra(
EXTRA_THREE_DS_REQUESTOR_APP_URL,
"sampleapp://omise.co/authorize_return"
)
authorizingPaymentLauncher.launch(this)
putExtra(EXTRA_THREE_DS_REQUESTOR_APP_URL, "sampleapp://omise.co/authorize_return")
}
authorizingPaymentLauncher.launch(intent)
}

private fun openPaymentSetting() {
Intent(this, PaymentSettingActivity::class.java).run {
startActivity(this)
}
startActivity(Intent(this, PaymentSettingActivity::class.java))
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
Expand All @@ -263,7 +222,6 @@ class CheckoutActivity : AppCompatActivity() {
}

private fun handleActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

// custom result code when web view is closed
if (resultCode == AuthorizingPaymentActivity.WEBVIEW_CLOSED_RESULT_CODE) {
snackbar.setText(R.string.webview_closed).show()
Expand Down Expand Up @@ -291,7 +249,6 @@ class CheckoutActivity : AppCompatActivity() {
Log.e(TAG, throwable.message, throwable.cause)
throwable.message ?: "Unknown error."
}

null -> "Not found the authorization result."
}
Log.d(TAG, resultMessage)
Expand All @@ -302,7 +259,7 @@ class CheckoutActivity : AppCompatActivity() {
PAYMENT_CREATOR_REQUEST_CODE -> {
// if the payment method requires both source and token then you will receive both objects
// otherwise one object will be received
if(data.hasExtra(OmiseActivity.EXTRA_TOKEN) && data.hasExtra(OmiseActivity.EXTRA_SOURCE_OBJECT)){
if (data.hasExtra(OmiseActivity.EXTRA_TOKEN) && data.hasExtra(OmiseActivity.EXTRA_SOURCE_OBJECT)) {
val source = data.parcelable<Source>(OmiseActivity.EXTRA_SOURCE_OBJECT)
val token = data.parcelable<Token>(OmiseActivity.EXTRA_TOKEN_OBJECT)
snackbar.setText((source?.id ?: "No source object.") + "/" + (token?.id ?: "No token object.")).show()
Expand All @@ -324,7 +281,6 @@ class CheckoutActivity : AppCompatActivity() {
snackbar.setText(token?.id ?: "No token object.").show()
Log.d(TAG, "token: ${token?.id}")
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView

import co.omise.android.ui.OmiseActivity

/**
* The example activity to receive the result of the payment.
*/
class PaymentResultActivity : AppCompatActivity() {
class PaymentResultActivity : OmiseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_payment_result)
Expand All @@ -22,9 +24,9 @@ class PaymentResultActivity : AppCompatActivity() {
}
}

override fun onNewIntent(intent: Intent?) {
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
// Depending on your application status, handle the result from the payment app as needed
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package co.omise.android.example

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import co.omise.android.ui.OmiseActivity

class PaymentSettingActivity : AppCompatActivity() {
class PaymentSettingActivity : OmiseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down
Loading
Loading