最近在工做中須要使用支付寶app支付,在初次使用過程當中也不可避免的出現了一些問題,那麼本次隨筆主要是概述支付寶app支付服務端的整個實現過程以及就服務端出現的一些問題作一些總結。java
https://open.alipay.com/platform/home.htmweb
首先須要建立一個應用。json
而後須要設置應用公鑰。安全
下載支付寶密鑰生成器。生成成功以後會有商戶應用公鑰和私鑰,將公鑰複製到這裏, 私鑰請妥善保存。下載地址:https://docs.open.alipay.com/291/106097/。保存設置以後會顯示支付寶公鑰,請妥善保存。app
最後提交審覈,等待。異步
注意:若是應用審覈經過上線以後,支付寶公鑰忘記後可經過進入應用詳情頁,按以下圖所示查看支付寶公鑰。maven
首先須要下載SDK,https://docs.open.alipay.com/54/104509。編碼
完成以後,須要切換命令行,進入SDK所在目錄,執行以下命令。若是命令沒法執行,請百度如何配置maven環境變量,配置好以後再執行。加密
mvn install:install-file -DgroupId=com.alipay.sdk -DartifactId=alipay-sdk-java -Dversion=3.1.0 -Dpackaging=jar -Dfile=SDK文件名.jar
groupId:能夠本身定義,pom文件依賴依據與此
artifactId:能夠本身定義,pom文件依賴依據與此
version:能夠本身定義,pom文件依賴依據與此
packaging:打包方式(jar)
file:文件的路徑的路徑
在pom.xml中引入依賴,以下。url
<!-- 支付寶支付相關start --> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>3.1.0</version> </dependency> <!-- 支付寶支付相關end -->
#支付寶支付相關配置
#支付寶分配給開發者的應用Id aliPayAppId=XXX
#賣家支付寶用戶號(對應異步通知返回參數seller_id)(能夠不配置,只是異步通知時爲了進一步校驗而配置) aliPaySellerId=XXX
#賣家支付寶帳號(對應異步通知返回參數seller_email)(能夠不配置,只是異步通知時爲了進一步校驗而配置) alipayAccount=XXX
#商戶應用公鑰 rsaPublicKey=XXX
#商戶應用私鑰(注意,若是是Java語言,須要使用pkcs8格式的私鑰,避免出現不可預知的錯誤) rsaPrivatKey=XXX
#支付寶公鑰 rsaAlipayPublicKey=XXX
#加密方式 signType=XXX
#僅支持JSON alipayFormat=json
#請求使用的編碼格式,如utf-8,gbk,gb2312等 alipayCharset=utf-8
/** *app支付 * *@author lp *@date 2019/1/4 16:32 */ @ApiOperation("app支付") @RequestMapping(value = "alipay", method = RequestMethod.POST) public String alipay(@RequestBody CombinedPaymentDto dto, HttpServletResponse response, HttpServletRequest request) { response.setHeader("Access-Control-Allow-Origin", "*"); // 獲取項目中實際的訂單的信息 // 此處是相關業務代碼 // 獲取配置文件中支付寶相關信息(可使用本身的方式獲取) String aliPayGateway = PropertiesUtils.getInstace("config/webService.properties").getProperty("aliPayGateway"); String aliPayAppId = PropertiesUtils.getInstace("config/webService.properties").getProperty("aliPayAppId"); String rsaPublicKey = PropertiesUtils.getInstace("config/webService.properties").getProperty("rsaPublicKey"); String rsaPrivatKey = PropertiesUtils.getInstace("config/webService.properties").getProperty("rsaPrivatKey"); String rsaAlipayPublicKey = PropertiesUtils.getInstace("config/webService.properties").getProperty("rsaAlipayPublicKey"); String signType = PropertiesUtils.getInstace("config/webService.properties").getProperty("signType"); String alipayFormat = PropertiesUtils.getInstace("config/webService.properties").getProperty("alipayFormat"); String alipayCharset = PropertiesUtils.getInstace("config/webService.properties").getProperty("alipayCharset"); // 開始使用支付寶SDK中提供的API AlipayClient alipayClient = new DefaultAlipayClient(aliPayGateway, aliPayAppId, rsaPrivatKey, alipayFormat, alipayCharset, rsaAlipayPublicKey, signType); // 注意:不一樣接口這裏的請求對象是不一樣的,這個能夠查看螞蟻金服開放平臺的API文檔查看 AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest(); AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); model.setBody("XXX"); model.setSubject("XXX"); // 惟一訂單號 根據項目中實際須要獲取相應的 model.setOutTradeNo(""); // 支付超時時間(根據項目須要填寫) model.setTimeoutExpress("30m"); // 支付金額(項目中實際訂單的須要支付的金額,金額的獲取與操做請放在服務端完成,相對安全) model.setTotalAmount(""); model.setProductCode("QUICK_MSECURITY_PAY"); alipayRequest.setBizModel(model); // 支付成功後支付寶異步通知的接收地址url alipayRequest.setNotifyUrl("XXX/getAlipayNotifyInfo"); // 注意:每一個請求的相應對象不一樣,與請求對象是對應。 AlipayTradeAppPayResponse alipayResponse = null; try { alipayResponse = alipayClient.sdkExecute(alipayRequest); } catch (AlipayApiException e) { e.printStackTrace(); } // 返回支付相關信息(此處能夠直接將getBody中的內容直接返回,無需再作一些其餘操做) return alipayResponse.getBody(); }
/** *接收支付寶異步通知消息 * *@author lp *@date 2019/1/4 17:19 */ @ApiOperation("接收支付寶異步通知消息") @RequestMapping(value = "getAlipayNotifyInfo", method = RequestMethod.POST) public String getAlipayNotifyInfoOfCombinedPayment(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException { response.setHeader("Access-Control-Allow-Origin", "*"); // 解決POST請求中文亂碼問題(推薦使用此種方式解決中文亂碼,由於是支付寶發送異步通知使用的是POST請求) request.setCharacterEncoding("UTF-8"); //獲取支付寶POST過來反饋信息 Map<String,String> params = new HashMap<>(); Map<String,String[]> requestParams = request.getParameterMap(); for (Iterator<String> 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] + ","; } // 官方demo中使用以下方式解決中文亂碼,在此本人不推薦使用,可能會出現中文亂碼解決無效的問題。 // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8"); params.put(name, valueStr); } // 支付寶公鑰(請注意,不是商戶公鑰) String rsaAlipayPublicKey = PropertiesUtils.getInstace("config/webService.properties").getProperty("rsaAlipayPublicKey"); String signType = PropertiesUtils.getInstace("config/webService.properties").getProperty("signType"); String alipayCharset = PropertiesUtils.getInstace("config/webService.properties").getProperty("alipayCharset"); boolean signVerified = false; try { //調用SDK驗證簽名 signVerified = AlipaySignature.rsaCheckV1(params, rsaAlipayPublicKey, alipayCharset, signType); if(signVerified) { // 驗證通知後執行本身項目須要的業務操做 // 通常須要判斷支付狀態是否爲TRADE_SUCCESS // 更嚴謹一些還能夠判斷 1.appid 2.sellerId 3.out_trade_no 4.total_amount 等是否正確,正確以後再進行相關業務操做。 // 成功要返回success,否則支付寶會不斷髮送通知。 return "success"; } // 驗籤失敗 筆者在這裏是輸出log,能夠根據須要作一些其餘操做 // 失敗要返回success,否則支付寶會不斷髮送通知。 return "fail"; } catch (AlipayApiException e) { e.printStackTrace(); // 驗籤異常 筆者在這裏是輸出log,能夠根據須要作一些其餘操做 return "fail"; } }