支付宝APP支付、退款、查询订单
最近在搞支付这块,总算告一段落了,来记录一下,以后找不迷路,在此也希望帮到一些同学,
其实支付宝的技术客服还挺好的,你可以找他们要示例,不像wx......就太......。
需要准备的东西如下:
appid、应用私钥、应用公钥证书、支付宝公钥证书、支付宝根证书
依赖
<!-- alipay-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<!--<version>3.7.26.ALL</version>-->
</dependency>
下面就粘下重要的代码
这里说明下,下面这些api都是以证书的方式请求的。如果你平台上是设置秘钥形式的。可以去掉证书。
APP支付
/**
* 支付宝APP支付
*
* @param aliPayParam 支付宝参数类
* @return
*/
@Override
public String aliPayAPPToPay(AliPayParam aliPayParam) {
try {
//设置支付宝请求
CertAlipayRequest certAlipayRequest = setUpAliPayAsk();
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay(app 支付接口)
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
// 设置业务参数
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
// 商户订单号,商户自定义,需保证在商户端不重复,如:20200612000001
String outTradeNo = String.valueOf(snowflake.nextId());
model.setOutTradeNo(outTradeNo);
//订单标题
model.setSubject(aliPayParam.getSubject());
// 销售产品码,固定值 QUICK_MSECURITY_PAY
model.setProductCode(AliPayConfig.product_code_app);
// 订单金额,精确到小数点后两位 **/
model.setTotalAmount(aliPayParam.getTotalAmount().toString());
// 订单描述
model.setBody(aliPayParam.getBody());
// 业务扩展参数
//ExtendParams extendParams = new ExtendParams();
// 系统商编号,填写服务商的PID用于获取返佣,返佣参数传值前提:传值账号需要签约返佣协议,用于isv商户。
//extendParams.setSysServiceProviderId("2088511****07846");
// 花呗分期参数传值前提:必须有该接口花呗收款准入条件,且需签约花呗分期
// 指定可选期数,只支持3/6/12期,还款期数越长手续费越高
// extendParams.setHbFqNum("3");
// 指定花呗分期手续费承担方式,手续费可以由用户全承担(该值为0),也可以商户全承担(该值为100),但不可以共同承担,即不可取0和100外的其他值。 **/
//extendParams.setHbFqSellerPercent("0");
//model.setExtendParams(extendParams);
// 将业务参数至request中
request.setBizModel(model);
// 异步通知地址,以http或者https开头的,商户外网可以post访问的异步地址,用于接收支付宝返回的支付结果,如果未收到该通知可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602475759
request.setNotifyUrl(AliPayConfig.notify_url + AliPayConfig.AliPay_APP_PAY_Callback);
//第三方调用(服务商模式),传值app_auth_token后,会收款至授权token对应商家账号,如何获传值app_auth_token请参考文档:https://opensupport.alipay.com/support/helpcenter/79/201602494631
//request.putOtherTextParam("app_auth_token", "传入获取到的app_auth_token值");
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
if (response.isSuccess()) {
return response.getBody();
} else {
return response.getSubMsg();
}
} catch (AlipayApiException e) {
e.printStackTrace();
return e.getMessage();
}
}
不需要处理,返回一段字符给前端唤醒收银台页面就ok。
参考:https://opendocs.alipay.com/apis/api_1/alipay.trade.app.pay
查询支付宝订单
/**
* 查询支付宝订单
*
* @param aliPayParam 支付宝参数类
* @return
*/
@Override
public AlipayTradeQueryResponse queryAliPayOrder(AliPayParam aliPayParam) {
try {
//设置支付宝请求
CertAlipayRequest certAlipayRequest = setUpAliPayAsk();
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
JSONObject bizContent = new JSONObject();
if (StringUtils.isNotEmpty(aliPayParam.getOutTradeNo())) {
bizContent.put("out_trade_no", aliPayParam.getOutTradeNo());
}
if (StringUtils.isNotEmpty(aliPayParam.getTradeNo())) {
bizContent.put("trade_no", aliPayParam.getTradeNo());
}
request.setBizContent(bizContent.toString());
AlipayTradeQueryResponse response = alipayClient.certificateExecute(request);
if (response.isSuccess()) {
System.out.println("调用成功");
return response;
} else {
System.out.println("调用失败");
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
throw new CustomException("系统繁忙,请稍后重试");
}
支付宝退款
/**
* 支付宝退款
*
* @param payRefund 支付宝退款参数类
* @return
*/
@Override
public AlipayTradeRefundResponse aliPayRefund(AliPayRefundParam payRefund) {
//设置支付宝请求
CertAlipayRequest certAlipayRequest = setUpAliPayAsk();
try {
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.refund(统一收单交易退款接口)
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
// 设置业务参数
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
// 支付接口传入的商户订单号。如:2020061601290011200000140004
model.setOutTradeNo(payRefund.getOutTradeNo());
// 退款金额,退款总金额不能大于该笔订单支付最大金额 **/
model.setRefundAmount(payRefund.getRefundAmount().toString());
// 异步通知/查询接口返回的支付宝交易号,如:2020061622001473951448314322
model.setTradeNo(payRefund.getTradeNo());
//随机数 不是全额退款,部分退款必须使用该参数,同一个订单,不同的out_request_no代表部分退款
//String outRequestNo = RandomStringUtils.randomAlphanumeric(13);
// 如需部分退款,则此参数必传,且每次请求不能重复,如:202006230001
model.setOutRequestNo(payRefund.getRefundNo());
model.setRefundReason(payRefund.getRefundReason());
request.setBizModel(model);
//第三方调用(服务商模式),传值app_auth_token后,会收款至授权token对应商家账号,如何获传值app_auth_token请参考文档:https://opensupport.alipay.com/support/helpcenter/79/201602494631
//request.putOtherTextParam("app_auth_token", "传入获取到的app_auth_token值");
// 通过alipayClient调用API,获得对应的response类
AlipayTradeRefundResponse response = alipayClient.certificateExecute(request);
// 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/101
return response;
} catch (AlipayApiException e) {
e.printStackTrace();
}
throw new CustomException("系统繁忙,请稍后重试");
}
参考:https://opendocs.alipay.com/apis/028pxn
查询支付宝退款订单
/**
* 查询支付宝退款订单
*
* @param payRefund 支付宝退款参数类
* @return
*/
@Override
public AlipayTradeFastpayRefundQueryResponse aliPayRefundQuery(AliPayRefundParam payRefund) {
try {
//设置支付宝请求
CertAlipayRequest certAlipayRequest = setUpAliPayAsk();
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
com.alibaba.fastjson.JSONObject bizContent = new com.alibaba.fastjson.JSONObject();
if (StringUtils.isNotEmpty(payRefund.getOutTradeNo())) {
bizContent.put("outTrade_no", payRefund.getOutTradeNo());
}
if (StringUtils.isNotEmpty(payRefund.getTradeNo())) {
bizContent.put("trade_no", payRefund.getTradeNo());
}
if (StringUtils.isNotEmpty(payRefund.getRefundNo())){
bizContent.put("out_request_no", payRefund.getRefundNo());
}
request.setBizContent(bizContent.toString());
AlipayTradeFastpayRefundQueryResponse response = alipayClient.certificateExecute(request);
if (response.isSuccess()) {
return response;
} else {
System.out.println("查订单失败");
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
throw new CustomException("系统繁忙,请稍后重试");
}
参考:https://opendocs.alipay.com/apis/028xqc
封装支付宝请求
/**
* 设置支付宝请求
*
* @return
*/
public CertAlipayRequest setUpAliPayAsk() {
// 初始化
CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
// 支付宝网关
certAlipayRequest.setServerUrl(AliPayConfig.SERVER_URL);
// 应用id
certAlipayRequest.setAppId(AliPayConfig.APP_ID);
// 应用私钥
certAlipayRequest.setPrivateKey(AliPayConfig.APP_PRIVATE_KEY);
try {
// 应用公钥证书路径,下载后保存位置的绝对路径
certAlipayRequest.setCertPath(String.valueOf(ResourceUtils.getFile(AliPayConfig.APPLICATION_PUBLIC_KEY_CERT)));
// 支付宝公钥证书路径,下载后保存位置的绝对路径
certAlipayRequest.setAlipayPublicCertPath(String.valueOf(ResourceUtils.getFile(AliPayConfig.AliPay_PUBLIC_CERT)));
// 支付宝根证书路径,下载后保存位置的绝对路径
certAlipayRequest.setRootCertPath(String.valueOf(ResourceUtils.getFile(AliPayConfig.ROOT_CERT_PATH)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 设置签名类型
certAlipayRequest.setSignType(AliPayConfig.sign_type);
// 设置请求格式,固定值json
certAlipayRequest.setFormat(AliPayConfig.FORMAT);
// 设置编码格式
certAlipayRequest.setCharset(AliPayConfig.charset);
return certAlipayRequest;
}
回调通知(支付宝的支付回调通知与退款的回调通知是一块的)
因此我们需要根据返回的字段值做判断
回调通知
/**
* 支付宝支付、退款成功回调
*
* @param request HttpServlet 请求
*/
@Override
public Integer aliPayNotify(HttpServletRequest request) {
//获取支付宝POST过来反馈信息
Map<String, String> params = new HashMap<String, String>();
Map requestParams = request.getParameterMap();
log.info("requestParams: {}", requestParams);
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);
}
// 商户订单号
//String out_trade_no = request.getParameter("out_trade_no");
// 订单内容
//String orderContent = request.getParameter("body");
// 交易状态 支付成功:TRADE_SUCCESS, 交易关闭:TRADE_CLOSED, 交易完成:TRADE_FINISHED
String tradeStatus = request.getParameter("trade_status");
//签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
try {
//调用SDK验证签名
boolean signVerified = AlipaySignature.rsaCheckV1(params, AliPayConfig.AliPay_PUBLIC_KEY, AliPayConfig.charset, AliPayConfig.sign_type);
//验证签约是否成功
if (signVerified) {
log.info("验签成功");
log.info("交易状态: {}", tradeStatus);
if (tradeStatus.equals("TRADE_SUCCESS")) {
System.out.println("交易状态为TRADE_SUCCESS");
}
//支付宝交易号
String tradeNo = params.get("trade_no");
log.info("tradeNo: {}", tradeNo);
//系统订单编号
String outTradeNo = params.get("out_trade_no");
log.info("outTradeNo: {}", outTradeNo);
//商户业务号 这里作为退款单号
String outBizNo = params.get("out_biz_no");
//退款总金额
String refundFee = params.get("refund_fee");
//交易退款时间
String gmtRefund = params.get("gmt_refund");
if (StringUtils.isNotEmpty(refundFee) && StringUtils.isNotEmpty(gmtRefund)) {
System.out.println("退款成功回调通知");
} else {
System.out.println("支付成功回调通知");
}
} else {
log.info("数字签名验证失败: {}", "500");
}
} catch (Exception e) {
e.printStackTrace();
log.info("异常状态: {} ", e.getMessage());
}
return Constants.SUCCESS;
}
参考:https://opendocs.alipay.com/open/204/105301
如有哪里写的不好的还请多多包涵,有问题请下方留言哦