最近在搞支付这块,总算告一段落了,来记录一下,以后找不迷路,在此也希望帮到一些同学,
其实支付宝的技术客服还挺好的,你可以找他们要示例,不像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
如有哪里写的不好的还请多多包涵,有问题请下方留言哦