通过中间企业再连接到在线银行(特征:风险大,适合小型的付款,但是维护容易)
这里用的是 易宝 作为中间企业
A.搭建Struts的环境
下载Struts的架包-->添加空项目下的lib中的包到WEB PROJECT 中的lib中
配置 struts.xml 和 xml filter的配置
B.创建Utils工具类
DigestUtil.java 这个类是用 商户(企业)的 密钥(易宝分配的)和一些付款的信息加起来产生 验证字段
package cn.xixi.utils;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
public class DigestUtil {
private static String encodingCharset = "UTF-8";
/**
* @param aValue
* @param aKey
* @return
*/
public static String hmacSign(String aValue, String aKey) {
byte k_ipad[] = new byte[64];
byte k_opad[] = new byte[64];
byte keyb[];
byte value[];
try {
keyb = aKey.getBytes(encodingCharset);
value = aValue.getBytes(encodingCharset);
} catch (UnsupportedEncodingException e) {
keyb = aKey.getBytes();
value = aValue.getBytes();
}
Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);
Arrays.fill(k_opad, keyb.length, 64, (byte) 92);
for (int i = 0; i < keyb.length; i++) {
k_ipad[i] = (byte) (keyb[i] ^ 0x36);
k_opad[i] = (byte) (keyb[i] ^ 0x5c);
}
MessageDigest md = null;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
return null;
}
md.update(k_ipad);
md.update(value);
byte dg[] = md.digest();
md.reset();
md.update(k_opad);
md.update(dg, 0, 16);
dg = md.digest();
return toHex(dg);
}
public static String toHex(byte input[]) {
if (input == null)
return null;
StringBuffer output = new StringBuffer(input.length * 2);
for (int i = 0; i < input.length; i++) {
int current = input[i] & 0xff;
if (current < 16)
output.append("0");
output.append(Integer.toString(current, 16));
}
return output.toString();
}
/**
*
* @param args
* @param key
* @return
*/
public static String getHmac(String[] args, String key) {
if (args == null || args.length == 0) {
return (null);
}
StringBuffer str = new StringBuffer();
for (int i = 0; i < args.length; i++) {
str.append(args[i]);
}
return (hmacSign(str.toString(), key));
}
/**
* @param aValue
* @return
*/
public static String digest(String aValue) {
aValue = aValue.trim();
byte value[];
try {
value = aValue.getBytes(encodingCharset);
} catch (UnsupportedEncodingException e) {
value = aValue.getBytes();
}
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
return toHex(md.digest(value));
}
}
2.使用上面的类 加上易宝要求的字段 产生 验证字段 hmac
package cn.xixi.utils;
public class payOnlineUtil {
/** *//**
* 生成hmac方法
*
* @param p0_Cmd
* 业务类型
* @param p1_MerId
* 商户编号
* @param p2_Order
* 商户订单ID号
* @param p3_Amt
* 支付金额
* @param p4_Cur
* 交易币种
* @param p5_Pid
* 商品名称
* @param p6_Pcat
* 商品种类
* @param p7_Pdesc
* 商品描述
* @param p8_Url
* 商户接受支付成功后的地址
* @param p9_SAF
* 送货地址
* @param pa_MP
* 商户扩展信息
* @param pd_FrpId
* 银行编码
* @param pr_NeedResponse
* 应答机制
* @param keyValue
* 商户密钥
* @return
*/
public static String createHmac(String p0_Cmd, String p1_MerId,
String p2_Order, String p3_Amt, String p4_Cur, String p5_Pid,
String p6_Pcat, String p7_Pdesc, String p8_Url,
String p9_SAF, String pa_MP, String pd_FrpId,
String pr_NeedResponse, String keyValue) {
StringBuffer sValue = new StringBuffer();
sValue.append(p0_Cmd);
sValue.append(p1_MerId);
sValue.append(p2_Order);
sValue.append(p3_Amt);
sValue.append(p4_Cur);
sValue.append(p5_Pid);
sValue.append(p6_Pcat);
sValue.append(p7_Pdesc);
sValue.append(p8_Url);
sValue.append(p9_SAF);
sValue.append(pa_MP);
sValue.append(pd_FrpId);
sValue.append(pr_NeedResponse);
String resultValue = DigestUtil.hmacSign(sValue.toString(), keyValue);
return resultValue;
}
/** *//**
* 返回校验hmac方法
*
* @param hmac
* 支付网关发来的加密验证码
* @param p1_MerId
* 商户编号
* @param r0_Cmd
* 业务类型
* @param r1_Code
* 支付结果
* @param r2_TrxId
* 易宝支付交易流水号
* @param r3_Amt
* 支付金额
* @param r4_Cur
* 交易币种
* @param r5_Pid
* 商品名称
* @param r6_Order
* 商户订单号
* @param r7_Uid
* 易宝支付会员ID
* @param r8_MP
* 商户扩展信息
* @param r9_BType
* 交易结果返回类型
* @param keyValue
* 密钥
* @return
*/
public static boolean verifyCallback(String hmac, String p1_MerId,
String r0_Cmd, String r1_Code, String r2_TrxId, String r3_Amt,
String r4_Cur, String r5_Pid, String r6_Order, String r7_Uid,
String r8_MP, String r9_BType, String keyValue) {
StringBuffer sValue = new StringBuffer();
// 商户编号
sValue.append(p1_MerId);
// 业务类型
sValue.append(r0_Cmd);
// 支付结果
sValue.append(r1_Code);
// 易宝支付交易流水号
sValue.append(r2_TrxId);
// 支付金额
sValue.append(r3_Amt);
// 交易币种
sValue.append(r4_Cur);
// 商品名称
sValue.append(r5_Pid);
// 商户订单号
sValue.append(r6_Order);
// 易宝支付会员ID
sValue.append(r7_Uid);
// 商户扩展信息
sValue.append(r8_MP);
// 交易结果返回类型
sValue.append(r9_BType);
String sNewString = DigestUtil.hmacSign(sValue.toString(), keyValue);
if (hmac.equals(sNewString)) {
return true;
}
return false;
}
}
3.开始写 发送请求之前的验证类 RayRequest.java 用到Spring的工具,包自己添加
package cn.xixi.actions;
import java.util.Properties;
import java.util.regex.Pattern;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import cn.xixi.utils.payOnlineUtil;
import com.opensymphony.xwork2.ActionSupport;
public class PayRequest extends ActionSupport {
/** *//**
* 生成hmac.Action
*
* @param p0_Cmd
* 业务类型
* @param p1_MerId
* 商户编号
* @param p2_Order
* 订单ID号
* @param p3_Amt
* 支付金额
* @param p4_Cur
* 交易币种
* @param p5_Pid
* 商品ID
* @param p6_Pcat
* 商品种类
* @param p7_Pdesc
* 商品描述
* @param p8_Url
* 商户接受支付成功后的地址
* @param p9_SAF
* 送货地址 "0"不需要 "1"为需要
* @param pa_MP
* 商户扩展信息
* @param pd_FrpId
* 银行编码
* @param pr_NeedResponse
* 应答机制
* @param keyValue
* 商户密钥
* @return
*/
// 从用户选择 或是 数据库获得的
private String orderid;// 订单ID p2_Order
private String amount; // 金额 p3_Amt
private String pd_FrpId; // 银行号 pd_FrpId
// 商户申请后得到的信息放在merchantInfo.properties
private String p1_MerId; // 商户ID p1_MerId
private String keyValue; // 商户密钥 keyValue
private String p8_Url; // 接受支付成功后返回的地址 p8_Url
// 一般默认值
private String p0_Cmd = "Buy";// 业务类型默认为"buy"
private String p4_Cur = "CNY";// 默认单位是人民币
private String p5_Pid = "";// 商品ID 留空
private String p6_Pcat = "";// 商品种类 留空
private String p7_Pdesc = "";// 商品描述 留空
private String p9_SAF = "0"; // 不需要地址
private String pa_Mp = ""; // 不需要商户扩展信息
private String pr_NeedResponse = "0"; // 不需要应答
private String hmacValue;
public String getOrderid() {
return orderid;
}
public void setOrderid(String orderid) {
this.orderid = orderid;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
public String getPd_FrpId() {
return pd_FrpId;
}
public void setPd_FrpId(String pd_FrpId) {
this.pd_FrpId = pd_FrpId;
}
public String getHmacValue() {
return hmacValue;
}
public void setHmacValue(String hmacValue) {
this.hmacValue = hmacValue;
}
public String getP1_MerId() {
return p1_MerId;
}
public String getP8_Url() {
return p8_Url;
}
public String getP0_Cmd() {
return p0_Cmd;
}
public String getP4_Cur() {
return p4_Cur;
}
public String getP5_Pid() {
return p5_Pid;
}
public String getP6_Pcat() {
return p6_Pcat;
}
public String getP7_Pdesc() {
return p7_Pdesc;
}
public String getP9_SAF() {
return p9_SAF;
}
public String getPa_Mp() {
return pa_Mp;
}
public String getPr_NeedResponse() {
return pr_NeedResponse;
}
// 重写 execute()和validate()方法
public String execute() throws Exception {
Properties props=PropertiesLoaderUtils.loadAllProperties("merchantInfo.properties");
p1_MerId=props.getProperty("p1_MerId");
keyValue=props.getProperty("keyValue");
p8_Url=props.getProperty("merchantCallbackURL");
// 产生hmac码
hmacValue=payOnlineUtil.createHmac(p0_Cmd, p1_MerId, orderid, amount, p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc, p8_Url, p9_SAF, pa_Mp, pd_FrpId, pr_NeedResponse, keyValue);
return SUCCESS;
}
public void validate() {
// 如果orderid amout不为空并且不在数字中
if(null==orderid||null==amount||"".equals(orderid.trim())||"".equals(amount.trim())||null==pd_FrpId||"".equals(pd_FrpId.trim())){
this.addFieldError("orderid","3项都不能为空!");
}
}
}
struts2.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="default" extends="struts-default">
<action name="payValidate" class="cn.xixi.actions.PayRequest">
<result name="input">/index.jsp</result>
<result name="success">/connect.jsp</result>
</action>
<action name="payResult" class="cn.xixi.actions.PayResult">
<result name="success" >/response.jsp</result>
</action>
</package>
</struts>
index.jsp的代码:需要输入订单号 金额 网上银行
<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>巴巴运动网_支付第一步,选择支付银行</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<H2><s:fielderror></s:fielderror></H2>
<table width="960" border="0" align="center">
<tr>
<td width="536" valign="top">
<form action="payValidate" method="post" name="paymentform">
<table width="100%" border="0">
<tr>
<td height="30" colspan="4"><table width="100%" height="50" border="0" cellpadding="0" cellspacing="1" bgcolor="#A2E0FF">
<tr>
<td align="center" bgcolor="#F7FEFF"><h3>u订单号:<INPUT TYPE="text" NAME="orderid"> 应付金额:¥<INPUT TYPE="text" NAME="amount" size="6">元</h3></td>
</tr>
</table></td>
</tr>
<tr>
<td colspan="4"> </td>
</tr>
<tr>
<td height="30" colspan="4" bgcolor="#F4F8FF"><span class="STYLE3">请您选择在线支付银行</span> </td>
</tr>
<tr>
<td width="26%" height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="CMBCHINA-NET">招商银行 </td>
<td width="25%" height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="ICBC-NET">工商银行</td>
<td width="25%" height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="ABC-NET">农业银行</td>
<td width="24%" height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="CCB-NET">建设银行 </td>
</tr>
<tr>
<td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="CMBC-NET">中国民生银行总行</td>
<td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="CEB-NET" >光大银行 </td>
<td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="BOCO-NET">交通银行</td>
<td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="SDB-NET">深圳发展银行</td>
</tr>
<tr>
<td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="BCCB-NET">北京银行</td>
<td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="CIB-NET">兴业银行 </td>
<td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="SPDB-NET">上海浦东发展银行 </td>
<td ><INPUT TYPE="radio" NAME="pd_FrpId" value="ECITIC-NET">中信银行</td>
</tr>
<tr>
<td colspan="4"> </td>
</tr>
<tr>
<td colspan="4" align="center"><input type="submit" value=" 确认支付 " /></td>
</tr>
</table>
</form> </td>
<td colspan="2" valign="top"><div class="divts"><table width="400" border="0" align="center" cellpadding="5" cellspacing="0">
<tr>
<td bgcolor="#F4F8FF"><span class="STYLE5"> 温馨提示</span></td>
</tr>
<tr>
<td><ul><li> 建行客户需到柜面签约网上银行才能支付</li>
<li>请关闭弹出窗口拦截功能</li>
<li>务必使用IE5.0以上浏览器</li>
<li>支付出错时勿按IE“后退”键</li>
</ul></td>
</tr>
</table>
</div>
<div id="blankmessage"></div> </td>
</tr>
<tr>
<td> </td>
<td width="290"> </td>
<td width="120"> </td>
</tr>
</table>
<H2><s:fielderror></s:fielderror></H2>
</body>
</html>
转发到connect.jsp
<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>连接易宝</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
</head>
<body onload="javascript:document.forms[0].submit()">
测试号的连接:http://tech.yeepay.com:8080/robot/debug.action
真实网址的连接:https://www.yeepay.com/app-merchant-proxy/node
<form name="yeepay" action="https://www.yeepay.com/app-merchant-proxy/node" method='post'>
<input type='hidden' name='p0_Cmd' value="${p0_Cmd}"> <!-- 请求命令,在线支付固定为Buy -->
<input type='hidden' name='p1_MerId' value="${p1_MerId}"> <!-- 商家ID -->
<input type="hidden" name="p2_Order" value="${orderid}"> <!-- 商家的交易定单号 -->
<input type='hidden' name='p3_Amt' value="${amount}"> <!-- 订单金额 -->
<input type='hidden' name='p4_Cur' value="${p4_Cur}"> <!-- 货币单位 -->
<input type='hidden' name='p5_Pid' value="${p5_Pid}"> <!-- 商品ID -->
<input type='hidden' name='p6_Pcat' value="${p6_Pcat}"> <!-- 商品种类 -->
<input type='hidden' name='p7_Pdesc' value="${p7_Pdesc}"> <!-- 商品描述 -->
<input type='hidden' name='p8_Url' value="${p8_Url}"> <!-- 交易结果通知地址 -->
<input type='hidden' name='p9_SAF' value="${P9_SAF}"> <!-- 需要填写送货信息 0:不需要 1:需要 -->
<input type='hidden' name='pa_MP' value="${pa_MP}"> <!-- 商家扩展信息 -->
<input type='hidden' name='pd_FrpId' value="${pd_FrpId}"> <!-- 银行ID -->
<!-- 应答机制 为“1”: 需要应答机制;为“0”: 不需要应答机制 -->
<input type="hidden" name="pr_NeedResponse" value="0">
<input type='hidden' name='hmac' value="${hmacValue}"><!-- MD5-hmac验证码 -->
<input type="submit" value="发送"/>
</form>
</body>
</html>
企业私密信息 merchantInfo.properties
p1_MerId=10000365642
keyValue=u278fHbT7JSNtox25S89342UJ3112GwDASn89YZ674445V6a183s6Aa4s3l3
merchantCallbackURL=http\://localhost\:8080/test/payResult
处理易宝返回的信息 PayResult.java
package cn.xixi.actions;
import java.util.Properties;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import cn.xixi.utils.payOnlineUtil;
import com.opensymphony.xwork2.ActionSupport;
public class PayResult extends ActionSupport {
/** *//**
* 返回校验hmac方法
*
* @param hmac
* 支付网关发来的加密验证码
* @param p1_MerId
* 商户编号
* @param r0_Cmd
* 业务类型
* @param r1_Code
* 支付结果
* @param r2_TrxId
* 易宝支付交易流水号
* @param r3_Amt
* 支付金额
* @param r4_Cur
* 交易币种
* @param r5_Pid
* 商品名称
* @param r6_Order
* 商户订单号
* @param r7_Uid
* 易宝支付会员ID
* @param r8_MP
* 商户扩展信息
* @param r9_BType
* 交易结果返回类型
* @param keyValue
* 密钥
* @param message
* 返回给用户的消息
* @return
*/
private String p1_MerId; //商号
private String r0_Cmd; //业务类型
private String r1_Code; //支付结果
private String r2_TrxId; //易宝支付交易订单号
private String r3_Amt; //支付金额
private String r4_Cur; //交易币种
private String r5_Pid; //商品名称
private String r6_Order; //商户订单号
private String r7_Uid; //易宝支付会员ID
private String r8_MP; //商户扩展信息
private String r9_BType; //交易结果返回类型 "1"为通过用户游览器 "2"为服务器点对点
private String rb_BankId; //交易的银行ID
private String ro_BankOrderId; //银行产生的订单ID
private String rp_PayDate; //付款ID
private String rq_CardNo; // 属性不是很重要
private String ru_Trxtime; // 属性不是很重要
private String hmac;
private String keyValue; //商户自己的密钥
private String message;//返回到游览器提示消息
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getR0_Cmd() {
return r0_Cmd;
}
public void setR0_Cmd(String cmd) {
r0_Cmd = cmd;
}
public String getR1_Code() {
return r1_Code;
}
public void setR1_Code(String code) {
r1_Code = code;
}
public String getR2_TrxId() {
return r2_TrxId;
}
public void setR2_TrxId(String trxId) {
r2_TrxId = trxId;
}
public String getR3_Amt() {
return r3_Amt;
}
public void setR3_Amt(String amt) {
r3_Amt = amt;
}
public String getR4_Cur() {
return r4_Cur;
}
public void setR4_Cur(String cur) {
r4_Cur = cur;
}
public String getR5_Pid() {
return r5_Pid;
}
public void setR5_Pid(String pid) {
r5_Pid = pid;
}
public String getR6_Order() {
return r6_Order;
}
public void setR6_Order(String order) {
r6_Order = order;
}
public String getR7_Uid() {
return r7_Uid;
}
public void setR7_Uid(String uid) {
r7_Uid = uid;
}
public String getR8_MP() {
return r8_MP;
}
public void setR8_MP(String r8_mp) {
r8_MP = r8_mp;
}
public String getR9_BType() {
return r9_BType;
}
public void setR9_BType(String type) {
r9_BType = type;
}
public void setRb_BankId(String rb_BankId) {
this.rb_BankId = rb_BankId;
}
public void setRo_BankOrderId(String ro_BankOrderId) {
this.ro_BankOrderId = ro_BankOrderId;
}
public void setRp_PayDate(String rp_PayDate) {
this.rp_PayDate = rp_PayDate;
}
public void setRq_CardNo(String rq_CardNo) {
this.rq_CardNo = rq_CardNo;
}
public void setRu_Trxtime(String ru_Trxtime) {
this.ru_Trxtime = ru_Trxtime;
}
public void setHmac(String hmac) {
this.hmac = hmac;
}
public String execute() throws Exception {
//获取商号和keyValue(密钥)
Properties props=PropertiesLoaderUtils.loadAllProperties("merchantInfo.properties");
p1_MerId=props.getProperty("p1_MerId");
keyValue=props.getProperty("keyValue");
boolean isLegal=payOnlineUtil.verifyCallback(hmac,p1_MerId, r0_Cmd, r1_Code, r2_TrxId, r3_Amt, r4_Cur, r5_Pid, r6_Order, r7_Uid, r8_MP, r9_BType,keyValue);
//如果验证为合法的话
if(isLegal){
//查看是否用户付钱成功 r1_Code为1表示成功
if("1".equals(r1_Code)){
message="订单号:"+r6_Order+"订单支付成功!";
//对数据库修改
message+="金额:"+r3_Amt+" M";
if("1".equals(r9_BType)){
message+="游览器重定向";
}else if("2".equals(r9_BType)){
message+="支付网关后台程序通知";
}
message+="易宝订单中自身生成的订单号:"+r2_TrxId;
}
}else{
message="数据来源不合法";
}
return SUCCESS;
}
}
结果显示:result.jsp
<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>连接结果</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
</head>
<body>
${message}
</body>
</html>