Files
peizhen/微信支付集成.txt
2025-12-19 23:45:38 +08:00

671 lines
20 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 微信支付集成文档
## 一、概述
### 1.1 文档说明
本文档详细说明项目中微信支付的集成方式、配置方法、调用流程和注意事项。
### 1.2 微信支付功能
- **支付方式**: 微信支付WeChat Pay
- **SDK版本**: wechat-sdk-android-without-mta-1.0.2
- **集成状态**: 已集成,但部分代码需要完善
### 1.3 微信配置信息
- **微信AppID**: wxaa49732bd3a29bec
- **微信AppSecret**: 038324288450b5dcb610915fea7fb1af
- **包名**: com.ruilaizi.service
## 二、依赖配置
### 2.1 Gradle依赖
在 `app/build.gradle` 文件中已配置以下依赖:
```gradle
dependencies {
// 微信SDK本地JAR
implementation files('libs/wechat-sdk-android-without-mta-1.0.2.jar')
implementation files('libs/ShareSDK-Wechat-Core-2.8.3.jar')
// 其他相关依赖
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.6'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
}
```
### 2.2 本地JAR文件位置
```
app/libs/
├── wechat-sdk-android-without-mta-1.0.2.jar
└── ShareSDK-Wechat-Core-2.8.3.jar
```
## 三、AndroidManifest配置
### 3.1 支付回调Activity配置
**重要**: 微信支付回调Activity必须配置在AndroidManifest.xml中且包名路径必须为`包名.wxapi.WXPayEntryActivity`
**当前状态**: ⚠️ **WXPayEntryActivity未在AndroidManifest.xml中注册需要添加配置**
需要在 `app/src/main/AndroidManifest.xml` 的 `<application>` 标签内添加:
```xml
<!-- 微信支付回调Activity -->
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
```
### 3.2 权限配置
微信支付需要以下权限已在AndroidManifest.xml中配置
```xml
<!-- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 其他必要权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
```
## 四、核心代码实现
### 4.1 微信支付回调Activity
**文件路径**: `app/src/main/java/com/ruilaizi/service/wxapi/WXPayEntryActivity.java`
**代码结构**:
```java
package com.ruilaizi.service.wxapi;
import com.ruilaizi.service.base.BaseActivity;
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;
/**
* 微信支付回调页
*/
public class WXPayEntryActivity extends BaseActivity implements IWXAPIEventHandler {
private IWXAPI api;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initData();
}
private void initData() {
// ⚠️ 注意当前代码中api初始化被注释需要修复
// api = WXAPIFactory.createWXAPI(this, WXEntryActivity.WEIXIN_APP_ID, true);
api.handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
@Override
public void onReq(BaseReq req) {
// 微信发送的请求将回调到onReq方法
}
@Override
public void onResp(BaseResp resp) {
// 支付结果回调
if (resp.errCode == 0) {
toast("支付成功");
} else if (resp.errCode == -1) {
toast("支付失败");
} else if (resp.errCode == -2) {
toast("取消支付");
}
// 发送广播通知支付结果
Intent intent = new Intent();
intent.setAction("com.antiphon.BroadcastReceiver");
intent.putExtra("payCode", resp.errCode);
sendBroadcast(intent);
finish();
}
}
```
### 4.2 支付结果错误码说明
| errCode | 说明 | 处理方式 |
|---------|------|----------|
| 0 | 支付成功 | 跳转到成功页面,更新订单状态 |
| -1 | 支付失败 | 提示用户支付失败,可重试 |
| -2 | 用户取消支付 | 提示用户已取消,返回订单页面 |
### 4.3 微信AppID配置
**文件路径**: `app/src/main/java/com/ruilaizi/service/wxapi/WXEntryActivity.java`
```java
public class WXEntryActivity extends WechatHandlerActivity {
// 微信AppID
public static final String WEIXIN_APP_ID = "wxaa49732bd3a29bec";
// 微信AppSecret用于登录支付不需要
private static final String APP_SECRET = "038324288450b5dcb610915fea7fb1af";
}
```
## 五、支付调用流程
### 5.1 支付流程概述
```
1. 用户点击支付
2. 调用后端接口获取支付参数prepay_id等
3. 构建PayReq对象设置支付参数
4. 调用IWXAPI.sendReq()发起支付
5. 跳转到微信支付界面
6. 用户在微信中完成支付
7. 微信回调到WXPayEntryActivity
8. 处理支付结果,发送广播通知
9. 更新订单状态
```
### 5.2 发起支付代码示例
**注意**: 以下代码为示例,实际项目中需要根据后端接口返回的支付参数进行构建。
```java
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
public class PaymentHelper {
private static final String WEIXIN_APP_ID = "wxaa49732bd3a29bec";
/**
* 发起微信支付
*
* @param context 上下文
* @param appId 应用ID
* @param partnerId 商户号
* @param prepayId 预支付交易会话ID
* @param nonceStr 随机字符串
* @param timeStamp 时间戳
* @param packageValue 扩展字段,固定值"Sign=WXPay"
* @param sign 签名
*/
public static void pay(Context context, String appId, String partnerId,
String prepayId, String nonceStr, String timeStamp,
String packageValue, String sign) {
// 1. 创建IWXAPI实例
IWXAPI api = WXAPIFactory.createWXAPI(context, WEIXIN_APP_ID, true);
// 2. 注册到微信
api.registerApp(WEIXIN_APP_ID);
// 3. 检查是否安装微信
if (!api.isWXAppInstalled()) {
Toast.makeText(context, "未安装微信", Toast.LENGTH_SHORT).show();
return;
}
// 4. 检查微信版本是否支持支付
if (!api.isWXAppSupportAPI()) {
Toast.makeText(context, "微信版本过低,不支持支付", Toast.LENGTH_SHORT).show();
return;
}
// 5. 构建支付请求
PayReq req = new PayReq();
req.appId = appId; // 应用ID
req.partnerId = partnerId; // 商户号
req.prepayId = prepayId; // 预支付交易会话ID
req.nonceStr = nonceStr; // 随机字符串
req.timeStamp = timeStamp; // 时间戳
req.packageValue = packageValue; // 扩展字段,固定值"Sign=WXPay"
req.sign = sign; // 签名
// 6. 发起支付
boolean result = api.sendReq(req);
if (!result) {
Toast.makeText(context, "调起支付失败", Toast.LENGTH_SHORT).show();
}
}
}
```
### 5.3 支付参数说明
| 参数名 | 说明 | 来源 |
|--------|------|------|
| appId | 应用ID | 固定值wxaa49732bd3a29bec |
| partnerId | 商户号 | 从后端接口获取 |
| prepayId | 预支付交易会话ID | 从后端接口获取 |
| nonceStr | 随机字符串 | 从后端接口获取 |
| timeStamp | 时间戳 | 从后端接口获取 |
| packageValue | 扩展字段 | 固定值:"Sign=WXPay" |
| sign | 签名 | 从后端接口获取(需要客户端重新签名) |
## 六、支付结果处理
### 6.1 广播接收器
支付结果通过广播发送Action为`com.antiphon.BroadcastReceiver`
**接收支付结果的示例代码**:
```java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
public class PaymentResultReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if ("com.antiphon.BroadcastReceiver".equals(intent.getAction())) {
int payCode = intent.getIntExtra("payCode", -999);
switch (payCode) {
case 0:
// 支付成功
handlePaymentSuccess();
break;
case -1:
// 支付失败
handlePaymentFailure();
break;
case -2:
// 用户取消
handlePaymentCancel();
break;
}
}
}
private void handlePaymentSuccess() {
// 更新订单状态
// 跳转到支付成功页面
}
private void handlePaymentFailure() {
// 提示支付失败
}
private void handlePaymentCancel() {
// 提示用户已取消支付
}
}
```
### 6.2 注册广播接收器
在需要接收支付结果的Activity中注册
```java
private PaymentResultReceiver paymentReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 注册广播接收器
paymentReceiver = new PaymentResultReceiver();
IntentFilter filter = new IntentFilter("com.antiphon.BroadcastReceiver");
registerReceiver(paymentReceiver, filter);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 注销广播接收器
if (paymentReceiver != null) {
unregisterReceiver(paymentReceiver);
}
}
```
## 七、需要修复的问题
### 7.1 当前存在的问题
#### 问题1: WXPayEntryActivity未在AndroidManifest中注册
**影响**: 微信无法回调到应用,支付结果无法接收
**解决方案**: 在AndroidManifest.xml中添加Activity配置见3.1节)
#### 问题2: WXPayEntryActivity中api未初始化
**代码位置**: `WXPayEntryActivity.java` 第64行
**当前代码**:
```java
private void initData() {
// api = WXAPIFactory.createWXAPI(this, PayUtils.APP_ID);
api.handleIntent(getIntent(), this);
}
```
**问题**: api为null会导致NullPointerException
**解决方案**: 取消注释并修复:
```java
private void initData() {
api = WXAPIFactory.createWXAPI(this, WXEntryActivity.WEIXIN_APP_ID, true);
api.handleIntent(getIntent(), this);
}
```
#### 问题3: 缺少支付发起代码
**说明**: 项目中未找到实际调用微信支付的代码
**建议**: 需要创建支付工具类或在相关Activity中添加支付调用逻辑
### 7.2 修复步骤
1. **修复WXPayEntryActivity初始化问题**
- 打开 `WXPayEntryActivity.java`
- 修复 `initData()` 方法中的api初始化
2. **添加AndroidManifest配置**
- 打开 `AndroidManifest.xml`
- 在 `<application>` 标签内添加WXPayEntryActivity配置
3. **创建支付工具类**
- 创建 `PaymentHelper.java` 或 `WeChatPayUtils.java`
- 实现支付发起逻辑
4. **在订单页面集成支付**
- 在订单确认页面添加支付按钮
- 调用后端接口获取支付参数
- 调用支付工具类发起支付
## 八、后端接口对接
### 8.1 获取支付参数接口
**接口说明**: 调用后端接口获取微信支付所需的参数
**请求示例**:
```java
// 假设后端接口为POST /api/order/createPay
@POST("order/createPay")
@FormUrlEncoded
Observable<ResponseBean<PayParams>> createPay(
@Field("order_id") String orderId,
@Field("amount") String amount
);
```
**响应数据模型**:
```java
public class PayParams {
private String appId; // 应用ID
private String partnerId; // 商户号
private String prepayId; // 预支付交易会话ID
private String nonceStr; // 随机字符串
private String timeStamp; // 时间戳
private String packageValue; // 扩展字段
private String sign; // 签名(可能需要客户端重新计算)
// getter和setter方法
}
```
### 8.2 支付结果通知接口
**说明**: 支付成功后,需要调用后端接口通知服务器更新订单状态
**接口示例**:
```java
@POST("order/payNotify")
@FormUrlEncoded
Observable<ResponseBean<OrderInfo>> payNotify(
@Field("order_id") String orderId,
@Field("pay_result") int payResult // 0:成功, -1:失败, -2:取消
);
```
## 九、测试验证
### 9.1 测试环境准备
1. **微信开发者账号**
- 注册微信开放平台账号
- 创建移动应用获取AppID
- 配置应用签名和包名
2. **测试设备**
- 安装微信客户端
- 使用测试账号登录微信
3. **测试账号**
- 微信支付测试账号(沙箱环境)
- 或使用真实商户号进行测试
### 9.2 测试步骤
1. **检查微信安装**
```java
IWXAPI api = WXAPIFactory.createWXAPI(context, WEIXIN_APP_ID, true);
if (!api.isWXAppInstalled()) {
// 提示用户安装微信
}
```
2. **测试支付流程**
- 创建测试订单
- 点击支付按钮
- 验证是否跳转到微信支付界面
- 完成支付(或取消)
- 验证是否回调到WXPayEntryActivity
- 验证广播是否发送
- 验证订单状态是否更新
3. **测试支付结果处理**
- 测试支付成功场景
- 测试支付失败场景
- 测试用户取消场景
### 9.3 常见问题排查
#### 问题1: 无法调起微信支付
- 检查微信是否安装
- 检查微信版本是否支持支付
- 检查AppID是否正确
- 检查支付参数是否完整
#### 问题2: 支付后无法回调
- 检查WXPayEntryActivity是否在AndroidManifest中注册
- 检查包名路径是否正确(必须是 包名.wxapi.WXPayEntryActivity
- 检查Activity的exported属性是否为true
#### 问题3: 签名错误
- 检查支付参数是否正确
- 检查签名算法是否正确
- 确认是否需要客户端重新计算签名
## 十、安全注意事项
### 10.1 签名安全
1. **服务端签名**: 支付签名应在服务端计算,客户端不应包含签名密钥
2. **参数校验**: 客户端应对服务端返回的参数进行基本校验
3. **防重放**: 时间戳和随机字符串用于防止重放攻击
### 10.2 数据安全
1. **敏感信息**: AppSecret等敏感信息不应硬编码在客户端
2. **网络传输**: 使用HTTPS进行网络通信
3. **日志安全**: 生产环境不应打印支付相关的敏感信息
### 10.3 支付结果验证
1. **服务端验证**: 支付结果应由服务端通过微信回调接口验证
2. **客户端验证**: 客户端仅作为展示,不应仅依赖客户端结果
3. **订单状态**: 最终订单状态以服务端为准
## 十一、代码示例汇总
### 11.1 完整的支付工具类
```java
package com.ruilaizi.service.utils;
import android.content.Context;
import android.widget.Toast;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import com.ruilaizi.service.wxapi.WXEntryActivity;
public class WeChatPayUtils {
private static final String WEIXIN_APP_ID = WXEntryActivity.WEIXIN_APP_ID;
/**
* 发起微信支付
*/
public static void pay(Context context, PayParams params) {
IWXAPI api = WXAPIFactory.createWXAPI(context, WEIXIN_APP_ID, true);
api.registerApp(WEIXIN_APP_ID);
if (!api.isWXAppInstalled()) {
Toast.makeText(context, "未安装微信", Toast.LENGTH_SHORT).show();
return;
}
if (!api.isWXAppSupportAPI()) {
Toast.makeText(context, "微信版本过低,不支持支付", Toast.LENGTH_SHORT).show();
return;
}
PayReq req = new PayReq();
req.appId = params.getAppId();
req.partnerId = params.getPartnerId();
req.prepayId = params.getPrepayId();
req.nonceStr = params.getNonceStr();
req.timeStamp = params.getTimeStamp();
req.packageValue = params.getPackageValue();
req.sign = params.getSign();
boolean result = api.sendReq(req);
if (!result) {
Toast.makeText(context, "调起支付失败", Toast.LENGTH_SHORT).show();
}
}
/**
* 支付参数Bean
*/
public static class PayParams {
private String appId;
private String partnerId;
private String prepayId;
private String nonceStr;
private String timeStamp;
private String packageValue;
private String sign;
// getter和setter方法
// ...
}
}
```
### 11.2 在Activity中使用支付
```java
public class OrderActivity extends BaseActivity {
private void payOrder(String orderId) {
// 1. 调用后端接口获取支付参数
ApiUtils.getApi()
.createPay(orderId, "100") // 假设金额为100
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<ResponseBean<PayParams>>() {
@Override
public void accept(ResponseBean<PayParams> response) throws Exception {
if (response.isSuccess()) {
// 2. 发起支付
WeChatPayUtils.pay(OrderActivity.this, response.getData());
} else {
Toast.makeText(OrderActivity.this,
response.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Toast.makeText(OrderActivity.this,
"获取支付参数失败", Toast.LENGTH_SHORT).show();
}
});
}
}
```
## 十二、参考资料
### 12.1 官方文档
- 微信支付开发文档: https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml
- 微信开放平台: https://open.weixin.qq.com/
- Android SDK下载: https://open.weixin.qq.com/cgi-bin/frame?t=home/android_tmpl&lang=zh_CN
### 12.2 项目相关文件
- 支付回调Activity: `app/src/main/java/com/ruilaizi/service/wxapi/WXPayEntryActivity.java`
- 微信登录Activity: `app/src/main/java/com/ruilaizi/service/wxapi/WXEntryActivity.java`
- 微信API工具: `app/src/main/java/com/ruilaizi/service/network/WeChatApi.java`
- 网络工具: `app/src/main/java/com/ruilaizi/service/network/ApiUtils.java`
### 12.3 相关配置
- AndroidManifest: `app/src/main/AndroidManifest.xml`
- Gradle配置: `app/build.gradle`
- 微信AppID: `WXEntryActivity.WEIXIN_APP_ID`
## 十三、总结
### 13.1 集成要点
1. ✅ 已添加微信SDK依赖
2. ✅ 已创建支付回调Activity
3. ⚠️ 需要修复WXPayEntryActivity初始化问题
4. ⚠️ 需要在AndroidManifest中注册WXPayEntryActivity
5. ⚠️ 需要创建支付工具类实现支付发起逻辑
6. ⚠️ 需要在订单页面集成支付功能
7. ⚠️ 需要实现支付结果广播接收器
### 13.2 下一步工作
1. 修复WXPayEntryActivity中的bug
2. 添加AndroidManifest配置
3. 创建支付工具类
4. 对接后端支付接口
5. 在订单页面集成支付
6. 实现支付结果处理
7. 进行支付功能测试
---
**文档版本**: 1.0
**最后更新**: 2025年1月
**项目路径**: D:\androidPj\peizhen
**适用版本**: Android SDK 26+, 微信SDK 1.0.2