2. 微信支付SDK接入与统一下单
微信支付 App 支付链路与关键对象
微信 App 支付与支付宝最大的差异在于:调起支付的参数不是客户端自己拼的,而是服务端调用微信「统一下单」接口后返回的 prepay_id。客户端只负责把服务端下发的这组参数交给微信 SDK,然后等待微信 App 回调结果。整条链路涉及三个角色:Android 客户端、业务服务端、微信支付系统。
SDK 集成与依赖配置
微信开放平台 App 支付 SDK 以 aar 形式提供,需从微信开放平台下载后放入 libs/ 目录。在 app/build.gradle 中声明依赖:
dependencies {
implementation files('libs/wechat-sdk-android-without-mta-6.8.0.aar')
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.google.code.gson:gson:2.10.1'
}
在 AndroidManifest.xml 中注册微信回调 Activity,包名路径必须严格为 你的应用包名.wxapi.WXPayEntryActivity:
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"/>
包名路径错误是微信支付回调不触发的最常见原因。微信 SDK 通过反射查找
{packageName}.wxapi.WXPayEntryActivity,路径不对则回调静默失败。服务端统一下单与客户端调起
服务端调用微信统一下单接口 https://api.mch.weixin.qq.com/pay/unifiedorder,核心参数如下:
| 参数 | 说明 | 示例值 |
|---|---|---|
| appid | 开放平台应用 ID | wx8888888888888888 |
| mch_id | 商户号 | 1900000109 |
| out_trade_no | 商户订单号 | 202501011200001 |
| total_fee | 金额(分) | 1 |
| body | 商品描述 | 测试商品 |
| notify_url | 异步通知地址 | https://your.domain/wx/notify |
| trade_type | 交易类型 | APP |
统一下单返回 prepay_id 后,服务端需进行二次签名,将以下字段按字典序拼接后 MD5 签名,返回给客户端:
// 服务端二次签名后返回给客户端的参数
{
"appId": "wx8888888888888888",
"partnerId": "1900000109",
"prepayId": "wx01120000abcdef1234567890",
"packageValue": "Sign=WXPay",
"nonceStr": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS",
"timeStamp": "1735700000",
"sign": "A1B2C3D4E5F6..."
}
客户端收到后构造 PayReq 并调起微信:
public void pay(PayParams params) {
IWXAPI api = WXAPIFactory.createWXAPI(context, params.appId, true);
api.registerApp(params.appId);
PayReq req = new PayReq();
req.appId = params.appId;
req.partnerId = params.partnerId;
req.prepayId = params.prepayId;
req.packageValue = "Sign=WXPay";
req.nonceStr = params.nonceStr;
req.timeStamp = params.timeStamp;
req.sign = params.sign;
boolean ok = api.sendReq(req);
if (!ok) {
// 微信未安装或参数校验失败
Toast.makeText(context, "调起微信失败,请检查微信是否安装", Toast.LENGTH_SHORT).show();
}
}
WXPayEntryActivity 回调处理
支付完成后微信会回调 WXPayEntryActivity.onResp,通过 BaseResp.errCode 判断结果:
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private IWXAPI api;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
api.handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
@Override
public void onResp(BaseResp resp) {
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
switch (resp.errCode) {
case 0:
// 支付成功,但最终以服务端异步通知为准
Toast.makeText(this, "支付成功", Toast.LENGTH_SHORT).show();
break;
case -1:
Toast.makeText(this, "支付失败:" + resp.errStr, Toast.LENGTH_SHORT).show();
break;
case -2:
Toast.makeText(this, "已取消支付", Toast.LENGTH_SHORT).show();
break;
}
}
finish();
}
}
客户端回调的
errCode == 0 只代表微信侧受理成功,不能作为发货依据。必须以服务端收到 notify_url 异步通知并验签通过后的结果为准。验证与排障要点
- 回调不触发:检查
WXPayEntryActivity是否位于{包名}.wxapi目录,且已在 Manifest 注册。 - 调起失败:
sendReq返回 false,通常是appId与开放平台不一致,或签名参数被篡改。 - 签名错误:服务端二次签名时字段顺序、大小写、空值处理必须与微信文档一致,
packageValue固定为Sign=WXPay。 - 金额单位:
total_fee单位为分,1 元需传 100,传错会导致金额异常。