feat: 新增前端支付模块
- 新增payment/支付管理(PaymentManager、微信/支付宝Handler) - 新增wxapi/WXPayEntryActivity微信支付回调 - 扩展ApiService、PaymentModels、PaymentRepository Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
package com.huaga.life_echo.data.repository
|
||||
|
||||
import com.huaga.life_echo.network.ApiService
|
||||
import com.huaga.life_echo.network.models.CreatePaymentOrderResponse
|
||||
import com.huaga.life_echo.network.models.OrderDto
|
||||
import com.huaga.life_echo.network.models.PaymentOrderStatusResponse
|
||||
import com.huaga.life_echo.network.models.PlanDto
|
||||
import com.huaga.life_echo.network.models.QuotaCheckDto
|
||||
import com.huaga.life_echo.network.models.TestSubscriptionResponse
|
||||
|
||||
class PaymentRepository(
|
||||
private val apiService: ApiService
|
||||
@@ -31,4 +34,37 @@ class PaymentRepository(
|
||||
suspend fun getOrderById(orderId: String): Result<OrderDto> {
|
||||
return apiService.getOrderById(orderId)
|
||||
}
|
||||
|
||||
// ==================== 支付订单(微信/支付宝) ====================
|
||||
|
||||
/**
|
||||
* 创建支付订单(获取支付参数)
|
||||
*/
|
||||
suspend fun createPaymentOrder(
|
||||
planId: String,
|
||||
paymentMethod: String
|
||||
): Result<CreatePaymentOrderResponse> {
|
||||
return apiService.createPaymentOrder(planId, paymentMethod)
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询支付订单状态
|
||||
*/
|
||||
suspend fun getPaymentOrderStatus(orderId: String): Result<PaymentOrderStatusResponse> {
|
||||
return apiService.getPaymentOrderStatus(orderId)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支付订单列表
|
||||
*/
|
||||
suspend fun getPaymentOrders(): Result<List<PaymentOrderStatusResponse>> {
|
||||
return apiService.getPaymentOrders()
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试订阅开关(仅当服务端开启时可用)
|
||||
*/
|
||||
suspend fun setTestSubscription(action: String, planId: String = "pro"): Result<TestSubscriptionResponse> {
|
||||
return apiService.setTestSubscription(action, planId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +237,75 @@ class ApiService(
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 支付订单API(微信/支付宝) ====================
|
||||
|
||||
/**
|
||||
* 创建支付订单
|
||||
* 返回微信支付参数或支付宝订单字符串
|
||||
*/
|
||||
suspend fun createPaymentOrder(
|
||||
planId: String,
|
||||
paymentMethod: String
|
||||
): Result<CreatePaymentOrderResponse> {
|
||||
return try {
|
||||
val response = client.post("$BASE_URL/api/payment/create-order") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(CreatePaymentOrderRequest(planId, paymentMethod))
|
||||
}
|
||||
Result.success(response.body())
|
||||
} catch (e: Exception) {
|
||||
Result.failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询支付订单状态
|
||||
*/
|
||||
suspend fun getPaymentOrderStatus(orderId: String): Result<PaymentOrderStatusResponse> {
|
||||
return try {
|
||||
val response = client.get("$BASE_URL/api/payment/order/$orderId/status") {
|
||||
contentType(ContentType.Application.Json)
|
||||
}
|
||||
Result.success(response.body())
|
||||
} catch (e: Exception) {
|
||||
Result.failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支付订单列表(新接口)
|
||||
*/
|
||||
suspend fun getPaymentOrders(): Result<List<PaymentOrderStatusResponse>> {
|
||||
return try {
|
||||
val response = client.get("$BASE_URL/api/payment/orders") {
|
||||
contentType(ContentType.Application.Json)
|
||||
}
|
||||
Result.success(response.body())
|
||||
} catch (e: Exception) {
|
||||
Result.failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 用户相关API ====================
|
||||
|
||||
/**
|
||||
* 测试订阅开关(仅当服务端 ENABLE_TEST_SUBSCRIPTION=1 时可用)
|
||||
* 用于微信支付审核通过前模拟付费通过,体验订阅额度。
|
||||
*/
|
||||
suspend fun setTestSubscription(
|
||||
action: String,
|
||||
planId: String = "pro"
|
||||
): Result<TestSubscriptionResponse> {
|
||||
return try {
|
||||
val response = client.post("$BASE_URL/api/user/test-subscription") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(TestSubscriptionRequest(action = action, planId = planId))
|
||||
}
|
||||
Result.success(response.body())
|
||||
} catch (e: Exception) {
|
||||
Result.failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getUserProfile(): Result<UserProfileDto> {
|
||||
return try {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.huaga.life_echo.network.models
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
@@ -18,19 +19,22 @@ data class PlanBenefitDto(
|
||||
val features: List<String> = emptyList() // 功能列表
|
||||
)
|
||||
|
||||
// 套餐信息DTO
|
||||
// 套餐信息DTO(与后端 /api/plans 返回字段对应)
|
||||
@Serializable
|
||||
data class PlanDto(
|
||||
val id: String,
|
||||
val name: String,
|
||||
val displayName: String,
|
||||
@SerialName("display_name") val displayName: String,
|
||||
val price: Double,
|
||||
val currency: String = "CNY",
|
||||
val billingCycle: String, // "monthly", "yearly"
|
||||
@SerialName("billing_cycle") val billingCycle: String? = null,
|
||||
val benefits: List<PlanBenefitDto> = emptyList(),
|
||||
val features: List<String> = emptyList(),
|
||||
val isActive: Boolean = true,
|
||||
val isCurrentPlan: Boolean = false
|
||||
val isCurrentPlan: Boolean = false,
|
||||
@SerialName("max_conversations") val maxConversations: Int? = null,
|
||||
@SerialName("max_chapters") val maxChapters: Int? = null,
|
||||
@SerialName("is_popular") val isPopular: Boolean = false
|
||||
)
|
||||
|
||||
// 订单信息DTO
|
||||
@@ -69,5 +73,84 @@ data class QuotaCheckDto(
|
||||
val remainingWords: Int? = null,
|
||||
val remainingChapters: Int? = null,
|
||||
val remainingConversations: Int? = null,
|
||||
// 已用量与上限(用于展示 "已用 X / 共 Y")
|
||||
val usedConversations: Int? = null,
|
||||
val usedChapters: Int? = null,
|
||||
val maxConversations: Int? = null,
|
||||
val maxChapters: Int? = null,
|
||||
val message: String? = null
|
||||
)
|
||||
|
||||
// ==================== 支付订单相关模型 ====================
|
||||
|
||||
/**
|
||||
* 创建支付订单请求
|
||||
*/
|
||||
@Serializable
|
||||
data class CreatePaymentOrderRequest(
|
||||
@SerialName("plan_id") val planId: String,
|
||||
@SerialName("payment_method") val paymentMethod: String // "wechat" / "alipay"
|
||||
)
|
||||
|
||||
/**
|
||||
* 创建支付订单响应
|
||||
*/
|
||||
@Serializable
|
||||
data class CreatePaymentOrderResponse(
|
||||
@SerialName("order_id") val orderId: String,
|
||||
@SerialName("payment_method") val paymentMethod: String,
|
||||
// 微信支付参数(仅当 paymentMethod == "wechat" 时有值)
|
||||
@SerialName("wechat_params") val wechatParams: WeChatPayParamsDto? = null,
|
||||
// 支付宝订单字符串(仅当 paymentMethod == "alipay" 时有值)
|
||||
@SerialName("alipay_order_string") val alipayOrderString: String? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* 微信支付参数 DTO
|
||||
*/
|
||||
@Serializable
|
||||
data class WeChatPayParamsDto(
|
||||
val appId: String = "",
|
||||
val partnerId: String = "",
|
||||
val prepayId: String = "",
|
||||
val nonceStr: String = "",
|
||||
val timeStamp: String = "",
|
||||
val sign: String = "",
|
||||
val packageValue: String = "Sign=WXPay"
|
||||
)
|
||||
|
||||
/**
|
||||
* 订单状态查询响应
|
||||
*/
|
||||
@Serializable
|
||||
data class PaymentOrderStatusResponse(
|
||||
@SerialName("order_id") val orderId: String,
|
||||
@SerialName("plan_id") val planId: String,
|
||||
@SerialName("plan_name") val planName: String,
|
||||
val amount: Int, // 金额(分)
|
||||
val currency: String,
|
||||
@SerialName("payment_method") val paymentMethod: String,
|
||||
val status: String, // pending / paid / failed / cancelled / refunded
|
||||
@SerialName("trade_no") val tradeNo: String? = null,
|
||||
@SerialName("created_at") val createdAt: String,
|
||||
@SerialName("paid_at") val paidAt: String? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* 测试订阅请求(仅开发/测试环境,微信支付审核通过前使用)
|
||||
*/
|
||||
@Serializable
|
||||
data class TestSubscriptionRequest(
|
||||
val action: String, // "activate" | "deactivate"
|
||||
@SerialName("plan_id") val planId: String? = "pro"
|
||||
)
|
||||
|
||||
/**
|
||||
* 测试订阅响应
|
||||
*/
|
||||
@Serializable
|
||||
data class TestSubscriptionResponse(
|
||||
val success: Boolean,
|
||||
val message: String,
|
||||
@SerialName("subscription_type") val subscriptionType: String
|
||||
)
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.huaga.life_echo.payment
|
||||
|
||||
import android.app.Activity
|
||||
import android.util.Log
|
||||
import com.alipay.sdk.app.PayTask
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* 支付宝支付处理器
|
||||
*
|
||||
* 负责:
|
||||
* 1. 调起支付宝 APP 支付
|
||||
* 2. 解析支付结果
|
||||
*/
|
||||
class AlipayHandler {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "AlipayHandler"
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起支付宝支付
|
||||
*
|
||||
* 注意:此方法需要在协程中调用(内部会切换到 IO 线程)
|
||||
*
|
||||
* @param activity 当前 Activity
|
||||
* @param orderString 从服务端获取的支付宝订单字符串
|
||||
* @param orderId 内部订单号
|
||||
* @return PaymentResult
|
||||
*/
|
||||
suspend fun startPay(
|
||||
activity: Activity,
|
||||
orderString: String,
|
||||
orderId: String
|
||||
): PaymentResult = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
Log.d(TAG, "发起支付宝支付: orderId=$orderId")
|
||||
|
||||
val payTask = PayTask(activity)
|
||||
val result: Map<String, String> = payTask.payV2(orderString, true)
|
||||
|
||||
Log.d(TAG, "支付宝支付结果: $result")
|
||||
|
||||
parseResult(result, orderId)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "支付宝支付异常", e)
|
||||
PaymentResult.Failure(
|
||||
orderId = orderId,
|
||||
paymentMethod = "alipay",
|
||||
errorCode = -1,
|
||||
errorMessage = e.message ?: "支付异常"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析支付宝支付结果
|
||||
*/
|
||||
private fun parseResult(result: Map<String, String>, orderId: String): PaymentResult {
|
||||
val resultStatus = result["resultStatus"] ?: ""
|
||||
val memo = result["memo"] ?: ""
|
||||
|
||||
return when (resultStatus) {
|
||||
"9000" -> {
|
||||
// 支付成功
|
||||
Log.d(TAG, "支付宝支付成功: orderId=$orderId")
|
||||
PaymentResult.Success(orderId = orderId, paymentMethod = "alipay")
|
||||
}
|
||||
"6001" -> {
|
||||
// 用户取消
|
||||
Log.d(TAG, "支付宝支付取消: orderId=$orderId")
|
||||
PaymentResult.Cancelled(orderId = orderId, paymentMethod = "alipay")
|
||||
}
|
||||
"6002" -> {
|
||||
// 网络连接出错
|
||||
Log.e(TAG, "支付宝支付网络错误: orderId=$orderId")
|
||||
PaymentResult.Failure(
|
||||
orderId = orderId,
|
||||
paymentMethod = "alipay",
|
||||
errorCode = 6002,
|
||||
errorMessage = "网络连接异常,请检查网络后重试"
|
||||
)
|
||||
}
|
||||
"4000" -> {
|
||||
// 支付失败
|
||||
Log.e(TAG, "支付宝支付失败: orderId=$orderId, memo=$memo")
|
||||
PaymentResult.Failure(
|
||||
orderId = orderId,
|
||||
paymentMethod = "alipay",
|
||||
errorCode = 4000,
|
||||
errorMessage = memo.ifEmpty { "支付失败" }
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
Log.e(TAG, "支付宝支付未知状态: resultStatus=$resultStatus, memo=$memo")
|
||||
PaymentResult.Failure(
|
||||
orderId = orderId,
|
||||
paymentMethod = "alipay",
|
||||
errorCode = resultStatus.toIntOrNull() ?: -1,
|
||||
errorMessage = memo.ifEmpty { "支付异常($resultStatus)" }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.huaga.life_echo.payment
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
|
||||
/**
|
||||
* 统一支付管理器
|
||||
*
|
||||
* 提供统一的支付入口,屏蔽微信/支付宝底层差异
|
||||
*
|
||||
* 使用方式:
|
||||
* ```
|
||||
* val manager = PaymentManager(context, wechatAppId)
|
||||
*
|
||||
* // 微信支付
|
||||
* manager.startWeChatPay(activity, params, orderId) { result -> ... }
|
||||
*
|
||||
* // 支付宝支付
|
||||
* val result = manager.startAlipay(activity, orderString, orderId)
|
||||
* ```
|
||||
*/
|
||||
class PaymentManager(
|
||||
context: Context,
|
||||
wechatAppId: String
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "PaymentManager"
|
||||
}
|
||||
|
||||
private val weChatPayHandler = WeChatPayHandler(context.applicationContext, wechatAppId)
|
||||
private val alipayHandler = AlipayHandler()
|
||||
|
||||
/**
|
||||
* 检查微信是否已安装
|
||||
*/
|
||||
fun isWeChatInstalled(): Boolean {
|
||||
return weChatPayHandler.isWeChatInstalled()
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起微信支付
|
||||
*
|
||||
* @param params 从服务端获取的微信支付参数
|
||||
* @param orderId 内部订单号
|
||||
* @param callback 支付结果回调(在主线程)
|
||||
*/
|
||||
fun startWeChatPay(
|
||||
params: WeChatPayParams,
|
||||
orderId: String,
|
||||
callback: (PaymentResult) -> Unit
|
||||
) {
|
||||
Log.d(TAG, "发起微信支付: orderId=$orderId")
|
||||
weChatPayHandler.startPay(params, orderId, callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起支付宝支付
|
||||
*
|
||||
* 注意:此方法需要在协程中调用
|
||||
*
|
||||
* @param activity 当前 Activity
|
||||
* @param orderString 从服务端获取的支付宝订单字符串
|
||||
* @param orderId 内部订单号
|
||||
* @return PaymentResult
|
||||
*/
|
||||
suspend fun startAlipay(
|
||||
activity: Activity,
|
||||
orderString: String,
|
||||
orderId: String
|
||||
): PaymentResult {
|
||||
Log.d(TAG, "发起支付宝支付: orderId=$orderId")
|
||||
return alipayHandler.startPay(activity, orderString, orderId)
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放资源,在不需要时调用
|
||||
*/
|
||||
fun release() {
|
||||
weChatPayHandler.release()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.huaga.life_echo.payment
|
||||
|
||||
/**
|
||||
* 支付结果封装
|
||||
*/
|
||||
sealed class PaymentResult {
|
||||
/** 支付成功 */
|
||||
data class Success(
|
||||
val orderId: String,
|
||||
val paymentMethod: String
|
||||
) : PaymentResult()
|
||||
|
||||
/** 支付失败 */
|
||||
data class Failure(
|
||||
val orderId: String,
|
||||
val paymentMethod: String,
|
||||
val errorCode: Int = -1,
|
||||
val errorMessage: String = "支付失败"
|
||||
) : PaymentResult()
|
||||
|
||||
/** 用户取消支付 */
|
||||
data class Cancelled(
|
||||
val orderId: String,
|
||||
val paymentMethod: String
|
||||
) : PaymentResult()
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付调起参数(从服务端获取)
|
||||
*/
|
||||
data class WeChatPayParams(
|
||||
val appId: String,
|
||||
val partnerId: String,
|
||||
val prepayId: String,
|
||||
val nonceStr: String,
|
||||
val timeStamp: String,
|
||||
val sign: String,
|
||||
val packageValue: String = "Sign=WXPay"
|
||||
)
|
||||
@@ -0,0 +1,187 @@
|
||||
package com.huaga.life_echo.payment
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.util.Log
|
||||
import com.tencent.mm.opensdk.modelpay.PayReq
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPI
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory
|
||||
|
||||
/**
|
||||
* 微信支付处理器
|
||||
*
|
||||
* 负责:
|
||||
* 1. 注册微信 SDK
|
||||
* 2. 调起微信支付
|
||||
* 3. 接收支付结果(通过 WXPayEntryActivity 转发)
|
||||
*/
|
||||
class WeChatPayHandler(
|
||||
private val context: Context,
|
||||
private val appId: String
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "WeChatPayHandler"
|
||||
|
||||
/** 微信支付结果广播 Action */
|
||||
const val ACTION_WECHAT_PAY_RESULT = "com.huaga.life_echo.WECHAT_PAY_RESULT"
|
||||
const val EXTRA_ERROR_CODE = "error_code"
|
||||
const val EXTRA_ERROR_MSG = "error_msg"
|
||||
}
|
||||
|
||||
private val wxApi: IWXAPI by lazy {
|
||||
WXAPIFactory.createWXAPI(context, appId, true).also {
|
||||
it.registerApp(appId)
|
||||
}
|
||||
}
|
||||
|
||||
/** 当前等待支付结果的回调 */
|
||||
private var pendingCallback: ((PaymentResult) -> Unit)? = null
|
||||
private var pendingOrderId: String? = null
|
||||
|
||||
/** 广播接收器:接收来自 WXPayEntryActivity 的支付结果 */
|
||||
private val payResultReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
val errCode = intent?.getIntExtra(EXTRA_ERROR_CODE, -1) ?: -1
|
||||
val errMsg = intent?.getStringExtra(EXTRA_ERROR_MSG) ?: ""
|
||||
handlePayResult(errCode, errMsg)
|
||||
}
|
||||
}
|
||||
|
||||
private var isReceiverRegistered = false
|
||||
|
||||
/**
|
||||
* 检查微信是否已安装
|
||||
*/
|
||||
fun isWeChatInstalled(): Boolean {
|
||||
return wxApi.isWXAppInstalled
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起微信支付
|
||||
*
|
||||
* @param params 从服务端获取的支付参数
|
||||
* @param orderId 内部订单号
|
||||
* @param callback 支付结果回调
|
||||
*/
|
||||
fun startPay(
|
||||
params: WeChatPayParams,
|
||||
orderId: String,
|
||||
callback: (PaymentResult) -> Unit
|
||||
) {
|
||||
if (!isWeChatInstalled()) {
|
||||
callback(
|
||||
PaymentResult.Failure(
|
||||
orderId = orderId,
|
||||
paymentMethod = "wechat",
|
||||
errorCode = -2,
|
||||
errorMessage = "未安装微信客户端"
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// 保存回调
|
||||
pendingCallback = callback
|
||||
pendingOrderId = orderId
|
||||
|
||||
// 注册广播接收器
|
||||
registerReceiver()
|
||||
|
||||
// 构建支付请求
|
||||
val req = PayReq().apply {
|
||||
appId = params.appId
|
||||
partnerId = params.partnerId
|
||||
prepayId = params.prepayId
|
||||
nonceStr = params.nonceStr
|
||||
timeStamp = params.timeStamp
|
||||
sign = params.sign
|
||||
packageValue = params.packageValue
|
||||
}
|
||||
|
||||
Log.d(TAG, "发起微信支付: orderId=$orderId")
|
||||
val result = wxApi.sendReq(req)
|
||||
if (!result) {
|
||||
Log.e(TAG, "微信支付调起失败")
|
||||
pendingCallback?.invoke(
|
||||
PaymentResult.Failure(
|
||||
orderId = orderId,
|
||||
paymentMethod = "wechat",
|
||||
errorCode = -3,
|
||||
errorMessage = "微信支付调起失败"
|
||||
)
|
||||
)
|
||||
pendingCallback = null
|
||||
pendingOrderId = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理微信支付结果
|
||||
* 由广播接收器调用
|
||||
*/
|
||||
private fun handlePayResult(errCode: Int, errMsg: String) {
|
||||
val orderId = pendingOrderId ?: ""
|
||||
val callback = pendingCallback
|
||||
|
||||
// 清理状态
|
||||
pendingCallback = null
|
||||
pendingOrderId = null
|
||||
|
||||
val result = when (errCode) {
|
||||
0 -> {
|
||||
Log.d(TAG, "微信支付成功: orderId=$orderId")
|
||||
PaymentResult.Success(orderId = orderId, paymentMethod = "wechat")
|
||||
}
|
||||
-1 -> {
|
||||
Log.e(TAG, "微信支付失败: errCode=$errCode, errMsg=$errMsg")
|
||||
PaymentResult.Failure(
|
||||
orderId = orderId,
|
||||
paymentMethod = "wechat",
|
||||
errorCode = errCode,
|
||||
errorMessage = errMsg.ifEmpty { "支付失败" }
|
||||
)
|
||||
}
|
||||
-2 -> {
|
||||
Log.d(TAG, "微信支付取消: orderId=$orderId")
|
||||
PaymentResult.Cancelled(orderId = orderId, paymentMethod = "wechat")
|
||||
}
|
||||
else -> {
|
||||
Log.e(TAG, "微信支付未知错误: errCode=$errCode")
|
||||
PaymentResult.Failure(
|
||||
orderId = orderId,
|
||||
paymentMethod = "wechat",
|
||||
errorCode = errCode,
|
||||
errorMessage = "未知错误($errCode)"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
callback?.invoke(result)
|
||||
}
|
||||
|
||||
private fun registerReceiver() {
|
||||
if (!isReceiverRegistered) {
|
||||
val filter = IntentFilter(ACTION_WECHAT_PAY_RESULT)
|
||||
context.registerReceiver(payResultReceiver, filter, Context.RECEIVER_NOT_EXPORTED)
|
||||
isReceiverRegistered = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放资源
|
||||
*/
|
||||
fun release() {
|
||||
if (isReceiverRegistered) {
|
||||
try {
|
||||
context.unregisterReceiver(payResultReceiver)
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
isReceiverRegistered = false
|
||||
}
|
||||
pendingCallback = null
|
||||
pendingOrderId = null
|
||||
wxApi.detach()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.huaga.life_echo.wxapi
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import com.huaga.life_echo.payment.WeChatPayHandler
|
||||
import com.tencent.mm.opensdk.constants.ConstantsAPI
|
||||
import com.tencent.mm.opensdk.modelbase.BaseReq
|
||||
import com.tencent.mm.opensdk.modelbase.BaseResp
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPI
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory
|
||||
import com.huaga.life_echo.config.AppConfig
|
||||
|
||||
/**
|
||||
* 微信支付结果回调 Activity
|
||||
*
|
||||
* 重要说明:
|
||||
* - 此类必须位于 {应用包名}.wxapi 目录下
|
||||
* - 类名必须为 WXPayEntryActivity
|
||||
* - 这是微信 SDK 的硬性要求,不可更改路径和类名
|
||||
*
|
||||
* 收到微信支付结果后,通过广播转发给 WeChatPayHandler
|
||||
*/
|
||||
class WXPayEntryActivity : Activity(), IWXAPIEventHandler {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "WXPayEntryActivity"
|
||||
}
|
||||
|
||||
private lateinit var wxApi: IWXAPI
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
wxApi = WXAPIFactory.createWXAPI(this, AppConfig.WECHAT_APP_ID)
|
||||
wxApi.handleIntent(intent, this)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
setIntent(intent)
|
||||
wxApi.handleIntent(intent, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信发送请求到第三方应用时回调(支付场景不会触发)
|
||||
*/
|
||||
override fun onReq(req: BaseReq?) {
|
||||
Log.d(TAG, "onReq: ${req?.type}")
|
||||
}
|
||||
|
||||
/**
|
||||
* 第三方应用发送到微信的请求处理后的响应结果回调
|
||||
* 支付结果在这里接收
|
||||
*/
|
||||
override fun onResp(resp: BaseResp?) {
|
||||
Log.d(TAG, "onResp: type=${resp?.type}, errCode=${resp?.errCode}, errStr=${resp?.errStr}")
|
||||
|
||||
if (resp?.type == ConstantsAPI.COMMAND_PAY_BY_WX) {
|
||||
// 通过广播将结果转发给 WeChatPayHandler
|
||||
val intent = Intent(WeChatPayHandler.ACTION_WECHAT_PAY_RESULT).apply {
|
||||
setPackage(packageName)
|
||||
putExtra(WeChatPayHandler.EXTRA_ERROR_CODE, resp.errCode)
|
||||
putExtra(WeChatPayHandler.EXTRA_ERROR_MSG, resp.errStr ?: "")
|
||||
}
|
||||
sendBroadcast(intent)
|
||||
}
|
||||
|
||||
// 关闭此透明 Activity
|
||||
finish()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user