集成微信支付

在APP中使用微信支付


前言

相对比支付宝支付,微信支付显得更LOW一些,集成的时候一大堆烦心事,这里总结一下怎么让APP集成微信支付

注册微信帐号

微信开放平台
微信商户平台

提交资料

按照步骤提交微信所需要的所有资料
ps:非常非常多,审核也很慢,要有耐心
(如果可以的话丢给行政或者运营去做,别说是我说的)

开发

总算是到了激动人心的开发时刻了(其实到了这一步已经被微信折磨的半死了,能开发确实有点激动人心…)

导入SDK

首先第一步,还是导入微信支付的SDK
在build.gradle(app)中添加

1
2
3
4
dependencies{
//微信支付
implementation 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
}

创建文件夹

在包名下一级目录里面,新建一个文件夹名字为wxapi。
例如程序包名为:com.cmy
那么最后结果就该是com.cmy.wxapi

开发

微信官方文档

我把支付相关的逻辑封装了一下,具体代码入下。注释很详细,就不多说了。

使用方法如下

1
2
3
4
5
6
7
8
9
10
WXPayUtil.WXPayBuilder builder = new WXPayUtil.WXPayBuilder();
builder.setAppId("")//应用ID
.setPartnerId("")//商户号
.setPrepayId("")//预支付交易会话ID
.setPackageValue("")//扩展字段
.setNonceStr("")//随机字符串
.setTimeStamp("")//时间戳
.setSign("")//签名
.build()
.toWXPayNotSign(this, "");

微信支付工具类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/**
* 文 件 名: WXPayUtil<p>
* 创 建 人: cmy<p>
* 创建日期: 2018/6/4 11:12<p>
* 邮 箱: mengyuan.cheng.mier@gmail.com<p>
* 文件说明:微信支付工具类,采用了Builder设计模式,
* 有后端签名和移动端签名两种调用方式
* 后端签名:由后端保存微信提供的KEY的值,比较安全,推荐使用
* 移动端签名:需要多保存一个微信提供的KEY,非常不安全,如果没有特殊情况请不要使用<p>
*/
public class WXPayUtil {
private IWXAPI iwxapi; //微信支付的api
private WXPayBuilder builder;

private WXPayUtil(WXPayBuilder builder) {
this.builder = builder;
}

public static class WXPayBuilder {
/**
* 应用ID
*/
public String appId;
/**
* 商户号
*/
public String partnerId;
/**
* 预支付交易会话ID
*/
public String prepayId;
/**
* 扩展字段
*/
public String packageValue;
/**
* 随机字符串
*/
public String nonceStr;
/**
* 时间戳
*/
public String timeStamp;
/**
* 签名
*/
public String sign;

public WXPayUtil build() {
return new WXPayUtil(this);
}

public String getAppId() {
return appId;
}

public WXPayBuilder setAppId(String appId) {
this.appId = appId;
return this;
}

public String getPartnerId() {
return partnerId;
}

public WXPayBuilder setPartnerId(String partnerId) {
this.partnerId = partnerId;
return this;
}

public String getPrepayId() {
return prepayId;
}

public WXPayBuilder setPrepayId(String prepayId) {
this.prepayId = prepayId;
return this;
}

public String getPackageValue() {
return packageValue;
}

public WXPayBuilder setPackageValue(String packageValue) {
this.packageValue = packageValue;
return this;
}

public String getNonceStr() {
return nonceStr;
}

public WXPayBuilder setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
return this;
}

public String getTimeStamp() {
return timeStamp;
}

public WXPayBuilder setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
return this;
}

public String getSign() {
return sign;
}

public WXPayBuilder setSign(String sign) {
this.sign = sign;
return this;
}
}

/**
* 调起微信支付的方法,由服务端完成签名。安全,推荐。
*
* @param context 上下文
* @param appid appid
*/
public void toWXPayNotSign(Context context, String appid) {
iwxapi = WXAPIFactory.createWXAPI(context, null); //初始化微信api
iwxapi.registerApp(appid); //注册appid appid可以在开发平台获取

Runnable payRunnable = new Runnable() { //这里注意要放在子线程
@Override
public void run() {
PayReq request = new PayReq(); //调起微信APP的对象
//下面是设置必要的参数,也就是前面说的参数,这几个参数从何而来请看上面说明
request.appId = builder.getAppId();
request.partnerId = builder.getPartnerId();
request.prepayId = builder.getPrepayId();
request.packageValue = "Sign=WXPay";
// request.packageValue = builder.getPackageValue();
request.nonceStr = builder.getNonceStr();
request.timeStamp = builder.getTimeStamp();
request.sign = builder.getSign();
Log.e("chx", "run: " + request.appId + request.nonceStr + request.sign);
iwxapi.sendReq(request);//发送调起微信的请求
}
};
Thread payThread = new Thread(payRunnable);
payThread.start();
}

/**
* 调起微信支付的方法,由移动端完成签名。不安全,不推荐。
*
* @param context 上下文
* @param appid appid
* @param key 微信提供的key
*/
public void toWXPayAndSign(Context context, String appid, final String key) {
iwxapi = WXAPIFactory.createWXAPI(context, null); //初始化微信api
iwxapi.registerApp(appid); //注册appid appid可以在开发平台获取
Runnable payRunnable = new Runnable() { //这里注意要放在子线程
@Override
public void run() {
if (TextUtils.isEmpty(builder.getAppId())
|| TextUtils.isEmpty(builder.getPartnerId())
|| TextUtils.isEmpty(builder.getPrepayId())) {
Log.e("chx", "toWXPayAndSign: " + "必须在builder中设置appId、PartnerId、PrepayId");
return;
}
PayReq request = new PayReq(); //调起微信APP的对象
//下面是设置必要的参数,也就是前面说的参数,这几个参数从何而来请看上面说明
request.appId = builder.getAppId();
request.partnerId = builder.getPartnerId();
request.prepayId = builder.getPrepayId();
request.packageValue = "Sign=WXPay";
request.nonceStr = genNonceStr();
request.timeStamp = String.valueOf(genTimeStamp());
request.sign = builder.getSign();
//签名
LinkedHashMap<String, String> signParams = new LinkedHashMap<>();
signParams.put("appid", request.appId);
signParams.put("noncestr", request.nonceStr);
signParams.put("package", request.packageValue);
signParams.put("partnerid", request.partnerId);
signParams.put("prepayid", request.prepayId);
signParams.put("timestamp", request.timeStamp);
request.sign = genPackageSign(signParams, key);
iwxapi.sendReq(request);//发送调起微信的请求
}
};
Thread payThread = new Thread(payRunnable);
payThread.start();
}

/**
* 调起微信APP支付,签名
* 生成签名
*/
private String genPackageSign(LinkedHashMap<String, String> params, String key) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
sb.append(entry.getKey());
sb.append('=');
sb.append(entry.getValue());
sb.append('&');
}
sb.append("key=");
sb.append(key);

String packageSign = getMessageDigest(sb.toString().getBytes()).toUpperCase();
return packageSign;
}

/**
* md5加密
*
* @param buffer
* @return 加密后的string
*/
private String getMessageDigest(byte[] buffer) {
char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
try {
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(buffer);
byte[] md = mdTemp.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
return null;
}
}

/**
* 获取随机数
*
* @return
*/
private String genNonceStr() {
Random random = new Random();
return getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}

/**
* 获取时间戳
*
* @return
*/
private long genTimeStamp() {
return System.currentTimeMillis() / 1000;
}
}

支付结果回调

在com.cmy.wxapi包下新建一个java类,取名为 “WXPayEntryActivity”,并且实现IWXAPIEventHandler接口
该类的名字一定是在wxapi包下,名字也一定是WXPayEntryActivity。因为他是微信回调的接口,如果改变位置或名字,就会导致微信无法将支付结果反馈,从而导致支付失败。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* 文 件 名: WXPayEntryActivity<p>
* 创 建 人: cmy<p>
* 创建日期: 2018/6/4 11:03<p>
* 邮 箱: mengyuan.cheng.mier@gmail.com<p>
* 文件说明:位置支付回调类<p>
*/
@SuppressLint("Registered")
public class WXPayEntryActivity extends AppCompatActivity implements IWXAPIEventHandler {
private IWXAPI api;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// FIXME: 2018/6/4 修改为微信支付的布局页面
setContentView(R.layout.activity_order_detail);
api = WXAPIFactory.createWXAPI(this, "appid");//这里填入自己的微信APPID
api.handleIntent(getIntent(), this);
}

@Override
public void onReq(BaseReq baseReq) {

}

@Override
public void onResp(BaseResp baseResp) {
Log.d("WXPayEntryActivity", "onPayFinish, errCode = " + baseResp.errCode);

if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
int errCord = baseResp.errCode;
if (errCord == 0) {
Log.d("WXPayEntryActivity", "支付成功!");
} else {
Log.d("WXPayEntryActivity", "支付失败!");
}
/*
这里接收到了返回的状态码可以进行相应的操作,
如果不想在这个页面操作可以把状态码存在本地然后finish掉这个页面,
这样就回到了你调起支付的那个页面
获取到你刚刚存到本地的状态码进行相应的操作就可以了
*/
finish();
}
}

@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
}

运行结果

微信测试接口地址

图片名称