SpringBoot集成支付寶沙箱支付的實現示例
開發(fā)前準備
1、密鑰工具
在線工具地址:https://miniu.alipay.com/keytool/create
無需下載,直接在線生成你的應用私鑰
點擊生成即可生成自己的公鑰和私鑰
這個公鑰后面會用到叫做alipayPublicKey
這個私鑰后面會用到叫做appPrivateKey
如果遇到生成失敗點擊鏈接選擇Web在線加密https://opendocs.alipay.com/open/291/introduce
再不行就自己下載客戶端工具
2、沙箱環(huán)境
注冊支付寶開發(fā)者賬戶,進入開發(fā)者控制臺
https://auth.alipay.com/login/ant_sso_index.htm?goto=https%3A%2F%2Fopenhome.alipay.com%2Fplatform%2FdeveloperIndex.htm
這個appid后面配置springboot會用到
這里的公鑰就是上面生成的,不要填錯了
3、內網穿透工具
我用的是natapp,下載地址:https://natapp.cn/
啟動命令:natapp.exe -authtoken=你的authtoken 這個authtoken是在natapp里面創(chuàng)建免費隧道產生的。
注意隧道的端口要配置成你的后臺端口,例如9090
直接在上面的命令后面加上就可以啟動你的 natapp,設置內網穿透了。
內網穿透就是把本機的 ip 和端口暴露到外網,通過指定的 url 可以訪問你本地的服務,當然 ,這存在一定的安全風險,請謹慎使用!使用命令開啟 natapp 后,會生成一個外網的地址指向你本地的服務地址,當你訪問http://tdqxnr.natappfree.cc,跟你訪問 127.0.0.1:9090 效果是一樣的,只不過一個是對外的,一個是只能本地訪問。
代碼集成
1、Java SDK
打開支付寶官方文檔:https://opendocs.alipay.com/open/54/00y8k9
他提供了一個Easy版本的Java SDK集成方案,我們可以直接用這個。
maven依賴:
<dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-easysdk</artifactId> <version>2.2.0</version> </dependency>
2、支付寶配置
在 application.properties 文件里面加上這些配置,appId 就是上面看到的沙箱環(huán)境里面提
供的appId,appPrivateKey 和 alipayPublicKey也是上面已經有了,直接復制過來即可。
notifyUrl是支付成功后的一個回調接口,用來修改訂單的狀態(tài),我們可以在
AliPayController 加上這個接口(后面有講到),注意,這個回調接口的地址必須是我們在
natapp 里面獲取到的公網地址,否則接口無法回調。
新建一個配置類AliPayConfig
package com.example.demo.common.config; import com.alipay.easysdk.factory.Factory; import com.alipay.easysdk.kernel.Config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @Data @Component @ConfigurationProperties(prefix = "alipay") public class AliPayConfig { private String appId; private String appPrivateKey; private String alipayPublicKey; private String notifyUrl; @PostConstruct public void init() { // 設置參數(全局只需設置一次) Config options = getOptions(); options.appId = this.appId; options.merchantPrivateKey = this.appPrivateKey; options.alipayPublicKey = this.alipayPublicKey; options.notifyUrl = this.notifyUrl; Factory.setOptions(options); System.out.println("=======支付寶SDK初始化成功======="); } private Config getOptions() { Config config = new Config(); config.protocol = "https"; config.gatewayHost = "openapi.alipaydev.com"; config.signType = "RSA2"; return config; } }
注意:在攔截器里面加上忽略alipay接口的配置!
3、支付和回調接口
新建一個 AliPayController,寫一個 Get 接口,這個是支付的接口,前端需要把 訂單的標
題、訂單編號、訂單的總金額傳到后臺來,后臺去調用支付寶的 APi 生成支付訂單,在網頁上
實現支付。
@GetMapping("/pay") public String pay(AliPay aliPay) { AlipayTradePagePayResponse response; try { // 發(fā)起API調用(以創(chuàng)建當面付收款二維碼為例) response = Factory.Payment.Page() .pay(aliPay.getSubject(), aliPay.getTraceNo(), aliPay.getTotalAmount(), ""); } catch (Exception e) { System.err.println("調用遭遇異常,原因:" + e.getMessage()); throw new RuntimeException(e.getMessage(), e); } return response.getBody(); }
第二個接口是支付成功回調的接口,我們在這個接口可以獲取到支付訂單的訂單編號和支付時
間,然后我們可以修改本地訂單的支付狀態(tài)。注意:這是一個 POST 接口。
@PostMapping("/notify") // 注意這里必須是POST接口 public String payNotify(HttpServletRequest request) throws Exception { if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) { System.out.println("=========支付寶異步回調========"); Map<String, String> params = new HashMap<>(); Map<String, String[]> requestParams = request.getParameterMap(); for (String name : requestParams.keySet()) { params.put(name, request.getParameter(name)); // System.out.println(name + " = " + request.getParameter(name)); } String tradeNo = params.get("out_trade_no"); String gmtPayment = params.get("gmt_payment"); // 支付寶驗簽 if (Factory.Payment.Common().verifyNotify(params)) { // 驗簽通過 System.out.println("交易名稱: " + params.get("subject")); System.out.println("交易狀態(tài): " + params.get("trade_status")); System.out.println("支付寶交易憑證號: " + params.get("trade_no")); System.out.println("商戶訂單號: " + params.get("out_trade_no")); System.out.println("交易金額: " + params.get("total_amount")); System.out.println("買家在支付寶唯一id: " + params.get("buyer_id")); System.out.println("買家付款時間: " + params.get("gmt_payment")); System.out.println("買家付款金額: " + params.get("buyer_pay_amount")); // 更新訂單未已支付 orderMapper.updateState(tradeNo, 1, gmtPayment); } } return "success"; }
4、前端Vue調用
在書籍的表格里,我加了個 購買的按鈕用來測試支付功能。
點擊購買按鈕,會發(fā)生一次網絡請求。請求后臺的 OrderController 生成一個訂單,并返
回調用 AliPayController 的調用地址:
@GetMapping("/buy/{bookId}") public Result<?> buy(@PathVariable Long bookId) { Book book = bookMapper.selectById(bookId); String orderNo = IdUtil.getSnowflake().nextIdStr(); String payUrl = "http://localhost:9090/alipay/pay?subject=" + book.getName() + "&traceNo=" + orderNo + "&totalAmount=" + book.getPrice(); User user = getUser(); Order order = new Order(); order.setOrderNo(orderNo); order.setTotalPrice(book.getPrice()); order.setPayPrice(book.getPrice()); order.setTransportPrice(BigDecimal.ZERO); order.setUserId(user.getId()); order.setUsername(user.getUsername()); order.setName(book.getName()); save(order); // 新建訂單,扣減庫存 return Result.success(payUrl); }
前端拿到這個地址,直接在新窗口打開即可出現支付寶的沙箱支付頁面:
buy(bookId) { request.get("/order/buy/" + bookId).then(res => { // 請求成功跳轉沙箱支付的頁面 window.open(res.data) }) },
支付寶沙箱頁面是這樣的:
這里的賬戶和密碼都是模擬的,可以在自己的沙箱賬戶里找到,地址:
https://openhome.alipay.com/platform/appDaily.htm?tab=account
賬戶是虛擬的,可以隨意充值。
如果一不小心出現了下面的這個頁面
別慌!你有 2 個選擇:
打開一個新的瀏覽器,進入系統(tǒng)再次購買即可!關閉所有網頁,清除緩存,重新進入購買頁面,點擊購買。
然后你輸入上面看到的賬戶密碼繼續(xù)就行了:
支付密碼也是 111111 ,點擊確認付款
跳轉到這個頁面,表示支付成功
一定要注意:每次重啟 natapp 都會重新生成新的外網地址,你需要在你的配置文件里面及
時更換,否則,無法回調!
到此這篇關于SpringBoot集成支付寶沙箱支付的實現示例的文章就介紹到這了,更多相關SpringBoot 支付寶沙箱支付內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java報NoClassDefFoundError異常的原因及解決
在 Java 開發(fā)過程中, java.lang.NoClassDefFoundError 是一個令人頭疼的運行時錯誤,本文將深入探討這一問題的原因和常見場景,并提供實用的解決方法,希望對大家有所幫助2025-03-03Java8 使用工廠方法supplyAsync創(chuàng)建CompletableFuture實例
這篇文章主要介紹了Java8 使用工廠方法supplyAsync創(chuàng)建CompletableFuture實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11一文講透為什么遍歷LinkedList要用增強型for循環(huán)
這篇文章主要為大家介紹了為什么遍歷LinkedList要用增強型for循環(huán)的透徹詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04SpringCloud Webflux過濾器增加header傳遞方式
這篇文章主要介紹了SpringCloud Webflux過濾器增加header傳遞方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02