# alipay **Repository Path**: YzHutMall/alipay ## Basic Information - **Project Name**: alipay - **Description**: SpringBoot整合支付宝支付 扫码支付+退款 详细文档 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2022-02-20 - **Last Updated**: 2026-01-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SpringBoot整合支付宝支付 ## 项目工程 ``` │ pom.xml │ Readme.md │ ├─src │ ├─main │ │ ├─java │ │ │ └─com │ │ │ └─alipay │ │ │ └─alipayDemo │ │ │ │ AlipayDemoApplication.java │ │ │ │ │ │ │ ├─bean │ │ │ │ AlipayBean.java │ │ │ │ │ │ │ ├─config │ │ │ │ AlipayUtil.java │ │ │ │ │ │ │ ├─controller │ │ │ │ NotifyController.java │ │ │ │ OrderController.java │ │ │ │ │ │ │ └─service │ │ │ │ PayService.java │ │ │ │ │ │ │ └─impl │ │ │ PayServiceImpl.java │ │ │ │ │ └─resources │ │ │ application.yml │ │ │ │ │ ├─config │ │ │ alipay.properties │ │ │ │ │ ├─static │ │ │ error.html │ │ │ index.html │ │ │ success.html │ │ │ │ │ └─templates │ └─test │ └─java │ └─com │ ├─java98k │ │ └─alipayDemo │ │ AlipayDemoApplicationTests.java │ │ │ └─kylin ``` ### 效果展示 #### 支付页面 ![img_7.png](images/img_7.png) #### 待支付页面 ![img_2.png](images/img_2.png) #### 扫码支付 ![img_5.png](images/img_5.png) #### 支付成功 ![img_3.png](images/img_3.png) #### 支付回调 ![img_6.png](images/img_6.png) ### 代码 #### 依赖 ```xml org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test com.alipay.sdk alipay-sdk-java 3.1.0 org.projectlombok lombok com.alibaba fastjson 1.2.44 ``` #### 支付控制层 ```java /** * 功能描述: 订单接口 * * @author CHENKAIFANG * @date 2022/2/20 2:44 * @since JDK 1.8 */ @RestController() @RequestMapping("order") public class OrderController { @Resource private PayService payService; /** * 功能描述: 支付宝支付 * * @param outTradeNo 订单号 * @param subject 主题 * @param totalAmount 总价 * @param body 主题 * @return {@link String} * @author CHENKAIFANG * @date 2022/2/20 2:44 * @since JDK 1.8 */ @PostMapping(value = "alipay") public String alipay(String outTradeNo, String subject, StringBuffer totalAmount, String body) throws AlipayApiException { return payService.aliPay(AlipayBean.builder() .body(body) .out_trade_no(outTradeNo) .total_amount(totalAmount) .subject(subject).build()); } /** * 功能描述: 退款 * * @author CHENKAIFANG * @date 2022/2/20 14:14 * @since JDK 1.8 */ @PostMapping(value = "alipayRefound") public String alipayRefound(@RequestParam("tradeNo") String tradeNo, @RequestParam("outRequestNo") String outRequestNo, @RequestParam("refundAmount") String refundAmount) throws AlipayApiException { return payService.alipayRefound(AlipayBean.builder() .tradeNo(tradeNo) .outRequestNo(outRequestNo) .refundAmount(refundAmount) .build()); } } ``` #### 支付配置 ```text 沙箱配置文档:https://open.alipay.com/dev/workspace ``` ```yml # 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号 app_id=2016102100734823 # 商户私钥,您的PKCS8格式RSA2私钥 merchant_private_key=商户私钥(支付宝沙箱配置) # 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。 alipay_public_key=支付宝公钥 (支付宝沙箱配置) # 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 notify_url=http://外网IP(ngrok内外网穿透工具)/notify/alipay # 面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 return_url=http://外网IP(ngrok内外网穿透工具)/success.html # 签名方式 sign_type=RSA2 # 字符编码格式 charset=utf-8 # 支付宝网关 gatewayUrl=https://openapi.alipaydev.com/gateway.do # 支付宝网关 log_path="C:\\" ``` #### 支付成功页面 ```html 支付成功 支付成功! ``` #### 支付回调 ```java /** *

* 支付回调 *

* * @SINCE 2022/2/20 2:53 * @AUTHOR CHENKAIFANG * @Date: 2022/2/20 02:53 */ @RestController() @RequestMapping("notify") public class NotifyController { @Autowired private PayService payService; /** * 功能描述: 支付成功回调 * * @author CHENKAIFANG * @date 2022/2/20 14:14 * @since JDK 1.8 */ @PostMapping(value = "alipay") public String pay(HttpServletRequest request) { System.out.println("支付成功回调!"); int im = 0; im++; //测试请求次数 System.out.println("次数:" + im); Map 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] + ","; } //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); params.put(name, valueStr); } //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)// //商户订单号 String outTradeNo = request.getParameter("out_trade_no"); System.out.println("商户订单号: " + outTradeNo); //支付宝交易号 String tradeNo = request.getParameter("trade_no"); System.out.println("支付宝交易号: " + tradeNo); //支付宝交易金额 String totalAmount = request.getParameter("total_amount"); System.out.println("支付宝交易金额: " + totalAmount); //交易状态 String tradeStatus = request.getParameter("trade_status"); System.out.println("交易状态: " + tradeStatus); System.out.println("params: " + JSONObject.toJSONString(params)); return payService.rsaCheck(params, tradeStatus); } } ``` #### 验签 ``` java /** * 功能描述: 支付回调验签 * * @param params 获取支付宝POST过来反馈信息 * @param tradeStatus 交易状态 * @return {@link Boolean} * @author CHENKAIFANG * @date 2022/2/20 15:20 */ public String rsaCheck(Map params, String tradeStatus) { try { boolean verifyResult = AlipaySignature.rsaCheckV1(params, alipayPublicKey, charset, signType); if (verifyResult) { //验证成功 //请在这里加上商户的业务逻辑程序代码 System.out.println("returnUrl_params: 验证成功"); //——请根据您的业务逻辑来编写程序(以下代码仅作参考)—— boolean flg = false; if ("TRADE_FINISHED".equals(tradeStatus)) { System.out.println("returnUrl_params: 交易结束"); //交易结束,不可退款 //注意: //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 } else if ("TRADE_SUCCESS".equals(tradeStatus)) { //交易支付成功 //注意: //付款完成后,支付宝系统发送该交易状态通知 //根据订单号将订单状态和支付宝记录表中状态都改为已支付 System.out.println("returnUrl_params: 交易支付成功"); flg = true; } //——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— if (flg) { return "success"; } else { return "fail"; } } else { return "fail"; } } catch (AlipayApiException e) { e.printStackTrace(); return "fail"; } } ``` #### 回调返回 ``` text 支付成功回调! 次数:1 商户订单号: 22 支付宝交易号: 2022031922001404550501570961 支付宝交易金额: 100.00 交易状态: TRADE_SUCCESS params: {"gmt_create":"2022-03-19 13:50:29","charset":"utf-8","gmt_payment":"2022-03-19 13:50:36","notify_time":"2022-03-19 13:50:38","subject":"E-c-mall 支付100元","sign":"XO1b5ELBiQ3SOKv9rw3A2BaHD+NnwAH3i1JHWZXGxHishhcTOqMvUx41aXdbtgYtJy2u/7wKjnfAptJlMG+aMQNIerxX8vFUORWryUSZkXHQTTIJGyx6E0BUnKtRtehBJnK7iHU3jgg3eRYfs65bYr5qlIB6N/PHjzALVrZcLD/ozepAkGKDKKHi+ZkYVF51G3AQr+AUF3hAzPw5SOorx7FmEhLShHA0hHn6Q9YQL+UgF0CWy6/be1Ilgf6/NVY9PfoQbC/KeEl9azfN1dCNVC6jFi4a9GHs4P4E1johtRuvc/p8u0Z5iUyQFHY5eX2clg4KqRaCred7wkrD0F6ciA==","buyer_id":"2088102180804554","body":"E-c-mall 支付100元","invoice_amount":"100.00","version":"1.0","notify_id":"2022031900222135037004550519937487","fund_bill_list":"[{\"amount\":\"100.00\",\"fundChannel\":\"ALIPAYACCOUNT\"}]","notify_type":"trade_status_sync","out_trade_no":"22","total_amount":"100.00","trade_status":"TRADE_SUCCESS","trade_no":"2022031922001404550501570961","auth_app_id":"2016102100734823","receipt_amount":"100.00","point_amount":"0.00","app_id":"2016102100734823","buyer_pay_amount":"100.00","sign_type":"RSA2","seller_id":"2088102180570093"} returnUrl_params: 验证成功 returnUrl_params: 交易支付成功 ``` #### 支付宝退款 ``` java /** * 功能描述: 支付宝退款 * * @param alipayBean 支付实体对象 * @return {@link String} * @author CHENKAIFANG * @date 2022/2/20 14:21 * @since JDK 1.8 */ public String alipayRefound(AlipayBean alipayBean) throws AlipayApiException { // 1.接口参数调用 AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, appId, merchantPrivateKey, FORMAT, charset, alipayPublicKey, signType); AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest(); JSONObject bizContent = new JSONObject(); bizContent.put(TRADE_NO, alipayBean.getTradeNo()); bizContent.put(OUT_REQUEST_NO, alipayBean.getOutRequestNo()); bizContent.put(REFUND_AMOUNT, alipayBean.getRefundAmount()); request.setBizContent(bizContent.toString()); // 2.接口调用<原理就是返回的form表单。然后执行而已> return alipayClient.execute(request).getBody(); } ``` ### 内外网穿透工具 ```shell Sunny-Ngrok www.ngrok.cc (Ctrl+C to quit) Tunnel Status online Version 2.1.1/2.1.1 Forwarding http://前置域名.vipgz1.91tunnel.com -> 127.0.0.1:8081 Web Interface 127.0.0.1:4040 # Conn 14 Avg Conn Time 48960.21ms ```