refactor: 优化前端支付与套餐相关
- 优化PaymentRepository、ApiService、PaymentModels - 优化PlanDetailsCard、PersonalInfoScreen、PlanBalanceScreen、ProfileScreen、UpgradePlanScreen - 优化PaymentViewModel Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package com.huaga.life_echo.data.repository
|
|||||||
|
|
||||||
import com.huaga.life_echo.network.ApiService
|
import com.huaga.life_echo.network.ApiService
|
||||||
import com.huaga.life_echo.network.models.CreatePaymentOrderResponse
|
import com.huaga.life_echo.network.models.CreatePaymentOrderResponse
|
||||||
|
import com.huaga.life_echo.network.models.CurrentPlanDto
|
||||||
import com.huaga.life_echo.network.models.OrderDto
|
import com.huaga.life_echo.network.models.OrderDto
|
||||||
import com.huaga.life_echo.network.models.PaymentOrderStatusResponse
|
import com.huaga.life_echo.network.models.PaymentOrderStatusResponse
|
||||||
import com.huaga.life_echo.network.models.PlanDto
|
import com.huaga.life_echo.network.models.PlanDto
|
||||||
@@ -15,7 +16,7 @@ class PaymentRepository(
|
|||||||
return apiService.getPlans()
|
return apiService.getPlans()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCurrentPlan(): Result<PlanDto> {
|
suspend fun getCurrentPlan(): Result<CurrentPlanDto> {
|
||||||
return apiService.getCurrentPlan()
|
return apiService.getCurrentPlan()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,15 @@ import io.ktor.client.call.*
|
|||||||
import io.ktor.client.engine.android.*
|
import io.ktor.client.engine.android.*
|
||||||
import io.ktor.client.plugins.contentnegotiation.*
|
import io.ktor.client.plugins.contentnegotiation.*
|
||||||
import io.ktor.client.plugins.logging.*
|
import io.ktor.client.plugins.logging.*
|
||||||
|
import io.ktor.client.plugins.HttpTimeout
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.serialization.kotlinx.json.*
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.jsonArray
|
||||||
|
import kotlinx.serialization.json.jsonObject
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
|
||||||
class ApiService(
|
class ApiService(
|
||||||
tokenManager: TokenManager? = null,
|
tokenManager: TokenManager? = null,
|
||||||
@@ -27,6 +31,11 @@ class ApiService(
|
|||||||
install(Logging) {
|
install(Logging) {
|
||||||
level = LogLevel.INFO
|
level = LogLevel.INFO
|
||||||
}
|
}
|
||||||
|
install(HttpTimeout) {
|
||||||
|
requestTimeoutMillis = 45_000 // 单次请求总超时(如创建订单)
|
||||||
|
connectTimeoutMillis = 15_000 // 连接超时
|
||||||
|
socketTimeoutMillis = 45_000 // 读写超时
|
||||||
|
}
|
||||||
|
|
||||||
// 如果提供了tokenManager和authService,安装认证拦截器
|
// 如果提供了tokenManager和authService,安装认证拦截器
|
||||||
if (tokenManager != null && authService != null) {
|
if (tokenManager != null && authService != null) {
|
||||||
@@ -181,7 +190,7 @@ class ApiService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCurrentPlan(): Result<PlanDto> {
|
suspend fun getCurrentPlan(): Result<CurrentPlanDto> {
|
||||||
return try {
|
return try {
|
||||||
val response = client.get("$BASE_URL/api/plans/current") {
|
val response = client.get("$BASE_URL/api/plans/current") {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
@@ -241,7 +250,8 @@ class ApiService(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建支付订单
|
* 创建支付订单
|
||||||
* 返回微信支付参数或支付宝订单字符串
|
* 返回微信支付参数或支付宝订单字符串。
|
||||||
|
* 失败时尽量返回后端返回的 detail 信息,便于 debug。
|
||||||
*/
|
*/
|
||||||
suspend fun createPaymentOrder(
|
suspend fun createPaymentOrder(
|
||||||
planId: String,
|
planId: String,
|
||||||
@@ -252,12 +262,40 @@ class ApiService(
|
|||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(CreatePaymentOrderRequest(planId, paymentMethod))
|
setBody(CreatePaymentOrderRequest(planId, paymentMethod))
|
||||||
}
|
}
|
||||||
|
if (!response.status.isSuccess()) {
|
||||||
|
val errorBody = response.body<String>()
|
||||||
|
val detail = parseApiErrorDetail(errorBody)
|
||||||
|
val msg = detail.ifEmpty { "请求失败: ${response.status}" }
|
||||||
|
return Result.failure(Exception(msg))
|
||||||
|
}
|
||||||
Result.success(response.body())
|
Result.success(response.body())
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
// 超时、网络异常等:保留原始异常信息
|
||||||
Result.failure(e)
|
Result.failure(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析 FastAPI 错误响应中的 detail 字段(字符串或数组),用于展示后端返回的详尽错误信息
|
||||||
|
*/
|
||||||
|
private fun parseApiErrorDetail(errorBody: String?): String {
|
||||||
|
if (errorBody.isNullOrBlank()) return ""
|
||||||
|
return try {
|
||||||
|
val json = Json.parseToJsonElement(errorBody).jsonObject
|
||||||
|
val detail = json["detail"] ?: return ""
|
||||||
|
when {
|
||||||
|
detail is kotlinx.serialization.json.JsonPrimitive -> detail.content
|
||||||
|
detail is kotlinx.serialization.json.JsonArray && detail.isNotEmpty() -> {
|
||||||
|
val first = detail.firstOrNull()?.jsonObject
|
||||||
|
first?.get("msg")?.jsonPrimitive?.content ?: detail.toString()
|
||||||
|
}
|
||||||
|
else -> detail.toString()
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
errorBody.take(500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询支付订单状态
|
* 查询支付订单状态
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.huaga.life_echo.network.models
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 付费系统相关的数据模型
|
* 付费系统相关的数据模型
|
||||||
@@ -19,6 +20,17 @@ data class PlanBenefitDto(
|
|||||||
val features: List<String> = emptyList() // 功能列表
|
val features: List<String> = emptyList() // 功能列表
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/** 当前套餐 DTO(与后端 /api/plans/current 返回的 CurrentPlanResponse 对应) */
|
||||||
|
@Serializable
|
||||||
|
data class CurrentPlanDto(
|
||||||
|
@SerialName("plan_id") val planId: String,
|
||||||
|
@SerialName("plan_name") val planName: String,
|
||||||
|
@SerialName("subscription_type") val subscriptionType: String? = null,
|
||||||
|
@SerialName("expires_at") val expiresAt: String? = null,
|
||||||
|
val features: List<String> = emptyList(),
|
||||||
|
val usage: Map<String, JsonElement>? = null
|
||||||
|
)
|
||||||
|
|
||||||
// 套餐信息DTO(与后端 /api/plans 返回字段对应)
|
// 套餐信息DTO(与后端 /api/plans 返回字段对应)
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PlanDto(
|
data class PlanDto(
|
||||||
@@ -66,18 +78,17 @@ data class SubscriptionStatusDto(
|
|||||||
val daysRemaining: Int? = null
|
val daysRemaining: Int? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
// 额度校验结果DTO
|
// 额度校验结果DTO(与后端 /api/quota/check 的 snake_case 对应)
|
||||||
@Serializable
|
@Serializable
|
||||||
data class QuotaCheckDto(
|
data class QuotaCheckDto(
|
||||||
val hasQuota: Boolean,
|
@SerialName("has_quota") val hasQuota: Boolean,
|
||||||
val remainingWords: Int? = null,
|
@SerialName("remaining_words") val remainingWords: Int? = null,
|
||||||
val remainingChapters: Int? = null,
|
@SerialName("remaining_chapters") val remainingChapters: Int? = null,
|
||||||
val remainingConversations: Int? = null,
|
@SerialName("remaining_conversations") val remainingConversations: Int? = null,
|
||||||
// 已用量与上限(用于展示 "已用 X / 共 Y")
|
@SerialName("used_conversations") val usedConversations: Int? = null,
|
||||||
val usedConversations: Int? = null,
|
@SerialName("used_chapters") val usedChapters: Int? = null,
|
||||||
val usedChapters: Int? = null,
|
@SerialName("max_conversations") val maxConversations: Int? = null,
|
||||||
val maxConversations: Int? = null,
|
@SerialName("max_chapters") val maxChapters: Int? = null,
|
||||||
val maxChapters: Int? = null,
|
|
||||||
val message: String? = null
|
val message: String? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,52 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.huaga.life_echo.network.models.CurrentPlanDto
|
||||||
import com.huaga.life_echo.network.models.PlanDto
|
import com.huaga.life_echo.network.models.PlanDto
|
||||||
import com.huaga.life_echo.utils.PaymentUtils
|
import com.huaga.life_echo.utils.PaymentUtils
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 套餐详情卡片组件
|
* 套餐详情卡片组件(当前套餐,来自 /api/plans/current)
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun PlanDetailsCard(
|
||||||
|
plan: CurrentPlanDto,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
modifier = modifier.fillMaxWidth(),
|
||||||
|
shape = RoundedCornerShape(12.dp),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = plan.planName,
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
|
)
|
||||||
|
if (plan.features.isNotEmpty()) {
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
plan.features.forEach { feature ->
|
||||||
|
Text(
|
||||||
|
text = "• $feature",
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 套餐详情卡片组件(完整套餐信息,来自 /api/plans 列表)
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun PlanDetailsCard(
|
fun PlanDetailsCard(
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ fun PersonalInfoScreen(
|
|||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
PlanStatusBadge(
|
PlanStatusBadge(
|
||||||
planName = currentPlan?.displayName ?: when (currentUser?.subscription_type) {
|
planName = currentPlan?.planName ?: when (currentUser?.subscription_type) {
|
||||||
"free" -> "免费体验版"
|
"free" -> "免费体验版"
|
||||||
"premium" -> "高级版"
|
"premium" -> "高级版"
|
||||||
"professional" -> "专业版"
|
"professional" -> "专业版"
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ fun PlanBalanceScreen(
|
|||||||
color = SlatePurple
|
color = SlatePurple
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = plan.displayName,
|
text = plan.planName,
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = MediumPurple
|
color = MediumPurple
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ fun ProfileScreen(
|
|||||||
userProfile?.nickname ?: currentUser!!.nickname
|
userProfile?.nickname ?: currentUser!!.nickname
|
||||||
} else null,
|
} else null,
|
||||||
planName = if (isLoggedIn && currentUser != null) {
|
planName = if (isLoggedIn && currentUser != null) {
|
||||||
currentPlan?.displayName ?: when (currentUser!!.subscription_type) {
|
currentPlan?.planName ?: when (currentUser!!.subscription_type) {
|
||||||
"free" -> "免费体验版"
|
"free" -> "免费体验版"
|
||||||
"pro" -> "Pro 版"
|
"pro" -> "Pro 版"
|
||||||
"pro_plus" -> "Pro+ 版"
|
"pro_plus" -> "Pro+ 版"
|
||||||
@@ -180,7 +180,7 @@ fun ProfileScreen(
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
icon = AppIcons.Star,
|
icon = AppIcons.Star,
|
||||||
label = "当前套餐",
|
label = "当前套餐",
|
||||||
description = plan.displayName,
|
description = plan.planName,
|
||||||
onPress = { navController?.navigate(Screen.PlanDetails.route) }
|
onPress = { navController?.navigate(Screen.PlanDetails.route) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ fun UpgradePlanScreen(
|
|||||||
if (AppConfig.isDebugMode) {
|
if (AppConfig.isDebugMode) {
|
||||||
item {
|
item {
|
||||||
TestSubscriptionSection(
|
TestSubscriptionSection(
|
||||||
currentPlanId = currentPlan?.id,
|
currentPlanId = currentPlan?.planId,
|
||||||
isLoading = testSubscriptionLoading,
|
isLoading = testSubscriptionLoading,
|
||||||
message = testSubscriptionMessage,
|
message = testSubscriptionMessage,
|
||||||
onSelectPlan = { planId -> viewModel.setTestPlan(planId) }
|
onSelectPlan = { planId -> viewModel.setTestPlan(planId) }
|
||||||
@@ -151,7 +151,10 @@ fun UpgradePlanScreen(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
items(
|
items(
|
||||||
items = plans,
|
items = plans.filter { plan ->
|
||||||
|
// 一分钱测试版仅在开发版本展示
|
||||||
|
plan.id != "test" || AppConfig.isDebugMode
|
||||||
|
},
|
||||||
key = { plan -> plan.id }
|
key = { plan -> plan.id }
|
||||||
) { plan ->
|
) { plan ->
|
||||||
val planWithCurrentFlag = com.huaga.life_echo.network.models.PlanDto(
|
val planWithCurrentFlag = com.huaga.life_echo.network.models.PlanDto(
|
||||||
@@ -164,7 +167,7 @@ fun UpgradePlanScreen(
|
|||||||
benefits = plan.benefits,
|
benefits = plan.benefits,
|
||||||
features = plan.features,
|
features = plan.features,
|
||||||
isActive = plan.isActive,
|
isActive = plan.isActive,
|
||||||
isCurrentPlan = currentPlan?.id == plan.id,
|
isCurrentPlan = currentPlan?.planId == plan.id,
|
||||||
maxConversations = plan.maxConversations,
|
maxConversations = plan.maxConversations,
|
||||||
maxChapters = plan.maxChapters,
|
maxChapters = plan.maxChapters,
|
||||||
isPopular = plan.isPopular
|
isPopular = plan.isPopular
|
||||||
@@ -172,7 +175,7 @@ fun UpgradePlanScreen(
|
|||||||
PlanCard(
|
PlanCard(
|
||||||
plan = planWithCurrentFlag,
|
plan = planWithCurrentFlag,
|
||||||
onClick = {
|
onClick = {
|
||||||
if (plan.id != currentPlan?.id && plan.price > 0) {
|
if (plan.id != currentPlan?.planId && plan.price > 0) {
|
||||||
selectedPlanId = plan.id
|
selectedPlanId = plan.id
|
||||||
showPaymentMethodDialog = true
|
showPaymentMethodDialog = true
|
||||||
}
|
}
|
||||||
@@ -188,9 +191,7 @@ fun UpgradePlanScreen(
|
|||||||
PaymentMethodDialog(
|
PaymentMethodDialog(
|
||||||
onSelectMethod = { method ->
|
onSelectMethod = { method ->
|
||||||
showPaymentMethodDialog = false
|
showPaymentMethodDialog = false
|
||||||
if (activity != null) {
|
viewModel.startPayment(activity, selectedPlanId!!, method)
|
||||||
viewModel.startPayment(activity, selectedPlanId!!, method)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
showPaymentMethodDialog = false
|
showPaymentMethodDialog = false
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.app.Activity
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.huaga.life_echo.data.repository.PaymentRepository
|
import com.huaga.life_echo.data.repository.PaymentRepository
|
||||||
|
import com.huaga.life_echo.network.models.CurrentPlanDto
|
||||||
import com.huaga.life_echo.network.models.OrderDto
|
import com.huaga.life_echo.network.models.OrderDto
|
||||||
import com.huaga.life_echo.network.models.PlanDto
|
import com.huaga.life_echo.network.models.PlanDto
|
||||||
import com.huaga.life_echo.network.models.QuotaCheckDto
|
import com.huaga.life_echo.network.models.QuotaCheckDto
|
||||||
@@ -16,6 +17,7 @@ import kotlinx.coroutines.delay
|
|||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付状态
|
* 支付状态
|
||||||
@@ -48,8 +50,8 @@ class PaymentViewModel(
|
|||||||
private val _plans = MutableStateFlow<List<PlanDto>>(emptyList())
|
private val _plans = MutableStateFlow<List<PlanDto>>(emptyList())
|
||||||
val plans: StateFlow<List<PlanDto>> = _plans
|
val plans: StateFlow<List<PlanDto>> = _plans
|
||||||
|
|
||||||
private val _currentPlan = MutableStateFlow<PlanDto?>(null)
|
private val _currentPlan = MutableStateFlow<CurrentPlanDto?>(null)
|
||||||
val currentPlan: StateFlow<PlanDto?> = _currentPlan
|
val currentPlan: StateFlow<CurrentPlanDto?> = _currentPlan
|
||||||
|
|
||||||
private val _quota = MutableStateFlow<QuotaCheckDto?>(null)
|
private val _quota = MutableStateFlow<QuotaCheckDto?>(null)
|
||||||
val quota: StateFlow<QuotaCheckDto?> = _quota
|
val quota: StateFlow<QuotaCheckDto?> = _quota
|
||||||
@@ -146,11 +148,11 @@ class PaymentViewModel(
|
|||||||
/**
|
/**
|
||||||
* 发起支付
|
* 发起支付
|
||||||
*
|
*
|
||||||
* @param activity 当前 Activity
|
* @param activity 当前 Activity(微信支付可不传,支付宝支付必传)
|
||||||
* @param planId 套餐 ID
|
* @param planId 套餐 ID
|
||||||
* @param paymentMethod "wechat" 或 "alipay"
|
* @param paymentMethod "wechat" 或 "alipay"
|
||||||
*/
|
*/
|
||||||
fun startPayment(activity: Activity, planId: String, paymentMethod: String) {
|
fun startPayment(activity: Activity?, planId: String, paymentMethod: String) {
|
||||||
if (paymentManager == null) {
|
if (paymentManager == null) {
|
||||||
_paymentState.value = PaymentState.Failed("支付模块未初始化")
|
_paymentState.value = PaymentState.Failed("支付模块未初始化")
|
||||||
return
|
return
|
||||||
@@ -162,11 +164,24 @@ class PaymentViewModel(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 微信支付不需要 Activity,可继续;支付宝需要 Activity
|
||||||
|
if (paymentMethod == "alipay" && activity == null) {
|
||||||
|
_paymentState.value = PaymentState.Failed("无法获取页面上下文,请重试")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
_paymentState.value = PaymentState.CreatingOrder
|
_paymentState.value = PaymentState.CreatingOrder
|
||||||
|
|
||||||
// 1. 创建支付订单
|
// 1. 创建支付订单(45 秒超时,避免卡在「正在创建订单」)
|
||||||
paymentRepository.createPaymentOrder(planId, paymentMethod).fold(
|
val orderResult = withTimeoutOrNull(45_000L) {
|
||||||
|
paymentRepository.createPaymentOrder(planId, paymentMethod)
|
||||||
|
}
|
||||||
|
if (orderResult == null) {
|
||||||
|
_paymentState.value = PaymentState.Failed("创建订单超时,请检查网络后重试")
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
orderResult.fold(
|
||||||
onSuccess = { response ->
|
onSuccess = { response ->
|
||||||
_paymentState.value = PaymentState.Paying(response.orderId, paymentMethod)
|
_paymentState.value = PaymentState.Paying(response.orderId, paymentMethod)
|
||||||
|
|
||||||
@@ -182,11 +197,13 @@ class PaymentViewModel(
|
|||||||
}
|
}
|
||||||
"alipay" -> {
|
"alipay" -> {
|
||||||
val orderString = response.alipayOrderString
|
val orderString = response.alipayOrderString
|
||||||
if (!orderString.isNullOrEmpty()) {
|
when {
|
||||||
invokeAlipay(activity, orderString, response.orderId)
|
orderString.isNullOrEmpty() ->
|
||||||
} else {
|
_paymentState.value = PaymentState.Failed("未获取到支付宝订单信息")
|
||||||
_paymentState.value =
|
activity == null ->
|
||||||
PaymentState.Failed("未获取到支付宝订单信息")
|
_paymentState.value = PaymentState.Failed("无法获取页面上下文,请重试")
|
||||||
|
else ->
|
||||||
|
invokeAlipay(activity, orderString, response.orderId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@@ -196,8 +213,8 @@ class PaymentViewModel(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFailure = { error ->
|
onFailure = { error ->
|
||||||
_paymentState.value =
|
val message = error.message ?: "创建订单失败"
|
||||||
PaymentState.Failed(error.message ?: "创建订单失败")
|
_paymentState.value = PaymentState.Failed(message)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user