TenpayUtil.java
package com.test.util.tenpay.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TenpayUtil {
/**
* 把对象转换成字符串
* @param obj
* @return String 转换成字符串,若对象为null,则返回空字符串.
*/
public static String toString(Object obj) {
if(obj == null)
return "";
return obj.toString();
}
/**
* 把对象转换为int数值.
*
* @param obj 包含数字的对象.
* @return int 转换后的数值,对不能转换的对象返回0。
*/
public static int toInt(Object obj) {
int a = 0;
try {
if (obj != null)
a = Integer.parseInt(obj.toString());
} catch (Exception e) {
}
return a;
}
/**
* 获取当前时间 yyyyMMddHHmmss
* @return String
*/
public static String getCurrTime() {
Date now = new Date();
SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
String s = outFormat.format(now);
return s;
}
/**
* 获取当前日期 yyyyMMdd
* @param date
* @return String
*/
public static String formatDate(Date date) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
String strDate = formatter.format(date);
return strDate;
}
/**
* 取出一个指定长度大小的随机正整数.
* @param length int 设定所取出随机数的长度。length小于11
* @return int 返回生成的随机数。
*/
public static int buildRandom(int length) {
int num = 1;
double random = Math.random();
if (random < 0.1) {
random = random + 0.1;
}
for (int i = 0; i < length; i++) {
num = num * 10;
}
return (int) ((random * num));
}
/**
* 获取编码字符集
* @param request
* @param response
* @return String
*/
public static String getCharacterEncoding(HttpServletRequest request,
HttpServletResponse response) {
if(null == request || null == response) {
return "gbk";
}
String enc = request.getCharacterEncoding();
if(null == enc || "".equals(enc)) {
enc = response.getCharacterEncoding();
}
if(null == enc || "".equals(enc)) {
enc = "gbk";
}
return enc;
}
/**
* 获取unix时间,从1970-01-01 00:00:00开始的秒数
* @param date
* @return long
*/
public static long getUnixTime(Date date) {
if( null == date ) {
return 0;
}
return date.getTime()/1000;
}
}
MD5Util.java
package com.test.util.tenpay.util;
import java.security.MessageDigest;
public class MD5Util {
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString;
}
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
}
package com.test.util.tenpay;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.test.util.tenpay.util.MD5Util;
import com.test.util.tenpay.util.TenpayUtil;
/**
* 即时到帐请求类
* api说明:
* init(),初始化函数,默认给一些参数赋值,如cmdno,date等。
* getGateURL()/setGateURL(),获取/设置入口地址,不包含参数值
* getKey()/setKey(),获取/设置密钥
* getParameter()/setParameter(),获取/设置参数值
* getAllParameters(),获取所有参数
* getRequestURL(),获取带参数的请求URL
* doSend(),重定向到财付通支付
* getDebugInfo(),获取debug信息
*
*/
public class PayRequestHandler extends RequestHandler {
public PayRequestHandler(HttpServletRequest request, HttpServletResponse response) {
super(request, response);
//支付网关地址
this.setGateUrl("http://service.tenpay.com/cgi-bin/v3.0/payservice.cgi");
}
/**
* @Override
* 初始化函数,默认给一些参数赋值,如cmdno,date等。
*/
public void init() {
Date now = new Date();
SimpleDateFormat dfDay = new SimpleDateFormat("yyyyMMdd");
String strDay = dfDay.format(now);
//任务代码
this.setParameter("cmdno", "1");
//日期
this.setParameter("date", strDay);
//商户号
this.setParameter("bargainor_id", "");
//财付通交易单号
this.setParameter("transaction_id", "");
//商家订单号
this.setParameter("sp_billno", "");
//商品价格,以分为单位
this.setParameter("total_fee", "");
//货币类型
this.setParameter("fee_type", "1");
//返回url
this.setParameter("return_url", "");
//自定义参数
this.setParameter("attach", "");
//用户ip
this.setParameter("spbill_create_ip", "");
//商品名称
this.setParameter("desc", "");
//银行编码
this.setParameter("bank_type", "0");
//字符集编码
this.setParameter("cs", "gbk");
//摘要
this.setParameter("sign", "");
}
/**
* @Override
* 创建签名
*/
protected void createSign() {
//获取参数
String cmdno = this.getParameter("cmdno");
String date = this.getParameter("date");
String bargainor_id = this.getParameter("bargainor_id");
String transaction_id = this.getParameter("transaction_id");
String sp_billno = this.getParameter("sp_billno");
String total_fee = this.getParameter("total_fee");
String fee_type = this.getParameter("fee_type");
String return_url = this.getParameter("return_url");
String attach = this.getParameter("attach");
String spbill_create_ip = this.getParameter("spbill_create_ip");
String key = this.getKey();
//组织签名
StringBuffer sb = new StringBuffer();
sb.append("cmdno=" + cmdno + "&");
sb.append("date=" + date + "&");
sb.append("bargainor_id=" + bargainor_id + "&");
sb.append("transaction_id=" + transaction_id + "&");
sb.append("sp_billno=" + sp_billno + "&");
sb.append("total_fee=" + total_fee + "&");
sb.append("fee_type=" + fee_type + "&");
sb.append("return_url=" + return_url + "&");
sb.append("attach=" + attach + "&");
if(!"".equals(spbill_create_ip)) {
sb.append("spbill_create_ip=" + spbill_create_ip + "&");
}
sb.append("key=" + key);
String enc = TenpayUtil.getCharacterEncoding(this.getHttpServletRequest(), this.getHttpServletResponse());
//算出摘要
String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();
this.setParameter("sign", sign);
//debug信息
this.setDebugInfo(sb.toString() + " => sign:" + sign);
}
}
package com.test.util.tenpay;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.test.util.tenpay.util.MD5Util;
import com.test.util.tenpay.util.TenpayUtil;
/**
* 即时到帐应答类
* api说明:
* getKey()/setKey(),获取/设置密钥
* getParameter()/setParameter(),获取/设置参数值
* getAllParameters(),获取所有参数
* isTenpaySign(),是否财付通签名,true:是 false:否
* doShow(),显示处理结果
* getDebugInfo(),获取debug信息
*
*/
public class PayResponseHandler extends ResponseHandler {
public PayResponseHandler(HttpServletRequest request, HttpServletResponse response) {
super(request, response);
}
/**
* 是否财付通签名
* @Override
* @return boolean
*/
public boolean isTenpaySign() {
//获取参数
String cmdno = this.getParameter("cmdno");
String pay_result = this.getParameter("pay_result");
String date = this.getParameter("date");
String transaction_id = this.getParameter("transaction_id");
String sp_billno = this.getParameter("sp_billno");
String total_fee = this.getParameter("total_fee");
String fee_type = this.getParameter("fee_type");
String attach = this.getParameter("attach");
String key = this.getKey();
String tenpaySign = this.getParameter("sign").toLowerCase();
//组织签名串
StringBuffer sb = new StringBuffer();
sb.append("cmdno=" + cmdno + "&");
sb.append("pay_result=" + pay_result + "&");
sb.append("date=" + date + "&");
sb.append("transaction_id=" + transaction_id + "&");
sb.append("sp_billno=" + sp_billno + "&");
sb.append("total_fee=" + total_fee + "&");
sb.append("fee_type=" + fee_type + "&");
sb.append("attach=" + attach + "&");
sb.append("key=" + key);
String enc = TenpayUtil.getCharacterEncoding(this.getHttpServletRequest(), this.getHttpServletResponse());
//算出摘要
String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();
//debug信息
this.setDebugInfo(sb.toString() + " => sign:" + sign + " tenpaySign:" + tenpaySign);
return tenpaySign.equals(sign);
}
}
PayResponseHandler.java
package com.test.util.tenpay;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.test.util.tenpay.util.MD5Util;
import com.test.util.tenpay.util.TenpayUtil;
/**
* 即时到帐应答类
* api说明:
* getKey()/setKey(),获取/设置密钥
* getParameter()/setParameter(),获取/设置参数值
* getAllParameters(),获取所有参数
* isTenpaySign(),是否财付通签名,true:是 false:否
* doShow(),显示处理结果
* getDebugInfo(),获取debug信息
*
*/
public class PayResponseHandler extends ResponseHandler {
public PayResponseHandler(HttpServletRequest request, HttpServletResponse response) {
super(request, response);
}
/**
* 是否财付通签名
* @Override
* @return boolean
*/
public boolean isTenpaySign() {
//获取参数
String cmdno = this.getParameter("cmdno");
String pay_result = this.getParameter("pay_result");
String date = this.getParameter("date");
String transaction_id = this.getParameter("transaction_id");
String sp_billno = this.getParameter("sp_billno");
String total_fee = this.getParameter("total_fee");
String fee_type = this.getParameter("fee_type");
String attach = this.getParameter("attach");
String key = this.getKey();
String tenpaySign = this.getParameter("sign").toLowerCase();
//组织签名串
StringBuffer sb = new StringBuffer();
sb.append("cmdno=" + cmdno + "&");
sb.append("pay_result=" + pay_result + "&");
sb.append("date=" + date + "&");
sb.append("transaction_id=" + transaction_id + "&");
sb.append("sp_billno=" + sp_billno + "&");
sb.append("total_fee=" + total_fee + "&");
sb.append("fee_type=" + fee_type + "&");
sb.append("attach=" + attach + "&");
sb.append("key=" + key);
String enc = TenpayUtil.getCharacterEncoding(
this.getHttpServletRequest(), this.getHttpServletResponse());
//算出摘要
String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();
//debug信息
this.setDebugInfo(sb.toString() + " => sign:" + sign +
" tenpaySign:" + tenpaySign);
return tenpaySign.equals(sign);
}
}
RequestHandler.java
package com.test.util.tenpay;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.test.util.tenpay.util.MD5Util;
import com.test.util.tenpay.util.TenpayUtil;
/**
* 请求处理类
* 请求处理类继承此类,重写createSign方法即可。
* @author miklchen
*/
public class RequestHandler {
/** 网关url地址 */
private String gateUrl;
/** 密钥 */
private String key;
/** 请求的参数 */
private SortedMap parameters;
/** debug信息 */
private String debugInfo;
private HttpServletRequest request;
private HttpServletResponse response;
/**
* 构造函数
* @param request
* @param response
*/
public RequestHandler(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;
this.gateUrl = "http://service.tenpay.com/cgi-bin/v3.0/payservice.cgi";
this.key = "";
this.parameters = new TreeMap();
this.debugInfo = "";
}
/**
*初始化函数。
*/
public void init() {
//nothing to do
}
/**
*获取入口地址,不包含参数值
*/
public String getGateUrl() {
return gateUrl;
}
/**
*设置入口地址,不包含参数值
*/
public void setGateUrl(String gateUrl) {
this.gateUrl = gateUrl;
}
/**
*获取密钥
*/
public String getKey() {
return key;
}
/**
*设置密钥
*/
public void setKey(String key) {
this.key = key;
}
/**
* 获取参数值
* @param parameter 参数名称
* @return String
*/
public String getParameter(String parameter) {
String s = (String)this.parameters.get(parameter);
return (null == s) ? "" : s;
}
/**
* 设置参数值
* @param parameter 参数名称
* @param parameterValue 参数值
*/
public void setParameter(String parameter, String parameterValue) {
String v = "";
if(null != parameterValue) {
v = parameterValue.trim();
}
this.parameters.put(parameter, v);
}
/**
* 返回所有的参数
* @return SortedMap
*/
public SortedMap getAllParameters() {
return this.parameters;
}
/**
*获取debug信息
*/
public String getDebugInfo() {
return debugInfo;
}
/**
* 获取带参数的请求URL
* @return String
* @throws UnsupportedEncodingException
*/
public String getRequestURL() throws UnsupportedEncodingException {
this.createSign();
StringBuffer sb = new StringBuffer();
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
sb.append(k + "=" + URLEncoder.encode(v, enc) + "&");
}
//去掉最后一个&
String reqPars = sb.substring(0, sb.lastIndexOf("&"));
return this.getGateUrl() + "?" + reqPars;
}
public void doSend() throws UnsupportedEncodingException, IOException {
this.response.sendRedirect(this.getRequestURL());
}
/**
* 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
*/
protected void createSign() {
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + this.getKey());
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();
this.setParameter("sign", sign);
//debug信息
this.setDebugInfo(sb.toString() + " => sign:" + sign);
}
/**
*设置debug信息
*/
protected void setDebugInfo(String debugInfo) {
this.debugInfo = debugInfo;
}
protected HttpServletRequest getHttpServletRequest() {
return this.request;
}
protected HttpServletResponse getHttpServletResponse() {
return this.response;
}
}
ResponseHandler.java
package com.test.util.tenpay;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.test.util.tenpay.util.MD5Util;
import com.test.util.tenpay.util.TenpayUtil;
/**
* 应答处理类
* 应答处理类继承此类,重写isTenpaySign方法即可。
* @author miklchen
*
*/
public class ResponseHandler {
/** 密钥 */
private String key;
/** 应答的参数 */
private SortedMap parameters;
/** debug信息 */
private String debugInfo;
private HttpServletRequest request;
private HttpServletResponse response;
private String uriEncoding;
/**
* 构造函数
*
* @param request
* @param response
*/
public ResponseHandler(HttpServletRequest request,
HttpServletResponse response) {
this.request = request;
this.response = response;
this.key = "";
this.parameters = new TreeMap();
this.debugInfo = "";
this.uriEncoding = "";
Map m = this.request.getParameterMap();
Iterator it = m.keySet().iterator();
while (it.hasNext()) {
String k = (String) it.next();
String v = ((String[]) m.get(k))[0];
this.setParameter(k, v);
}
}
/**
*获取密钥
*/
public String getKey() {
return key;
}
/**
*设置密钥
*/
public void setKey(String key) {
this.key = key;
}
/**
* 获取参数值
* @param parameter 参数名称
* @return String
*/
public String getParameter(String parameter) {
String s = (String)this.parameters.get(parameter);
return (null == s) ? "" : s;
}
/**
* 设置参数值
* @param parameter 参数名称
* @param parameterValue 参数值
*/
public void setParameter(String parameter, String parameterValue) {
String v = "";
if(null != parameterValue) {
v = parameterValue.trim();
}
this.parameters.put(parameter, v);
}
/**
* 返回所有的参数
* @return SortedMap
*/
public SortedMap getAllParameters() {
return this.parameters;
}
/**
* 是否财付通签名,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
* @return boolean
*/
public boolean isTenpaySign() {
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(!"sign".equals(k) && null != v && !"".equals(v)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + this.getKey());
//算出摘要
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();
String tenpaySign = this.getParameter("sign").toLowerCase();
//debug信息
this.setDebugInfo(sb.toString() + " => sign:" + sign +
" tenpaySign:" + tenpaySign);
return tenpaySign.equals(sign);
}
/**
* 显示处理结果。
* @param show_url 显示处理结果的url地址,绝对url地址的形式(http://www.xxx.com/xxx.jsp)。
* @throws IOException
*/
public void doShow(String show_url) throws IOException {
String strHtml = "<html><head>\r\n" +
"<meta name=\"TENCENT_ONLINE_PAYMENT\" content=\"China TENCENT\">\r\n" +
"<script language=\"javascript\">\r\n" +
"window.location.href='" + show_url + "';\r\n" +
"</script>\r\n" +
"</head><body></body></html>";
PrintWriter out = this.getHttpServletResponse().getWriter();
out.println(strHtml);
out.flush();
out.close();
}
/**
* 获取uri编码
* @return String
*/
public String getUriEncoding() {
return uriEncoding;
}
/**
* 设置uri编码
* @param uriEncoding
* @throws UnsupportedEncodingException
*/
public void setUriEncoding(String uriEncoding)
throws UnsupportedEncodingException {
if (!"".equals(uriEncoding.trim())) {
this.uriEncoding = uriEncoding;
// 编码转换
String enc = TenpayUtil.getCharacterEncoding(request, response);
Iterator it = this.parameters.keySet().iterator();
while (it.hasNext()) {
String k = (String) it.next();
String v = this.getParameter(k);
v = new String(v.getBytes(uriEncoding.trim()), enc);
this.setParameter(k, v);
}
}
}
/**
*获取debug信息
*/
public String getDebugInfo() {
return debugInfo;
}
/**
*设置debug信息
*/
protected void setDebugInfo(String debugInfo) {
this.debugInfo = debugInfo;
}
protected HttpServletRequest getHttpServletRequest() {
return this.request;
}
protected HttpServletResponse getHttpServletResponse() {
return this.response;
}
/**
* 是否财付通签名
* @param signParameterArray 签名的参数数组
* @return boolean
*/
protected boolean isTenpaySign(String signParameterArray[]) {
StringBuffer signPars = new StringBuffer();
for(int index = 0; index < signParameterArray.length; index++) {
String k = signParameterArray[index];
String v = this.getParameter(k);
if(null != v && !"".equals(v)) {
signPars.append(k + "=" + v + "&");
}
}
signPars.append("key=" + this.getKey());
String enc = TenpayUtil.getCharacterEncoding(
this.getHttpServletRequest(), this.getHttpServletResponse());
//算出摘要
String sign = MD5Util.MD5Encode(signPars.toString(), enc).toLowerCase();
String tenpaySign = this.getParameter("sign").toLowerCase();
//debug信息
this.setDebugInfo(signPars.toString() + " => sign:" + sign +
" tenpaySign:" + tenpaySign);
return tenpaySign.equals(sign);
}
}
//以上都是一些财付通的基础类,可以拿过来直接用。
//下面是设置商户信息,也可写到到配置文件里,这里为了简单、方便起见,这里把原先写在TenpayConfig下的,直接写在支付中心的action里了。
//商户号
String bargainor_id = "1900000109";
//密钥
String key = "8934e7d15453e97507ef794cf7b0519d";
//回调通知URL,让财付通回调使用
//String return_url = "http://localhost:8080/tenpay/return_url.jsp";
String return_url=http:www.xxx.com:8080/myProject/caiftTrade.action
//当前时间 yyyyMMddHHmmss
String currTime = TenpayUtil.getCurrTime();
//8位日期
String strDate = currTime.substring(0, 8);
//6位时间
String strTime = currTime.substring(8, currTime.length());
//四位随机数
String strRandom = TenpayUtil.buildRandom(4) + "";
//10位序列号,可以自行调整。
String strReq = strTime + strRandom;
//商家订单号,长度若超过32位,取前32位。财付通只记录商家订单号,不保证唯一。
String sp_billno = strReq;
//财付通交易单号,规则为:10位商户号+8位时间(YYYYmmdd)+10位流水号
String transaction_id = bargainor_id + strDate + strReq;
//在业务逻辑层里,可以做一些订单处理,例如:商品名称,编号,价格,订单号,财付通交易单号
//从前台用户请求的信息,进行设置,这里就不再进行重复了,各位可以自己处理自己的商品信息
int totalmoney = 0.01;
String subject = "购买的商品名称";
// 订单表
OrderForm of = new OrderForm();
of.setOutTradeNo(sp_billno);// 订单号
of.setTradeNo(transaction_id);// 财付通交易单号
of.setUserId(Long.valueOf(userId));
of.setTradeStatus(0);// 表示未完成
of.setCreateTime(new Date());// 订单创建时间
of.setTotalFee(BigDecimal.valueOf(totalmoney));// 此次交易的总金额
of.setPayType(payType);
// 保存订单信息
orderFormService.save(of);
//之后,将提交本次的订单请求
getRequest().setAttribute("totalMoney",String.valueOf(totalmoney));
getRequest().setAttribute("out_trade_no", sp_billno);
getRequest().setAttribute("transaction_id", transaction_id);
getRequest().setAttribute("subject", subject);
//跳转到JSP,让JSP提交订单请求 tenpay.jsp
//import org.apache.struts2.ServletActionContext;
protected HttpServletRequest getRequest() {
return ServletActionContext.getRequest();
}
tenpay.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.Date" %>
<%@ page import="com.test.util.tenpay.util.TenpayUtil" %>
<%@ page import="com.test.util.tenpay.PayRequestHandler"%>
<%@ page import="com.test.constants.TenpayConfig"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>财付通即时到帐付款</title>
<style type="text/css">
.font_content{
font-family:"宋体";
font-size:14px;
color:#FF6600;
}
.font_title{
font-family:"宋体";
font-size:16px;
color:#FF0000;
font-weight:bold;
}
table{
border: 1px solid #CCCCCC;
}
</style>
</head>
<body>
<%
//创建PayRequestHandler实例
PayRequestHandler reqHandler = new PayRequestHandler(request, response);
//设置密钥
reqHandler.setKey(TenpayConfig.key);
//初始化
reqHandler.init();
//设置编码方式,否则如果是中文的商品名称时,财付通会出现乱码
reqHandler.setParameter("cs", "UTF-8");
//设置支付参数
//商家订单号,长度若超过32位,取前32位。财付通只记录商家订单号,不保证唯一。
String out_trade_no = (String)request.getAttribute("out_trade_no");
//商品金额,以分为单位
String total_fee = (String)request.getAttribute("totalMoney");
//财付通交易单号,规则为:10位商户号+8位时间(YYYYmmdd)+10位流水号
String transaction_id = (String)request.getAttribute("transaction_id");
String subject = (String)request.getAttribute("subject");
String temp_total_fee =(Integer.parseInt(total_fee)*100)+""; //让用户看到以元为单位金额
reqHandler.setParameter("bargainor_id", bargainor_id); //商户号
reqHandler.setParameter("sp_billno", out_trade_no); //商家订单号
reqHandler.setParameter("transaction_id", transaction_id); //财付通交易单号
reqHandler.setParameter("return_url", return_url); //支付通知url
reqHandler.setParameter("desc", subject); //商品名称
//设置金额
reqHandler.setParameter("total_fee", temp_total_fee); //商品金额,以分为单位,财付通规定不能出现任何字付,包括小数点
//用户ip,测试环境时不要加这个ip参数,正式环境再加此参数
reqHandler.setParameter("spbill_create_ip",request.getRemoteAddr());
//获取请求带参数的url
String requestUrl = reqHandler.getRequestURL();
//获取debug信息
String debuginfo = reqHandler.getDebugInfo();
//System.out.println("requestUrl:" + requestUrl);
System.out.println("debuginfo:" + debuginfo);
%>
<table align="center" width="350" cellpadding="5" cellspacing="0">
<tr>
<td align="center" class="font_title" colspan="2">订单确认</td>
</tr>
<tr>
<td class="font_content" align="right">商品名称:</td>
<td class="font_content" align="left"><%=subject%></td>
</tr>
<tr>
<td class="font_content" align="right">订单号:</td>
<td class="font_content" align="left"><%=out_trade_no%></td>
</tr>
<tr>
<td class="font_content" align="right">付款总金额:</td>
<td class="font_content" align="left"><%=total_fee%>元</td>
</tr>
<tr>
<td align="center" colspan="2"><a target="_blank" href="<%=requestUrl%>">财付通支付</a></td>
</tr>
</table>
</body>
</html>
注:
几个问题说明一下:
一、在JSP提交订单请求的时候,如果没有设置reqHandler.setParameter("cs", "UTF-8");会出现乱码,加上编码方式就可以了。
二、在支付时,当交易金额>=1元时,如果报支付失败,出现:“支付失败,您的资金未被扣除,原因可能是:您所下单网站链接有更新或者存在风险,请您稍后尝试或者与该网站客服联系”。
出现这种情况的主要原因是:
1.如果是本地调试,请务必输入支付金额<1元,比如:0.01元,这样就可以了。
2.在申请的域名下测试,也就是正式环境,可以自由输入金额,不受相关限制。也就是不会有类似的错误。
也可以直接去看它的解释:从:http://support.qq.com/cgi-bin/content_new?tid=13037268950282884&num=10&order=0&fid=565&dispn,可以看到。
//一切都成功之后,写一个让财付通回调的,同时,也做一些我们自己的业务逻辑处理。
struts.xml
<action name="caiftTrade" class="com.test.action.payment.CaiftNotify" method="caiftTrade">
<result name="success">/page/payment/cftsuccess.jsp</result>
<result name="failure">/page/payment/cftfailure.jsp</result>
// 处理财付通传过来的参数信息
public String caiftTrade() throws Exception {
//密钥
String key = "8934e7d15453e97507ef794cf7b0519d";
//创建PayResponseHandler实例
PayResponseHandler resHandler = new PayResponseHandler(request, response);
resHandler.setKey(key);
//判断签名
if(resHandler.isTenpaySign()) {
// 订单号
String out_trade_no = resHandler.getParameter("sp_billno");
//交易单号
String transaction_id = resHandler.getParameter("transaction_id");
//金额金额,以分为单位
String total_fee = resHandler.getParameter("total_fee");
//支付结果
String pay_result = resHandler.getParameter("pay_result");
if( "0".equals(pay_result) ) {
//处理业务开始
//注意交易单不要重复处理
//注意判断返回金额
OrderForm of = (OrderForm) orderFormService.findOrderFormsByOut_trade_no(out_trade_no);
of.setTradeStatus(1);
of.setTradeNo(trade_no);
of.setNotifyTime(new Date());
orderFormService.updateOldModel(of); // 更新
//其它的一些处理
//处理业务完毕
return SUCCESS;
} else {
//当做不成功处理("支付失败");
return "failure";
}
} else {
//("认证签名失败");
//String debugInfo = resHandler.getDebugInfo();
//System.out.println("debugInfo:" + debugInfo);
return "failure";
}
cftsuccess.jsp 和 cftfailure.jsp
这两个JSP只是一个显示成为与失败的作用,这里就不再多说了。