1、配置java
用戶註冊web
首先用公司相關信息在螞蟻金服開放平臺註冊一個支付寶帳戶(https://openhome.alipay.com/platform/home.htm) spring
而後在進入開放平臺後進入開發者中心>網頁&移動應用接入中express
接着和支付寶簽約,接入支付功能(手機網站支付)apache
配置和獲取相關開發信息json
進入申請的支付功能頁面,配置受權回調地址和密鑰api
ok,如今咱們獲取了APPID、支付寶網關、受權回調地址、商戶私鑰、應用公鑰、支付寶公鑰等相關信息,開發時我將會把他們寫到配置文件中瀏覽器
另外,咱們還須要一個支付寶的SDK,請你們自行下載安全
到此,所需的所有準備工做完成,你們能夠愉快的開發了微信
2、開發
支付邏輯
公共請求參數
與支付無關的業務邏輯
這部分代碼已經在上篇文章微信支付中貼出,這裏就再也不從新貼一遍了
package com.andata.conf; /* * *類名:AlipayConfig *功能:基礎配置類 *詳細:設置賬戶有關信息及返回路徑 *提示:如何獲取安全校驗碼和合做身份者ID *1.用您的簽約支付寶帳號登陸支付寶網站(www.alipay.com) *2.點擊「商家服務」(https://b.alipay.com/order/myOrder.htm) *3.點擊「查詢合做者身份(PID)」、「查詢安全校驗碼(Key)」 *安全校驗碼查看時,輸入支付密碼後,頁面呈灰色的現象,怎麼辦? *解決方法: *一、檢查瀏覽器配置,不讓瀏覽器作彈框屏蔽設置 *二、更換瀏覽器或電腦,從新登陸查詢。 */ public class AlipayConfig { //ServiceURL public static String ServiceUrl="https://openapi.alipay.com/gateway.do"; //APP支付寶支付業務:app_id public static String app_id = "20180xxxxxxxxxxxxxx"; // 商戶的私鑰,使用支付寶自帶的openssl工具生成。 public static String private_key = "xxxxxxxxxxxxxxxxxxx"; // 應用的公鑰,無需修改該值 public static String ali_public_key = "xxxxxxxxxxxxxxxxxxxxx"; // 支付寶的公鑰,去open.alipay.com對應應用下查看。 public static String zfb_public_key = "xxxxxxxxxxxxxxxxxxxxx"; // 字符編碼格式 目前支持 gbk 或 utf-8 public static String input_charset = "UTF-8"; }
package com.andata.controller; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.internal.util.AlipaySignature; import com.alipay.api.request.AlipayTradeCancelRequest; import com.alipay.api.request.AlipayTradePrecreateRequest; import com.alipay.api.request.AlipayTradeQueryRequest; import com.alipay.api.response.AlipayTradeCancelResponse; import com.alipay.api.response.AlipayTradePrecreateResponse; import com.alipay.api.response.AlipayTradeQueryResponse; import com.andata.conf.AlipayConfig; import com.andata.pojo.ProductOrders; import com.andata.service.ProOrdersService; import com.andata.util.QRCodeUtil; import net.sf.json.JSONObject; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @Controller public class AliPayController { @Resource private ProOrdersService proOrdersService; /** * 支付邏輯 * 一、商戶系統調用支付寶預下單接口alipay.trade.precreate,得到該訂單二維碼圖片地址。 * 二、發起輪詢得到支付結果:等待5秒後調用交易查詢接口alipay.trade.query經過支付時傳入的商戶訂單號(out_trade_no)查詢支付結果(返回參數TRADE_STATUS), 若是仍然返回等待用戶付款(WAIT_BUYER_PAY),則再次等待5秒後繼續查詢,直到返回確切的支付結果(成功TRADE_SUCCESS 或 已撤銷關閉TRADE_CLOSED), 或是超出輪詢時間。在最後一次查詢仍然返回等待用戶付款的狀況下,必須當即調用交易撤銷接口alipay.trade.cancel將這筆交易撤銷,避免用戶繼續支付。 * 三、除了主動輪詢,也能夠經過接受異步通知得到支付結果 */ /** * 阿里訂單取消接口 * 請求返回值示例: * {"alipay_trade_cancel_response":{"code":"40004","msg":"Business Failed","sub_code":"ACQ.INVALID_PARAMETER","sub_msg":"參數無效","out_trade_no":"20150320010101002", * "retry_flag":"N"},"sign":""} * @return * @throws AlipayApiException */ @RequestMapping(value = "aliremove.do") @ResponseBody private Map<String, Object> remove(@Param("orderid")String orderid) throws AlipayApiException { AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //得到初始化的AlipayClient AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();//建立API對應的request類 Map<String,Object> returnmap=new HashMap<>(); try { //判斷訂單是否完成支付,完成支付的訂單禁止撤銷 int i = this.proOrdersService.selectOrderStatus(orderid); if (i==1) { returnmap.put("type","0"); returnmap.put("data","訂單已支付,撤銷訂單失敗"); }else { Map<String,Object> map=new HashMap<>(); map.put("out_trade_no",orderid); String returndata = JSONObject.fromObject(map).toString(); request.setBizContent(returndata); //設置業務參數 AlipayTradeCancelResponse response = alipayClient.execute(request);//經過alipayClient調用API,得到對應的response類 JSONObject query_response = JSONObject.fromObject(response.getBody()).getJSONObject("alipay_trade_cancel_response"); String code = query_response.getString("code"); String msg = query_response.getString("msg"); if (code.equals("10000") && msg.equals("Success")) { System.out.println("阿里訂單取消接口調用成功!"); returnmap.put("type","1"); returnmap.put("data","撤銷訂單成功"); }else { System.out.println("撤銷訂單請求失敗"); returnmap.put("type","0"); returnmap.put("data",query_response.getString("sub_msg")); System.out.println(query_response);//返回失敗信息 } //根據response中的結果繼續業務邏輯處理 } }catch (Exception e) { System.out.println("撤銷訂單異常"); e.printStackTrace(); } return returnmap; } /** * 阿里交易查詢接口 * out_trade_no 支付時傳入的商戶訂單號,與trade_no必填一個 * trade_no 支付時返回的支付寶交易號,與out_trade_no必填一個 * 請求返回值示例: * {"alipay_trade_query_response":{"code":"10000","msg":"Success","buyer_logon_id":"159****4027","buyer_pay_amount":"0.01","buyer_user_id":"2088012351746164", * "fund_bill_list":[{"amount":"0.01","fund_channel":"PCREDIT"}],"invoice_amount":"0.01","out_trade_no":"020910312752381","point_amount":"0.00","receipt_amount":"0.01", * "send_pay_date":"2018-02-09 10:31:45","total_amount":"0.01","trade_no":"2018020921001004160275738069","trade_status":"TRADE_SUCCESS"}, * "sign":""} * @return * @throws Exception */ @RequestMapping(value="/aliget") @ResponseBody private Map<String, Object> get(@Param("orderid")String orderid) throws AlipayApiException{ AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //得到初始化的AlipayClient AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();//建立API對應的request類 Map<String,Object> map=new HashMap<>(); map.put("out_trade_no",orderid); String returndata = JSONObject.fromObject(map).toString(); request.setBizContent(returndata); //設置業務參數 AlipayTradeQueryResponse response = alipayClient.execute(request);//經過alipayClient調用API,得到對應的response類 JSONObject jsonObject = JSONObject.fromObject(response.getBody()).getJSONObject("alipay_trade_query_response"); String code = jsonObject.getString("code"); String msg = jsonObject.getString("msg"); Map<String,Object> returnmap=new HashMap<>(); if (code.equals("10000") && msg.equals("Success")) { System.out.println("交易查詢請求成功"); String trade_status = jsonObject.getString("trade_status"); if (trade_status.equals("TRADE_SUCCESS")) { returnmap.put("type","1"); returnmap.put("data","支付成功"); }else { returnmap.put("type","0"); returnmap.put("data",trade_status); } }else { System.out.println("交易查詢請求失敗"); returnmap.put("type","0"); returnmap.put("data",jsonObject.getString("sub_msg")); System.out.println(jsonObject);//返回失敗信息 } return returnmap; } /** * @name 預下單請求,阿里獲取二維碼接口 * @throws AlipayApiException * @Param out_trade_no 商戶訂單號,64個字符之內、只能包含字母、數字、下劃線;需保證在商戶端不重複 * @Param total_amount 訂單總金額,單位爲元,精確到小數點後兩位,取值範圍[0.01,100000000] 若是同時傳入了【打折金額】,【不可打折金額】, * 【訂單總金額】三者,則必須知足以下條件:【訂單總金額】=【打折金額】+【不可打折金額】 * @Param subject 訂單標題 * @Param store_id 商戶門店編號 * @Param timeout_express 該筆訂單容許的最晚付款時間,逾期將關閉交易。 * 取值範圍:1m~15d。m-分鐘,h-小時,d-天,1c-當天(1c-當天的狀況下,不管交易什麼時候建立,都在0點關閉)。 該參數數值不接受小數點, 如 1.5h,可轉換爲 90m。 */ @RequestMapping(value="/alipay.do") @ResponseBody private Map list(HttpServletResponse responses, @Param("orderid")String orderid) throws AlipayApiException{ AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //得到初始化的AlipayClient AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();//建立API對應的request類 Map<String,Object> map=new HashMap<>(); if (orderid.isEmpty()) { map.put("type","2"); map.put("data","訂單號不能爲空"); return map; } //設置回調地址 request.setNotifyUrl("http://www.andata.com.cn/aliPayCallBack.do"); //根據訂單號查詢訂單信息 ProductOrders productOrders = this.proOrdersService.selectByOrderId(orderid); Map<String,Object> maps=new HashMap<>(); maps.put("out_trade_no",productOrders.getOrdernumber()); maps.put("total_amount","0.01"); maps.put("subject","小編機器人糾錯"); maps.put("store_id","XB001"); maps.put("timeout_express","1m"); //把訂單信息轉換爲json對象的字符串 String postdata = JSONObject.fromObject(maps).toString(); request.setBizContent(postdata); AlipayTradePrecreateResponse response = alipayClient.execute(request); String body = response.getBody(); JSONObject jsonObject = JSONObject.fromObject(body); String qr_code = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code"); //流輸出 ServletOutputStream sos = null; try { sos = responses.getOutputStream(); //生成二維碼 QRCodeUtil.encode(qr_code, sos); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return map; } /** * 支付寶支付成功回調 */ @RequestMapping(value = "aliPayCallBack.do") @ResponseBody public void aliPayCallBack(HttpServletResponse response, HttpServletRequest request) { System.out.println("支付寶回調成功"); try { //獲取支付寶POST過來反饋信息 Map<String,String> params = new HashMap<String,String>(); 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] + ","; } //亂碼解決,這段代碼在出現亂碼時使用。 //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); params.put(name, valueStr); } boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfig.zfb_public_key, AlipayConfig.input_charset,"RSA2"); // 獲取支付寶的通知返回參數,可參考技術文檔中頁面跳轉同步通知參數列表(如下僅供參考)// String order_no = request.getParameter("out_trade_no"); // 獲取訂單號 // String trade_no = request.getParameter("trade_no"); // 支付寶交易號 // String total_amount = request.getParameter("total_amount"); // 獲取總金額 // String subject = new String(request.getParameter("subject") // .getBytes("ISO-8859-1"), "gbk");// 商品名稱、訂單名稱 // String body = ""; // if (request.getParameter("body") != null) { // body = new String(request.getParameter("body").getBytes( // "ISO-8859-1"), "gbk");// 商品描述、訂單備註、描述 // } // String buyer_email = request.getParameter("buyer_email"); // 買家支付寶帳號 String trade_status = request.getParameter("trade_status"); // 交易狀態 // 獲取支付寶的通知返回參數,可參考技術文檔中頁面跳轉同步通知參數列表(以上僅供參考)// if (flag==true) {// 驗證成功 try{ int i = this.proOrdersService.updateByOrderId(order_no); if (i==1) { System.out.println("支付寶訂單支付成功!"); } }catch (Exception e) { System.out.println("支付寶支付異常"); e.printStackTrace(); } } response.getWriter().write("success"); } catch (Exception e) { e.printStackTrace(); } } }
如今,基本的代碼都貼完了,生成二維碼的邏輯和微信同樣,拿到code_url後,用二維碼生成工具類生成二維碼,把他貼到網頁上須要支付的頁面,就成功了~