與微信支付對比,支付寶支付就沒有那麼多坑了,畢竟支付寶開放平臺的文檔仍是描述的很詳細的。java
支付寶開放平臺地址:https://docs.open.alipay.com/204/105297/web
支付寶支付的流程以下圖所示:spring
項目中接入支付寶支付的步驟:express
在這裏分爲了三個文件進行整理:json
AlipayConfig.javaapi
此文件中主要是配置了應用ID、支付寶公鑰、應用密鑰等基礎信息,以及支付寶支付API提供的對外接口地址信息。服務器
1 package com.xhgx.web.pay.aliPay; 2 3 import com.erenju.util.GlobleConfig; 4 5 /** 6 * 支付寶支付基礎信息配置 7 * @author rxn 8 * @date 2018/04/25 9 */ 10 public class AlipayConfig { 11 12 /** 13 * 合做身份者ID,簽約帳號,16位純數字 14 */ 15 public static String partner = "2088******"; 16 /** 17 * 收款支付寶帳號,通常狀況下收款帳號是簽約帳號 18 */ 19 public static String seller_id = partner; 20 /** 21 * appid 22 */ 23 public static String app_id = "2018*****";//正式 24 // public static String app_id = "2016*****";//沙箱 25 /** 26 * MD5密鑰,32位字符串 27 */ 28 public static String key = "******"; 29 /** 30 * 支付寶公鑰 (使用工具生成) 31 */ 32 public static String public_key = "";//正式 33 /** 34 * 應用密鑰 (特別長) 35 */ 36 public static String private_key = ""; 37 38 /** 39 * 服務器異步通知頁面路徑,需http://格式的完整路徑,不能加自定義參數,必須外網能夠正常訪問 40 * 異步通知頁面,就是接受支付寶支付結果返回信息的Contrller,能夠處理本身的支付後的邏輯 41 */ 42 public static String notify_url = GlobleConfig.getProperty("PayNotifyUrl")+"/alipay/notify.json"; 43 /** 44 * 服務器同步通知頁面路徑,需http://格式的完整路徑,不能加自定義參數,必須外網能夠正常訪問 45 * 同步通知頁面,就是支付寶支付成功後頁面跳轉的url 46 */ 47 public static String return_url = GlobleConfig.getProperty("PayNotifyUrl")+"/alipay/return.json"; 48 /** 49 * 簽名方式 ,(必須與生成密鑰的簽名方式一致) 50 */ 51 // public static String sign_type = "MD5"; 52 public static String sign_type = "RSA2"; 53 /** 54 * 日誌文件 55 */ 56 public static String log_path = ""; 57 /** 58 * 字符編碼格式 59 */ 60 public static String charset = "utf-8"; 61 /** 62 * 返回格式 63 */ 64 public static String format = "json"; 65 /** 66 * 支付類型 67 */ 68 public static String payment_type = "1"; 69 /** 70 * 支付寶網關(app支付接口) 71 */ 72 public static String AppPayUrl = "https://openapi.alipay.com/gateway.do";//線上 73 // public static String AppPayUrl = "https://openapi.alipaydev.com/gateway.do";//調試 74 }
AliPayUtil.java微信
此文件爲工具類文件,實現了調用支付寶API提供的一些接口,下面的代碼中主要包含了調用支付的接口和統一查詢支付結果的接口。app
1 package com.xhgx.web.pay.aliPay; 2 3 import java.net.URLEncoder; 4 import java.util.HashMap; 5 import java.util.LinkedHashMap; 6 import java.util.Map; 7 import org.activiti.engine.repository.Model; 8 import org.springframework.security.web.header.writers.frameoptions.StaticAllowFromStrategy; 9 import com.alipay.api.AlipayApiException; 10 import com.alipay.api.AlipayClient; 11 import com.alipay.api.DefaultAlipayClient; 12 import com.alipay.api.domain.AlipayTradeAppPayModel; 13 import com.alipay.api.request.AlipayTradeAppPayRequest; 14 import com.alipay.api.response.AlipayTradeAppPayResponse; 15 16 /** 17 * 支付寶支付調用API接口 18 * @author rxn 19 * @date 2018/04/28 20 * 21 */ 22 public class AliPayUtil { 23 24 /** 25 * 建立訂單 26 * @param orderId 訂單id 27 * @param total_amount 付款金額(單位:元) 28 * @return 29 * @throws AlipayApiException 30 */ 31 public static Map<String, Object> createOrder(String orderId,String total_amount) throws AlipayApiException{ 32 33 String orderStr = ""; 34 Map<String,Object> m = new HashMap<String, Object>(); 35 try { 36 //封裝訂單 37 Map<String, String> orderMap = new LinkedHashMap<String,String>(); 38 //公共參數 39 Map<String, String> bizModel = new LinkedHashMap<String,String>(); 40 41 //商品參數封裝 42 orderMap.put("out_trade_no",orderId);//商戶訂單號,必填 43 orderMap.put("subject", "*****");//訂單名稱,必填 44 // orderMap.put("total_amount", total_amount);//付款金額,必填 45 orderMap.put("total_amount", 0.01+"");//付款金額,必填 46 orderMap.put("body", "");//商品描述,選填 47 orderMap.put("timeout_express", "30m");//超時時間,選填 48 orderMap.put("prodect_code", "QUICK_MSECURITY_PAY");//銷售產品碼 49 50 //公共參數封裝 51 bizModel.put("app_id", AlipayConfig.app_id);//appId 52 bizModel.put("method", AlipayConfig.AppPayUrl);//請求網關地址 53 bizModel.put("format", AlipayConfig.format);//返回格式 54 bizModel.put("private_key", AlipayConfig.private_key);//密鑰 55 56 //實例化客戶端,只須要實例化一次便可 57 AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.AppPayUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.charset, AlipayConfig.public_key, AlipayConfig.sign_type); 58 //實例化具體API對應的request類,類名稱和接口名稱對應 59 AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest(); 60 61 //傳入參數,sdk已經封裝了公共參數,這裏只需傳入業務參數。 62 //如下方法是sdk的model入參方式(model和biz_content同時存在的狀況下取biz_content) 63 AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); 64 // model.setPassbackParams(URLEncoder.encode(orderMap.get("body")));//公用回傳參數,選填,UrlEncode以後才能夠發送給支付寶。 65 model.setBody(orderMap.get("body"));//商品信息 66 model.setSubject(orderMap.get("subject"));//商品名稱 67 model.setOutTradeNo(orderMap.get("out_trade_no"));//商品訂單號 68 model.setTimeoutExpress(orderMap.get("timeout_express"));//交易超出時間 69 model.setTotalAmount(orderMap.get("total_amount"));//總金額 70 model.setProductCode(orderMap.get("prodect_code"));//銷售產品碼 71 model.setSellerId(AlipayConfig.seller_id);//支付寶用戶id 72 ali_request.setBizModel(model); 73 ali_request.setNotifyUrl(AlipayConfig.notify_url);//回調地址 74 75 AlipayTradeAppPayResponse response = alipayClient.sdkExecute(ali_request); 76 orderStr = response.getBody(); 77 78 if(response.isSuccess()){ 79 m.put("result", orderStr); 80 m.put("code", 0); 81 m.put("msg", "訂單生成成功"); 82 }else{ 83 m.put("code", 1); 84 m.put("msg", "訂單生成失敗"); 85 } 86 87 } catch (Exception e) { 88 // TODO: handle exception 89 m.put("code", 1); 90 e.printStackTrace(); 91 m.put("msg", "訂單生成失敗"); 92 } 93 94 return m; 95 } 96 /** 97 * 查詢訂單 98 * @param orderId 訂單id 99 * @return 100 * @throws AlipayApiException 101 */ 102 public static Map<String, Object> getOrder(String orderId) throws AlipayApiException{ 103 System.out.println("查詢支付結果"); 104 Map<String,Object> m = new HashMap<String, Object>(); 105 try { 106 //封裝訂單 107 Map<String, String> orderMap = new LinkedHashMap<String,String>(); 108 //商品參數封裝 109 orderMap.put("out_trade_no",orderId);//商戶訂單號,必填 110 111 //實例化客戶端 112 AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.AppPayUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.charset, AlipayConfig.public_key, AlipayConfig.sign_type); 113 //實例化具體API對應的request類,類名稱和接口名稱對應 114 AlipayTradeQueryRequest ali_request = new AlipayTradeQueryRequest(); 115 116 //傳入參數,sdk已經封裝了公共參數,這裏只需傳入業務參數。 117 //如下方法是sdk的model入參方式(model和biz_content同時存在的狀況下取biz_content) 118 AlipayTradeQueryModel model = new AlipayTradeQueryModel(); 119 model.setOutTradeNo(orderMap.get("out_trade_no"));//商品訂單號 120 ali_request.setBizModel(model); 121 ali_request.setNotifyUrl(AlipayConfig.notify_url);//回調地址 122 123 AlipayTradeQueryResponse response = alipayClient.execute(ali_request); 124 System.out.println(response.getCode()+"---"+response.getMsg()); 125 if(response.isSuccess()){ 126 System.out.println(response.getTradeStatus()); 127 switch (response.getTradeStatus()) { 128 case "TRADE_FINISHED"://交易結束並不可退款 129 m.put("status", "OK"); 130 break; 131 case "TRADE_SUCCESS"://交易支付成功 132 m.put("status", "OK"); 133 break; 134 case "TRADE_CLOSED"://未付款交易超時關閉或支付完成後全額退款 135 m.put("status", "ERROR"); 136 break; 137 case "WAIT_BUYER_PAY"://交易建立並等待買家付款 138 m.put("status", "ERROR"); 139 break; 140 default: 141 m.put("status", "ERROR"); 142 break; 143 } 144 145 m.put("code", 0); 146 m.put("msg", "訂單生成成功"); 147 }else{ 148 m.put("code", 1); 149 m.put("msg", "訂單生成失敗"); 150 } 151 152 } catch (Exception e) { 153 m.put("code", 1); 154 e.printStackTrace(); 155 m.put("msg", "訂單生成失敗"); 156 } 157 158 return m; 159 } 160 }
AlipayController.javadom
此文件中主要是對外的異步通知接口,異步通知接口和同步通知接口性質是同樣的,都是爲了接收支付後平臺返回的信息,下面的代碼中只實現了異步通知接口。
1 package com.xhgx.web.pay.aliPay; 2 3 import java.util.Date; 4 import java.util.HashMap; 5 import java.util.Iterator; 6 import java.util.Map; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import org.springframework.stereotype.Controller; 10 import org.springframework.web.bind.annotation.RequestMapping; 11 import org.springframework.web.bind.annotation.ResponseBody; 12 import com.alipay.api.AlipayApiException; 13 import com.alipay.api.internal.util.AlipaySignature; 14 import com.xhgx.service.PayNotifyTblService; 15 import com.xhgx.service.domain.PayNotifyTbl; 16 import com.xhgx.web.SpringContextUtil; 17 import common.Logger; 18 19 @Controller 20 public class AlipayController { 21 22 public static Logger log = Logger.getLogger(AlipayController.class); 23 24 /** 25 * 支付寶支付成功後,異步通知,回調該接口 26 * @param request 27 * @param response 28 * @return 29 */ 30 @ResponseBody 31 @RequestMapping("/alipay/notify.json") 32 public static String notifyUrl(HttpServletRequest request,HttpServletResponse response){ 33 log.info("支付寶支付:"+"異步通知"); 34 Map<String, String> params = new HashMap<String, String>(); 35 36 //1.從支付寶回調的request中取值 37 Map<String, String[]> requestParams = request.getParameterMap(); 38 39 for(Iterator<String> iter = requestParams.keySet().iterator();iter.hasNext();){ 40 String name = iter.next(); 41 String[] values = requestParams.get(name); 42 String valueStr = ""; 43 for(int i=0;i<values.length;i++){ 44 valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; 45 } 46 //亂碼解決 47 // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); 48 params.put(name, valueStr); 49 } 50 51 //2.封裝必須的參數 52 String out_trade_no = request.getParameter("out_trade_no"); 53 String orderType = request.getParameter("body"); 54 String tradeStatus = request.getParameter("trade_status"); 55 String app_id = request.getParameter("app_id"); 56 String trade_no = request.getParameter("trade_no");//支付寶交易號 57 String notify_time = request.getParameter("notify_time");//通知時間 58 String total_amount = request.getParameter("total_amount");//訂單金額,單位元 59 60 //3.簽名驗證(對支付寶返回的數據驗證,肯定是支付寶返回的) 61 boolean signVerified = false; 62 //3.1調用SDK驗證簽名 63 try { 64 signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.public_key, AlipayConfig.charset,AlipayConfig.sign_type); 65 } catch (AlipayApiException e) { 66 // TODO Auto-generated catch block 67 e.printStackTrace(); 68 } 69 70 if(payNotifyTblService==null){ 71 payNotifyTblService= (PayNotifyTblService) SpringContextUtil.getBean(PayNotifyTblService.class); 72 } 73 74 //建立有一個對象,保存通知信息,根據業務需求來決定 75 PayNotifyTbl payNotifyTbl = new PayNotifyTbl(); 76 payNotifyTbl.setPay_type(2);//支付類型:2支付寶 77 payNotifyTbl.setCreate_dt(new Date()); 78 79 payNotifyTbl.setReturn_code(tradeStatus); 80 payNotifyTbl.setResult_code(tradeStatus); 81 82 //4.對驗籤進行處理 83 if(signVerified){ 84 if(tradeStatus.equals("TRADE_SUCCESS")){ 85 86 //支付成功,進行業務處理 87 88 payNotifyTbl.setAppid(app_id); 89 payNotifyTbl.setOrder_id(out_trade_no); 90 payNotifyTbl.setTotal_fee(Double.parseDouble(total_amount)); 91 payNotifyTbl.setTransaction_id(trade_no); 92 payNotifyTbl.setTime_end(notify_time); 93 payNotifyTbl.setPay_result("交易成功"); 94 95 payNotifyTbl = payNotifyTblService.save(payNotifyTbl); 96 97 return "success"; 98 }else{ 99 payNotifyTbl.setPay_result("參數有誤"); 100 payNotifyTbl = payNotifyTblService.save(payNotifyTbl); 101 log.info("參數有誤"); 102 return "fail"; 103 } 104 }else{ 105 payNotifyTbl.setPay_result("交易失敗"); 106 payNotifyTbl = payNotifyTblService.save(payNotifyTbl); 107 log.info("交易失敗"); 108 return "fail"; 109 } 110 }else{ 111 payNotifyTbl.setPay_result("驗籤失敗"); 112 payNotifyTbl = payNotifyTblService.save(payNotifyTbl); 113 log.info("驗籤失敗"); 114 return "fail"; 115 } 116 } 117 118 /** 119 * 支付寶支付成功後,同步通知 120 * @param request 121 * @param response 122 * @return 123 */ 124 @ResponseBody 125 @RequestMapping("/alipay/return.json") 126 public static String returnUrl(HttpServletRequest request,HttpServletResponse response){ 127 log.info("支付寶支付:"+"同步通知"); 128 129 130 131 return null; 132 } 133 }
開發中用到的工具包:https://files.cnblogs.com/files/ning0628/alipay-sdk-JAVA-3.0.0.zip;https://files.cnblogs.com/files/ning0628/alipaytradeapppay.zip