Android应用接入微信支付实现支付功能
记得很早以前公司项目中添加过移动支付这一块, 包括 微信,支付宝,银联等第三方的整合。 但是后来懒于总结就没留下什么, 最近公司项目打算添加,所以打算简单总结一下,记上一笔以备将来使用。 毕竟第三方的支付SDK , 一般定下了以后三五年不会改变。 闲话少说,开干。 集成第三方SDK没什么难度,只要我们用心阅读文档和开发引导,集成起来再留点神,一切都不是问题。
申请准备材料
首先说一下,微信支付需要在开放平台进行注册,申请商户资质。不是公众平台,另外这两个平台却用了同一套账号体系也就是说,有一个邮箱你注册公众平台,开放平台就不行了。
先给个官网链接https://pay.weixin.qq.com/index.php.
申请商户的准备工作,需要申请商户资质的材料也不会特殊,大概都需要以下几种:
- 单位营业执照彩色扫描件或数码照片
- 对公银行账户(基本账户、一般账户均可)
- 法定代表人的身份证彩色扫描件或数码照片
若为代理人(即法人以外的公司代表)申请认证,需额外提供以下两项材料 - 代理人的身份证彩色扫描件或数码照片
- 委托书,委托书上必须盖有单位公章或财务专用章(合同专用章、业务专用章等无效)下载委托书模版
- 开发者资质审核需要299元RMB/年.
申请过程按照微信官网提示进行操作即可,就不在赘述了。
SDK配置
集成过程很简单,现在一般都使用gradle看一下配置
//下面依赖根据业务需要,任选其一
dependencies {
//包含统计功能
compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
//不包含统计功能,不使用统计功能的话这个就足够使用了。
compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
}
如果还是用eclipse的话, 就记得把libammsdk.jar 放到libs目录中, 记得addToBuildPath
下边是权限配置
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
下边就看一下Manifest.xml 文档配置。
<activity android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop" />
这个文件就是支付完成之后微信通过Aidl回调传送结果的类,所以exported属性为true。 另外这个文件的放置目录一定要准确包名的路径和AndroidManifest.xml文件中WXPayEntryActivity配置一致 ,微信回调找不到class 就会checkargs出错,调不起微信。
接下来就看一下代码吧:
官网SDKDemo下载解压导入eclipse之后可以看到。一个很简单的调用过程。
检查当前的微信版本是否支持.发起req的时候一定要检测一下sdk是否支持.
Button checkPayBtn = (Button) findViewById(R.id.check_pay_btn);
checkPayBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean isPaySupported = api.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT;
Toast.makeText(PayActivity.this, String.valueOf(isPaySupported), Toast.LENGTH_SHORT).show();
}
});
下边看一下发起支付请求的主调用方法
try {
Log.d("get server pay params:", content);
JSONObject json = new JSONObject(content);
if (null != json && !json.has("retcode")) {
PayReq req = new PayReq();
req.appId = Constants.APP_ID;
req.prepayId = json.getString("prepayid");
req.nonceStr = json.getString("noncestr");
req.timeStamp = json.getString("timestamp");
req.packageValue = json.getString("package");
req.sign = json.getString("sign");
req.extData = "app data"; // optional
Toast.makeText(PayActivity.this, "正常调起支付", Toast.LENGTH_SHORT).show();
api.sendReq(req);
} else {
Log.d("PAY_GET", "返回错误" + json.getString("retmsg"));
Toast.makeText(PayActivity.this, "返回错误" + json.getString("retmsg"), Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.e("PAY_GET", "异常:" + e.getMessage());
Toast.makeText(PayActivity.this, "异常:" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信:
api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
api.registerApp(Constants.APP_ID);
createWXAPI这个方法,有个参数checkSignature,是否要检查签名。前期调试很好使,上线时候记得关掉。
下边看一下支付完成之后的微信的回调
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity";
private IWXAPI api;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pay_result);
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 onReq(BaseReq req) {
}
@Override
public void onResp(BaseResp resp) {
Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("R.string.app_tip");
builder.setMessage(getString(R.string.pay_result_callback_msg, String.valueOf(resp.errCode)));
builder.show();
}
}
}
这里有个方法可以根据onResp方法的BaseResp参数来判断支付结果。 errCode =0 就是没错,支付成功。 -2 用户取消支付, -1 支付出错。
- 这里有个坑,我觉得有必要说一下,一般支付完毕之后可以告诉用户是否成功, 如果产品让添加一下支付的介面呢, 比如添加一下UI, 这时候就需要根据结果来初始化UI, 这里的声明周期方法 就是 onResp –> onNewIntent –> onCreate , 所以需要声明一个字段提前保存支付状态。然后再根据结果再onCreate中进行初始化UI元素,以及其他操作。
整体流程分析
说起流程分析最适合的就是弄个sequence, 看图
红色的主体是我们自己的APP的和Server 。
这里注意14步,支付验证授权,完成支付交易之后,这里触发的是一个并行的流程。
* 微信后台通知微信APP ,然后再回调我们的APP通知结果
* 微信后台异步通知我们的后台Server,我们Server再进行接收保存等处理。
另一个地方是对于支付的结果,我们自己可以查询自己Server之前保存的结果,也可以Server调用微信的后台API来查询支付结果,这里不再赘述。
注意事项
- APPId一定要配置成自己的APPID,别忘改了。
- 在SDK集成封装完成之后,一定要用正式签名来打包。否则就会出errorCode -1
- WXPayEntryActivity这个类要放到wxapi的package下,并声明export=true ,这个一般复制demo的话也不容易出错。
- 我们的支付结果一般认为使用sdk提供的onResp回调就行了,可是移动端毕竟有很多不可控因素,所以在一些特殊的场合(断网或者弱网,断电,kill进程,等等)还是依赖我们自己Server的回调确认比较好。
总结
说到官网API不得不说和支付宝的根本没法比,
首先就说Demo,支付宝提供的demo两种版本,eclipse & gradle。 微信sdkdemo 只放的有eclipse 代码已经很久没有维护了,网络请求还在主线程中写着。
再说支付结构来说,微信是使用aidl进程间通信来回调WXPayEntryActivity这个类,使用上限制比较多,比如包名,签名,类放置位置,甚至在调起微信的过程还得请求验签。 支付宝很简单,靠的是强大的RSA2加密算法把自己的SDK嵌入到了调用者的APP中,调用十分方便,整洁。
另附完整支付宝微信集成源码:https://github.com/samuelhehe/PayDemo
关于支付宝的集成看我的另一篇文章Android应用接入支付宝实现支付功能