易宝支付Demo,生产中封装成简洁的代付接口,不用request如何获取项目运行时的真实路径
最近项目在做融360引流,涉及到了易宝支付的代扣和代付。易宝官方给出的demo只能简单运行,而且都是通过form表单的形式提交,返回XML格式。同时接口代码都写在了JSP中看起来不友好。项目在生成中想要用,必须修改整合到自己的项目工程中(文末附我修改的源码下载地址)。
首先说明易宝的版本号:易宝支付-代付代发-商户接入包-V3.3
言归正传,相信易宝官方的demo大家都能获取到,所以这里不再赘述demo的难看点。在这里直接截图给大家说明我修改后的代码。有不好的地方请大家看了代码后及时在下方评论
上图是通过request获取项目的真实路径,以便下面用于获取证书地址,但是实际我们在封装成自己的代码时,传入request是不太好的,因为有可能在我们用的时候,无法获取到request对象。而且这里的功能单一,所以我用下面的方法进行了修改,以便获取到证书真实路径(urlss这里需要替换成自己的当前类全限定名称,TransferParamResolver这个都要替换。下面有可Cp代码)
这里代替为用静态代码块获取证书的真实路径,这里的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
易宝支付Demo,生产中封装成简洁的代付接口,不用request如何获取项目运行时的真实路径的更多相关文章
- 【SSH网上商城项目实战21】从Demo中看易宝支付的流程
转自: https://blog.csdn.net/eson_15/article/details/51447492 这一节我们先写一个简单点的Demo来测试易宝支付的流程,熟悉这个流程后, ...
- 【Java EE 学习 21 下】【 使用易宝支付接口实现java网上支付功能】
一.网上支付分为两种情况,一种方法是使用直接和银行的支付接口,另外一种方法是使用第三方支付平台和银行对接完成支付. 1.直接和银行对接. 2.使用第三方支付平台 3.常见的第三方支付平台 二.使用易宝 ...
- 开发自己的网上支付案例代码(易宝支付php)
1.简单的图解(如上所示) 易宝支付与支付宝是不一样的,但也有类似之处,支付宝是专门为淘宝软件开发的一套机制,资金会在中间支付公司(支付宝)停留,等待顾客确认,当顾客确认后,才会真正扣钱.而易宝支付时 ...
- PHPEXCEL在thinkphp中封装成类使用
PHPEXCEL在thinkphp中封装成类使用 标签: phpexcel导出导入thinkphp -- : 435人阅读 评论() 收藏 举报 分类: php() 版权声明:本文为博主原创文章,未经 ...
- Bug2020011601,在ssh项目的applicaitonContext.xml中,少了一个双引号,打包成功(没报错),项目运行才发现
在ssh项目的applicaitonContext.xml中,少了一个双引号,打包成功(没报错),项目运行才发现. 加上少的双引号,解决了.
- 自定义实现InputFormat、OutputFormat、输出到多个文件目录中去、hadoop1.x api写单词计数的例子、运行时接收命令行参数,代码例子
一:自定义实现InputFormat *数据源来自于内存 *1.InputFormat是用于处理各种数据源的,下面是实现InputFormat,数据源是来自于内存. *1.1 在程序的job.setI ...
- WordPress按钮秒支付插件发布,支持微信支付,支付宝,银联,京东,苏宁,易宝支付
痛点: 我们用WordPress建设网站和开发移动应用,有时候我们其实不需要太多的流程,只是需要一个收款通道,但是可能对支持的渠道更加关注,特别是手机应用.所以WordPress按钮秒支付插件诞生了, ...
- 打包项目成war包并部署到服务器上,项目运行一直显示加载中
查看服务器上的Tomcat路径下的log 显示 org.apache.catalina.LifecycleException: Failed to initialize component [Conn ...
- Django项目运行时出现self.status.split(' ',1)[0], self.bytes_sent,ConnectionAbortedError: [WinError 10053] 你的主机中的软件中止了一个已建立的连接。
[02/Nov/2018 09:46:51] "GET /new_industry/category HTTP/1.1" 200 2891792 Traceback (most r ...
随机推荐
- MacOS使用Charles抓去HTTPS数据
1.安装Charles,示例版本为4.0.1 2.Proxy->Proxy Settings 3.MacOS->Terminal->ifconfig 获取本机IP地址,如192.16 ...
- eclipse安装及配置pydev
1.首先安装jre,这里记住jre的安装目录,32位操作系统默认安装在“C:\Program Files (x86)\Java\jre1.8.0_91” 2.配置eclipse,这里使用的是压缩包不需 ...
- 于bugku中游荡意外得到关于CBC翻转攻击思路
个人简介:渣渣一枚,萌新一个,会划水,会喊六六今天在bugku遇到关于CBC翻转攻击的题目,总结了一下关于CBC翻转攻击的原理,以及关于这道题目的解题思路个人博客:https://www.cnblog ...
- Mac 系统安装教程
上周末买了一个二手的Mac,当时是抹掉整个硬盘的,所以只能选择重装系统了.但是,多次重装都是失败了.最后使用USB安装,试了好几次,误打误撞总算成功了. 下面是整个安装的教程: 1. 备份好所有的私人 ...
- 卷积神经网络CNN的原理(二)---公式推导
卷积神经网络与普通神经网络的区别在于,卷积神经网络包含多个由卷积层和池化层构成的特征抽取器.在卷积神经网络的卷积层中,一个神经元只与部分邻层神经元连接.在CNN的一个卷积层中,通常包含若干个特征平面( ...
- java中MD5加密
MD5加密是一种不可逆(一些网站通过庞大的数据库可以解密一些简单的)的加密算法(其实是信息摘要算法),常用于用户密码,文件上传等 MD5算法具有以下特点: 1.压缩性:任意长度的数据,算出的MD5值长 ...
- ajax实现异步前后台交互,模拟百度搜索框智能提示
1.什么是异步?在传统的网站项目中,填写一堆数据,最后点击提交,在点击提交的这一刻才实现数据提交,前后台交互.在你点击提交之前数据是没有提交到后台的.这样就会造成很大的不便.比如,我填了一大堆数据,结 ...
- Spring面试底层原理的那些问题,你是不是真的懂Spring?
1.什么是 Spring 框架?Spring 框架有哪些主要模块?Spring 框架是一个为 Java 应用程序的开发提供了综合.广泛的基础性支持的 Java 平台.Spring帮助开发者解决了开发中 ...
- springBoot(8)---整合redis
Springboot整合redis 步骤讲解 1.第一步jar导入: <dependency> <groupId>org.springframework.boot</gr ...
- VueJs(14)---理解Vuex
理解Vuex 一.Vuex 是什么? 首先我们来分析一种实际开发中用vue.js的场景,你有n个组件,当你改变一个组件数据的时候需要同时改变其它n个组件的数据,那么我想你可能会对 vue 组件之间的通 ...