前言
移动支付目前在市场上风生水起,微信支付也逐渐成为人们消费的一大主力方式。今天对Android端微信支付的集成做一个简单的说明。
流程
先盗一张官网上的时序图
微信支付的主要流程:
- 商户APP端选择择商品下单并选择微信支付
- 商户APP端将商品信息传到商户后台端,商户后台调用微信支付统一下单接口
- 微信支付系统返回预付订单信息(prepay_id)到商户后台,商户后台生成带签名的客户端支付信息,并传给商户APP客户端
- 商户APP客户端收到信息后通过SDK调起微信支付
- 用户确认支付,微信提交支付授权,微信支付系统将支付结果通知商户后台和微信
- 微信将支付结果返回到商户APP客户端,商户APP端也要向商户后台查询支付结果并展示。支付结果以商户后台的查询为准。
集成步骤
测试支付时,务必使用申请时填写的keystore文件签名,包名也需要核对清楚,必然无法调起支付,返回-1错误码。
1.平台配置
首先需要在微信开放平台申请开发应用,微信开放平台会生成APP的唯一标识APPID。此处需要填写应用包名和应用签名。此处这个应用签名需要使用微信平台提供的app获取。签名工具下载地址https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk。
2.添加依赖和权限
// 微信支付 compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:1.0.2'
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3.注册APPID
IWXAPI mWxApi = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
// 将该app注册到微信
mWxApi.registerApp(Constants.APP_ID);
4.向商户后台传商品信息
params.put("appid", Constants.APP_ID);// 微信appid,选择性上传,服务器写死亦可
params.put("money", 1);// 支付金额,单位:分
params.put("name", "book");// 商品名称
params.put("currencytype", "CNY");// 支付币种,只能填CNY,代表人民币
详细字段请参考:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
微信支付和银联支付都是「分」为单位,而支付宝则使用「元」为单位。
5.唤起微信支付
商户后台返回支付参数,由商户APP唤起微信支付。
/**
* 用服务器传回的信息调起微信支付
*/
private void pay(ResponseInfo responseInfo) {
mWxApi.registerApp(Constants.APP_ID);
if (mWxApi != null) {
PayReq req = new PayReq();
req.appId = Constants.APP_ID;// 微信开放平台审核通过的应用APPID
req.partnerId = responseInfo.getPartnerId();
req.prepayId = responseInfo.getPrepayId();
req.packageValue = responseInfo.getPackage();
req.nonceStr = responseInfo.getNonceStr();
req.timeStamp = responseInfo.getTimeStamp();
req.sign = responseInfo.getSign();
mWxApi.sendReq(req);
Log.i(TAG, "发起微信支付申请");
}
}
6.处理微信支付返回信息
在app包下新建wxapi包,在该包下新建WXPayEntryActivity。需要注意的是,package和Activity一定要这么写,包名或类名不一致会造成无法回调。
在WXPayEntryActivity类中实现onResp函数,支付完成后,微信APP会返回到商户APP并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码,如果支付成功则去后台查询支付结果再展示用户实际支付结果。
注意一定不能以客户端返回作为用户支付的结果,应以服务器端的接收的支付通知或查询API返回的结果为准。
回调中errCode值列表:
名称 | 描述 | 解决方案 |
---|---|---|
0 | 成功 | 展示成功页面(要自行向服务器请求支付结果,以服务器未返回为准) |
-1 | 错误 | 签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。(╯‵□′)╯︵┻━┻ |
-2 | 用户取消 | 无需处理。发生场景:用户不支付了,点击取消,返回APP。 |
WXPayEntryActivity示例代码:
public class WXPayEntryActivity extends AppCompatActivity implements IWXAPIEventHandler {
private static final String TAG = "fate";
private IWXAPI mWxApi;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wxpay_entry);
mWxApi = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
mWxApi.handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
mWxApi.handleIntent(intent, this);
}
@Override
public void onReq(BaseReq baseReq) {
}
/**
* 得到支付结果回调
*/
@Override
public void onResp(BaseResp baseResp) {
Log.d(TAG, "onPayFinish, errCode = " + baseResp.errCode);// 支付结果码
switch (baseResp.errCode) {
case BaseResp.ErrCode.ERR_OK:
Log.i(TAG, "支付成功");
// 还需要向商户后台请求支付结果,最终结果以后台返回结果为准
finish();
break;
case BaseResp.ErrCode.ERR_COMM:
// 发生错误 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、
// 注册的APPID与设置的不匹配、其他异常等。
Log.i(TAG, "发生错误");
Toast.makeText(WXPayEntryActivity.this, "支付失败", Toast.LENGTH_SHORT).show();
finish();
break;
case BaseResp.ErrCode.ERR_USER_CANCEL:
// -2 用户取消 发生场景:用户不支付了,点击取消,返回APP。
Log.i(TAG, "用户取消");
break;
default:
Log.i(TAG, "支付失败-其他的锅" + baseResp.errCode);
break;
}
}
}