Java调用支付宝接口
一、环境准备
准备:内网穿透工具以及支付宝沙箱环境
1、内网穿透,申请免费域名(用于支付宝异步通知回调,要求外网可访问)
下载Ngrok客户端
解压,点击bat文件启动
输入刚才申请的隧道id,回车
端口映射完成
项目启动可使用http://donleo.free.idcfengye.com 访问
2、登录支付宝电脑端
网站地址:https://open.alipay.com/platform/home.htm
沙箱文档地址:https://opendocs.alipay.com/open/200/105311
首页-->支付宝扫码登录-->进入管理中心-->开发服务-->研发服务
设置秘钥
下载开发助手:https://opendocs.alipay.com/open/291/introduce
下载解压-->安装-->打开工具-->生成密匙(安装路径不要有空格)
将刚才通过工具生成的应用公钥复制到沙箱应用中,自动生成对应的支付宝公钥
沙箱账号,提供了卖家和买家两个测试账号,用于开发时方便测试
二、搭建项目
以电脑网站支付为例
支付宝接口文档:https://opendocs.alipay.com/open/270/105900
接口英文名 |
接口中文名 |
统一收单下单并支付页面接口 |
|
统一收单交易退款接口 |
|
统一收单交易退款查询接口 |
|
统一收单线下交易查询接口 |
|
统一收单交易关闭接口 |
|
查询对账单下载地址 |
|
收单退款冲退完成通知 |
参考官方demo:https://opendocs.alipay.com/open/270/106291
下载demo参考
1、新建SpringBoot项目,向pom文件添加alipay-sdk-java依赖
<dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.11.54.ALL</version> </dependency>
2、在官方给的demo例子,拷贝AlipayConfig配置文件到项目中
import java.io.FileWriter; import java.io.IOException; /** * 类名:AlipayConfig * 功能:基础配置类 * 详细:设置帐户有关信息及返回路径 * 修改日期:2017-04-05 * 说明: * 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。 * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 */ public class AlipayConfig { //↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号 public static String app_id = ""; // 商户私钥,您的PKCS8格式RSA2私钥 public static String merchant_private_key = ""; // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。 public static String alipay_public_key = ""; // 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 public static String notify_url = "http://工程公网访问地址/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp"; // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 public static String return_url = "http://工程公网访问地址/alipay.trade.page.pay-JAVA-UTF-8/return_url.jsp"; // 签名方式 public static String sign_type = "RSA2"; // 字符编码格式 public static String charset = "utf-8"; // 支付宝网关 public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do"; // 支付宝网关 public static String log_path = "C:\\"; //↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ /** * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库) * * @param sWord 要写入日志里的文本内容 */ public static void logResult(String sWord) { FileWriter writer = null; try { writer = new FileWriter(log_path + "alipay_log_" + System.currentTimeMillis() + ".txt"); writer.write(sWord); } catch (Exception e) { e.printStackTrace(); } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
应用id(自己的应用id):
商户私钥(刚才支付宝开发助手生成的):
支付宝公钥:
更改支付宝网关地址为开发环境地址:https://openapi.alipaydev.com/gateway.do
notify_url异步通知接口地址,例如:http://donleo.free.idcfengye.com/alipay/notifyPay
return_url页面跳转同步通知路径
三、测试接口
1、支付接口测试
接口文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.page.pay/
调用流程
公共请求参数,每次请求都会包含的参数
查看支付请求参数,这四个参数必选
创建支付记录和退款记录两个实体类,用于将交易信息保存到本地数据库
Base:基础类
class Base implements Serializable { /** * id 主键,自增 */ @TableId(value = "id", type = IdType.AUTO) private Integer id; /** * 创建时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; /** * 更新时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date updateTime; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
PayLog:交易记录
@Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) public class PayLog extends Base { /** * 商户订单号 */ private String outTradeNo; /** * 支付宝交易号 */ private String tradeNo; /** * 支付金额 */ private Double totalAmount; /** * 支付订单名称 */ private String subject; /** * 支付订单详情 */ private String subjectInfo; /** * 支付时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date payTime; /** * 支付状态 */ private Integer status; /** * 退款总金额 */ private Double refundTotalAmount; }
RefundLog:退款记录
@Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) public class RefundLog extends Base { /** * 商户订单号 */ private String outTradeNo; /** * 退款编号 */ private String refundNo; /** * 退款金额 */ private Double refundAmount; /** * 退款原因 */ private String refundInfo; /** * 退款时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date refundTime;
这些只是部分部分,具体参数可参考支付宝接口文档
交易支付状态常量类
public class Constant { //待支付 public static final int PAY_STATUS_WAITING=0; //已支付 public static final int PAY_STATUS_PAID=1; //已关闭 public static final int ABLE_PRAISE_CLOSED=2; //已部分退款 public static final int PAY_STATUS_REFUNDED=3; //已全额退款 public static final int PAY_STATUS_ALL_REFUNDED=4; }
支付代码请求示例:
@Override public void pay(String price, String name, HttpServletResponse response) { try { //获得初始化的AlipayClient DefaultAlipayClient client = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key,
"json",AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type); //电脑网页支付 AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); //手机网页支付 // AlipayTradeWapPayRequest request=new AlipayTradeWapPayRequest(); Map<Object, Object> map = new HashMap<>(); //商户订单号,商户网站订单系统中唯一订单号,必填 String outTradeNo = UUIDUtil.getUUID(); map.put("out_trade_no", outTradeNo); //销售产品码,目前仅支持FAST_INSTANT_TRADE_PAY,必填 map.put("product_code", "FAST_INSTANT_TRADE_PAY"); //付款金额,必填 map.put("total_amount", price); //订单名称,必填 map.put("subject", name); String string = JSONObject.toJSONString(map); log.info("--------" + string); request.setBizContent(string); //创建订单 createPayLog(outTradeNo, name, price); //异步通知 request.setNotifyUrl(AlipayConfig.notify_url); //页面跳转 request.setReturnUrl(AlipayConfig.return_url); String body = client.pageExecute(request).getBody(); response.setContentType("text/html;charset=utf-8"); response.getWriter().write(body); response.getWriter().flush(); response.getWriter().close(); } catch (Exception e) { log.error(e.getMessage()); } } /** * 创建订单,保存到本地数据库 * * @param outTradeNo 商户订单号 * @param name 订单名称 * @param price 付款金额 */ private void createPayLog(String outTradeNo, String name, String price) { PayLog payLog = new PayLog(); payLog.setOutTradeNo(outTradeNo); payLog.setSubject(name); payLog.setTotalAmount(parseDouble(price)); payLog.setStatus(Constant.PAY_STATUS_WAITING); payLog.setCreateTime(new Date()); payLogDao.insert(payLog); }
异步通知回调,post请求
@Override public String notifyPay(HttpServletRequest request) { try { log.info("进入异步通知接口"); //获取支付宝POST过来反馈信息 Map<String, String> params = new HashMap<>(); Map<String, String[]> requestParams = request.getParameterMap(); for (String name : requestParams.keySet()) { String[] values = requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } params.put(name, valueStr); } //调用SDK验证签名 boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); /* 实际验证过程建议商户务必添加以下校验: 1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号, 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额), 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email) 4、验证app_id是否为该商户本身。 */ if (signVerified) {//验证成功 //商户订单号 String out_trade_no = request.getParameter("out_trade_no"); //支付宝交易号 String trade_no = request.getParameter("trade_no"); //交易状态 String trade_status = request.getParameter("trade_status"); //支付金额 String total_amount = request.getParameter("total_amount"); if (StringUtils.isEmpty(out_trade_no)) { log.error("商户订单号为空"); return "fail"; } if (StringUtils.isEmpty(trade_no)) { log.error("支付宝交易号为空"); return "fail"; } if (StringUtils.isEmpty(total_amount)) { log.error("支付金额为空"); return "fail"; } if (StringUtils.isEmpty(trade_status)) { log.error("交易状态为空"); return "fail"; } //比对金额和交易号是否一致 PayLog payLog = new LambdaQueryChainWrapper<>(payLogDao).eq(PayLog::getOutTradeNo, out_trade_no).one(); if (payLog == null) { log.error("订单编号不存在!【" + out_trade_no + "】"); return "fail"; } else { if (payLog.getTotalAmount().compareTo(new Double(total_amount)) != 0) { log.error("支付金额不同!【" + total_amount + "】" + "【" + payLog.getTotalAmount() + "】"); return "fail"; } } //参数验证合法,将交易号与状态更新到本地数据库 payLog.setTradeNo(trade_no); payLog.setStatus(Constant.PAY_STATUS_PAID); payLog.setPayTime(new Date()); payLogDao.updateById(payLog); return "success"; } else {//验证失败 //调试用,写文本函数记录程序运行情况是否正常 // String sWord = AlipaySignature.getSignCheckContentV1(params); // AlipayConfig.logResult(sWord); return "fail"; } } catch (Exception e) { log.error(e.getMessage()); } return "fail"; }
请求示例:
http://donleo.free.idcfengye.com/alipay/pay?price=9000&name=华为Pro40
可以下载支付宝App沙箱版扫码支付,也可以输入账号密码支付
方便测试,直接输入账号密码
输入密码可支付成功后会进入异步通知接口,是否真正支付成功是以异步通知为准,可在异步通知接口中进行一系列的逻辑验证
2、交易查询测试
接口文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.query
代码示例:
@Override public String queryPayLog(HttpServletRequest request) { try { //获得初始化的AlipayClient AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key,
"json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type); //设置请求参数 AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest(); //商户订单号,商户网站订单系统中唯一订单号 String out_trade_no = request.getParameter("out_trade_no"); //支付宝交易号 String trade_no = request.getParameter("trade_no"); //请二选一设置,两者都存在优先取trade_no Map<String, Object> map = new HashMap<>(); map.put("out_trade_no", out_trade_no); map.put("trade_no", trade_no); alipayRequest.setBizContent(JSONObject.toJSONString(map)); //请求 String result = alipayClient.execute(alipayRequest).getBody(); log.info("交易查询:【" + result + "】"); return result; } catch (Exception e) { log.error(e.getMessage()); return e.getMessage(); }
返回结果示例:
{ "alipay_trade_query_response": { "code": "10000", "msg": "Success", "buyer_logon_id": "stb***@sandbox.com", "buyer_pay_amount": "0.00", "buyer_user_id": "2088622955538298", "buyer_user_type": "PRIVATE", "invoice_amount": "0.00", "out_trade_no": "39d1a795c14d4078bbb26665a6f9fe69", "point_amount": "0.00", "receipt_amount": "0.00", "send_pay_date": "2021-03-08 16:36:35", "total_amount": "99.90", "trade_no": "2021030822001438290501186947", "trade_status": "TRADE_SUCCESS" }, "sign": "ceDc9LR7Co8kh/oJbWpzdCQhylR6JEG6pxQnh89WQLUal0+t5Sds493XHET8QdZONb2tbRNAxwhbgbgLRiQjMCNQLRg+Hxu8uGjH2dpwEIlCWwc3LfFOZo5bCmofKV03sl+ABa4HhMVhVYIwEjCUlEofMoeC2n/PNA8HeQ8h7uPHAv/A9yIxMnzXraoBTYcXiXGtV/IdTWLepq9vmrmMRDVxjFqAzRH/p1dtq+D5fTb45jSUFUYU1UC1MDsVqkS6iM9oVGtqRS8JrZun9HVUFiMPm9Bi17HDnCfQBjo63olPk2620N9W5HwV3W9xUD2Yp6ncndCB99rhOuDf8BwQ==" }
3、交易关闭测试
接口文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.close
请求流程
代码示例:
@Override public String closePayLog(HttpServletRequest request) { try { //获得初始化的AlipayClient AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key,
"json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type); //设置请求参数 AlipayTradeCloseRequest alipayRequest = new AlipayTradeCloseRequest(); //商户订单号,商户网站订单系统中唯一订单号 String out_trade_no = request.getParameter("out_trade_no"); //支付宝交易号 // String trade_no = request.getParameter("trade_no"); //请二选一设置 alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\"}"); //请求 String result = alipayClient.execute(alipayRequest).getBody(); log.info("返回数据------>" + result); JSONObject jsonObject = JSONObject.parseObject(result).getJSONObject("alipay_trade_close_response"); Long code = Long.valueOf(jsonObject.get("code").toString()); //关闭成功,同步数据状态 if (code.compareTo(10000L) == 0) { PayLog payLog = new LambdaQueryChainWrapper<>(payLogDao).eq(PayLog::getOutTradeNo, out_trade_no).one(); payLog.setStatus(Constant.ABLE_PRAISE_CLOSED); payLog.setUpdateTime(new Date()); payLogDao.updateById(payLog); } return result; } catch (Exception e) { log.error(e.getMessage()); return e.getMessage(); } }
4、退款接口测试
接口文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.refund
调用流程
如果可以多次退款,out_request_no必传,且保证唯一
代码示例(支持一个订单多次退款)
@Override public String refundPay(HttpServletRequest request) { try { //获得初始化的AlipayClient AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key,
"json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type); //设置请求参数 AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest(); //商户订单号,商户网站订单系统中唯一订单号 String out_trade_no = request.getParameter("out_trade_no"); //支付宝交易号 // String trade_no = request.getParameter("trade_no"); //请二选一设置 //需要退款的金额,该金额不能大于订单金额,必填 String refund_amount = request.getParameter("refund_amount"); //退款的原因说明 String refund_reason = request.getParameter("refund_reason"); //标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传 String out_request_no = UUIDUtil.getUUID(); //判断是否可以退款 int payCode = refundAliPay(out_trade_no, refund_amount); if (payCode == 1) { return "退款金额不能大于可退款金额"; } else if (payCode == 2) { return "订单已关闭,不能退款"; } else if (payCode == 3) { return "订单未支付,不能退款"; } else if (payCode == 4) { return "订单已全部退款"; } else { alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\"," + "\"refund_amount\":\"" + refund_amount + "\"," + "\"refund_reason\":\"" + refund_reason + "\"," + "\"out_request_no\":\"" + out_request_no + "\"}"); //请求 String result = alipayClient.execute(alipayRequest).getBody(); log.info("退款信息------>" + result); JSONObject jsonObject = JSONObject.parseObject(result).getJSONObject("alipay_trade_refund_response"); Long code = Long.valueOf(jsonObject.get("code").toString()); //退款成功,更新数据库并保存退款记录 if (code.compareTo(10000L) == 0) { //查询退款记录 List<RefundLog> refundLogList = new LambdaQueryChainWrapper<>(refundLogDao).eq(RefundLog::getOutTradeNo, out_trade_no).list(); double refundTotalAmount = 0.00; BigDecimal d1 = new BigDecimal(refundTotalAmount); if (refundLogList.size() > 0) { for (RefundLog aRefundLogList : refundLogList) { BigDecimal d2 = new BigDecimal(aRefundLogList.getRefundAmount()); refundTotalAmount += d1.add(d2).doubleValue(); } } //插入退款记录 RefundLog refundLog = new RefundLog(); refundLog.setOutTradeNo(out_trade_no); refundLog.setRefundNo(out_request_no); refundLog.setRefundAmount(parseDouble(refund_amount)); refundLog.setRefundInfo(refund_reason); refundLog.setRefundTime(new Date()); refundLogDao.insert(refundLog); //更新支付记录 refundTotalAmount += parseDouble(refund_amount); PayLog payLog = new LambdaQueryChainWrapper<>(payLogDao).eq(PayLog::getOutTradeNo, out_trade_no).one(); payLog.setUpdateTime(new Date()); if (refundTotalAmount == payLog.getTotalAmount()) { payLog.setStatus(Constant.PAY_STATUS_ALL_REFUNDED); } else { payLog.setStatus(Constant.PAY_STATUS_REFUNDED); } payLog.setRefundTotalAmount(refundTotalAmount); payLogDao.updateById(payLog); } return result; } } catch (Exception e) { log.error(e.getMessage()); return e.getMessage(); } } /** * 判断是否可以退款 * * @param out_trade_no 订单号 * @param refund_amount 退款金额 * @return int */ private int refundAliPay(String out_trade_no, String refund_amount) { List<RefundLog> refundLogList = new LambdaQueryChainWrapper<>(refundLogDao).eq(RefundLog::getOutTradeNo, out_trade_no).list(); double refundTotalAmount = 0.00; BigDecimal d1 = new BigDecimal(refundTotalAmount); if (refundLogList.size() > 0) { for (RefundLog aRefundLogList : refundLogList) { BigDecimal d2 = new BigDecimal(aRefundLogList.getRefundAmount()); refundTotalAmount += d1.add(d2).doubleValue(); } } //查询支付记录 PayLog payLog = new LambdaQueryChainWrapper<>(payLogDao).eq(PayLog::getOutTradeNo, out_trade_no).one(); //退款金额 double refundAmount = parseDouble(refund_amount); //支付总金额 double totalAmount = payLog.getTotalAmount(); //可退款金额 BigDecimal b1 = new BigDecimal(totalAmount); BigDecimal b2 = new BigDecimal(refundTotalAmount); double enableAmount = b1.subtract(b2).doubleValue(); if (payLog.getStatus().equals(Constant.ABLE_PRAISE_CLOSED)) { //订单已关闭,不能退款 return 2; } else if (payLog.getStatus().equals(Constant.PAY_STATUS_WAITING)) { //订单未支付,不能退款 return 3; } else if (payLog.getStatus().equals(Constant.PAY_STATUS_ALL_REFUNDED)) { //订单已全部退款 return 4; } else { //表示可以退款 if (refundAmount > enableAmount) { //退款金额不能大于可退款金额 return 1; } return 0; } }
请求示例:
http://donleo.free.idcfengye.com/alipay/refundPay?out_trade_no=15baf0eb282844c9a7bbcf491a3ab214&refund_amount=100&refund_reason=好评返现
响应示例:
{ "alipay_trade_refund_response": { "code": "10000", "msg": "Success", "buyer_logon_id": "stb***@sandbox.com", "buyer_user_id": "2088622955538298", "fund_change": "Y", "gmt_refund_pay": "2021-03-09 10:36:00", "out_trade_no": "15baf0eb282844c9a7bbcf491a3ab214", "refund_fee": "322.20", "send_back_fee": "0.00", "trade_no": "2021030622001438290501185818" }, "sign": "h6k02XohrwCg4HhEFjHXdER+AkOc4jbt5c06nuEYAI/RjCfnX9Km3LO0+Z2Xz+0RJTGgAtWJcp94Te4/Uomdnug9m+LA3bX1O1HSi/wlThUXT7QGwN/EyYxxZV5uAJzd5Q49bZZIsh8n39NXnShzRcZ2FP8sSp02kECCyiKjYVDrMLyOPoR4gcJiGUmwE2jKNIHZ2dxJ6D75XBtQkg9YsaOfbX47bDqAEEIxAcySBVfF0WkNha0rpTXWtriqZHrLzJZsNSwwqdM2W+EezLnxmpfzIdSE35fCJHXehVXm5veJ9czgkiDpuToaD+o0qUo6ex+1pnxu8nqmSMFraaTA==" }
查看本地数据库中的退款记录
5、退款查询测试
接口文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.fastpay.refund.query
代码示例:
@Override public String refundQuery(HttpServletRequest request) { try { //获得初始化的AlipayClient AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type); //设置请求参数 AlipayTradeFastpayRefundQueryRequest alipayRequest = new AlipayTradeFastpayRefundQueryRequest(); //商户订单号,商户网站订单系统中唯一订单号 String out_trade_no = request.getParameter("out_trade_no"); //请求退款接口时,传入的退款请求号,如果在退款请求时未传入,则该值为创建交易时的外部交易号,必填 //此处为退款记录编号 String out_request_no = request.getParameter("refund_no"); alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\"," + "\"out_request_no\":\"" + out_request_no + "\"}"); //请求 String result = alipayClient.execute(alipayRequest).getBody(); log.info("退款记录------>" + result); return result; } catch (Exception e) { log.error(e.getMessage()); return e.getMessage(); } }
请求示例:
http://localhost:9000/alipay/refundQuery?out_trade_no=15baf0eb282844c9a7bbcf491a3ab214&refund_no=65bdc5dc0afa457688be38b7d5042e4b
响应示例:
{ "alipay_trade_fastpay_refund_query_response": { "code": "10000", "msg": "Success", "out_request_no": "65bdc5dc0afa457688be38b7d5042e4b", "out_trade_no": "15baf0eb282844c9a7bbcf491a3ab214", "refund_amount": "100.00", "total_amount": "9000.00", "trade_no": "2021030622001438290501185818" }, "sign": "TOIvyxk+FGQPuTgX9s6rWyxRSEaEA0AgqlJj7dmwU6IPfjgLIBDMw6NXsax0nQQTaYFOfLaZ56c0ap7+I/t31WQbF5/6DczWKoxK7ijenXvtQ9IcYx17e272xdUDrwLMe/w3q5b30py0WBqTLfBRUkV9tqystI7yeF9QAx90wMp9oe8spxeYXKcfuJ3fVpjEpCA0RbL6SvO69Vawh400adcVu2PIG5W1/gkKTOCgE6cXsJ1MGL7GvYnXgfFwMFwnhZP+JZFmktdfTNsIV8eakp+oyVNJJvobIKjjcr5Bfvrzt3BIqN2M6XOAxfkaZ9nxE0hcmRY/LTZ5FFvo2b2A==" }
6、账单下载测试
接口文档地址:https://opendocs.alipay.com/apis/api_15/alipay.data.dataservice.bill.downloadurl.query
调用流程
代码示例:
@Override public String downloadPayLog(HttpServletRequest request) { try { //获得初始化的AlipayClient AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type); AlipayDataDataserviceBillDownloadurlQueryRequest alipayRequest = new AlipayDataDataserviceBillDownloadurlQueryRequest(); //账单类型 trade:商户基于支付宝交易收单的业务账单;signcustomer:基于商户支付宝余额收入及支出等资金变动的帐务账单。 String bill_type = request.getParameter("bill_type"); //账单时间,必填 String bill_date = request.getParameter("bill_date"); alipayRequest.setBizContent("{\"bill_type\":\"" + bill_type + "\"," + "\"bill_date\":\"" + bill_date + "\"}"); //请求 String result = alipayClient.execute(alipayRequest).getBody(); log.info("账单记录------>" + result); return result; } catch (Exception e) { log.error(e.getMessage()); return e.getMessage(); } }
请求示例:
http://localhost:9000/alipay/downloadPayLog?bill_type=trade&bill_date=2020-03-08
响应示例:
{ "alipay_data_dataservice_bill_downloadurl_query_response": { "code": "10000", "msg": "Success", "bill_download_url": "http://dwbillcenter-2-1-2.daily.alipay.net/downloadBillFile.resource?bizType=trade&userId=20886219553637780156&fileType=csv.zip&bizDates=20200308&downloadFileName=2088621955363770156_20200308.csv.zip&fileId=%2Ftrade%2F20886219553637780156%2F20200308.csv.zip×tamp=1615257961&token=515b244e8b28fe10e0b0fcd3923c6b6" }, "sign": "q1vX2Pt+Sm4iThIiGeMb9JwAOlew1zCcPUhotuE3iPsyE4c6m35TgpiqyYNZwTMse59fovogCUfiw1XwbG/7d5p7z6LWfgWws88Mh1v1nWYb7HNyNfh0KMd5CWf3KLJ0tE2hWeUpWAoOVruDQ8NVyWM1it/iDQa+Mh9Nr7KwWpMxOhNK2vH7MzRt5lKECQOLPXc5ko6IgYI4ddF62nMtLdKkJQeLyP7ByWGpWcBpLLca5pYTVvnMwo1dfobgNi05jYE5id+n6J2/q81gTPbJaP9UMv99qmURX37SJKwdekICRXMdfHRaEnTztM6BqCw0EvrnUMf/0BAt4RhvKw==" }