也是第一次搞證書方式的,算是記錄一下 ,免得以后用到再去翻了,支付JDK 使用的是4.5 工具類如下
package Test; import java.io.IOException; import java.math.BigDecimal; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.alipay.api.AlipayApiException; import com.chanxa.monitor.model.AlipayLog; public interface AlipayInterface { /** * 獲取支付寶簽名 * @param subject * @param timeoutExpress * @param notifyUrl * @param orderId * @param actualPay * @return */ public String getSign(String subject,String timeoutExpress,String notifyUrl,String orderId,String actualPay)throws AlipayApiException; /** * 驗證接受的數據是否為支付寶合法數據 */ public boolean reaCert(Map<String, String> params)throws AlipayApiException; /** * 驗證返回信息是否正確 正常 返回true 異常返回false */ public boolean verific(AlipayLog log,Integer type); /** * 支付寶分賬關系綁定接口 * @param account 分賬方賬號 (登陸賬號 或 用戶號) * @param type 分賬類型 (分賬方類型。userId:表示是支付寶賬號對應的支付寶唯一用戶號;loginName:表示是支付寶登錄號 ) * @param name 分賬方全稱 * @param outRequestNo 外部請求號。32個字符以內,可包含字母、數字、下划線。需保證在商戶端不重復。 * @throws AlipayApiException */ public boolean bindPaypal(String account,String type,String name,String outRequestNo) throws AlipayApiException; /** * 支付寶分賬關系解綁接口 * @param account 分賬方賬號 (登陸賬號 或 用戶號) * @param type 分賬類型 (分賬方類型。userId:表示是支付寶賬號對應的支付寶唯一用戶號;loginName:表示是支付寶登錄號 ) * @param name 分賬方全稱 * @param outRequestNo 外部請求號。32個字符以內,可包含字母、數字、下划線。需保證在商戶端不重復。 * @throws AlipayApiException */ public boolean unBindPaypal(String account,String type,String name,String outRequestNo) throws AlipayApiException; /** * 支付寶分賬接口 * @param outRequestNo 外部請求號。32個字符以內,可包含字母、數字、下划線。需保證在商戶端不重復。 * @param tradeNo 支付寶訂單號 * @param transIn 收入方賬戶。如果收入方賬戶類型為userId,本參數為收入方的支付寶賬號對應的支付寶唯一用戶號,以2088開頭的純16位數字;如果收入方類型為cardAliasNo,本參數為收入方在支付寶綁定的卡編號;如果收入方類型為loginName,本參數為收入方的支付寶登錄號; * @throws AlipayApiException * @param amount 分賬金額 */ public boolean settlePaypal(String outRequestNo,String tradeNo,String transIn,BigDecimal amount) throws AlipayApiException; /** * 支付寶轉賬接口 * @param outBizNo 商戶端的唯一訂單號,對於同一筆轉賬請求,商戶需保證該訂單號唯一。 * @param transAmount 訂單總金額,單位為元,精確到小數點后兩位, * @param orderTitle 轉賬業務的標題,用於在支付寶用戶的賬單里顯示 * @param identity 參與方的唯一標識 * @param name 參與方真實姓名,如果非空,將校驗收款支付寶賬號姓名一致性。當identity_type=ALIPAY_LOGON_ID時,本字段必填。 * @throws AlipayApiException */ public boolean transfer(String outBizNo,BigDecimal transAmount,String orderTitle,String identity,String name ) throws AlipayApiException; /** * 支付寶掃碼支付接口 --web *@param outTradeNo 商戶訂單號 *@param totalAmount 訂單金額 *@param subject 訂單標題 *@param sellerId 賣家支付寶用戶ID * @throws AlipayApiException * @throws IOException */ public String Precreate(String outTradeNo,BigDecimal totalAmount,String subject,String sellerId) throws AlipayApiException, IOException; }
package Test; import java.io.IOException; import java.math.BigDecimal; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Service; import com.alipay.api.AlipayApiException; import com.alipay.api.CertAlipayRequest; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.domain.AlipayTradeAppPayModel; import com.alipay.api.internal.util.AlipaySignature; import com.alipay.api.request.AlipayFundTransUniTransferRequest; import com.alipay.api.request.AlipayTradeAppPayRequest; import com.alipay.api.request.AlipayTradeOrderSettleRequest; import com.alipay.api.request.AlipayTradePagePayRequest; import com.alipay.api.request.AlipayTradePrecreateRequest; import com.alipay.api.request.AlipayTradeRoyaltyRelationBindRequest; import com.alipay.api.request.AlipayTradeRoyaltyRelationUnbindRequest; import com.alipay.api.response.AlipayFundTransUniTransferResponse; import com.alipay.api.response.AlipayTradeAppPayResponse; import com.alipay.api.response.AlipayTradeOrderSettleResponse; import com.alipay.api.response.AlipayTradePrecreateResponse; import com.alipay.api.response.AlipayTradeRoyaltyRelationBindResponse; import com.alipay.api.response.AlipayTradeRoyaltyRelationUnbindResponse; import com.chanxa.monitor.model.AlipayLog; import com.chanxa.monitor.pay.service.AlipayInterface; import com.chanxa.monitor.utils.Configuration; @Service public class AlipayService implements AlipayInterface { String appid = Configuration.getConfig().getValue("alipau_appKey"); // 私鑰 String private_key = Configuration.getConfig().getValue("key_rsa"); // 公鑰 String alipay_public_key = Configuration.getConfig().getValue("alipay_public_key"); // 應用公鑰證書路徑(app_cert_path 文件絕對路徑) String app_cert_path = Configuration.getConfig().getValue("app_cert_path"); // 支付寶公鑰證書文件路徑(alipay_cert_path 文件絕對路徑),支付寶CA根證書文件路徑(alipay_root_cert_path // 文件絕對路徑) String alipay_cert_path = Configuration.getConfig().getValue("alipay_cert_path"); // 支付寶CA根證書文件路徑(alipay_root_cert_path 文件絕對路徑) String alipay_root_cert_path = Configuration.getConfig().getValue("alipay_root_cert_path"); CertAlipayRequest certAlipayRequest = new CertAlipayRequest(); public AlipayService() { certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do"); certAlipayRequest.setAppId(appid); certAlipayRequest.setPrivateKey(private_key); certAlipayRequest.setFormat("json"); certAlipayRequest.setCharset("utf-8"); certAlipayRequest.setSignType("RSA2"); certAlipayRequest.setCertPath(app_cert_path); certAlipayRequest.setAlipayPublicCertPath(alipay_cert_path); certAlipayRequest.setRootCertPath(alipay_root_cert_path); } /** * @param subject * 交易標題 * @param timeoutExpress * 有效時間 * @param notifyUrl * 回調路徑 * @param orderId * 訂單編號 * @param actualPay * 支付金額 * @throws AlipayApiException */ @Override public String getSign(String subject, String timeoutExpress, String notifyUrl, String orderId, String actualPay) throws AlipayApiException { DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest); // 實例化具體API對應的request類,類名稱和接口名稱對應,當前調用接口名稱:alipay.trade.app.pay AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest(); // SDK已經封裝掉了公共參數,這里只需要傳入業務參數。以下方法為sdk的model入參方式(model和biz_content同時存在的情況下取biz_content)。 AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); model.setSubject(subject); model.setOutTradeNo(orderId); model.setTimeoutExpress(timeoutExpress); model.setTotalAmount(actualPay + ""); model.setProductCode("QUICK_MSECURITY_PAY"); request.setBizModel(model); request.setNotifyUrl(notifyUrl); try { // 這里和普通的接口調用不同,使用的是sdkExecute AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request); return response.getBody(); } catch (AlipayApiException e) { e.printStackTrace(); } return ""; } /** * APP 充值 支付寶回調驗簽 公共方法 */ @Override public boolean reaCert(Map<String, String> params) throws AlipayApiException { return AlipaySignature.rsaCertCheckV1(params, alipay_cert_path, "utf-8", "RSA2"); } /** * APP 充值 驗證公共參數部分是否正確 公共方法 */ @Override public boolean verific(AlipayLog log, Integer type) { String seller_email = Configuration.getConfig().getValue("seller_email"); // 判斷 回調里賣家支付寶賬號 是否為系統賣家支付寶ID if (!seller_email.equals(log.getSellerEmail())) { return false; } // 判斷APPID 是否為系統的APPID String alipau_appKey = Configuration.getConfig().getValue("alipau_appKey"); if (!alipau_appKey.equals(log.getAuthAppId())) { return false; } return true; } /** * 支付寶分賬關系綁定接口 * * @param account * 分賬方賬號 (登陸賬號 或 用戶號) * @param type * 分賬類型 (分賬方類型。userId:表示是支付寶賬號對應的支付寶唯一用戶號;loginName:表示是支付寶登錄號 ) * @param name * 分賬方全稱 * @param outRequestNo * 外部請求號。32個字符以內,可包含字母、數字、下划線。需保證在商戶端不重復。 * @throws AlipayApiException */ @Override public boolean bindPaypal(String account, String type, String name, String outRequestNo) throws AlipayApiException { DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest); AlipayTradeRoyaltyRelationBindRequest request = new AlipayTradeRoyaltyRelationBindRequest(); request.setBizContent( "{\"receiver_list\":[{\"type\":\"loginName\",\"account\":\"" + account + "\",\"name\":\"" + name + "\"}],\"out_request_no\":" + outRequestNo + "}"); AlipayTradeRoyaltyRelationBindResponse response = alipayClient.certificateExecute(request); if (response.isSuccess()) { return true; } else { return false; } } /** * 支付寶分賬關系解綁接口 * * @param account * 分賬方賬號 (登陸賬號 或 用戶號) * @param type * 分賬類型 (分賬方類型。userId:表示是支付寶賬號對應的支付寶唯一用戶號;loginName:表示是支付寶登錄號 ) * @param name * 分賬方全稱 * @param outRequestNo * 外部請求號。32個字符以內,可包含字母、數字、下划線。需保證在商戶端不重復。 * @throws AlipayApiException */ @Override public boolean unBindPaypal(String account, String type, String name, String outRequestNo) throws AlipayApiException { DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest); AlipayTradeRoyaltyRelationUnbindRequest request = new AlipayTradeRoyaltyRelationUnbindRequest(); request.setBizContent( "{\"receiver_list\":[{\"type\":\"loginName\",\"account\":\"" + account + "\",\"name\":\"" + name + "\"}]," + "\"out_request_no\":" + outRequestNo + "}"); AlipayTradeRoyaltyRelationUnbindResponse response = alipayClient.certificateExecute(request); if (response.isSuccess()) { return true; } else { return false; } } /** * 支付寶分賬接口 * * @param outRequestNo * 外部請求號。32個字符以內,可包含字母、數字、下划線。需保證在商戶端不重復。 * @param tradeNo * 支付寶訂單號 * @param transIn * 收入方賬戶。如果收入方賬戶類型為userId,本參數為收入方的支付寶賬號對應的支付寶唯一用戶號, * 以2088開頭的純16位數字;如果收入方類型為cardAliasNo,本參數為收入方在支付寶綁定的卡編號; * 如果收入方類型為loginName,本參數為收入方的支付寶登錄號; * @throws AlipayApiException * @param amount * 分賬金額 */ @Override public boolean settlePaypal(String outRequestNo, String tradeNo, String transIn, BigDecimal amount) throws AlipayApiException { DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest); AlipayTradeOrderSettleRequest request = new AlipayTradeOrderSettleRequest(); request.setBizContent("{\"out_request_no\":\"" + outRequestNo + "\",\"trade_no\":\"" + tradeNo + "\",\"royalty_parameters\":[{\"trans_in\":\"" + transIn + "\",\"amount\":"+amount+",\"trans_in_type\":\"loginName\"}]}"); AlipayTradeOrderSettleResponse response = alipayClient.certificateExecute(request); if (response.isSuccess()) { return true; } else { return false; } } /** * 支付寶轉賬接口 * @param outBizNo 商戶端的唯一訂單號,對於同一筆轉賬請求,商戶需保證該訂單號唯一。 * @param transAmount 訂單總金額,單位為元,精確到小數點后兩位, * @param orderTitle 轉賬業務的標題,用於在支付寶用戶的賬單里顯示 * @param identity 參與方的唯一標識 * @param name 參與方真實姓名,如果非空,將校驗收款支付寶賬號姓名一致性。當identity_type=ALIPAY_LOGON_ID時,本字段必填。 * @throws AlipayApiException */ @Override public boolean transfer(String outBizNo, BigDecimal transAmount, String orderTitle, String identity, String name) throws AlipayApiException { DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest); AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest(); request.setBizContent("{\"out_biz_no\":\""+outBizNo+"\",\"trans_amount\":"+transAmount+",\"product_code\":\"TRANS_ACCOUNT_NO_PWD\",\"order_title\":\""+orderTitle+"\",\"biz_scene\":\"DIRECT_TRANSFER\",\"payee_info\":{\"identity\":\""+identity+"\",\"identity_type\":\"ALIPAY_LOGON_ID\",\"name\":\""+name+"\"}}"); AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request); if(response.isSuccess()){ return true; } else { return false; } } @Override public String Precreate(String outTradeNo, BigDecimal totalAmount, String subject, String sellerId) throws AlipayApiException, IOException { DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest); AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();//創建API對應的request alipayRequest.setBizContent("{\"out_trade_no\":\""+outTradeNo+"\",\"total_amount\":"+totalAmount+",\"subject\":\""+subject+"\",\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); alipayRequest.setReturnUrl("這里是跳轉頁面"); alipayRequest.setNotifyUrl("這里是返回通知路徑");
String form=""; try { form = alipayClient.pageExecute(alipayRequest).getBody(); //調用SDK生成表單 } catch (AlipayApiException e) { e.printStackTrace(); } return form; } }
接下來是回調
package Test; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.chanxa.monitor.model.AlipayLog; import com.chanxa.monitor.pay.service.AlipayInterface; import com.chanxa.monitor.utils.CheckUtil; @Controller @RequestMapping("/text/callBack/") public class PayCallbackController { Logger logger = LoggerFactory.getLogger( PayCallbackController.class ); @Resource private AlipayInterface alipayService; /** * 處理支付寶回調返回的數據 * @param request * @return * @throws Exception */ public AlipayLog getAlipayLog(HttpServletRequest request) throws Exception { AlipayLog log = new AlipayLog(); // 訂單號 String out_trade_no = request.getParameter("out_trade_no"); // 支付寶交易號 String trade_no = request.getParameter("trade_no"); // 交易狀態 String trade_status = request.getParameter("trade_status"); //交易標題 String subject = request.getParameter("subject"); //賣家支付寶用戶號 String seller_id = request.getParameter("seller_id"); //賣家支付寶賬號 String seller_email = request.getParameter("seller_email"); //買家支付寶賬號對應的支付寶唯一用戶號 String buyer_id = request.getParameter("buyer_id"); //買家支付寶賬號 String buyer_email = request.getParameter("buyer_email"); //本次交易支付的訂單金額,單位為人民幣(元) String total_fee = request.getParameter("total_amount"); //用戶在交易中實際付款金額 String buyer_pay_amount = request.getParameter("buyer_pay_amount"); //商家實際收到的金額 String receipt_amount = request.getParameter("receipt_amount"); //appID String auth_app_id=request.getParameter("auth_app_id"); String gmt_refund = request.getParameter("gmt_refund"); String body = request.getParameter("body"); log.setOrderId(out_trade_no); log.setBuyerEmail(buyer_email); log.setBuyerId(buyer_id); log.setBuyerPayAmount(buyer_pay_amount); log.setReceiptAmount(receipt_amount); log.setAuthAppId(auth_app_id); String gmt_create = request.getParameter("gmt_create"); String gmt_payment = request.getParameter("gmt_payment"); String refund_status = request.getParameter("refund_status"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); log.setGmtCreate(CheckUtil.isNullEmpty(gmt_create) ? null : dateFormat.parse(gmt_create)); log.setGmtPayment(CheckUtil.isNullEmpty(gmt_payment) ? null : dateFormat.parse(gmt_payment)); log.setGmtRefund(CheckUtil.isNullEmpty(gmt_refund) ? null : dateFormat.parse(gmt_refund)); log.setRefundStatus(refund_status); log.setSellerEmail(seller_email); log.setSellerId(seller_id); log.setSubject(subject); log.setTotalFee(total_fee); log.setTradeNo(trade_no); log.setTradeStatus(trade_status); log.setBody(body); return log; } /** * 獲取POST過來反饋信息 * @param request * @return */ public Map<String, String> getParamsFromRequest(HttpServletRequest request) { Map<String, String> params = new HashMap<String, String>(); 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] + ","; } // 亂碼解決,這段代碼在出現亂碼時使用。如果mysign和sign不相等也可以使用這段代碼轉化 params.put(name, valueStr); } return params; } /** * 支付寶回調 * @param request * @param response * @throws Exception */ @RequestMapping(value = "alipayCallback") public void alipayCallback(HttpServletRequest request, HttpServletResponse response) throws Exception { // 獲取POST過來反饋信息 Map<String, String> params=this.getParamsFromRequest(request); //驗證是否為支付寶合法參數 boolean flag=alipayService.reaCert(params); PrintWriter out = response.getWriter(); if(flag){//驗簽通過 AlipayLog log =this.getAlipayLog(request); if(log.getTradeStatus().equals("TRADE_SUCCESS")||log.getTradeStatus().equals("TRADE_FINISHED")){ //驗證支付信息和訂單信息是否匹配 boolean brook=alipayService.verific(log, 1); if(brook){//驗證通過,執行相應的邏輯 //執行完畢 添加支付日志 //返回成功給支付寶 out.println("success"); }else{ //不匹配 原路退回 out.println("failure"); } }else{ out.println("failure"); } }else{ out.println("failure"); } out.flush(); out.close(); } }