SpringBoot+MyBatis集成支付寶支付流程
核心流程
- 商戶系統(tǒng)生成訂單
- 調(diào)用支付寶創(chuàng)建預(yù)支付訂單
- 用戶跳轉(zhuǎn)支付寶完成支付
- 支付寶異步通知支付結(jié)果
- 商戶處理支付結(jié)果更新訂單狀態(tài)
- 支付寶同步跳轉(zhuǎn)回商戶頁面
代碼實現(xiàn)示例(電腦網(wǎng)站支付)
1. 添加依賴
<!-- pom.xml --> <dependencies> <!-- Spring Boot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis & MySQL --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 支付寶SDK --> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.35.0.ALL</version> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
2. 支付寶配置類
@Configuration public class AlipayConfig { @Value("${alipay.app_id}") private String appId; @Value("${alipay.merchant_private_key}") private String merchantPrivateKey; @Value("${alipay.alipay_public_key}") private String alipayPublicKey; @Value("${alipay.notify_url}") private String notifyUrl; @Value("${alipay.return_url}") private String returnUrl; @Value("${alipay.gateway_url}") private String gatewayUrl; @Value("${alipay.sign_type}") private String signType; @Value("${alipay.charset}") private String charset; @Bean public AlipayClient alipayClient() { return new DefaultAlipayClient( gatewayUrl, appId, merchantPrivateKey, "json", charset, alipayPublicKey, signType ); } }
3. 實體類和Mapper
// 訂單實體 @Data public class Order { private Long id; private String orderNo; // 商戶訂單號 private BigDecimal amount;// 支付金額 private Integer status; // 0-待支付, 1-已支付 private LocalDateTime createTime; } // MyBatis Mapper @Mapper public interface OrderMapper { @Insert("INSERT INTO orders(order_no, amount, status, create_time) " + "VALUES(#{orderNo}, #{amount}, 0, NOW())") @Options(useGeneratedKeys = true, keyProperty = "id") void insert(Order order); @Update("UPDATE orders SET status = #{status} WHERE order_no = #{orderNo}") void updateStatus(@Param("orderNo") String orderNo, @Param("status") int status); }
4. 支付服務(wù)類
@Service public class PayService { @Autowired private AlipayClient alipayClient; @Autowired private OrderMapper orderMapper; @Value("${alipay.return_url}") private String returnUrl; @Value("${alipay.notify_url}") private String notifyUrl; // 創(chuàng)建支付訂單 public String createPayOrder(Order order) throws AlipayApiException { orderMapper.insert(order); // 保存訂單到數(shù)據(jù)庫 AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); request.setReturnUrl(returnUrl); request.setNotifyUrl(notifyUrl); // 構(gòu)造業(yè)務(wù)參數(shù) JSONObject bizContent = new JSONObject(); bizContent.put("out_trade_no", order.getOrderNo()); bizContent.put("total_amount", order.getAmount()); bizContent.put("subject", "商品支付"); bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY"); // 電腦網(wǎng)站支付 request.setBizContent(bizContent.toString()); return alipayClient.pageExecute(request).getBody(); } // 處理異步通知 public boolean handleNotify(Map<String, String> params) throws AlipayApiException { // 1. 驗證簽名 boolean signVerified = AlipaySignature.rsaCheckV1( params, alipayPublicKey, // 注入支付寶公鑰 charset, signType ); if (!signVerified) return false; // 2. 驗證交易狀態(tài) String tradeStatus = params.get("trade_status"); if (!"TRADE_SUCCESS".equals(tradeStatus)) return false; // 3. 更新訂單狀態(tài) String orderNo = params.get("out_trade_no"); orderMapper.updateStatus(orderNo, 1); // 更新為已支付 return true; } }
5. 控制器
@RestController @RequestMapping("/pay") public class PayController { @Autowired private PayService payService; // 創(chuàng)建支付訂單 @PostMapping("/create") public String createOrder(@RequestParam BigDecimal amount) throws AlipayApiException { Order order = new Order(); order.setOrderNo(UUID.randomUUID().toString().replace("-", "")); order.setAmount(amount); return payService.createPayOrder(order); // 返回支付頁面表單 } // 支付寶異步通知(需公網(wǎng)可訪問) @PostMapping("/notify") public String alipayNotify(HttpServletRequest request) throws UnsupportedEncodingException, AlipayApiException { Map<String, String> params = parseRequestParams(request); boolean success = payService.handleNotify(params); return success ? "success" : "failure"; // 通知支付寶處理結(jié)果 } // 支付寶同步跳轉(zhuǎn) @GetMapping("/return") public String alipayReturn(HttpServletRequest request) { // 簡單展示支付結(jié)果(實際需要驗簽和狀態(tài)檢查) return "支付完成!訂單號:" + request.getParameter("out_trade_no"); } // 解析請求參數(shù) private Map<String, String> parseRequestParams(HttpServletRequest request) { // 轉(zhuǎn)換參數(shù)Map(參考支付寶示例代碼) } }
6. 配置文件
# application.properties # 支付寶配置 alipay.app_id=2021000123456789 alipay.merchant_private_key=MIIEvQIBADANB... alipay.alipay_public_key=MIIBIjANBgkq... alipay.notify_url=http://your-domain.com/pay/notify alipay.return_url=http://your-domain.com/pay/return alipay.gateway_url=https://openapi.alipay.com/gateway.do alipay.sign_type=RSA2 alipay.charset=UTF-8 # MySQL配置 spring.datasource.url=jdbc:mysql://localhost:3306/alipay_demo spring.datasource.username=root spring.datasource.password=123456
關(guān)鍵流程說明
生成商戶訂單
- 生成唯一訂單號(推薦雪花算法)
- 保存訂單到數(shù)據(jù)庫(狀態(tài)=待支付)
調(diào)用支付寶接口
- 使用
AlipayTradePagePayRequest
構(gòu)建請求 - 關(guān)鍵參數(shù):訂單號、金額、支付標(biāo)題、回調(diào)地址
- 使用
接收異步通知
- 必須驗證簽名(防止偽造請求)
- 檢查 trade_status 是否為 TRADE_SUCCESS
- 更新訂單狀態(tài)(注意處理冪等性)
安全注意事項
- 支付金額需與訂單金額比對(防止金額篡改)
- 敏感操作記錄日志
- 異步通知處理需要保證冪等性
擴(kuò)展功能
- 訂單超時關(guān)閉:定時任務(wù)掃描未支付訂單
- 支付結(jié)果查詢:通過 trade_no 調(diào)用支付寶查詢接口
- 退款功能:使用
AlipayTradeRefundRequest
提示:實際開發(fā)中需要:
替換為正式支付寶賬戶
配置公網(wǎng)可訪問的域名
添加完整的錯誤處理
實現(xiàn)參數(shù)解析工具方法
添加數(shù)據(jù)庫事務(wù)管理
到此這篇關(guān)于SpringBoot+MyBatis集成支付寶支付流程的文章就介紹到這了,更多相關(guān)SpringBoot MyBatis 支付寶支付內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot+mybatis配置clickhouse實現(xiàn)插入查詢功能
這篇文章主要介紹了springboot+mybatis配置clickhouse實現(xiàn)插入查詢功能,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08SpringBoot 應(yīng)用程序測試實現(xiàn)方案
這篇文章主要介紹了SpringBoot 應(yīng)用程序測試實現(xiàn)方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11Java異步調(diào)用轉(zhuǎn)同步方法實例詳解
這篇文章主要介紹了Java異步調(diào)用轉(zhuǎn)同步方法實例詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06Java使用TarsosDSP庫實現(xiàn)音頻的處理和格式轉(zhuǎn)換
在音頻處理領(lǐng)域,Java雖然有原生的音頻處理類庫,但其功能相對基礎(chǔ),而TarsosDSP是一個強(qiáng)大的開源音頻處理庫,提供了豐富的功能,本文將介紹如何在Java中結(jié)合使用TarsosDSP庫,來實現(xiàn)音頻的處理和格式轉(zhuǎn)換,需要的朋友可以參考下2025-04-04Spring Boot 把配置文件和日志文件放到j(luò)ar外部
如果不想使用默認(rèn)的application.properties,而想將屬性文件放到j(luò)ar包外面,怎么做呢?下面小編給大家?guī)砹藘煞N方法解決Spring Boot 把配置文件和日志文件放到j(luò)ar外部問題,感興趣的朋友一起看看吧2018-02-02Java日常練習(xí)題,每天進(jìn)步一點點(62)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你2021-08-08Java并發(fā)編程學(xué)習(xí)之Unsafe類與LockSupport類源碼詳析
這篇文章主要給大家介紹了關(guān)于Java并發(fā)編程學(xué)習(xí)之Unsafe類與LockSupport類源碼的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧2018-06-06