这两天为项目集成微信、支付宝支付功能写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里
<activity android:name=".wxapi.WXPayEntryActivity" android:exported="true" android:launchMode="singleTop" />
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; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); api = WXAPIFactory.createWXAPI(getApplicationContext(), AppID); api.handleIntent(getIntent(), this); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); api.handleIntent(intent, this); } @Override public void onReq(BaseReq baseReq) { } @Override public 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);
同时对应的要在文档下载指定的沙箱支付宝客户端,支付宝登录使用沙箱用户登录
<activity android:name="com.alipay.sdk.app.H5PayActivity" android:configChanges="orientation|keyboardHidden|navigation|screenSize" android:exported="false" android:screenOrientation="behind" android:windowSoftInputMode="adjustResize|stateHidden"></activity> <activity android:name="com.alipay.sdk.app.H5AuthActivity" android:configChanges="orientation|keyboardHidden|navigation" android:exported="false" android:screenOrientation="behind" android:windowSoftInputMode="adjustResize|stateHidden"></activity>
另外不得不说。RxJava简直不要太爽,上述逻辑完全可以封装成一个方法
MyClient.orderApi().aliOrderRx(...)//这部分是retrofit 返回一个Observable 参数略 .subscribeOn(Schedulers.io()) .map(new Func1<AliOrderBean, String>() { @Override public String call(AliOrderBean aliOrderBean) { //这里将返回参数拼接成一段字符串,签名已经在参数中,不要在这里签名 Map<String, String> params=OrderInfoUtil2_0.buildOrderParamMap(aliOrderBean); return OrderInfoUtil2_0.buildOrderParam(params); } }) .map(new Func1<String, AliPayResult>() { @Override public AliPayResult call(String orderInfo) { //这里调用支付宝的支付SDK 是按照文档需要在非主线程 EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX); PayTask alipay = new PayTask(activity); Map<String, String> result = alipay.payV2(orderInfo, true); return new AliPayResult(result); } }) .flatMap(new Func1<AliPayResult, Observable<String>>() { @Override public Observable<String> 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这两个类。
共同学习,写下你的评论
评论加载中...
作者其他优质文章