最近项目在做融360引流,涉及到了易宝支付的代扣和代付。易宝官方给出的demo只能简单运行,而且都是通过form表单的形式提交,返回XML格式。同时接口代码都写在了JSP中看起来不友好。项目在生成中想要用,必须修改整合到自己的项目工程中(文末附我修改的源码下载地址)。

首先说明易宝的版本号:易宝支付-代付代发-商户接入包-V3.3

言归正传,相信易宝官方的demo大家都能获取到,所以这里不再赘述demo的难看点。在这里直接截图给大家说明我修改后的代码。有不好的地方请大家看了代码后及时在下方评论

 

java直接易宝支付_xml

 上图是通过request获取项目的真实路径,以便下面用于获取证书地址,但是实际我们在封装成自己的代码时,传入request是不太好的,因为有可能在我们用的时候,无法获取到request对象。而且这里的功能单一,所以我用下面的方法进行了修改,以便获取到证书真实路径(urlss这里需要替换成自己的当前类全限定名称,TransferParamResolver这个都要替换。下面有可Cp代码)

java直接易宝支付_System_02

这里代替为用静态代码块获取证书的真实路径,这里的System.Properties功能还是很多的



//        System.err.println(sysPath);
//        Properties props = System.getProperties();
//        propertis = props.getProperty("user.dir")+"文件分隔符:" + //props.getProperty("file.separator");    
//        System.out.println("操作系统的名称:" + props.getProperty("os.name"));
//        System.out.println("操作系统的构架:" + props.getProperty("os.arch"));
//        System.out.println("操作系统的版本号:" + props.getProperty("os.version"));
//        System.out.println("文件分隔符:" + props.getProperty("file.separator"));
//        //在 unix 系统中是"/"
//        System.out.println("路径分隔符:" + props.getProperty("path.separator"));
//        //在 unix 系统中是":"
//        System.out.println("行分隔符:" + props.getProperty("line.separator"));
//        //在 unix 系统中是"/n"
//        System.out.println("用户的账户名称:" + props.getProperty("user.name"));
//        System.out.println("用户的主文件夹:" + props.getProperty("user.home"));
//        System.out.println("用户的当前工作文件夹:" + props.getProperty("user.dir"));

//        操作系统的名称:Windows 8.1
//        操作系统的构架:amd64
//        操作系统的版本号:6.3
//        文件分隔符:\
//        路径分隔符:;
//        行分隔符:
//        用户的账户名称:雷神
//        用户的主文件夹:C:\Users\雷神
//        用户的当前工作文件夹:D:\JAVAInstall\intelIdeaWorkSpace\TestProject1



  剩下的就是传参和返回值的获取,这里直接放入所有代码

 



package com.ssm.yibaoPay.yeepay.common.transfer;

import com.cfca.util.pki.api.CertUtil;
import com.cfca.util.pki.api.KeyUtil;
import com.cfca.util.pki.api.SignatureUtil;
import com.cfca.util.pki.cert.X509Cert;
import com.cfca.util.pki.cipher.JCrypto;
import com.cfca.util.pki.cipher.JKey;
import com.cfca.util.pki.cipher.Session;
import com.ssm.yibaoPay.yeepay.common.securityplatform.Digest;
import com.ssm.yibaoPay.yeepay.common.utils.CallbackUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.io.File;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * com.fastx.cooperate.threeInterface.yeepay.common.transfer;
 * 功能:;
 *
 * @author 李冉 Email:1828581413@qq.com
 * Time:2018/7/11 10:56
 */
public class TransferParamResolver {

    private static String sysPath;

    static {
        String urlss = "com.fastx.cooperate.threeInterface.yeepay.common.transfer.TransferParamResolver";
        urlss = "classes/" + urlss.substring(0, urlss.indexOf("TransferParamResolver")).replace(".", "/");
        java.net.URL url = TransferParamResolver.class.getResource("");
        sysPath = (System.getProperties().getProperty("os.name").toUpperCase().startsWith("WIN") ? "" :
                System.getProperties().getProperty("file.separator"))
                + String.valueOf(url).substring(String.valueOf(url).indexOf("file:/")
                + 6, String.valueOf(url).indexOf(urlss)) + "lib/";
    }

    //protected final static Log log = Log.getLog(TransferParamResolver.class); //添加日志

    /**
     * 单笔打款xml请求报文
     *
     * @param transferSingle
     * @return
     * @throws Exception
     */
    public static Map transferSingle(TransferSingle transferSingle) throws Exception {
//TranferSingle 这个实体类 是传参的实体,对应文档自己查看,生产中把下面amount对应修改成自己的实际金额即可
        String xml = "<data>\n" +
                "\t<cmd>TransferSingle</cmd>\n" +
                "\t<version>1.1</version>\n" +
                "\t<mer_Id>10022581269</mer_Id>\n" +
                "\t<group_Id>10022581269</group_Id>\n" +
                "\t<batch_No>" + transferSingle.getBatch_no() + "</batch_No>\n" +
                "\t<order_Id>" + transferSingle.getOrder_id() + "</order_Id>\n" +
                "\t<bank_Code>" + transferSingle.getBank_code() + "</bank_Code>\n" +
                "\t<cnaps>100123123123</cnaps>\n" +
                "\t<bank_Name>" + transferSingle.getBank_name() + "</bank_Name>\n" +
                "\t<branch_Bank_Name>农业银行北京市朝阳支行</branch_Bank_Name>\n" +
                "\t<amount>" + "0.01" + "</amount>\n" +
                "\t<account_Name>" + transferSingle.getAccount_name() + "</account_Name>\n" +
                "\t<account_Number>" + transferSingle.getAccount_number() + "</account_Number>\n" +
                "\t<province>110000</province>\n" +
                "\t<city>110000</city>\n" +
                "\t<fee_Type>SOURCE</fee_Type>\n" +
                "\t<payee_Email></payee_Email>\n" +
                "\t<payee_Mobile></payee_Mobile>\n" +
                "\t<leave_Word></leave_Word>\n" +
                "\t<abstractInfo></abstractInfo>\n" +
                "\t<remarksInfo></remarksInfo>\n" +
                "\t<urgency>0</urgency>\n" +
                "\t<hmac></hmac>\n" +
                "</data>";
        //需要参加签名的参数:其中(hmacKey)指的是商户自己的密钥
        String todigestValues = "cmd,mer_Id,batch_No,order_Id,amount,account_Number,hmacKey";
        //验证返回参数签名的参数:其中(hmacKey)指的是商户自己的密钥
        String tobackDigestValues = "cmd,ret_Code,mer_Id,batch_No,total_Amt,total_Num,r1_Code,hmacKey";
        try {
            return DoTransferSingle(xml, todigestValues, tobackDigestValues);
        } catch (Exception e) {
            e.printStackTrace();
            //  log.info("单笔打款异常---------------->" + e.getMessage());
            // log.info("异常输入的参数---------------->" + transferSingle.toString());
            throw e;
        }

    }

    /**
     * 打款明细查询xml请求报文
     *
     * @param betchNo 订单批次号
     * @param orderId 订单ID号
     * @return
     * @throws Exception
     */

    public static Map singlePayQuery(String betchNo, String orderId) throws Exception {
        String xml = "<data>\n" +
                "\t<cmd>BatchDetailQuery</cmd>\n" +
                "\t<version>1.1</version>\n" +
                "\t<group_Id>10022581269</group_Id>\n" +
                "\t<mer_Id>10022581269</mer_Id>\n" +
                "\t<query_Mode>1</query_Mode>\n" +
                "\t<batch_No>" + betchNo + "</batch_No>\n" +
                "\t<order_Id>" + orderId + "</order_Id>\n" +
                "\t<page_No>1</page_No>\n" +
                "\t<hmac></hmac>\n" +
                "</data>";
        //需要参加签名的参数:其中(hmacKey)指的是商户自己的密钥
        String todigestValues = "cmd,mer_Id,batch_No,order_Id,page_No,hmacKey";
        //验证返回参数签名的参数:其中(hmacKey)指的是商户自己的密钥
        String tobackDigestValues = "cmd,ret_Code,batch_No,total_Num,end_Flag,hmacKey";
        try {
            return DoTransferSingle(xml, todigestValues, tobackDigestValues);
        } catch (Exception e) {
            e.printStackTrace();
            //log.info("单笔打款查询异常---------------->" + e.getMessage());
            // log.info("异常输入的参数---------------->" + "betchNo" + betchNo + "orderId" + orderId);
            throw e;
        }

    }

    private static Map DoTransferSingle(String xml, String todigestValues, String tobackDigestValues) throws Exception {

        //商户密钥
        String hmacKey = "02Ji5At46r9BwZ8TVW7aFHox1pNm9N0n8c7DsA8e5813IEu74T50i901F762";

        Map result = new LinkedHashMap();
        Map xmlMap = new LinkedHashMap();
        Map xmlBackMap = new LinkedHashMap();
        //需要参加签名的参数:其中(hmacKey)指的是商户自己的密钥
        String[] digestValues = todigestValues.split(",");
        //验证返回参数签名的参数:其中(hmacKey)指的是商户自己的密钥
        String[] backDigestValues = tobackDigestValues.split(",");
        //String xml = request.getParameter("xml");

        //第一步:将请求的数据和商户自己的密钥拼成一个字符串,
        Document document = null;
        try {
            document = DocumentHelper.parseText(xml);
        } catch (DocumentException e) {
        }
        Element rootEle = document.getRootElement();
        String cmdValue = rootEle.elementText("cmd");
        List list = rootEle.elements();
        for (int i = 0; i < list.size(); i++) {
            Element ele = (Element) list.get(i);
            String eleName = ele.getName();
            if (!eleName.equals("list")) {
                xmlMap.put(eleName, ele.getText().trim());
            } else {
                continue;
            }
        }

        String hmacStr = "";
        for (int i = 0; i < digestValues.length; i++) {
            if (digestValues[i].equals("hmacKey")) {
                hmacStr = hmacStr + hmacKey;
                continue;
            }
            hmacStr = hmacStr + xmlMap.get(digestValues[i]);

        }
        System.out.println("签名之前的源数据为---||" + hmacStr + "||");

        //下面用数字证书进行签名
        Session tempsession = null;
        String ALGORITHM = SignatureUtil.SHA1_RSA;
        JCrypto jcrypto = null;
        if (tempsession == null) {
            try {
                //初始化加密库,获得会话session
                //多线程的应用可以共享一个session,不需要重复,只需初始化一次
                //初始化加密库并获得session。
                //系统退出后要jcrypto.finalize(),释放加密库
                jcrypto = JCrypto.getInstance();
                jcrypto.initialize(JCrypto.JSOFT_LIB, null);
                tempsession = jcrypto.openSession(JCrypto.JSOFT_LIB);
            } catch (Exception ex) {
                System.out.println(ex.toString());
            }
        }
        String sysPath = TransferParamResolver.sysPath;
        System.out.println("------" + sysPath + "------" + File.separator + "------");
        JKey jkey = KeyUtil.getPriKey(sysPath + File.separator + "7.3.pfx", "123456");
        X509Cert cert = CertUtil.getCert(sysPath + File.separator + "7.3.pfx", "123456");
        System.out.println(cert.getSubject());
        X509Cert[] cs = new X509Cert[1];
        cs[0] = cert;
        String signMessage = "";
        SignatureUtil signUtil = null;
        try {
            // 第二步:对请求的串进行MD5对数据进行签名

            String yphs = Digest.hmacSign(hmacStr);
            signUtil = new SignatureUtil();
            byte[] b64SignData;
            // 第三步:对MD5签名之后数据调用CFCA提供的api方法用商户自己的数字证书进行签名
            b64SignData = signUtil.p7SignMessage(true, yphs.getBytes(), ALGORITHM, jkey, cs, tempsession);
            if (jcrypto != null) {
                jcrypto.finalize(JCrypto.JSOFT_LIB, null);
            }
            signMessage = new String(b64SignData, "UTF-8");
        } catch (Exception e) {
        }
        System.out.println("经过md5和数字证书签名之后的数据为---||" + signMessage + "||");
        Element r = rootEle.element("hmac");
        r.setText(signMessage);
        result.put("xml", xml);
        document.setXMLEncoding("GBK");
        System.out.println("完整xml请求报文:" + document.asXML());

        String textHost = "http://cha.yeepay.com/app-merchant-proxy/groupTransferController.action";
        System.out.println("请求地址为:" + textHost);

        //第四步:发送https请求
        String responseMsg = CallbackUtils.httpRequest(textHost, document.asXML(), "POST", "gbk", "text/xml ;charset=gbk", false);

//       out.println(
//               "<html><body><textarea rows=\"23\" cols=\"120\" name=\"xml\" id=\"xml\">" +
//                       responseMsg +
//                       "</textarea></body></html>");
//       System.out.println("服务器响应xml报文:" + responseMsg);

        try {
            document = DocumentHelper.parseText(responseMsg);
        } catch (DocumentException e) {
        }
        rootEle = document.getRootElement();
        cmdValue = rootEle.elementText("hmac");

        //第五步:对服务器响应报文进行验证签名
        boolean sigerCertFlag = false;
        if (cmdValue != null) {
            sigerCertFlag = signUtil.p7VerifySignMessage(cmdValue.getBytes(), tempsession);
            String backmd5hmac = xmlBackMap.get("hmac") + "";
            if (sigerCertFlag) {
                System.out.println("证书验签成功");
                backmd5hmac = new String(signUtil.getSignedContent());
                System.out.println("证书验签获得的MD5签名数据为----" + backmd5hmac);
                System.out.println("证书验签获得的证书dn为----" + new String(signUtil.getSigerCert()[0].getSubject()));
                //第六步.将验签出来的结果数据与自己针对响应数据做MD5签名之后的数据进行比较是否相等
                Document backDocument = null;
                try {
                    backDocument = DocumentHelper.parseText(responseMsg);
                } catch (DocumentException e) {
                    System.out.println(e);
                }
                Element backRootEle = backDocument.getRootElement();
                List backlist = backRootEle.elements();
                for (int i = 0; i < backlist.size(); i++) {
                    Element ele = (Element) backlist.get(i);
                    String eleName = ele.getName();
                    if (!eleName.equals("list")) {
                        xmlBackMap.put(eleName, ele.getText().trim());
                    } else {
                        continue;
                    }
                }
                String backHmacStr = "";
                for (int i = 0; i < backDigestValues.length; i++) {
                    if (backDigestValues[i].equals("hmacKey")) {
                        backHmacStr = backHmacStr + hmacKey;
                        continue;
                    }
                    String tempStr = (String) xmlBackMap.get(backDigestValues[i]);
                    backHmacStr = backHmacStr + ((tempStr == null) ? "" : tempStr);
                }
                String newmd5hmac = Digest.hmacSign(backHmacStr);
                System.out.println("提交返回源数据为---||" + backHmacStr + "||");
                System.out.println("经过md5签名后的验证返回hmac为---||" + newmd5hmac + "||");
                System.out.println("提交返回的hmac为---||" + backmd5hmac + "||");
                if (newmd5hmac.equals(backmd5hmac)) {
                    System.out.println("md5验签成功");
                    //第七步:判断该证书DN是否为易宝
                    if (signUtil.getSigerCert()[0].getSubject().toUpperCase().indexOf("OU=YEEPAY,") > 0) {
                        System.out.println("证书DN是易宝的");

                        if (todigestValues.equals("cmd,mer_Id,batch_No,order_Id,page_No,hmacKey")) {
                            return resolve(responseMsg);
                        }
                        return xmlBackMap;
                    } else {
                        System.out.println("证书DN不是易宝的");
                    }

                    //
                } else {
                    System.out.println("md5验签失败");
                }
            } else {
                System.out.println("证书验签失败....");
            }
        }
        return null;
    }

    private static Map resolve(String responseMsg) {
        Map xmlBackMap = new LinkedHashMap();
        Map listBackMap = new LinkedHashMap();
        Document backDocument;
        try {
            backDocument = DocumentHelper.parseText(responseMsg);
            Element backRootEle = backDocument.getRootElement();
            List backlist = backRootEle.elements();
            for (int i = 0; i < backlist.size(); i++) {
                Element ele = (Element) backlist.get(i);
                String eleName = ele.getName();
                if (!eleName.equals("list")) {
                    xmlBackMap.put(eleName, ele.getText().trim());
                } else {
                    List backList = ((Element) (((Element) (((Element) backlist.get(i)).elements().get(0))).elements().get(0))).elements();
                    for (int j = 0; j < backList.size(); j++) {
                        Element e1111 = (Element) backList.get(j);
                        listBackMap.put(e1111.getName(), e1111.getText().trim());
                    }
                }
            }
            xmlBackMap.put("listBackMap", listBackMap);
            return xmlBackMap;
        } catch (DocumentException e) {
            //log.info("易宝解析返回XML参数错误----->" + e.getMessage());
            return null;
        }
    }


    /**
     * 根据易宝代付订单批次号和订单号查询支付状态
     *
     * @param betch_no
     * @param order_Id
     * @return
     */
    public static Integer getPayStatus(String betch_no, String order_Id) {
        //代付状态/1 代付中 /2 代付成功/ 3 代付失败
        try {
            Map transferMap = TransferParamResolver.singlePayQuery(betch_no, order_Id);
            if (transferMap == null || transferMap.get("listBackMap") == null) {
                return 3;
            }
            Map listBackMap = (Map) transferMap.get("listBackMap");
            if (transferMap.get("ret_Code") != null && listBackMap.get("r1_Code") != null && listBackMap.get("bank_Status") != null) {
                if ("1".equals(String.valueOf(transferMap.get("ret_Code"))) && "0026".equals(String.valueOf(listBackMap.get("r1_Code"))) && "S".equals(String.valueOf(listBackMap.get("bank_Status")))) {
                    return 2;
                }
                //失败情况
                if ("1".equals(String.valueOf(transferMap.get("ret_Code"))) && ("0026".equals(String.valueOf(listBackMap.get("r1_Code"))) || "0027".equals(String.valueOf(listBackMap.get("r1_Code")))) && "F".equals(String.valueOf(listBackMap.get("bank_Status")))) {
                    return 3;
                }

                //正在进行中
                if ("1".equals(String.valueOf(transferMap.get("ret_Code"))) && ("0026".equals(String.valueOf(listBackMap.get("r1_Code")))) || "0025".equals(String.valueOf(listBackMap.get("r1_Code")))) {
                    return 1;
                }
            } else {
                return 3;
            }
        } catch (Exception e) {
            e.printStackTrace();
            //log部分
        }
        return 3;
    }


}



 这里附上源码下载地址(源码在TestProject中):链接:https://pan.baidu.com/s/1UVUCG4zNYDJmJl9q5twrkw 密码:32gw