财付通 第三方支付 即时到帐支付接口

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只是一个显示成为与失败的作用,这里就不再多说了。

你可能感兴趣的:(支付,财付通)