这两天为项目集成微信、支付宝支付功能写demo。多多少少遇到些坑,把这些记录一下,防止再掉进去。
自动代扣
又称“委托代扣”,“委托扣费”。使用不当会造成很严重的结果。也是比较流氓的功能。功能例子嘛:参考微博会员,爱奇艺会员,滴滴打车,Uber。基本就是在一次购买之后,每月会自动扣费,一旦中招很难察觉。但是无论微信还是支付宝,会员自动扣费的功能都是没有对普通开发者开放的,需要深度合作,查了半天资料,才确定金坷垃是不要想了。 不过意外的发现了两个开发文档,就当参考吧
下面是正篇
微信
微信的各种平台很多,支付开发,首先要来这里 1.创建一个应用, 2.审核通过后,再申请开放微信支付的权限。 3.审核的过程中会发给你一个的账号 做完了这些就可以开始正式开发了(总共大概需要几天时间,企业的话需要银行对公账户) 微信支付的demo比较坑,文档上说了好多资源,实际下载下来只有一个SDK的jar包和html的Javadoc,其他的基本靠猜,好在之前做过微信登录,基本逻辑差不多。(而且微信登录和微信支付其实SDK都是同一个)
腾讯的产品,参数中带签名,签名逻辑从来都是很麻烦的,不过还好,这部分内容扔给服务端了,客户端这边就是调个接口,所有参数就都有了 写个解析类大概这样
public class WxOrdersBean { public String appid; public String noncestr; public String partnerid; public String prepayid; public String sign; public String timestamp; public WxOrdersBean() { } @Override public String toString() { return "WxOrdersBean{" + "appid='" + appid + '\'' + ", noncestr='" + noncestr + '\'' + ", partnerid='" + partnerid + '\'' + ", prepayid='" + prepayid + '\'' + ", sign='" + sign + '\'' + ", timestamp='" + timestamp + '\'' + '}'; }}复制代码
这时,在Activity中可以对微信发起支付请求了
public void payByWeChat(WxOrdersBean wxOrdersBean) { //这些参数全部来自服务端 IWXAPI api = WXAPIFactory.createWXAPI(getApplicationContext(), null); api.registerApp(AppID); PayReq request = new PayReq(); request.appId = wxOrdersBean.appid;//微信开放平台审核通过的应用APPID request.partnerId = wxOrdersBean.partnerid;//微信支付分配的商户号 request.prepayId = wxOrdersBean.prepayid;//微信返回的支付交易会话ID request.packageValue = "Sign=WXPay";//暂填写固定值Sign=WXPay request.nonceStr = wxOrdersBean.noncestr;//随机字符串,不长于32位。推荐随机数生成算法 request.timeStamp = wxOrdersBean.timestamp;//时间戳,请见接口规则-参数规定 request.sign = wxOrdersBean.sign;//签名,详见签名生成算法 api.sendReq(request); }复制代码
这中间会遇到一些问题: 1.服务端签名错误,比如签名时没有区分大小写,拼写错误,再有就是可能没加入Sign=WXPay这类的 2.客户端APP签名错误,微信客户端在被调起时会检查发起者的签名,一般需要正式keystore签名过的才可以调起,建议先做微信分享或者微信登录,如果成功完成,那么微信支付基本不会是客户端的错误。这样有利于错误定位,排除客户端的原因。 3.关于微信的回调,按照微信一贯的蛋疼作风自然回调要在指定名字的 包名.wxapi.WXPayEntryActivity
里
复制代码
WXPayEntryActivity. java
public static final int CODE_SUCCESS = 0;public static final int CODE_ERROR = -1;public static final int CODE_CANCLE = -2;IWXAPI api;@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); api = WXAPIFactory.createWXAPI(getApplicationContext(), AppID); api.handleIntent(getIntent(), this);} @Overrideprotected void onNewIntent(Intent intent) { super.onNewIntent(intent); api.handleIntent(intent, this);}@Overridepublic void onReq(BaseReq baseReq) {}@Overridepublic void onResp(BaseResp baseResp) { if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) { if (baseResp.errCode == CODE_SUCCESS) { //在这里需要向自己的服务器发送请求查询是否真正成功 } else if (baseResp.errCode == CODE_ERROR) { } else if (baseResp.errCode == CODE_CANCLE) { } } }复制代码
支付宝
其实支付宝要和微信做的也差不多,都是向自己服务端发起请求,获取参数和签名,通知支付宝客户端进行支付,返回结果后去自己服务器查询实际结果。 这里也会有几个问题 1.还是两个认证,一个蚂蚁金服商家账号,一个开发账号,这次可以是同一个用户名,不过都要填写认真资料。 2.还是签名,服务端的签名这次是需要自己生成RSA的公钥和私钥,并且把公钥上传,用私钥签名。 3.注意沙箱环境!!! 沙箱环境用它生成的沙箱应用,新的APPID,公钥也需要重新上传,客户端需要在调起支付宝前加入代码
EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);复制代码
同时对应的要在文档下载指定的沙箱支付宝客户端,支付宝登录使用沙箱用户登录
复制代码
另外不得不说。RxJava简直不要太爽,上述逻辑完全可以封装成一个方法
MyClient.orderApi().aliOrderRx(...)//这部分是retrofit 返回一个Observable 参数略 .subscribeOn(Schedulers.io()) .map(new Func1() { @Override public String call(AliOrderBean aliOrderBean) { //这里将返回参数拼接成一段字符串,签名已经在参数中,不要在这里签名 Map params=OrderInfoUtil2_0.buildOrderParamMap(aliOrderBean); return OrderInfoUtil2_0.buildOrderParam(params); } }) .map(new Func1 () { @Override public AliPayResult call(String orderInfo) { //这里调用支付宝的支付SDK 是按照文档需要在非主线程 EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX); PayTask alipay = new PayTask(activity); Map result = alipay.payV2(orderInfo, true); return new AliPayResult(result); } }) .flatMap(new Func1 >() { @Override public Observable call(AliPayResult aliPayResult) { /** 对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。 */ String resultStatus = aliPayResult.getResultStatus(); // 判断resultStatus 为9000则代表支付成功 if (TextUtils.equals(resultStatus, "9000")) { //这里发起网络请求查询支付结果 return MyClient.getAliOrderRx(...); } //TODO 这里可能需要更合理的返回错误方式 throw new Error(aliPayResult.toString()); } }) .observeOn(AndroidSchedulers.mainThread()) //这里交个外部传入的observer来处理对应的结果 .subscribe(observer);复制代码
阿里还是很良心的,demo写的相当全,上面的代码很大一部分都来自官方的demo中,包括AliPayResult,OrderInfoUtil2_0这两个类。