Springboot?對接支付寶實(shí)現(xiàn)掃碼支付功能
前言
最近項(xiàng)目中需要對接支付模塊,需要考慮到微信支付與支付寶支付的實(shí)現(xiàn)。
由于微信支付的還在審核中,先預(yù)研demo做一個(gè)支付寶支付碼獲取的實(shí)現(xiàn)。
官方文檔以及說明
本次開發(fā)環(huán)境中編寫demo實(shí)現(xiàn),采用的是支付寶的沙箱
方式,后續(xù)上線會重新申請正式的appid等信息。
支付寶開發(fā)平臺鏈接:https://open.alipay.com/
1、申請沙箱
進(jìn)入支付寶的開發(fā)平臺,用支付寶登錄后,在控制臺面板中找到沙箱
,并創(chuàng)建第一個(gè)沙箱。
https://open.alipay.com/develop/manage
2、進(jìn)入沙箱獲取對應(yīng)的關(guān)鍵信息
對于像授權(quán)回調(diào)地址
、應(yīng)用網(wǎng)關(guān)地址
這些暫時(shí)不設(shè)置。
3、拿到系統(tǒng)生成的公鑰和密鑰
這里會有應(yīng)用公鑰
、支付寶公鑰
和應(yīng)用私鑰
。但這里通過個(gè)人實(shí)踐,只需要支付寶公鑰
和應(yīng)用私鑰
。
應(yīng)用公鑰
在某些特定的場景中并不會生效還會出現(xiàn)各種奇怪的報(bào)錯。
注意事項(xiàng)
沙箱
并不是所有的操作都能夠在其中進(jìn)行開發(fā)操作,詳情參考官方文檔說明。
https://opendocs.alipay.com/common/097jyi?pathHash=9fcbe0d0&highlight_field=%E6%B2%99%E7%AE%B1%E7%8E%AF%E5%A2%83
創(chuàng)建springboot項(xiàng)目
1、引入依賴
選用的是springboot 2.x
的版本,并且引用的依賴在官方文檔中有版本說明。
<dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.34.47.ALL</version> </dependency> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-easysdk</artifactId> <version>2.0.0</version> </dependency>
參考官方文檔依賴版本規(guī)定:
https://opendocs.alipay.com/common/02n6z6?pathHash=f5e2a056
其中,針對通用版
的版本要求,官方文檔中有做說明:
https://opendocs.alipay.com/common/02kkv2?pathHash=358ff034
2、配置連接參數(shù)
在src/main/resources
中新建一個(gè)application.yml
文件,如果是nacos項(xiàng)目,可以在對應(yīng)的配置中心中新增配置項(xiàng)。
# 支付寶支付 alipay: # 應(yīng)用ID,標(biāo)識你的應(yīng)用 appId: # 應(yīng)用私鑰,用于簽名請求 appPrivateKey: # 應(yīng)用公鑰,用于驗(yàn)證支付寶的響應(yīng) #alipayPublicKey: 沙箱頁面中的應(yīng)用公鑰 # 支付寶公鑰(推薦使用這個(gè)) alipayPublicKey: 支付寶公鑰 # 支付通知的回調(diào)地址,支付寶會在支付完成后通知這個(gè)地址 notifyUrl: 支付成功后的回調(diào)地址,必須要求公網(wǎng)能夠訪問 # 頁面跳轉(zhuǎn)地址,支付完成后跳轉(zhuǎn)到此URL returnUrl: 場景一中登錄成功后的重定向頁面 # 簽名類型,通常為RSA2 signType: RSA2 # 字符編碼,通常為utf-8 charset: utf-8 # 支付寶網(wǎng)關(guān)地址,用于發(fā)送請求 gatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do
3、創(chuàng)建配置類,用于接收這些參數(shù)
package cn.alipay.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * 支付寶 支付參數(shù)配置類 */ @Data @Component @ConfigurationProperties(prefix = "alipay") public class AlipayProperties { /** * APPID */ private String appId; /** * 應(yīng)用私鑰,就是工具生成的應(yīng)用私鑰 */ public String appPrivateKey; /** * 支付寶公鑰,對應(yīng)APPID下的支付寶公鑰 */ public String alipayPublicKey; /** * 支付寶會悄悄的給我們發(fā)送一個(gè)請求,告訴我們支付成功的信息 */ public String notifyUrl; /** * 同步通知,支付成功,一般跳轉(zhuǎn)到成功頁 */ public String returnUrl; /** * 簽名方式 */ private String signType; /** * 字符編碼格式 */ private String charset; /** * 支付寶網(wǎng)關(guān);https://openapi-sandbox.dl.alipaydev.com/gateway.do */ public String gatewayUrl; /** * 訂單超時(shí)時(shí)間 */ private String timeout = "5m"; }
新建配置類,獲取對應(yīng)的配置參數(shù),并構(gòu)建連接對象
package cn.alipay.config; import com.alibaba.fastjson.JSONObject; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.domain.AlipayTradePagePayModel; import com.alipay.api.domain.AlipayTradePayModel; import com.alipay.api.domain.AlipayTradePrecreateModel; import com.alipay.api.domain.BusinessParams; import com.alipay.api.domain.ExtendParams; import com.alipay.api.domain.GoodsDetail; import com.alipay.api.domain.SettleDetailInfo; import com.alipay.api.domain.SettleInfo; import com.alipay.api.internal.util.WebUtils; import com.alipay.api.request.AlipayTradePagePayRequest; import com.alipay.api.request.AlipayTradePayRequest; import com.alipay.api.request.AlipayTradePrecreateRequest; import com.alipay.api.response.AlipayTradePagePayResponse; import com.alipay.api.response.AlipayTradePayResponse; import com.alipay.api.response.AlipayTradePrecreateResponse; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; /** * 支付寶支付 模板 */ @Slf4j @Data @Component public class AliPayTemplate { @Autowired private AlipayProperties alipayProperties; private AlipayClient alipayClient; @PostConstruct public void init() { log.info("APPID:" + alipayProperties.getAppId()); log.info("應(yīng)用私鑰:" + alipayProperties.getAppPrivateKey()); log.info("支付寶公鑰:" + alipayProperties.getAlipayPublicKey()); log.info("支付寶會悄悄的給我們發(fā)送一個(gè)請求,告訴我們支付成功的信息:" + alipayProperties.getNotifyUrl()); log.info("同步通知,支付成功,一般跳轉(zhuǎn)到成功頁:" + alipayProperties.getReturnUrl()); log.info("簽名方式:" + alipayProperties.getSignType()); log.info("字符編碼格式:" + alipayProperties.getCharset()); log.info("訂單超時(shí)時(shí)間:" + alipayProperties.getTimeout()); log.info("支付寶網(wǎng)關(guān):" + alipayProperties.getGatewayUrl()); // 1. 根據(jù)支付寶的配置生成一個(gè)支付客戶端 alipayClient = new DefaultAlipayClient( alipayProperties.getGatewayUrl(), alipayProperties.getAppId(), alipayProperties.getAppPrivateKey(), "json", alipayProperties.getCharset(), alipayProperties.getAlipayPublicKey(), alipayProperties.getSignType() ); } }
4、中間類的定義(訂單類)
創(chuàng)建一個(gè)訂單類,主要用于一些基本信息的傳參處理。
package cn.alipay.config; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * 訂單表 */ @Data public class Order implements Serializable { /** * 訂單Id */ private Long id; /** * 用戶Id */ private Long userId; /** * 接口Id */ private Long interfaceInfoId; /** * 支付金額 */ private Double money; /** * 支付方式 */ private String paymentMethod; /** * 0 - 未支付 1 - 已支付 */ private Integer status; /** * 創(chuàng)建時(shí)間 */ private Date createTime; /** * 更新時(shí)間 */ private Date updateTime; /** * 是否刪除 */ private Integer isDelete; private static final long serialVersionUID = 1L; }
5、編寫測試接口
場景一、pc端請求后端后,生成支付寶的特制頁面(AlipayTradePagePayRequest)
在支付寶的PC端案例文檔
中,有一個(gè)注意事項(xiàng)。
https://opendocs.alipay.com/open/00dn7o?pathHash=c1e36251
像這種傳遞訂單信息至后臺,后臺調(diào)用支付寶的對應(yīng)接口后,返回前端頁面樣式或者地址,前端再進(jìn)行渲染實(shí)現(xiàn)。可以參照以下的方式。
定義接口
package cn.alipay.controller; import cn.alipay.config.AliPayTemplate; import cn.alipay.config.Order; import com.alipay.api.AlipayApiException; import com.alipay.easysdk.factory.Factory; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.MimeTypeUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; /** * 阿里支付寶支付與回調(diào)接口 */ @Slf4j @RestController @RequestMapping("/alipay") public class AliPayController { @Autowired private AliPayTemplate aliPayTemplate; /** * 獲取支付寶 * post 請求 生成 frame 頁面 * get 請求生成 頁面url * @param id * @return * @throws AlipayApiException */ @GetMapping(value = "/pay", produces = MimeTypeUtils.TEXT_HTML_VALUE) @ResponseBody public String pay(@RequestParam long id) throws AlipayApiException { // 創(chuàng)建訂單對象并設(shè)置屬性 Order order = createOrder(id); // 調(diào)用支付寶支付模板進(jìn)行支付 return aliPayTemplate.pay(order); } /** * 偽造訂單數(shù)據(jù) * @param id * @return */ private Order createOrder(long id) { Order order = new Order(); order.setId(id); order.setUserId(1111111L); order.setInterfaceInfoId(294389472934L); order.setMoney(1000.0); order.setPaymentMethod("支付寶"); return order; } }
定義請求邏輯代碼
package cn.alipay.config; import com.alibaba.fastjson.JSONObject; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.domain.AlipayTradePagePayModel; import com.alipay.api.domain.AlipayTradePayModel; import com.alipay.api.domain.AlipayTradePrecreateModel; import com.alipay.api.domain.BusinessParams; import com.alipay.api.domain.ExtendParams; import com.alipay.api.domain.GoodsDetail; import com.alipay.api.domain.SettleDetailInfo; import com.alipay.api.domain.SettleInfo; import com.alipay.api.internal.util.WebUtils; import com.alipay.api.request.AlipayTradePagePayRequest; import com.alipay.api.request.AlipayTradePayRequest; import com.alipay.api.request.AlipayTradePrecreateRequest; import com.alipay.api.response.AlipayTradePagePayResponse; import com.alipay.api.response.AlipayTradePayResponse; import com.alipay.api.response.AlipayTradePrecreateResponse; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; /** * 支付寶支付 模板 */ @Slf4j @Data @Component public class AliPayTemplate { @Autowired private AlipayProperties alipayProperties; private AlipayClient alipayClient; @PostConstruct public void init() { log.info("APPID:" + alipayProperties.getAppId()); log.info("應(yīng)用私鑰:" + alipayProperties.getAppPrivateKey()); log.info("支付寶公鑰:" + alipayProperties.getAlipayPublicKey()); log.info("支付寶會悄悄的給我們發(fā)送一個(gè)請求,告訴我們支付成功的信息:" + alipayProperties.getNotifyUrl()); log.info("同步通知,支付成功,一般跳轉(zhuǎn)到成功頁:" + alipayProperties.getReturnUrl()); log.info("簽名方式:" + alipayProperties.getSignType()); log.info("字符編碼格式:" + alipayProperties.getCharset()); log.info("訂單超時(shí)時(shí)間:" + alipayProperties.getTimeout()); log.info("支付寶網(wǎng)關(guān):" + alipayProperties.getGatewayUrl()); // 1. 根據(jù)支付寶的配置生成一個(gè)支付客戶端 alipayClient = new DefaultAlipayClient( alipayProperties.getGatewayUrl(), alipayProperties.getAppId(), alipayProperties.getAppPrivateKey(), "json", alipayProperties.getCharset(), alipayProperties.getAlipayPublicKey(), alipayProperties.getSignType() ); } /** * 調(diào)用支付接口 * @param order * @return * @throws AlipayApiException */ public String pay(Order order) throws AlipayApiException { //2、創(chuàng)建一個(gè)支付請求,并設(shè)置請求參數(shù) AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); alipayRequest.setReturnUrl(alipayProperties.getReturnUrl()); alipayRequest.setNotifyUrl(alipayProperties.getNotifyUrl()); Long id = order.getId(); Long interfaceInfoId = order.getInterfaceInfoId(); Double money = order.getMoney(); String paymentMethod = order.getPaymentMethod(); // 設(shè)置業(yè)務(wù)內(nèi)容,包含必要的支付參數(shù) AlipayTradePagePayModel pagePayModel = new AlipayTradePagePayModel(); pagePayModel.setOutTradeNo(String.valueOf(id)); pagePayModel.setTotalAmount(String.valueOf(money)); pagePayModel.setSubject(String.valueOf(interfaceInfoId)); pagePayModel.setBody(paymentMethod); pagePayModel.setTimeoutExpress(alipayProperties.getTimeout()); // 電腦支付場景下僅支持FAST_INSTANT_TRADE_PAY pagePayModel.setProductCode("FAST_INSTANT_TRADE_PAY"); alipayRequest.setBizModel(pagePayModel); // post 請求返回 frame 前端樣式 AlipayTradePagePayResponse response = alipayClient.pageExecute(alipayRequest, "POST"); // get 請求返回一個(gè)頁面地址url AlipayTradePagePayResponse response2 = alipayClient.pageExecute(alipayRequest, "GET"); String result = response.getBody(); //返回支付寶響應(yīng)的結(jié)果 return result; } }
啟動服務(wù),請求后的效果如下:
localhost:8080/alipay/pay?id=123456
post 請求生成的樣式如下所示:
<form name="punchout_form" method="post" action="會有對應(yīng)的信息"> <input type="hidden" name="biz_content" value="{"body":"支付寶","out_trade_no":"125477","product_code":"FAST_INSTANT_TRADE_PAY","subject":"294389472934","timeout_express":"5m","total_amount":"1000.0"}"> <input type="submit" value="立即支付" style="display:none" > </form> <script>document.forms[0].submit();</script>
如果是GET
請求,則只會是上面action
的地址。
場景二、前端請求后端,只返回對應(yīng)的二維碼地址(AlipayTradePrecreateRequest)
參照官方文檔中的案例實(shí)現(xiàn)
https://opendocs.alipay.com/open/8ad49e4a_alipay.trade.precreate?scene=2ae8516856f24a5592194d237f3f235d&pathHash=d18bff53
編寫對應(yīng)的接口和實(shí)現(xiàn)類
@GetMapping(value = "/pay3") @ResponseBody public String pay3(@RequestParam long id) throws AlipayApiException { // 創(chuàng)建訂單對象并設(shè)置屬性 Order order = createOrder(id); // 調(diào)用支付寶支付模板進(jìn)行支付 return aliPayTemplate.pay3(order); }
package cn.alipay.config; import com.alibaba.fastjson.JSONObject; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.domain.AlipayTradePagePayModel; import com.alipay.api.domain.AlipayTradePayModel; import com.alipay.api.domain.AlipayTradePrecreateModel; import com.alipay.api.domain.BusinessParams; import com.alipay.api.domain.ExtendParams; import com.alipay.api.domain.GoodsDetail; import com.alipay.api.domain.SettleDetailInfo; import com.alipay.api.domain.SettleInfo; import com.alipay.api.internal.util.WebUtils; import com.alipay.api.request.AlipayTradePagePayRequest; import com.alipay.api.request.AlipayTradePayRequest; import com.alipay.api.request.AlipayTradePrecreateRequest; import com.alipay.api.response.AlipayTradePagePayResponse; import com.alipay.api.response.AlipayTradePayResponse; import com.alipay.api.response.AlipayTradePrecreateResponse; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; /** * 支付寶支付 模板 */ @Slf4j @Data @Component public class AliPayTemplate { @Autowired private AlipayProperties alipayProperties; private AlipayClient alipayClient; @PostConstruct public void init() { log.info("APPID:" + alipayProperties.getAppId()); log.info("應(yīng)用私鑰:" + alipayProperties.getAppPrivateKey()); log.info("支付寶公鑰:" + alipayProperties.getAlipayPublicKey()); log.info("支付寶會悄悄的給我們發(fā)送一個(gè)請求,告訴我們支付成功的信息:" + alipayProperties.getNotifyUrl()); log.info("同步通知,支付成功,一般跳轉(zhuǎn)到成功頁:" + alipayProperties.getReturnUrl()); log.info("簽名方式:" + alipayProperties.getSignType()); log.info("字符編碼格式:" + alipayProperties.getCharset()); log.info("訂單超時(shí)時(shí)間:" + alipayProperties.getTimeout()); log.info("支付寶網(wǎng)關(guān):" + alipayProperties.getGatewayUrl()); // 1. 根據(jù)支付寶的配置生成一個(gè)支付客戶端 alipayClient = new DefaultAlipayClient( alipayProperties.getGatewayUrl(), alipayProperties.getAppId(), alipayProperties.getAppPrivateKey(), "json", alipayProperties.getCharset(), alipayProperties.getAlipayPublicKey(), alipayProperties.getSignType() ); } public String pay3(Order order) throws AlipayApiException { AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest(); // 強(qiáng)制關(guān)閉 ssl 證書校驗(yàn) WebUtils.setNeedCheckServerTrusted(false); alipayRequest.setNotifyUrl(alipayProperties.getNotifyUrl()); JSONObject jsonObject = new JSONObject(); jsonObject.put("out_trade_no",order.getId());// 商戶訂單號 jsonObject.put("total_amount",order.getMoney());// 商品價(jià)格 jsonObject.put("subject","這只是個(gè)商品標(biāo)題");// 商品標(biāo)題 jsonObject.put("store_id","香蕉集團(tuán)");//組織或公司名 // jsonObject.put("timeout_express","5m");// 訂單有效時(shí)間 alipayRequest.setBizContent(jsonObject.toString()); AlipayTradePrecreateResponse response = alipayClient.execute(alipayRequest); System.out.println("創(chuàng)建訂單結(jié)果:"+response.getBody()); System.out.println("訂單編號是"+response.getOutTradeNo()); String qrCode = response.getQrCode(); // AlipayTradePrecreateModel model = new AlipayTradePrecreateModel(); return qrCode; } }
請求后會得到一個(gè)支付的地址,使用ZXing
框架,將其轉(zhuǎn)換為二維碼。
場景三、沙箱APP掃碼支付后回調(diào)處理
在每次請求AliPay
的接口時(shí),都會傳遞一個(gè)回調(diào)接口
參數(shù)。
alipayRequest.setNotifyUrl(alipayProperties.getNotifyUrl());
這個(gè)參數(shù)主要是用于告知AliPay
在支付操作中,各項(xiàng)信息的回調(diào)信息,是個(gè)異步的操作。
針對回調(diào),判斷是否是支付成功,可以參照如下邏輯:
/** * 支付寶 支付 異步回調(diào)接口 必須是 Post * @param request * @return * @throws Exception */ @PostMapping("/notify") public String payNotify(HttpServletRequest request) throws Exception { // 檢查交易狀態(tài)是否為成功 if (!"TRADE_SUCCESS".equalsIgnoreCase(request.getParameter("trade_status"))) { // 如果狀態(tài)不是成功,則返回失敗 return "failure"; } log.info("=========支付寶異步回調(diào)========"); // .... 此處省略部分業(yè)務(wù)邏輯 aliPayServide.payNotify(request); return "success"; }
業(yè)務(wù)層中的代碼片段如下:
public void payNotify(HttpServletRequest request) throws AlipayApiException { // 創(chuàng)建一個(gè)存儲請求參數(shù)的Map Map<String, String> params = getRequestParams(request); String tradeNo = params.get("out_trade_no"); // 驗(yàn)證支付寶返回的簽名 if (!verifySignature(params)) { log.info("----驗(yàn)簽失敗----"); return; } // 記錄交易詳情 logTransactionDetails(params); // 其他業(yè)務(wù)邏輯 } /** * 記錄交易詳情的方法 * @param params */ private void logTransactionDetails(Map<String, String> params) { log.info("交易名稱: " + params.get("subject")); log.info("交易狀態(tài): " + params.get("trade_status")); log.info("支付寶交易憑證號: " + params.get("trade_no")); log.info("商戶訂單號: " + params.get("out_trade_no")); log.info("交易金額: " + params.get("total_amount")); log.info("買家在支付寶唯一id: " + params.get("buyer_id")); log.info("買家付款時(shí)間: " + params.get("gmt_payment")); log.info("買家付款金額: " + params.get("buyer_pay_amount")); // 記錄日志 ChatAliPayDetailLog chatAliPayDetailLog = ChatAliPayDetailLog.builder() .id(IdUtil.getSnowflakeNextIdStr()) .subject(params.get("subject")) .tradeStatus(params.get("trade_status")) .tradeNo(params.get("trade_no")) .outTradeNo(params.get("out_trade_no")) .totalAmount(new BigDecimal(params.get("total_amount"))) .buyerId(params.get("buyer_id")) .gmtPayment(DateUtil.parseDate(params.get("gmt_payment"))) .buyerPayAmount(new BigDecimal(params.get("buyer_pay_amount"))) .createdTime(new Date()) .build(); chatAliPayDetailLogMapper.insert(chatAliPayDetailLog); } /** * 驗(yàn)證簽名 * @param params * @return */ private boolean verifySignature(Map<String, String> params) throws AlipayApiException { String sign = params.get("sign"); String content = AlipaySignature.getSignCheckContentV1(params); return AlipaySignature.rsa256CheckContent(content, sign, alipayProperties.getAlipayPublicKey(), "UTF-8"); } /** * 提取請求參數(shù)的方法 * @param request * @return */ private Map<String, String> getRequestParams(HttpServletRequest request) { Map<String, String> params = new HashMap<>(); Map<String, String[]> requestParams = request.getParameterMap(); for (String name : requestParams.keySet()) { params.put(name, request.getParameter(name)); } return params; }
但回調(diào)處理是一個(gè)異步
,如果前端界面中需要實(shí)時(shí)獲取支付成功狀態(tài),可以使用輪訓(xùn)
的方式,定時(shí)去查詢支付結(jié)果。
場景四、定時(shí)查詢支付結(jié)果
在官方文檔中,其中提供有一個(gè)alipay.trade.query(統(tǒng)一收單交易查詢)
,專門提供查詢操作。
https://opendocs.alipay.com/open/217dd591_alipay.trade.query?scene=common&pathHash=62ae74aa
代碼片段如下所示:
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); AlipayTradeQueryModel model = new AlipayTradeQueryModel(); model.setOutTradeNo(chatUserPayOrder.getOrderNo()); request.setBizModel(model); try { AlipayTradeQueryResponse response = alipayClient.execute(request); if ("TRADE_SUCCESS".equalsIgnoreCase(response.getTradeStatus())) { // 成功支付 則進(jìn)行后續(xù)處理 insertLog(response); // 根據(jù) response.getOutTradeNo() 修改對應(yīng)的支付信息 updatePayOrderStatus(response); } } catch (AlipayApiException e) { throw new RuntimeException(e); }
也可以考慮定時(shí)任務(wù)xxl-job
定時(shí)去獲取所有未收到支付狀態(tài)的數(shù)據(jù),請求獲取最終結(jié)果?;蛘叱^限定時(shí)間表示失效等邏輯。
到此這篇關(guān)于Springboot 對接支付寶實(shí)現(xiàn)掃碼支付的文章就介紹到這了,更多相關(guān)Springboot 掃碼支付內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
FeignClient實(shí)現(xiàn)接口調(diào)用方式(不同參數(shù)形式)
這篇文章主要介紹了FeignClient實(shí)現(xiàn)接口調(diào)用方式(不同參數(shù)形式),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03SpringBoot生產(chǎn)環(huán)境和測試環(huán)境配置分離的教程詳解
這篇文章主要介紹了SpringBoot生產(chǎn)環(huán)境和測試環(huán)境配置分離的教程詳解,需要的朋友可以參考下2020-08-08java lambda循環(huán)_使用Java 8 Lambda簡化嵌套循環(huán)操作
這篇文章主要介紹了java lambda循環(huán)_使用Java 8 Lambda簡化嵌套循環(huán)操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09mybatis3.4.6 批量更新 foreach 遍歷map 的正確姿勢詳解
這篇文章主要介紹了mybatis3.4.6 批量更新 foreach 遍歷map 的正確姿勢詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11使用FeignClient進(jìn)行微服務(wù)交互方式(微服務(wù)接口互相調(diào)用)
這篇文章主要介紹了使用FeignClient進(jìn)行微服務(wù)交互方式(微服務(wù)接口互相調(diào)用),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03Java?I/O?(Input/Output)文件字節(jié)流舉例詳解
Java的輸入輸出流(IO)是用于與外部設(shè)備(如文件、網(wǎng)絡(luò)連接等)進(jìn)行數(shù)據(jù)交互的機(jī)制,下面這篇文章主要給大家介紹了關(guān)于Java?I/O?(Input/Output)文件字節(jié)流的相關(guān)資料,需要的朋友可以參考下2024-08-08