欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android多種支付方式的實(shí)現(xiàn)示例

 更新時(shí)間:2023年09月06日 09:29:57   作者:派大星不吃蟹  
App的支付流程,添加多種支付方式,不同的支付方式,對(duì)應(yīng)的操作不一樣,有的會(huì)跳轉(zhuǎn)到一個(gè)新的webview,有的會(huì)調(diào)用系統(tǒng)瀏覽器,有的會(huì)進(jìn)去一個(gè)新的表單頁(yè)面,等等,本文就給大家詳細(xì)介紹一下Android 多種支付方式的優(yōu)雅實(shí)現(xiàn),需要的朋友可以參考下

1.場(chǎng)景

App 的支付流程,添加多種支付方式,不同的支付方式,對(duì)應(yīng)的操作不一樣,有的會(huì)跳轉(zhuǎn)到一個(gè)新的webview,有的會(huì)調(diào)用系統(tǒng)瀏覽器,有的會(huì)進(jìn)去一個(gè)新的表單頁(yè)面,等等。

并且可以添加的支付方式也是不確定的,由后臺(tái)動(dòng)態(tài)下發(fā)。

如下圖所示:

根據(jù)上圖 ui 理一下執(zhí)行流程:

  • 點(diǎn)擊不同的添加支付方式 item。
  • 進(jìn)入相對(duì)應(yīng)的添加支付方式流程(表單頁(yè)面、webview、彈框之類(lèi)的)。
  • 在第三方回調(diào)里面根據(jù)不同的支付方式執(zhí)行不同的操作。
  • 調(diào)用后臺(tái)接口查詢(xún)添加是否成功。
  • 根據(jù)接口結(jié)果展示不同的成功或者失敗的ui.

2.以前的實(shí)現(xiàn)方式

用一個(gè) Activity 承載,上述所有的流程都在 Activity 中。Activity 包含了列表展示、多種支付方式的實(shí)現(xiàn)和 ui。

偽代碼如下:

class AddPaymentListActivity : AppCompatActivity(R.layout.activity_add_card) {
    private val addPaymentViewModel : AddPaymentViewModel = ...
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        addPaymentViewModel.checkPaymentStatusLiveData.observer(this) { isSuccess ->
            // 從后臺(tái)結(jié)果判斷是否添加成功
            if (isSuccess) {
                addCardSuccess(paymentType)
            } else {
                addCardFailed(paymentType)
            }
        }
    }
    private fun clickItem(paymentType: PaymentType) {
        when (paymentType) {
            PaymentType.ADD_GOOGLE_PAY -> //執(zhí)行添加谷歌支付流程
            PaymentType.ADD_PAY_PEL-> //執(zhí)行添加PayPel支付流程
            PaymentType.ADD_ALI_PAY-> //執(zhí)行添加支付寶支付流程
            PaymentType.ADD_STRIPE-> //執(zhí)行添加Stripe支付流程
        }
    }
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when (resultCode) {
            PaymentType.ADD_GOOGLE_PAY -> {
                // 根據(jù)第三方回調(diào)的結(jié)果,拿到key
                // 根據(jù)key調(diào)用后臺(tái)的Api接口查詢(xún)是否添加成功
            }
            PaymentType.ADD_PAY_PEL -> // 同上
            // ...
        }
    }
    private fun addCardSuccess(paymentType: PaymentType){
        when (paymentType) {
            PaymentType.ADD_GOOGLE_PAY -> // 添加對(duì)應(yīng)的支付方式成功,展示成功的ui,然后執(zhí)行下一步操作
            PaymentType.ADD_PAY_PEL-> // 同上
            // ...
        }
    }
    private fun addCardFailed(paymentType: PaymentType){
        when (paymentType) {
            PaymentType.ADD_GOOGLE_PAY -> // 添加對(duì)應(yīng)的支付方式失敗,展示失敗的ui
            PaymentType.ADD_PAY_PEL-> // 同上
            // ...
        }
    }
    enum class PaymentType {
        ADD_GOOGLE_PAY, ADD_PAY_PEL, ADD_ALI_PAY, ADD_STRIPE
    }
}

雖然看起來(lái)根據(jù) paymentType 來(lái)判斷,邏輯條理也還過(guò)得去,但是實(shí)際上復(fù)雜度遠(yuǎn)遠(yuǎn)不止如此。

• 不同的支付方式跳轉(zhuǎn)的頁(yè)面相差很大。

• 結(jié)果的回調(diào)獲取也相差很大,并不是所有的都在onActivityResult中。

• 成功和失敗實(shí)際上也不能統(tǒng)一來(lái)處理,里面包含很多的if…else…判斷。

• 如果支付方式是后臺(tái)動(dòng)態(tài)下發(fā)的,處理起來(lái)判斷邏輯就更多了。

此外,最大的問(wèn)題:擴(kuò)展性問(wèn)題。

當(dāng)新來(lái)一種支付方式,例如微信支付之類(lèi)的,改動(dòng)代碼就很大了,基本就是將整個(gè)Activity中的代碼都要改動(dòng)??梢哉f(shuō)上面這種方式的可擴(kuò)展性為零,就是簡(jiǎn)單的將代碼都揉在一起。

3.優(yōu)化后的代碼

要想實(shí)現(xiàn)高內(nèi)聚低耦合,最簡(jiǎn)單的就是套用常見(jiàn)的設(shè)計(jì)模式,回想一下,發(fā)現(xiàn)策略模式+簡(jiǎn)單工廠模式非常這種適合這種場(chǎng)景。

先看下優(yōu)化后的代碼:

class AddPlatformActivity : BaseActivity() {
    private var addPayPlatform: IAddPayPlatform? = null
    private fun addPlatform(payPlatform: String) {
        // 將后臺(tái)返回的支付平臺(tái)字符串變成枚舉類(lèi)
        val platform: PayPlatform = getPayPlatform(payPlatform) ?: return
        addPayPlatform = AddPayPlatformFactory.getCurrentPlatform(this, platform)
        addPayPlatform?.getLoadingLiveData()?.observe(this@AddPlatformActivity) { showLoading ->
                if (showLoading) startLoading() else stopLoading()
            }
        addPayPlatform?.addPayPlatform(AddCardParameter(platform))
    }
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        // 將onActivityResult的回調(diào)轉(zhuǎn)接到需要監(jiān)聽(tīng)的策略類(lèi)里面
        addPayPlatform?.thirdAuthenticationCallback(requestCode, resultCode, data)
    }
}

4.策略模式

意圖: 定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái), 并且使它們可相互替換。

主要解決: 在有多種算法相似的情況下,使用if…else所帶來(lái)的復(fù)雜和難以維護(hù)。

何時(shí)使用: 一個(gè)系統(tǒng)有許多許多類(lèi),而區(qū)分它們的只是他們直接的行為。

如何解決: 將這些算法封裝成一個(gè)一個(gè)的類(lèi),任意地替換。

關(guān)鍵代碼: 實(shí)現(xiàn)同一個(gè)接口。

**優(yōu)點(diǎn): **

1、算法可以自由切換。

2、避免使用多重條件判斷。

3、擴(kuò)展性良好。

缺點(diǎn)

1、策略類(lèi)會(huì)增多。

2、所有策略類(lèi)都需要對(duì)外暴露。

**使用場(chǎng)景: **

1、如果在一個(gè)系統(tǒng)里面有許多類(lèi),它們之間的區(qū)別僅在于它們的行為,那么使用策略模式可以動(dòng)態(tài)地讓一個(gè)對(duì)象在許多行為中選擇一種行為。

2、一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種。

3、如果一個(gè)對(duì)象有很多的行為,如果不用恰當(dāng)?shù)哪J?,這些行為就只好使用多重的條件選擇語(yǔ)句來(lái)實(shí)現(xiàn)。

5.需要實(shí)現(xiàn)的目標(biāo)

5.1 解耦宿主 Activity

現(xiàn)在宿主Activity中代碼太重了,包含多種支付方式實(shí)現(xiàn),還有列表ui的展示,網(wǎng)絡(luò)請(qǐng)求等。

現(xiàn)在目標(biāo)是將 Activity 中的代碼拆分開(kāi)來(lái),讓宿主 Activity 變得小而輕。

如果產(chǎn)品說(shuō)新增一種支付方式,只需要改動(dòng)很少的代碼,就可以輕而易舉的實(shí)現(xiàn)。

5.2 抽取成獨(dú)立的模塊

因?yàn)楣局杏锌赡艽嬖诙鄠€(gè)項(xiàng)目,支付模塊的分層應(yīng)該處于可復(fù)用的層級(jí),以后很有可能將其封裝成一個(gè)獨(dú)立的 mouble,給不同的項(xiàng)目使用。

現(xiàn)在代碼全在 Activity 中,以后若是抽取 mouble 的話,相當(dāng)于整個(gè)需求重做。

5.3 組件黑盒

"組件黑盒"這個(gè)名詞是我自己的一個(gè)定義。大致意思:

將一個(gè) View 或者一個(gè)類(lèi)進(jìn)行高度封裝,盡可能少的暴露public方法給外部使用,自成一體。

業(yè)務(wù)方在使用時(shí),可以直接黑盒使用某個(gè)業(yè)務(wù)組件,不必關(guān)心其中的邏輯。

業(yè)務(wù)方只需要一個(gè)簡(jiǎn)單的操作,例如點(diǎn)擊按鈕調(diào)用方法,然后邏輯都在組件內(nèi)部實(shí)現(xiàn),組件內(nèi)處理外部事件的所有操作,例如:Loading、請(qǐng)求網(wǎng)絡(luò)、成功或者失敗。

業(yè)務(wù)方都不需要知道組件內(nèi)部的操作,做到宿主和組件的隔離。

當(dāng)然這種處理也是要分場(chǎng)景考慮的,其中一個(gè)重點(diǎn)就是這個(gè)組件是偏業(yè)務(wù)還是偏功能,也就是是否要將業(yè)務(wù)邏輯統(tǒng)一包進(jìn)組件,想清楚這個(gè)問(wèn)題后,才能去開(kāi)發(fā)一個(gè)業(yè)務(wù)組件。

因?yàn)樘砑又Ц斗绞绞且粋€(gè)偏業(yè)務(wù)的功能,我的設(shè)計(jì)思路是:

外部 Activity 點(diǎn)擊添加對(duì)應(yīng)的支付方式,將支付方式的枚舉類(lèi)型和支付方式有關(guān)的參數(shù)通過(guò)傳遞,然后不同的策略類(lèi)組件執(zhí)行自己的添加邏輯,再通過(guò)一層回調(diào)將第三方支付的回調(diào)從 Activity 中轉(zhuǎn)接過(guò)來(lái),每個(gè)策略類(lèi)內(nèi)部處理自己的回調(diào)操作,具體的策略類(lèi)自己維護(hù)成功或者失敗的ui。摘自https://xuyisheng.top/author/xuyisheng/

6.具體實(shí)現(xiàn)

6.1 定義頂層策略接口

interface IAddPayPlatform {
    fun addPayPlatform(param: AddCardParameter)
    fun thirdAuthenticationCallback(requestCode: Int?, resultCode: Int?, data: Intent?)
    fun addCardFailed(message: String?)
    fun addCardSuccess()
}

6.2 通用支付參數(shù)類(lèi)

open class AddCardParameter(val platform: PayPlatform)
class AddStripeParameter(val card: Card, val setPrimaryCard: Boolean, platform: PayPlatform)
    : AddCardParameter(platform = PayPlatform.Stripe)

因?yàn)橛泻芏喾N添加支付方式,不同的支付方式對(duì)應(yīng)的參數(shù)都不一樣。

所以先創(chuàng)建一個(gè)通用的卡片參數(shù)基類(lèi)AddCardParameter, 不同的支付方式去實(shí)現(xiàn)不同的具體參數(shù)。這樣的話策略接口就可以只要寫(xiě)一個(gè)添加卡片的方法addPayPlatform(param: AddCardParameter)。

6.3 Loading 的處理

因?yàn)槲蚁雽?shí)現(xiàn)的是黑盒組件的效果,所有添加卡片的loading也是封裝在每一個(gè)策略實(shí)現(xiàn)類(lèi)里面的。

Loading的出現(xiàn)和消失這里有幾種常見(jiàn)的實(shí)現(xiàn)方式:

• 傳遞BaseActivity的引用,因?yàn)槲业膌oading有關(guān)的方法是放在BaseActivity中,這種方式簡(jiǎn)單但是會(huì)耦合BaseActivity。

• 使用消息事件總線,例如EventBus之類(lèi)的,這種方式解耦強(qiáng),但是消息事件不好控制,還要添加多余的依賴(lài)庫(kù)。

• 使用LiveData,在策略的通用接口中添加一個(gè)方法返回Loading的LiveData, 讓宿主Activity自己去實(shí)現(xiàn)。

interface IAddPayPlatform {
    // ...
    fun getLoadingLiveData(): LiveData<Boolean>?
}

6.4 提取BaseAddPayStrategy

因?yàn)槊恳粋€(gè)添加卡的策略會(huì)存在很多相同的代碼,這里我抽取一個(gè)BaseAddPayStrategy來(lái)存放模板代碼。

需要實(shí)現(xiàn)黑盒組件的效果,宿主Activity中都不需要去關(guān)注添加支付方式是不是存在網(wǎng)絡(luò)請(qǐng)求這一個(gè)過(guò)程,所以網(wǎng)絡(luò)請(qǐng)求也分裝在每一個(gè)策略實(shí)現(xiàn)類(lèi)里面。

abstract class BaseAddPayStrategy(val activity: AppCompatActivity, val platform: PayPlatform) : IAddPayPlatform {
  private val loadingLiveData = SingleLiveData<Boolean>()
  protected val startActivityIntentLiveData = SingleLiveData<Intent>()
  override fun getLoadingLiveData(): LiveData<Boolean> = loadingLiveData
  protected fun startLoading() = loadingLiveData.setValue(true)
  protected fun stopLoading() = loadingLiveData.setValue(false)
  private fun reloadWallet() {
      startLoading()
      // 添加卡片完成后,重新刷新錢(qián)包數(shù)據(jù)
  }
  override fun addCardSuccess() {
      reloadWallet()
  }
  override fun addCardFailed(message: String?) {
      stopLoading()
      if (isEWalletPlatform(platform)) showAddEWalletFailedView() else showAddPhysicalCardFailedView(message)
  }
   /**
    * 添加實(shí)體卡片失敗展示ui
    */
  private fun showAddPhysicalCardFailedView(message: String?) {
       showSaveErrorDialog(activity, message)
  }
   /**
    * 添加實(shí)體卡片成功展示ui
    */
  private fun showAddPhysicalCardSuccessView() {
      showCreditCardAdded(activity) {
          activity.setResult(Activity.RESULT_OK)
          activity.finish()
      }
  }
  private fun showAddEWalletSucceedView() {
      // 添加電子錢(qián)包成功后的執(zhí)行
      activity.setResult(Activity.RESULT_OK)
      activity.finish()
  }
  private fun showAddEWalletFailedView() {
      // 添加電子錢(qián)包失敗后的執(zhí)行
  }
  // ---默認(rèn)空實(shí)現(xiàn),有些支付方式不需要這些方法---
  override fun thirdAuthenticationCallback(requestCode: Int?, resultCode: Int?, data: Intent?) = Unit
  override fun getStartActivityIntent(): LiveData<Intent> = startActivityIntentLiveData
}

6.5 具體的策略類(lèi)實(shí)現(xiàn)

通過(guò)傳遞過(guò)來(lái)的AppCompatActivity引用獲取添加卡片的ViewModel實(shí)例AddPaymentViewModel,然后通過(guò)AddPaymentViewModel去調(diào)用網(wǎng)絡(luò)請(qǐng)求查詢(xún)添加卡片是否成功。

class AddXXXPayStrategy(activity: AppCompatActivity) : BaseAddPayStrategy(activity, PayPlatform.XXX) {
  protected val addPaymentViewModel: AddPaymentViewModel by lazy {
      ViewModelProvider(activity).get(AddPaymentViewModel::class.java)
  }
  init {
      addPaymentViewModel.eWalletAuthorizeLiveData.observeState(activity) {
          onSuccess { addCardSuccess()}
          onError { addCardFailed(it.detailed) }
      }
  }
  override fun thirdAuthenticationCallback(requestCode: Int?, resultCode: Int?, result: Intent?) {
      val uri: Uri = result?.data ?: return
      if (uri.host == "www.xxx.com") {
          uri.getQueryParameter("transactionId")?.let {
              addPaymentViewModel.confirmEWalletAuthorize(platform.name, it)
          }
      }
  }
  override fun addPayPlatform(param: AddCardParameter) {
      startLoading()
      addPaymentViewModel.addXXXCard(param)
  }
}

7.簡(jiǎn)單工廠進(jìn)行優(yōu)化

因?yàn)槲也幌朐贏ctivity中去引用每一個(gè)具體的策略類(lèi),只想引用抽象接口類(lèi)IAddPayPlatform, 這里通過(guò)一個(gè)簡(jiǎn)單工廠來(lái)優(yōu)化。

fun setCurrentPlatform(activity: AppCompatActivity, payPlatform: PayPlatform): IAddPayPlatform? {
    return when (payPlatform) {
        PayPlatform.STRIPE -> AddStripeStrategy(activity)
        PayPlatform.PAYPAL -> AddPayPalStrategy(activity)
        PayPlatform.LINEPAY -> AddLinePayStrategy(activity)
        PayPlatform.GOOGLEPAY -> AddGooglePayStrategy(activity)
        PayPlatform.RAPYD -> AddRapydStrategy(activity)
        else -> null
    }
}

8.再增加一種支付方式

如果再增加一種支付方式,宿主Activity中的代碼都可以不要改動(dòng),只需要新建一個(gè)新的策略類(lèi),實(shí)現(xiàn)頂層策略接口即可。

這樣,不管是刪除還是新增一種支付方式,維護(hù)起來(lái)就很容易了。

策略模式的好處就顯而易見(jiàn)了。

以上就是Android多種支付方式的實(shí)現(xiàn)示例的詳細(xì)內(nèi)容,更多關(guān)于Android支付方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論