671 lines
20 KiB
Plaintext
671 lines
20 KiB
Plaintext
|
|
# 微信支付集成文档
|
|||
|
|
|
|||
|
|
## 一、概述
|
|||
|
|
|
|||
|
|
### 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
|
|||
|
|
|