微信支付的回调 一般的做法有:
1、用单例类解决/静态函数
- 需要注意回收
- 如果有多个地方有支付,需要维护多个回调
2、Eventbus (这个比较常用)
- 需要注册和接触注册
- 支付的页面在有叠加的情况下
- 如果需要准确的回调到对应的页面,那么需要每个页面都要做订单id判断
3、系统广播
-
需要注册和解除注册
-
用订单号来发广播不需要维护多个回调
-
系统广播 + Lifecycle 封装后, 不需要每个页面都去注册和解除注册
-
WXPayEntryActivity 中的代码:
@Override
public void onResp(BaseResp resp) {
AppPayHelper.sendWeiXinPayResp(this, resp);
finish();
}
- 使用的时候代码:
AppPayHelper.get(this).setCallback(object : AppPayHelper.OnPayCallback() {
override fun onSuccess(prepayId: String) {
loadingDialog.dismiss()
finish()
}
override fun onCancel(prepayId: String) {
loadingDialog.dismiss()
ToastUtil.show("支付已取消")
}
override fun onError(prepayId: String, throwable: Throwable) {
loadingDialog.dismiss()
ToastUtil.show(throwable.message.toDefault(""))
}
}).onWeiXinPay(WeiXinUtil.WEIXIN_APP_ID, dto.noncestr, dto.partnerid, dto.prepayid, dto.pck, dto.timestamp, dto.sign)
- 封装代码:
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.tencent.mm.opensdk.constants.ConstantsAPI
import com.tencent.mm.opensdk.modelpay.PayReq
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import com.tencent.mm.opensdk.modelbase.BaseResp
import com.tencent.mm.opensdk.modelpay.PayResp
/**
* 微信支付 帮助类
*/
object WxPayHelper {
/**
* 微信返回的参数 支付实体
*/
private const val WX_PAY_RESP = "wx_pay_resp"
private const val BROADCAST_PAY = "WxPayHelper"
/**
* 微信支付成功,通过发广播来回调给 发起支付的页面
*/
@JvmStatic
fun sendWeiXinPayResp(context: Context?, resp: BaseResp?) {
context ?: return
resp ?: return
//这里只处理微信支付的回调
if (resp.type != ConstantsAPI.COMMAND_PAY_BY_WX) {
return
}
//将微信的baseResp 转成 payResp 能拿到 预订单id,
//通过预订单id 发送对应的广播,保证发起支付对象的 预订单id,和 支付结果的 预订单id一致
val payResp = (resp as? PayResp)
//toDefault 使用来判空的
val intent = Intent(BROADCAST_PAY + payResp?.prepayId.toDefault(""))
//转成json 字符串 来发送
intent.putExtra(WX_PAY_RESP, payResp.toJsonString())
LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
}
@JvmStatic
fun get(activity: AppCompatActivity): WxPayRequestHelper {
val helper = WxPayRequestHelper(activity)
activity.lifecycle.addObserver(helper)
return helper
}
@JvmStatic
fun get(fragment: Fragment): WxPayRequestHelper {
val helper = WxPayRequestHelper(fragment.context)
fragment.lifecycle.addObserver(helper)
return helper
}
@JvmStatic
fun get(owner: LifecycleOwner, context: Context): WxPayRequestHelper {
val helper = WxPayRequestHelper(context)
owner.lifecycle.addObserver(helper)
return helper
}
class WxPayRequestHelper(private val context: Context?) : LifecycleEventObserver {
/**
* 支付回调
*/
private var mPayCallback: OnWxPayCallback? = null
/**
* 广播通知
*/
private var mBroadcastReceiver: BroadcastReceiver? = null
private val mLocalBroadcastManager by lazy { context?.let { LocalBroadcastManager.getInstance(it) } }
/**
* 正在执行支付的 订单id/预订单号 /支付交易会话ID
*/
private var mPrepayId: String? = null
/**
* 生命周期发送变化时
*/
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_DESTROY) {
mBroadcastReceiver?.let {
mLocalBroadcastManager?.unregisterReceiver(it)
}
mBroadcastReceiver = null
mPayCallback = null
}
}
/**
* 注册广播
*/
private fun onRegisterBroadcast() {
if (mBroadcastReceiver != null) {
return
}
mBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent == null) {
mPayCallback?.onError(mPrepayId.toDefault(""), "-1", Throwable("未返回支付结果"))
return
}
val payResp = intent.getStringExtra(WX_PAY_RESP).stringToObj<PayResp>()
if (payResp == null) {
mPayCallback?.onError(mPrepayId.toDefault(""), "-1", Throwable("未返回支付结果"))
return
}
if (mPrepayId == null || payResp.prepayId != mPrepayId) {
mPayCallback?.onError(mPrepayId.toDefault(""), "-1", Throwable("订单号错误"))
return
}
//当 请求支付的 订单id 与 支付完成的 订单id一致时才能有回调
when (payResp.errCode) {
BaseResp.ErrCode.ERR_OK -> mPayCallback?.onSuccess(mPrepayId.toDefault(""))
BaseResp.ErrCode.ERR_USER_CANCEL -> mPayCallback?.onCancel(mPrepayId.toDefault(""))
else -> mPayCallback?.onError(
mPrepayId.toDefault(""),
payResp.errCode.toString(),
Throwable(String.format("%s,错误码:%d", payResp.errStr.toDefault(""), payResp.errCode))
)
}
//收到广播通知后,及时解出注册
mBroadcastReceiver?.let {
mLocalBroadcastManager?.unregisterReceiver(it)
}
mBroadcastReceiver = null
}
}
mBroadcastReceiver?.let { broadcastReceiver ->
val intentFilter = IntentFilter()
intentFilter.addAction(BROADCAST_PAY + mPrepayId.toDefault(""))
mLocalBroadcastManager?.registerReceiver(broadcastReceiver, intentFilter)
}
}
/**
* 设置回调
*/
fun setCallback(callback: OnWxPayCallback): WxPayRequestHelper {
mPayCallback = callback
return this
}
/**
* 微信支付
*/
fun onWeiXinPay(wxDto: WxPayRequestData) {
onWeiXinPay(wxDto.getWxAppId(), wxDto.getWxNonceStr(), wxDto.getWxPartnerId(), wxDto.getWxPrepayId(), wxDto.getWxPck(), wxDto.getWxTimestamp(), wxDto.getWxSign())
}
/**
* 微信支付
* @param appId 微信开放平台 appId
* @param nonceStr 随机字符串,随机字符串,不长于32位。推荐随机数生成算法
* @param partnerId 微信支付分配的商户号
* @param prepayId 微信返回的支付交易会话ID
* @param pck 固定值
* @param timestamp 时间戳,请见接口规则-参数规定
* @param sign 签名,详见签名生成算法注意:签名方式一定要与统一下单接口使用的一致
*/
fun onWeiXinPay(appId: String?, nonceStr: String?, partnerId: String?, prepayId: String?, pck: String?, timestamp: String?, sign: String?) {
if (context == null) {
mPayCallback?.onError(prepayId.toDefault(""), "-1", Throwable("订单生成错误:context不存在"))
return
}
if (appId.isNullOrEmpty()) {
mPayCallback?.onError(prepayId.toDefault(""), "-1", Throwable("订单生成错误:appId"))
return
}
if (nonceStr.isNullOrEmpty()) {
mPayCallback?.onError(prepayId.toDefault(""), "-1", Throwable("订单生成错误:nonceStr"))
return
}
if (partnerId.isNullOrEmpty()) {
mPayCallback?.onError(prepayId.toDefault(""), "-1", Throwable("订单生成错误:partnerId"))
return
}
if (prepayId.isNullOrEmpty()) {
mPayCallback?.onError("", "-1", Throwable("订单生成错误:prepayId"))
return
}
if (pck.isNullOrEmpty()) {
mPayCallback?.onError(prepayId.toDefault(""), "-1", Throwable("订单生成错误:pck"))
return
}
if (timestamp.isNullOrEmpty()) {
mPayCallback?.onError(prepayId.toDefault(""), "-1", Throwable("订单生成错误:timestamp"))
return
}
if (sign.isNullOrEmpty()) {
mPayCallback?.onError(prepayId.toDefault(""), "-1", Throwable("订单生成错误:sign"))
return
}
mPrepayId = prepayId
//这里的appid,替换成自己的即可
val wxApi = WXAPIFactory.createWXAPI(context, appId)
wxApi.registerApp(appId)
if (!wxApi.isWXAppInstalled) {
mPayCallback?.onError(prepayId, "-1", Throwable("请先安装微信App"))
return
}
val payRequest = PayReq()
payRequest.appId = appId
////随机字符串,随机字符串,不长于32位。推荐随机数生成算法
payRequest.nonceStr = nonceStr
////微信支付分配的商户号
payRequest.partnerId = partnerId
////微信返回的支付交易会话ID
payRequest.prepayId = prepayId
//固定值
payRequest.packageValue = pck
//时间戳,请见接口规则-参数规定
payRequest.timeStamp = timestamp
//签名,详见签名生成算法注意:签名方式一定要与统一下单接口使用的一致
payRequest.sign = sign
//发起请求,调起微信前去支付
val isSendReq = wxApi.sendReq(payRequest)
if (!isSendReq) {
mPayCallback?.onError(prepayId, "-1", Throwable("微信支付请求发送失败"))
}
onRegisterBroadcast()
}
}
/**
* 选择回调
*/
abstract class OnWxPayCallback(val context: Context?) {
/**
* 成功
* @param prepayId 预定单id/订单id
*/
abstract fun onSuccess(prepayId: String)
/**
* @param prepayId 预定单id/订单id
*/
open fun onCancel(prepayId: String) {
}
/**
* @param prepayId 预定单id/订单id
* @param code 错误码
* @param throwable 错误信息
*/
open fun onError(prepayId: String, code: String, throwable: Throwable) {
}
}
/**
* 实体类继承这个 可以直接使用
*/
interface WxPayRequestData {
fun getWxAppId(): String?
fun getWxNonceStr(): String?
fun getWxPartnerId(): String?
fun getWxPrepayId(): String?
fun getWxPck(): String?
fun getWxTimestamp(): String?
fun getWxSign(): String?
}
}