APP支付宝支付(不使用证书)JAVA服务端接口详情
介绍
简单的集成APP使用支付宝进行支付,只是用了APP支付2.0接口和回调接口。
JAR包或者MAVEN依赖
alipay的JAR包和maven依赖地址:https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java
接口详情
移动端调起支付宝请求参数获取接口
service 层 ,参数用户id,移动端传过来的
public String aliPaySubmitOrder(String accountId) {
//生成商户订单号
SimpleDateFormat sfDate = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String strDate = sfDate.format(new Date());
String random = “TEST”+strDate;
//订单号存入redis,过期时间5个小时,下单接口的参数订单过期时间为30分钟,值:用户id
RedisHelper.setEX(random, accountId, 5 * 60);
//支付宝费用单位元,测试使用1分
String payStr = “0.01”;
String paySubmitOrder = paySubmitOrder("测试支付", payStr, random);
return paySubmitOrder;
}
app支付接口2.0
官方api文档:https://docs.open.alipay.com/api_1/alipay.trade.app.pay
/**
* APP调起支付宝需要的参数
* @return
* @throws Exception
*/
public String paySubmitOrder(String title, String amount, String outTradeNo) {
String str = null;
//实例化客户端
//参数1:请求地址,参数2:APPID,开发平台查看,参数3:密钥,开发平台查看,参数4:传输格式json,
//参数5:编码格式,参数6:支付宝公钥(不是应用公钥),参数7:加密方式,开通APP支付时,生成的密钥的加密方式
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","123456","123456", "json", "utf-8", "123456", "RSA2");
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody("paypay"); //交易的描述
model.setSubject(title); //交易标题
//商户订单号
model.setOutTradeNo(outTradeNo);
//过期时间,30分钟
model.setTimeoutExpress("30m");
model.setTotalAmount(amount); //金额 单位元
request.setBizModel(model); //非公共请求参数
request.setNotifyUrl(“http://api.test.alipay.net/atinterface/receive_notify.htm”); //支付宝回调地址,商户应用的接口,必须支付宝能访问到。
try {
//这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
str = response.getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
return str;
}
回调接口,支付宝服务器主动通知商户服务器里指定的页面http/https路径。返回值:“success” 或者 “fail”
/**
* 支付宝支付回调
*
* @param request
*/
public String aliPayNotify(HttpServletRequest request) {
//获取支付宝POST过来反馈信息
try {
Map<String, String> params = new HashMap<>();
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
//乱码解决,这段代码在出现乱码时使用。有乱码在使用,没有乱码注释
// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
//查询redis中是否存在该商户订单号
String out_trade_no = params.get("out_trade_no");
String data = RedisHelper.get(out_trade_no);
if (data != null && !data.equals("")) {
//用户id
String id = data;
//验证签名
boolean flag = aliCheckRsa(params);
if (flag) {
String trade_status = params.get("trade_status");
//支付成功,进行业务操作
if (trade_status.equals("TRADE_SUCCESS")) {
//业务操作,省略
//操作完成删除key
RedisHelper.del(out_trade_no);
}else{
System.out.println("支付宝订单-支付状态异常订单:"+JSON.toJSONString(params));
}
return "success";
}else{
System.out.println("支付宝订单-验证失败订单:"+JSON.toJSONString(params));
}
}else{
System.out.println("支付宝订单-redis过期订单:"+JSON.toJSONString(params));
}
} catch (Exception e) {
e.printStackTrace();
}
return "fail";
}
回调接口签名验证
/**
* 异步回调验证接口
* @param params
* @return
* @throws AlipayApiException
*/
public boolean aliCheckRsa(Map<String,String> params) throws AlipayApiException {
//切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。
//jar中方法,参数1:回调信息map,参数2:支付宝公钥(不是应用公钥),参数3:编码格式,参数4:加密类型
return AlipaySignature.rsaCheckV1(params, “123456”, “utf-8”, ""RSA2"");
}
redis工具类,这个就不发了,网上一堆,把调用redis工具类的地方改成自己的方法就行
改进
把生成的商户订单号存入redis中,设置了5个小时,但是也可能会过期,所以最好存到数据库。
总结
主要流程是:移动端请求>>服务端生成商户订单号,存入redis,请求APP支付2.0接口,获取返回数据>>返回移动端>>移动端使用返回数据调起支付宝支付>>支付成功,回调,本地方法,获取回调参数中的商户订单号,查询redis中是否存在,如果存在,校验回调参数的签名,校验成功,判断支付状态,如果支付成功,进行业务操作,删除redis中等于商户订单号的key
写的非常简单,有很多不足,希望可以帮我改进。