項目結構 :

下單核心代碼:
package com.alipay.pay.controller; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.internal.util.AlipaySignature; import com.alipay.api.request.AlipayTradePagePayRequest; import com.alipay.api.response.AlipayTradePagePayResponse; import com.alipay.demo.trade.model.builder.AlipayTradeQueryRequestBuilder; import com.alipay.demo.trade.model.result.AlipayF2FQueryResult; import com.alipay.demo.trade.service.AlipayTradeService; import com.alipay.pay.config.AlipayConfig; import com.alipay.pay.model.Order; /** * 支付寶-電腦網站支付. * 注意 下單頁面可以加一個ajax輪詢進行 訂單查詢避免長時間等待 * <p> * 電腦網站支付 https://docs.open.alipay.com/270/105898/ * * @author zhourong * @version 1.0 * @since 2018/12/27 */ @Controller @RequestMapping("/alipay/page") public class PayController { @Autowired private AlipayConfig alipayConfig;//支付寶查詢接口初始化 @Autowired private AlipayClient alipayClient;//初始化 相關配置 @Autowired private AlipayTradeService tradeService; private final Logger log = LoggerFactory.getLogger(PayController.class); @GetMapping("/gotoPayPage") public void gotoPayPage(HttpServletResponse response,Order order) throws AlipayApiException, IOException { //下單 插入數據庫 //一系列業務判斷 //insert into order ...... //正常業務流程會把 支付接口抽出來 // 設置請求參數 AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); // 同步通知地址:支付成功后頁面自動跳轉到傳值地址中 alipayRequest.setReturnUrl("http://zhouixi.free.idcfengye.com/alipay/page/returnUrl"); // 異步通知地址:支付成功生成之后會post返回訂單信息詳情到該地址,用於商家做業務邏輯處理 alipayRequest.setNotifyUrl("http://zhouixi.free.idcfengye.com/alipay/page/NotifyUrl"); // 商戶訂單號,商戶網站訂單系統中唯一訂單號,必填 String out_trade_no = order.getOutTradeNo(); // 付款金額,必填 String total_amount = order.getTotalAmount(); // 訂單名稱,必填 String subject = order.getSubject(); // 商品描述,可空 String body = "用戶訂購商品個數:1"; // 該筆訂單允許的最晚付款時間,逾期將關閉交易。取值范圍:1m~15d。m-分鍾,h-小時,d-天,1c-當天(1c-當天的情況下,無論交易何時創建,都在0點關閉)。 // 該參數數值不接受小數點, 如 1.5h,可轉換為 90m。 String timeout_express = "5m"; alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\"," + "\"total_amount\":\"" + total_amount + "\"," + "\"subject\":\"" + subject + "\"," + "\"body\":\"" + body + "\"," + "\"timeout_express\":\"" + timeout_express + "\"," + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); /** * BizContent傳值模式 alipayRequest.setBizContent("{\"out_trade_no\":\""+ * out_trade_no +"\"," + "\"total_amount\":\""+ total_amount +"\"," + * "\"subject\":\""+ subject +"\"," + "\"qr_pay_mode\":\"4\"," + * "\"timeout_express\":\"1m\"," + "\"passback_params2\":\""+ passback_params2 * +"\"," + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); * **/ // get請求方式,返回http鏈接 // AlipayTradePagePayResponse respose = alipayClient.pageExecute(alipayRequest, // "get"); // post請求方式,返回from表單 AlipayTradePagePayResponse aliResponse = alipayClient.pageExecute(alipayRequest); // 打印請求信息 String html = aliResponse.getBody(); response.setContentType("text/html;charset=" + alipayConfig.getCharset()); response.getWriter().write(html); response.getWriter().flush(); response.getWriter().close(); } @RequestMapping("/returnUrl") public String returnUrl(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException, AlipayApiException { response.setContentType("text/html;charset=" + "utf-8"); boolean verifyResult = this.checkParam(request); if (verifyResult) { // 驗證成功 //添加自己的業務。。。進行業務核對 // 商戶訂單號 String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8"); // 支付寶交易號 String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8"); // (必填) 商戶訂單號,通過此商戶訂單號查詢當面付的交易狀態 AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder() .setOutTradeNo(out_trade_no); AlipayF2FQueryResult result = tradeService.queryTradeResult(builder); System.out.println(result.getTradeStatus()); return "success"; } else { return "fail"; } } @RequestMapping("/notifyUrl") public String NotifyUrl(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException, AlipayApiException { response.setContentType("text/html;charset=" + "utf-8"); boolean verifyResult = this.checkParam(request); if (verifyResult) { // 驗證成功 //添加自己的業務。。。進行業務核對 // 商戶訂單號 String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8"); // 支付寶交易號 String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8"); // (必填) 商戶訂單號,通過此商戶訂單號查詢當面付的交易狀態 AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder() .setOutTradeNo(out_trade_no); AlipayF2FQueryResult result = tradeService.queryTradeResult(builder); System.out.println(result.getTradeStatus()); return "success"; } else { return "fail"; } } /** * 校驗簽名 * * @param request * @return */ private boolean checkParam(HttpServletRequest request) { // https://docs.open.alipay.com/54/106370 官方文檔 // 獲取支付寶POST過來反饋信息 Map<String, String> 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] + ","; } params.put(name, valueStr); } try { boolean verifyResult = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType()); return verifyResult; } catch (AlipayApiException e) { log.debug("verify sigin error, exception is:{}", e); return false; } } }
效果:


支付只能用支付寶提供的沙箱帳號及沙箱app
不然會提示二維碼過期。
問題總結:
1.AlipayTradeServiceImpl gatewayUrl should not be NULL!
支付寶查詢接口 AlipayTradeServiceImpl 沒有初始化
2.驗簽失敗 :返回false
使用支付寶公鑰沙箱應用里面的公鑰,不能使用工具生成的公鑰
3.支付過程中,一直要做訂單號重復過濾。不然。支付寶生成不了二維碼頁面。
4.支付過程中,支付接口有自動過濾重復支付。盡量把業務處理在自己的接口里面。避免重復支付。
5.支付寶回調接口一定要是外網可以直接訪問的。支付成功之后。支付寶會自動回接回調接口推送相關信息過來 。可以做一些業務處理。比如說:支付訂單的檢驗,自己系統的業務檢驗。入庫等
