人生倒计时
- 今日已经过去小时
- 这周已经过去天
- 本月已经过去天
- 今年已经过去个月
android支付宝支付接入(连接手机支付)
Android之支付宝支付集成
支付宝集成流程
(使用浏览器扫码进入在线客服窗口)
复制联系方式
主要的回调返回类两个:PayResult与AuthResult
支付接口的调用:
支付结果的接收:

Android手机APP怎么调用支付宝接口进行支付
去支付宝的开放平台申请开发者ID,然后把支付宝的SDK集成到你的APP中,具体调用请参考支付宝开发文档。
单个APP接入多个微信支付宝支付的一种解决方案
背景
最近在对接微信支付宝支付的时候出现了一个需求,由于我们公司在不同的地区有分公司,为了实现财务对账方便,不同公司的客户需要打款到相应的公司的账户,也就是要实现接口分账,一听到这个需求,我一脸懵逼,之前做商城的时候,一个APP的收款不管是微信还是支付宝,都是只打到一个账户里面去,现在需要实现不管对于微信支付还是支付宝支付都需要有多个支付账户,实现接口分账,当时总经理提出这个需求,Android跟ios历史性地异口同声地说,这个做不到,并且从技术的角度在那儿跟总经理弹了一会儿琴,毕竟还是太年轻了,总经理说,这个肯定是可以实现的,因为在他眼里,没有什么是实现不了的,然后我们就回去搬砖了,然后思考这个问题的解决方案。
分析问题
需要实现的技术点
用户支付的时候,根据用户的uid,来把钱达到相应的账户里面去,判断身份很简单,问题主要在于如何使得一个APP接入多个微信或者支付宝账户,下面来逐个分析一下微信跟支付宝的接入方式
微信
对接过微信支付的应该很熟悉上面的这些东西,首先你得去微信开放平台注册一个账号,一年300块钱,然后再在这个账号里面开通微信支付功能,所以一开始我们尝试的就是不停地去骚扰微信客服,问问能不能通过一个微信支付账号进行接口分账,每次那边的回答都是不可以,然后又问一个APP能不能申请多个微信支付账号,那边回答也说是不可以,卧槽,基本上到这个份上,我们已经是放弃了,因为如果一个APP不能申请多个微信支付账号,那么微信基本上是做不了接口分账了,当时IOS了解到的微信支付情况是这个样子的,下面看看支付宝的过程。
支付宝
支付接入的时候其实也比较郁闷,苦逼之处在于支付宝以前是支持接口分账的,也就是只需要注册一个支付宝主账户,然后在注册几个子账户就可以进行接口分账,只是我们的APP生不逢时,支付宝关闭了这个服务,而且那边的客服也是说一个APP只能注册一个支付宝账户
发现希望
基本上到这里,我们已经打算放弃了,因为毕竟跟我们最初的设想是一样的,但是还是有点不甘心,因为在跟支付宝的技术客服,注意是技术客服,不是普通的人工客服,当时跟他说了一下我们的使用场景,他说可以通过注册多个支付宝账号,其实这一点跟我之前的设想是一样的,因为Android在介入支付宝的时候不需要应用的签名,可以通过服务端动态下发签名,从而调起支付宝支付,我突然间好像明白了什么,因为之前的思路走不通的原因在于总是想通过一个APP来注册多个支付宝账号,没有想到用多个支付宝账户来实线曲线救国。
支付宝实现接口分账
注册支付宝账户
支付宝应用名称
支付宝应用信息
支付宝支付跟微信支付最大的区别在于Android客户端的接入,需要应用的签名,所以如果用两个APP注册的话势必会导致签名不一致,支付宝的注册只需要填写一个应用名称就好了,注意应用名称不能一样,否则会失败。
基本上到这里,支付宝实现接口分账的链路打通了,测试也完全通过,吼吼
微信实现接口分账
对于微信来说,一个APP对应唯一的APPID,注册信息大致如下:
微信支付应用名称
微信支付应用信息
受到支付宝的启发,能不能注册在微信开放平台注册两个账号,然后申请两个微信支付账号,只不过这两个账号除了名称不一样以外,其余地全都一样,不过虽然这么想还是有点虚,因为IOS在跟客服沟通的时候客服只是说同一个APP只能申请一个微信支付账号,但是我们反问客服微信的判断规则是什么的时候,微信那边却说不知道,如果是名称,那么就能够通过审核,如果是应用的包名或者bundleid那基本上微信接入原生的APP支付彻底走不通了。
当时是分了两步走,总经理说微信支付必须得接入,万一不行只能接入微信H5支付,因为H5的话就可以实现动态下发了。所以当时H5支付跟原生支付的账号同时在申请,服务端那边也是在做两手的准备,比较苦逼。最后万幸的是,微信是通过应用名称来判断APP的唯一性,很幸运,可以完全放弃H5支付了,微信支付接口分账也打通了。
小结
这篇文章没有涉及到任何技术,但是这次实现一个APP实现多个接口分账,确实让我感触很多,很多时候,我们在做一件事情的时候,会调用我们以往的经验,有好也有坏,之前做的支付都是单个微信支付宝,按照之前的经验,在尝试之前就做出了错误的判断,很多时候还是需要敢于拆掉思维里的墙,去尝试一些新东西,包括在实现一些功能的时候,要勇于尝试一些新的思维,新的解决方式,尤其是在用已有的知识实现不了或者实现起来比较痛苦的时候,毕竟改变是痛苦的,不改变只会更加痛苦。
接入支付宝支付SDK
接入支付宝支付SDK
可以说支付宝支付接入是所有SDK最好接入的,没有之一。
客户端不用签名,也不用管包名,也不用管签名文件,就接口返回订单,把订单交给支付宝SDK调用就行,成功或者失败都在当前界面返回给你。你再去通知接口。
支付流程图
官方文档地址
!支付宝支付官方文档地址
按照文档说明接入SDK和相关配置,在这就不重复了
客户端支付关键代码===》支付接口的调用(调起支付弹框)
记住支付接口的调用必须在独立的非ui线程中执行,即需新开线程里面调用。可以想官方demo一样用new Thread方式。
下面我给出用Observable方式示例代码
在PayUtils中
/**
* desc:支付宝支付
* Created by congge on 2018/8/27 17:20
* @param orderInfo 接口返回的订单
**/
public static void aliPay(final Activity activity, final String orderInfo, final OrderListener orderListener) {
Observable.just(orderInfo)
.map(new Function () {
@Override
public String apply(String orderInfo) throws Exception {
//用户在商户app内部点击付款,是否需要一个loading做为在钱包唤起之前的过渡,这个值设置为true
return new PayTask(activity).pay(orderInfo, true);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer () {
@Override
public void accept(String payResult) throws Exception {
orderListener.onPayResult(payResult);
}
});
}
支付结果返回处理
返回例子:
resultStatus={9000};memo={};result={{"alipay_trade_app_pay_response":{"code":"10000","msg":"Success","app_id":"2016091300503896","auth_app_id":"2016091300503896","charset":"utf-8","timestamp":"2018-08-28 17:51:11","out_trade_no":"nVElbd74TW6WnEyxQwvX8A","total_amount":"0.01","trade_no":"2018082821001004680500208879","seller_id":"2088102175487650"},"sign":"W0Hg9k4GxL8Oaxymvqk2i65WNDQxYp6HGve32ek6VjSRnymmI3GQTjpQVbZuDzvjcwQ/HIkM97PoBGAVlTmi/wiJcqDgSSDzDY7AFnNN0OcK0ehWGwKQINA4IDGh51A7yY/vYKmR0VW+2OwGhlRPPMMZtQOEqh8a9/aIijzT6ZLwy9Hl4ayG/fVKhdC1VdckF6+C25BFNp3fIxarg5tfEunm7N9iWngKCUsnP+IZz05OHdvynimgYPcBnbBERHG97GVqRT/EdBWTQyIDMc0LemScAYxJixTVgXDkRddQjzWZ7HgLdBfjs0nXY24puHudT76ERxVY+8NkoKle/QI+FA==","sign_type":"RSA2"}}
也可以自己打log看看
处理示例代码:
//支付宝支付
PayUtils.aliPay(this, result.getSignDataStr(), new PayUtils.OrderListener() {
@Override
public void onPayResult(String payResult) {
PayResult pr = new PayResult(payResult);
String rs = pr.getResultStatus();
String r = pr.getResult();
switch (rs) {
case AliPayResultStatus.PAY_SUCCESS:
ToastUtils.show(R.string.pay_success);
//通知接口支付成功
break;
case AliPayResultStatus.PAY_PROCESSING:
case AliPayResultStatus.PAY_UNKNOWN:
ToastUtils.show(R.string.pay_fail);
//支付可能成功,要接口去查询
break;
default:
ToastUtils.show(R.string.pay_fail);
//通知接口支付失败,取消订单
}
}
});
上面方法中:
//通知接口支付成功 //支付可能成功,要接口去查询 //通知接口支付失败,取消订单。根据你产品需求要不要通知你服务器做的操作。正常是要的,用来改变订单状态
PayResult.class
public class PayResult {
private String resultStatus;
private String result;
private String memo;
public PayResult(String rawResult) {
if (TextUtils.isEmpty(rawResult))
return;
String[] resultParams = rawResult.split(";");
for (String resultParam : resultParams) {
if (resultParam.startsWith("resultStatus")) {
resultStatus = gatValue(resultParam, "resultStatus");
}
if (resultParam.startsWith("result")) {
result = gatValue(resultParam, "result");
}
if (resultParam.startsWith("memo")) {
memo = gatValue(resultParam, "memo");
}
}
}
@Override
public String toString() {
return "resultStatus={" + resultStatus + "};memo={" + memo
+ "};result={" + result + "}";
}
private String gatValue(String content, String key) {
String prefix = key + "={";
return content.substring(content.indexOf(prefix) + prefix.length(),
content.lastIndexOf("}"));
}
public String outOrder() {
String order = ""out_trade_no"";
if (result.contains(order)) {
String begin = result.substring(result.indexOf(order));
String ss = begin.split(",")[0];
String newS = ss.replace(""", "")
.replace("}", "")
.replace(":", "")
.replace("out_trade_no", "");
try {
return newS;
} catch (Exception e) {
e.printStackTrace();
}
}
return "";
}
/**
* @return the resultStatus
*/
public String getResultStatus() {
return resultStatus;
}
/**
* @return the memo
*/
public String getMemo() {
return memo;
}
/**
* @return the result
*/
public String getResult() {
return result;
}}
最后给下支付返回码表
AliPayResultStatus.class
public class AliPayResultStatus {
/**
* 订单支付成功,唯一肯定是支付成功的
*/
public static final String PAY_SUCCESS = "9000";
/**
* 正在处理中,支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态
*/
public static final String PAY_PROCESSING = "8000";
/**
* 订单支付失败
*/
public static final String PAY_FAIL = "4000";
/**
* 重复请求
*/
public static final String PAY_REPEAT = "5000";
/**
* 用户中途取消
*/
public static final String PAY_PROCESS_CANCEL = "6001";
/**
* 网络连接出错
*/
public static final String PAY_NET_ERROR = "6002";
/**
* 支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态
*/
public static final String PAY_UNKNOWN = "6004";}
还有一个直接弃用沙箱调试模式,否则提示支付失败也有可能不知道错在那,怕金额大,和接口商量,测试服务器就用0.01测试。

