支付寶支付+分賬功能(證書方式)


  也是第一次搞證書方式的,算是記錄一下 ,免得以后用到再去翻了,支付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();
        }
        
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM