以下文章 所用证书为银联提供的测试证书,要真实在项目中使用需要向银联申请对应数据

进入银联网站https://open.unionpay.com  登录或注册用户   找到代付 下载对应测试证书   以及sdk操作工具类等等

集成springMVC 具体代码如下:

自定义springMVC的核心类继承 dispatcherServlet  重写 inits ...  我这里重写它是为了获取当前项目的所有url  所以就在这里顺便把证书初始化了,当前你也可以通过别的方式初始   

java 银联转帐 银联转账_java

上面sdkconfig.getconfig.loadProp   方法sdk里面应该 会有

然后接下来是 acp_sdk.properties 文件  这个也在你下载的 代付 dome 里面也有    具体改一下里面的类容如下:

##########################入网测试环境交易发送地址(线上测试需要使用生产环境交易请求地址)#############################
##交易请求地址 
acpsdk.frontTransUrl=https://101.231.204.80:5000/gateway/api/frontTransReq.do
acpsdk.backTransUrl=https://101.231.204.80:5000/gateway/api/backTransReq.do
acpsdk.singleQueryUrl=https://101.231.204.80:5000/gateway/api/queryTrans.do
acpsdk.batchTransUrl=https://101.231.204.80:5000/gateway/api/batchTrans.do
acpsdk.fileTransUrl=https://101.231.204.80:9080/
acpsdk.appTransUrl=https://101.231.204.80:5000/gateway/api/appTransReq.do
acpsdk.cardTransUrl=https://101.231.204.80:5000/gateway/api/cardTransReq.do
#########################入网测试环境签名证书配置 ################################
##签名证书路径,必须使用绝对路径,如果不想使用绝对路径,可以自行实现相对路径获取证书的方法;测试证书所有商户共用开发包中的测试签名证书,生产环境请从cfca下载得到
#windows下
acpsdk.signCert.path=D:/certs/acp_test_sign.pfx
#linux下(注意:在linux下读取证书需要保证证书有被应用读的权限)
#acpsdk.signCert.path=/SERVICE01/usr/ac_frnas/conf/ACPtest/acp700000000000001.pfx
##签名证书密码,测试环境固定000000,生产环境请修改为从cfca下载的正式证书的密码,正式环境证书密码位数需小于等于6位,否则上传到商户服务网站会失败
acpsdk.signCert.pwd=000000
##签名证书类型,固定不需要修改
acpsdk.signCert.type=PKCS12
##########################验签证书配置################################
##验证签名证书目录,只配置到目录即可,必须使用绝对路径,如果不想使用绝对路径,可以自行实现相对路径获取证书的方法;测试证书所有商户共用开发包中的测试验证证书,生产环境所有商户共用开发包中的生产验签证书
#windows下
acpsdk.validateCert.dir=D:/certs/
#linux下(注意:在linux下读取证书需要保证证书有被应用读的权限)
#acpsdk.validateCert.dir=/SERVICE01/usr/ac_frnas/conf/ACPtest/
##########################加密证书配置################################
##敏感信息加密证书路径(商户号开通了商户对敏感信息加密的权限,需要对 卡号accNo,pin和phoneNo,cvn2,expired加密(如果这些上送的话),对敏感信息加密使用)
acpsdk.encryptCert.path=d:/certs/acp_test_enc.cer
##是否启用多证书模式(true:单证书|false:多证书---没有配置此项时,默认为单证书模式)
acpsdk.singleMode=true

还有就是别忘了把dome里面 lib文件下的  jar  也拷贝到你的项目里面

bcprov-jdk15on-1.54.jar    upacp_sdk-1.1.0-20151216.jar  这两个比较重要

然后随便来写一个 springmvc 的控制层类

package com.hnust.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.jfinal.kit.HttpKit;
import com.unionpay.acp.sdk.LogUtil;
import com.upacp.yn.pay.AcpService;
import com.upacp.yn.pay.DemoBase;
import com.upacp.yn.pay.SDKConfig;
@Controller
@RequestMapping(value = "/unpay")
public class UnPayController {

	@SuppressWarnings("unused")
	@RequestMapping(value = "/toDf", method = RequestMethod.GET)
	public void toDf(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		//其实这四行就没用了  我懒得删除
		String merId = req.getParameter("merId");
		String txnAmt = req.getParameter("txnAmt");
		String orderId = req.getParameter("orderId");
		String txnTime = req.getParameter("txnTime");

		Map<String, String> data = new HashMap<String, String>();

		/*** 银联全渠道系统,产品参数,除了encoding自行选择外其他不需修改 ***/
		data.put("version", DemoBase.version); // 版本号 全渠道默认值
		data.put("encoding", DemoBase.encoding_UTF8); // 字符集编码 可以使用UTF-8,GBK两种方式
		data.put("signMethod", "01"); // 签名方法
		data.put("txnType", "12"); // 交易类型 12:代付
		data.put("txnSubType", "00"); // 默认填写00
		data.put("bizType", "000401"); // 000401:代付
		data.put("channelType", "07"); // 渠道类型

		/*** 商户接入参数 ***/
		data.put("merId", "自己的测试商户号"); // 商户号码,请改成自己申请的商户号或者open上注册得来的777商户号测试
		data.put("accessType", "0"); // 接入类型,商户接入填0 ,不需修改(0:直连商户, 1: 收单机构
										// 2:平台商户)
		data.put("orderId", "4001602001111611291184672731"); // 商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则
		data.put("txnTime", "20170310110952"); // 订单发送时间,取系统时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效
		data.put("accType", "01"); // 账号类型 01:银行卡02:存折03:IC卡帐号类型(卡介质)

		// 如果商户号开通了 商户对敏感信息加密的权限那么,需要对 卡号accNo加密使用:
		data.put("encryptCertId", AcpService.getEncryptCertId()); // 上送敏感信息加密域的加密证书序列号
		String accNo = AcpService.encryptData("6216261000000000018",
				DemoBase.encoding_UTF8); // 这里测试的时候使用的是测试卡号,正式环境请使用真实卡号
		data.put("accNo", accNo);

		// 代收交易的上送的卡验证要素为:姓名或者证件类型+证件号码
		Map<String, String> customerInfoMap = new HashMap<String, String>();
		customerInfoMap.put("certifTp", "01"); // 证件类型
		customerInfoMap.put("certifId", "341126197709218366"); // 证件号码
		// customerInfoMap.put("customerNm", "全渠道"); //姓名
		String customerInfoStr = AcpService.getCustomerInfo(customerInfoMap,
				"6216261000000000018", DemoBase.encoding_UTF8);

		data.put("customerInfo", customerInfoStr);
		data.put("txnAmt", "10"); // 交易金额 单位为分,不能带小数点
		data.put("currencyCode", "156"); // 境内商户固定 156 人民币
		// data.put("billNo", "保险");
		// 后台通知地址
		data.put("backUrl", "这里加上域名/unpay/un_notify.do");
		/** 对请求参数进行签名并发送http post请求,接收同步应答报文 **/
		Map<String, String> reqData = AcpService.sign(data,
				DemoBase.encoding_UTF8); // 报文中certId,signature的值是在signData方法中获取并自动赋值的,只要证书配置正确即可。
		String requestBackUrl = SDKConfig.getConfig().getBackRequestUrl(); // 交易请求url从配置文件读取对应属性文件acp_sdk.properties中的
																			// acpsdk.backTransUrl
		Map<String, String> rspData = AcpService.post(reqData, requestBackUrl,
				DemoBase.encoding_UTF8); // 发送请求报文并接受同步应答(默认连接超时时间30秒,读取返回结果超时时间30秒);这里调用signData之后,调用submitUrl之前不能对submitFromData中的键值对做任何修改,如果修改会导致验签不通过
		/** 对应答码的处理,请根据您的业务逻辑来编写程序,以下应答码处理逻辑仅供参考-------------> **/
		// 应答码规范参考open.unionpay.com帮助中心 下载 产品接口规范 《平台接入接口规范-第5部分-附录》
		if (!rspData.isEmpty()) {
			if (AcpService.validate(rspData, DemoBase.encoding_UTF8)) {
				LogUtil.writeLog("验证签名成功");
				String respCode = rspData.get("respCode");
				if (("00").equals(respCode)) {
					// 交易已受理(不代表交易已成功),等待接收后台通知确定交易成功,也可以主动发起 查询交易确定交易状态。
					// TODO
					// 如果返回卡号且配置了敏感信息加密,解密卡号方法:
					// String accNo1 = resmap.get("accNo");
					// String accNo2 = AcpService.decryptPan(accNo1, "UTF-8");
					// //解密卡号使用的证书是商户签名私钥证书acpsdk.signCert.path
					// LogUtil.writeLog("解密后的卡号:"+accNo2);
				} else if (("03").equals(respCode) || ("04").equals(respCode)
						|| ("05").equals(respCode) || ("01").equals(respCode)
						|| ("12").equals(respCode) || ("34").equals(respCode)
						|| ("60").equals(respCode)) {
					// 后续需发起交易状态查询交易确定交易状态。
					// TODO
				} else {
					// 其他应答码为失败请排查原因
					// TODO
				}
			} else {
				LogUtil.writeErrorLog("验证签名失败");
				// TODO 检查验证签名失败的原因
			}
		} else {
			// 未返回正确的http状态
			LogUtil.writeErrorLog("未获取到返回报文或返回http状态码非200");
		}

		String reqMessage = DemoBase.genHtmlResult(reqData);
		String rspMessage = DemoBase.genHtmlResult(rspData);
		System.err.println(reqMessage);
		System.err.println(rspMessage);
		resp.getWriter().write(
				"代付交易</br>请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>"
						+ rspMessage + "");
	}

	// 回调
	@RequestMapping(value = "/un_notify", method = RequestMethod.POST)
	public void un_notify(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		// 支付结果通用通知文档:
		String xmlMsg = HttpKit.readData(request);
		System.out.println("支付通知=" + xmlMsg);

	}

}

下面截图 全部执行过程 以及打印:

这是程序启动 加载证书的过程

java 银联转帐 银联转账_银联_02

直接以get的方式 访问测试打款 接口

java 银联转帐 银联转账_java_03

执行接口 当中打印签名的过程

java 银联转帐 银联转账_spring_04

执行的 结果转账成功

java 银联转帐 银联转账_java_05

开始走回调  然后你在处理  后台业务流程

java 银联转帐 银联转账_银联_06