休息食客

随心而动

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  16 随笔 :: 7 文章 :: 2 评论 :: 0 Trackbacks

2014年11月12日 #

当请求结束后,会受到微信服务器返回给我们的结果
处理第三节中的reback
//将接收到的返回信息
  Map<String,Object> mso = new HashMap<String,Object>();
   mso = XMLParser.getMapFromXML(reback);
需要抓取异常
写一个XMLParser类
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
 * User: rizenguo
 * Date: 2014/11/1
 * Time: 14:06
 */
public class XMLParser {
    public static Map<String,Object> getMapFromXML(String xmlString) throws ParserConfigurationException, IOException, SAXException {
        //这里用Dom的方式解析回包的最主要目的是防止API新增回包字段
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        InputStream is =  Util.getStringStream(xmlString);
        Document document = builder.parse(is);
        //获取到document里面的全部结点
        NodeList allNodes = document.getFirstChild().getChildNodes();
        Node node;
        Map<String, Object> map = new HashMap<String, Object>();
        int i=0;
        while (i < allNodes.getLength()) {
            node = allNodes.item(i);
            if(node instanceof Element){
                map.put(node.getNodeName(),node.getTextContent());
            }
            i++;
        }
        return map;
    }
   
}
好吧,到这里,已经将结果都放入一个map里面去了,,笔者自己写了一个返回类,把map里的结果都set到返回类中,
最终都返回给调用这个现金红包接口的其他业务。
大家可以参考一下
写一个WechatCashHongbaoSendRsp类
public class WechatCashHongbaoSendRsp {
 
 private String return_code;                 //返回状态码
 private String return_msg;                  //返回信息
 
 //以下字段在return_code为SUCCESS的时候有返回
 private String sign;                        //签名
 private String result_code;                 //业务结果
 private String err_code;                    //错误代码
 private String err_code_des;                //错误代码描述
 
 //以下字段在return_code和result_code都为SUCCESS的时候有返回
 private String mch_billno;                  //商户订单号
 private String mch_id;                      //商户号
 private String wxappid;                     //公众账号appid
 private String re_openid;                   //用户openid
 private String total_amount;                //付款金额
 private String send_time;                   //发放成功时间
 private String send_listid;                 //微信单号
 
 public String getReturn_code() {
  return return_code;
 }
 public void setReturn_code(String return_code) {
  this.return_code = return_code;
 }
 public String getReturn_msg() {
  return return_msg;
 }
 public void setReturn_msg(String return_msg) {
  this.return_msg = return_msg;
 }
 public String getSign() {
  return sign;
 }
 public void setSign(String sign) {
  this.sign = sign;
 }
 public String getResult_code() {
  return result_code;
 }
 public void setResult_code(String result_code) {
  this.result_code = result_code;
 }
 public String getErr_code() {
  return err_code;
 }
 public void setErr_code(String err_code) {
  this.err_code = err_code;
 }
 public String getErr_code_des() {
  return err_code_des;
 }
 public void setErr_code_des(String err_code_des) {
  this.err_code_des = err_code_des;
 }
 public String getMch_billno() {
  return mch_billno;
 }
 public void setMch_billno(String mch_billno) {
  this.mch_billno = mch_billno;
 }
 public String getMch_id() {
  return mch_id;
 }
 public void setMch_id(String mch_id) {
  this.mch_id = mch_id;
 }
 public String getWxappid() {
  return wxappid;
 }
 public void setWxappid(String wxappid) {
  this.wxappid = wxappid;
 }
 public String getRe_openid() {
  return re_openid;
 }
 public void setRe_openid(String re_openid) {
  this.re_openid = re_openid;
 }
 public String getTotal_amount() {
  return total_amount;
 }
 public void setTotal_amount(String total_amount) {
  this.total_amount = total_amount;
 }
 public String getSend_time() {
  return send_time;
 }
 public void setSend_time(String send_time) {
  this.send_time = send_time;
 }
 public String getSend_listid() {
  return send_listid;
 }
 public void setSend_listid(String send_listid) {
  this.send_listid = send_listid;
 }
}
将map里的值都set进来
WechatCashHongbaoSendRsp rsp = new WechatCashHongbaoSendRsp();
  rsp.setReturn_code(String.valueOf(mso.get("return_code")));
  rsp.setReturn_msg(String.valueOf(mso.get("return_msg")));
 
  //以下字段在return_code为SUCCESS的时候有返回
  if(String.valueOf(mso.get("return_code")).equals("SUCCESS")){
   rsp.setSign(String.valueOf(mso.get("sign")));
   rsp.setResult_code(String.valueOf(mso.get("result_code")));
   rsp.setErr_code(String.valueOf(mso.get("err_code")));
   rsp.setErr_code_des(String.valueOf(mso.get("err_code_des")));
   
   //以下字段在return_code为SUCCESS的时候有返回
   if(String.valueOf(mso.get("result_code")).equals("SUCCESS")) {
    rsp.setMch_billno(String.valueOf(mso.get("mch_billno")));
    rsp.setMch_id(String.valueOf(mso.get("mch_id")));
    rsp.setWxappid(String.valueOf(mso.get("wxappid")));
    rsp.setRe_openid(String.valueOf(mso.get("re_openid")));
    rsp.setTotal_amount(String.valueOf(mso.get("total_amount")));
    rsp.setSend_time(String.valueOf(mso.get("send_time")));
    rsp.setSend_listid(String.valueOf(mso.get("send_listid")));
   }
  }
将此结果返回出去吧!
声明:工具类代码参考微信支付开发的demo,有些自己做了小改动。

最后说一点点,开发这个应用接口,除了在加载证书那里遇到困难,其他地方还是比较顺利的,然后笔者写这篇博客,希望将
自己的研究的东西分享出去,有哪些不对的地方,或者不好的地方,请指教,毕竟当局者迷旁观者清。
posted @ 2015-09-15 11:44 休息食客 阅读(298) | 评论 (0)编辑 收藏

当把要发送的数据准备好之后,接下来是要写https请求,把它发送给微信服务器
String reback = HttpClientUtil.sendHttpsUrl("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack", data);
需要抓取异常,并处理好异常
写一个HttpClientUtil类
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import com.yxht.core.common.tools.LoadProperties;
import com.yxht.core.modules.WechatPay.client.TenpayHttpClient;
/**
 * Http客户端工具类<br/>
 * 这是内部调用类,请不要在外部调用。
 * @author miklchen
 *
 */
public class HttpClientUtil {
 
 /**
  * 发送请求(微信支付用,发红包等等)
  * @param url
  * @param params
  * @return
  * @throws Exception
  */
 public static String sendHttpsUrl(String sendUrl, String params) throws Exception{
  String jsonStr = "";
  String certificate_path = "d\:\\rootca.pem"; //信任库证书
  String keystore_path = "d\:\\apiclient_cert.p12"; //密钥库证书
  String password = "xxxxxxxx"; //商户号,也是加载证书的密码
 
  // 声明SSL上下文  
        SSLContext sslContext = null;  
        // 实例化主机名验证接口  
        sslContext = getSSLContext(password, keystore_path, certificate_path);  
        if (sslContext != null) {  
            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext  
                    .getSocketFactory());  
        }  
  URL url = new URL(sendUrl);
  HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
  con.setRequestMethod("POST");
  con.setDoOutput(true);
  con.setDoInput(true);
  con.setUseCaches(false);
  //设置套接工厂
  con.setSSLSocketFactory(sslContext.getSocketFactory());
  OutputStreamWriter writer = new OutputStreamWriter(
    con.getOutputStream(), "UTF-8");
  writer.write(params);
  writer.flush();
  writer.close();
  InputStream in = con.getInputStream();
  BufferedReader db = new BufferedReader(new InputStreamReader(in, "UTF-8"));
  String tmp = "";
  while ((tmp = db.readLine()) != null) {
   jsonStr += tmp;
  }
  return jsonStr;
 
 }
 
 /**
     * 获得SSLSocketFactory.
     * @param password
     *            密码
     * @param keyStorePath
     *            密钥库路径
     * @param trustStorePath
     *            信任库路径
     * @return SSLSocketFactory
     * @throws Exception
     */  
    public static SSLContext getSSLContext(String password,  
            String keyStorePath, String trustStorePath) throws Exception {  
        // 实例化密钥库  
        KeyManagerFactory keyManagerFactory = KeyManagerFactory  
                .getInstance(KeyManagerFactory.getDefaultAlgorithm());  
        // 获得密钥库  
        KeyStore keyStore = getKeyStore(password, keyStorePath);  
        // 初始化密钥工厂  
        keyManagerFactory.init(keyStore, password.toCharArray());  
 
        // 实例化信任库  
//        TrustManagerFactory trustManagerFactory = TrustManagerFactory  
//                .getInstance(TrustManagerFactory.getDefaultAlgorithm());  
//        // 获得信任库  
//        KeyStore trustStore = getKeyStore(password, trustStorePath);  
//        // 初始化信任库  
//        trustManagerFactory.init(trustStore);  
        // 实例化SSL上下文  
        SSLContext ctx = SSLContext.getInstance("TLS");  
        // 初始化SSL上下文  
        ctx.init(keyManagerFactory.getKeyManagers(),  
                null, null);  
        // 获得SSLSocketFactory  
        return ctx;  
    }  
   
    /**
     * 获得KeyStore.
     * @param keyStorePath
     *            密钥库路径
     * @param password
     *            密码
     * @return 密钥库
     * @throws Exception
     */  
    public static KeyStore getKeyStore(String password, String keyStorePath)  
            throws Exception {  
        // 实例化密钥库  
        KeyStore ks = KeyStore.getInstance("PKCS12");  
        // 获得密钥库文件流  
        FileInputStream is = new FileInputStream(keyStorePath);  
        // 加载密钥库  
        ks.load(is, password.toCharArray());  
        // 关闭密钥库文件流  
        is.close();  
        return ks;  
    }  
}
有些import的没用,可以删掉,只要程序代码没有报错的地方就行。
到这里,如果发送请求,会失败,它会说你没有安装证书,到商户平台上去下载证书,文档里有说明
下载后一共有4个证书,至少需要密钥库证书apiclient_cert.p12,因为信任库证书rootca.pem我不会用(哪位大神会用教教我),
文档里也说了信任库证书不用也行,证书安装请仔细研究文档,代码上面已经写好了。

最后最后,,请发送请求吧!!!

声明:工具类代码参考微信支付开发的demo,有些自己做了小改动。

PS:需要引入http相关jar包,httpcore-4.2.3.jar,httpmine-4.2.3.jar,httpclient-4.2.3.jar,httpclient-cache-4.2.3.jar。一样,
还是去https://repository.sonatype.org里面找吧,如果是maven建立的项目,就把他们引入到pom.xml里面去吧!
posted @ 2015-09-14 12:23 休息食客 阅读(349) | 评论 (0)编辑 收藏

第一节讲了怎么准备所有的参数,这里讲怎么将这些参数组成xml(即要通过HTTPS发送的数据)
大家可以先在网上了解一下java bean转xml的相关知识
1、我建了里一个请求参数类
public class WechatCashHongbaoSendReq {
 
 private String nonce_str;             //随机字符串
 private String sign;                  //签名
 private String mch_billno;            //商户订单号
 private String mch_id;                //商户号
 private String wxappid;               //公众账号appid
 private String send_name;             //商户名称
 private String re_openid;             //用户openid
 private int total_amount;          //付款金额
 private int total_num;             //红包发放总人数
 private String wishing;               //红包祝福语
 private String client_ip;             //Ip地址
 private String act_name;              //活动名称
 private String remark;                //备注
 
 public String getNonce_str() {
  return nonce_str;
 }
 public void setNonce_str(String nonce_str) {
  this.nonce_str = nonce_str;
 }
 public String getSign() {
  return sign;
 }
 public void setSign(String sign) {
  this.sign = sign;
 }
 public String getMch_billno() {
  return mch_billno;
 }
 public void setMch_billno(String mch_billno) {
  this.mch_billno = mch_billno;
 }
 public String getMch_id() {
  return mch_id;
 }
 public void setMch_id(String mch_id) {
  this.mch_id = mch_id;
 }
 public String getWxappid() {
  return wxappid;
 }
 public void setWxappid(String wxappid) {
  this.wxappid = wxappid;
 }
 public String getSend_name() {
  return send_name;
 }
 public void setSend_name(String send_name) {
  this.send_name = send_name;
 }
 public String getRe_openid() {
  return re_openid;
 }
 public void setRe_openid(String re_openid) {
  this.re_openid = re_openid;
 }
 public int getTotal_amount() {
  return total_amount;
 }
 public void setTotal_amount(int total_amount) {
  this.total_amount = total_amount;
 }
 public int getTotal_num() {
  return total_num;
 }
 public void setTotal_num(int total_num) {
  this.total_num = total_num;
 }
 public String getWishing() {
  return wishing;
 }
 public void setWishing(String wishing) {
  this.wishing = wishing;
 }
 public String getClient_ip() {
  return client_ip;
 }
 public void setClient_ip(String client_ip) {
  this.client_ip = client_ip;
 }
 public String getAct_name() {
  return act_name;
 }
 public void setAct_name(String act_name) {
  this.act_name = act_name;
 }
 public String getRemark() {
  return remark;
 }
 public void setRemark(String remark) {
  this.remark = remark;
 }
}

2、然后把13个参数都set进去
WechatCashHongbaoSendReq sendReq = new WechatCashHongbaoSendReq();
  sendReq.setNonce_str(nonce_str);
  sendReq.setSign(sign);
  sendReq.setMch_billno(mch_billno);
  sendReq.setMch_id(mch_id);
  sendReq.setWxappid(wxappid);
  sendReq.setSend_name(send_name);
  sendReq.setRe_openid(re_openid);
  sendReq.setTotal_amount(total_amount);
  sendReq.setTotal_num(total_num);
  sendReq.setWishing(wishing);
  sendReq.setClient_ip(client_ip);
  sendReq.setAct_name(act_name);
  sendReq.setRemark(remark);
3、将请求类转为xml
String data = Util.bean2XML(req).replaceAll("__", "_");    //为什么要加一个replaceAll("__", "_"),如果不加,会有什么情况,大家可以试试
写一个Util类,代码如下:
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Map;
/**
 * User: rizenguo
 * Date: 2014/10/23
 * Time: 14:59
 */
public class Util {
    //打log用
    /**
     * 通过反射的方式遍历对象的属性和属性值,方便调试
     *
     * @param o 要遍历的对象
     * @throws Exception
     */
    public static void reflect(Object o) throws Exception {
        Class cls = o.getClass();
        Field[] fields = cls.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field f = fields[i];
            f.setAccessible(true);
            Util.log(f.getName() + " -> " + f.get(o));
        }
    }
    public static byte[] readInput(InputStream in) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
        }
        out.close();
        in.close();
        return out.toByteArray();
    }
    public static String inputStreamToString(InputStream is) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int i;
        while ((i = is.read()) != -1) {
            baos.write(i);
        }
        return baos.toString();
    }
    public static InputStream getStringStream(String sInputString) throws UnsupportedEncodingException {
        ByteArrayInputStream tInputStringStream = null;
        if (sInputString != null && !sInputString.trim().equals("")) {
            tInputStringStream = new ByteArrayInputStream(sInputString.getBytes("UTF-8"));
        }
        return tInputStringStream;
    }
    public static Object getObjectFromXML(String xml, Class tClass) {
        //将从API返回的XML数据映射到Java对象
     xstream.alias("xml", tClass);
        return xstream.fromXML(xml);
    }
    public static String getStringFromMap(Map<String, Object> map, String key, String defaultValue) {
        if (key == "" || key == null) {
            return defaultValue;
        }
        String result = (String) map.get(key);
        if (result == null) {
            return defaultValue;
        } else {
            return result;
        }
    }
    public static int getIntFromMap(Map<String, Object> map, String key) {
        if (key == "" || key == null) {
            return 0;
        }
        if (map.get(key) == null) {
            return 0;
        }
        return Integer.parseInt((String) map.get(key));
    }
    /**
     * 打log接口
     * @param log 要打印的log字符串
     * @return 返回log
     */
    public static String log(Object log){
        return log.toString();
    }
    /**
     * 读取本地的xml数据,一般用来自测用
     * @param localPath 本地xml文件路径
     * @return 读到的xml字符串
     */
    public static String getLocalXMLString(String localPath) throws IOException {
        return Util.inputStreamToString(Util.class.getResourceAsStream(localPath));
    }
   
    /**
     * 将java对象转为xml字符串
     * @param clazz
     * @return
     */
    public static String bean2XML(Object o){
     xstream.alias("xml", o.getClass());
     return xstream.toXML(o);
    }
   
    /**
  * 扩展xstream,使其支持CDATA块
  *  
  * @date 2013-05-19
  */  
 private static XStream xstream = new XStream(new XppDriver() {  
     public HierarchicalStreamWriter createWriter(Writer out) {  
         return new PrettyPrintWriter(out) {  
             // 对所有xml节点的转换都增加CDATA标记  
             boolean cdata = true;  
   
             @SuppressWarnings("unchecked")  
             public void startNode(String name, Class clazz) {  
                 super.startNode(name, clazz);  
             }  
   
             protected void writeText(QuickWriter writer, String text) {  
                 if (cdata) {  
                     writer.write("<![CDATA[");  
                     writer.write(text);  
                     writer.write("]]>");  
                 } else {  
                     writer.write(text);  
                 }  
             }  
         };  
     }  
 });  
   
}
到这一步,已经完成了最终要发送出去的数据,然后是写http请求方法。
声明:工具类代码参考微信支付开发的demo,有些自己做了小改动。
PS:需要引入xstream-1.3.1.jar包,大家可以去apache中央仓库找https://repository.sonatype.org,输入xstream就可以搜索到,并下载出来,如果你的项目是maven建立的,直接在pom.xml里面加上就行
<dependency>
     <groupId>com.thoughtworks.xstream</groupId>
     <artifactId>xstream</artifactId>
     <version>1.3.1</version>
</dependency>
posted @ 2015-09-11 15:46 休息食客 阅读(317) | 评论 (0)编辑 收藏

开发之前,最好有一些微信开发的经验,先看一下文档,了解一下https://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5
文档过了一遍之后,脑海里应该有些印象了,废话不说,进入开发。
准备参数,一个一个来。
参数1:随机字符串    nonce_str
//获取随机数,这里设定长度20,只要不成长于32位
String nonce_str = RandomStringGenerator.getRandomStringByLength(20); 

写一个RandomStringGenerator类,写一个getRandomStringByLength静态方法
import java.util.Random;
/**
 * User: rizenguo
 * Date: 2014/10/29
 */
public class RandomStringGenerator {
    /**
     * 获取一定长度的随机字符串
     * @param length 指定字符串长度
     * @return 一定长度的字符串
     */
    public static String getRandomStringByLength(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
}
参数2 : 商户号   mch_id
String mch_id = “xxxxxxxx”;

参数3 : 商户订单号  mch_billno

String mch_billno = mch_id + GenerateSequenceUtil.generateSequenceNo();

些一个GenerateSequenceUtil类,写一个generateSequenceNo方法

import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.Format;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
 
import org.apache.log4j.Logger;
 
public class GenerateSequenceUtil {
 
 /** .log */
 private static final Logger logger = Logger.getLogger(GenerateSequenceUtil.class);
 
 /** The FieldPosition. */
 private static final FieldPosition HELPER_POSITION = new FieldPosition(0);
 
 /** This Format for format the data to special format. */
 private final static Format dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
 
 /** This Format for format the number to special format. */
 private final static NumberFormat numberFormat = new DecimalFormat("0000");
 
 /** This int is the sequence number ,the default value is 0. */
 private static int seq = 0;
 
 private static final int MAX = 9999;
 
 /**
 * 时间格式生成序列
 * @return String
 */
 public static synchronized String generateSequenceNo() {
 
  Calendar rightNow = Calendar.getInstance();
   
  StringBuffer sb = new StringBuffer();
   
  dateFormat.format(rightNow.getTime(), sb, HELPER_POSITION);
   
  numberFormat.format(seq, sb, HELPER_POSITION);
   
  if (seq == MAX) {
   seq = 0;
  } else {
   seq++;
  }
   
  logger.info("THE SQUENCE IS :" + sb.toString());
   
  return sb.toString();
 }

参数4: 公众账号appid   wxappid

这个参数可以在微信开发者中心里面看到
//微信分配的公众账号ID
String wxappid = "wx8888888888888888";
参数5 : 商户名称   send_name
随便写
String send_name = "测试者";   
参数6 : 用户openid   re_openid
微信号和公众号对应的唯一的加密过的字符串
String re_openid = "xxxxxxxxxxxxxxxxxxxxxxx";
参数7: 付款金额   total_amount
int total_amount = 100;    单位分
参数8 : 红包发放总人数  total_num
int total_num = 1;
参数9 : 红包祝福语   wishing
随便写
String wishing = "测试";
参数10 : Ip地址   client_ip
String client_ip = InetAddress.getLocalHost().getHostAddress().toString();
这里可能报异常,需要抓取一下
参数11 : 活动名称   act_name
随便写
String act_name = "测试创建20150906";
参数12 : 备注  remark
随便写
String remark = "测试";
最后一个参数sign
//签名
  Map<String,Object> map = new HashMap<String,Object>();
  map.put("nonce_str", nonce_str);
  map.put("mch_billno", mch_billno);
  map.put("mch_id", mch_id);
  map.put("wxappid", wxappid);
  map.put("send_name", send_name);
  map.put("re_openid", re_openid);
  map.put("total_amount", total_amount);
  map.put("total_num", total_num);
  map.put("wishing", wishing);
  map.put("client_ip", client_ip);
  map.put("act_name", act_name);
  map.put("remark", remark);
  String sign = Signature.getSign(map);
写一个Signature类,代码如下:
import org.xml.sax.SAXException;
import com.yxht.core.common.tools.LoadProperties;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
/**
 * User: rizenguo
 * Date: 2014/10/29
 * Time: 15:23
 */
public class Signature {
    /**
     * 签名算法
     * @param o 要参与签名的数据对象
     * @return 签名
     * @throws IllegalAccessException
     */
    public static String getSign(Object o) throws IllegalAccessException {
        ArrayList<String> list = new ArrayList<String>();
        Class cls = o.getClass();
        Field[] fields = cls.getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            if (f.get(o) != null && f.get(o) != "") {
                list.add(f.getName() + "=" + f.get(o) + "&");
            }
        }
        int size = list.size();
        String [] arrayToSort = list.toArray(new String[size]);
        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < size; i ++) {
            sb.append(arrayToSort[i]);
        }
        String result = sb.toString();
        result += "key=" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";   //这里是开发者中心里面服务器配置里面的消息加解密密钥
        Util.log("Sign Before MD5:" + result);
        result = MD5.MD5Encode(result).toUpperCase();
        Util.log("Sign Result:" + result);
        return result;
    }
    public static String getSign(Map<String,Object> map){
        ArrayList<String> list = new ArrayList<String>();
        for(Map.Entry<String,Object> entry:map.entrySet()){
            if(entry.getValue()!=""){
                list.add(entry.getKey() + "=" + entry.getValue() + "&");
            }
        }
        int size = list.size();
        String [] arrayToSort = list.toArray(new String[size]);
        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < size; i ++) {
            sb.append(arrayToSort[i]);
        }
        String result = sb.toString();
        result += "key=" + LoadProperties.getSystemdefaultValue("APP_KEY");
        result = MD5.MD5Encode(result).toUpperCase();
        return result;
    }
    /**
     * 从API返回的XML数据里面重新计算一次签名
     * @param responseString API返回的XML数据
     * @return 新鲜出炉的签名
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws SAXException
     */
    public static String getSignFromResponseString(String responseString) throws IOException, SAXException, ParserConfigurationException {
        Map<String,Object> map = XMLParser.getMapFromXML(responseString);
        //清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名
        map.put("sign","");
        //将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
        return Signature.getSign(map);
    }
    /**
     * 检验API返回的数据里面的签名是否合法,避免数据在传输的过程中被第三方篡改
     * @param responseString API返回的XML数据字符串
     * @return API签名是否合法
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws SAXException
     */
    public static boolean checkIsSignValidFromResponseString(String responseString) throws ParserConfigurationException, IOException, SAXException {
        Map<String,Object> map = XMLParser.getMapFromXML(responseString);
        Util.log(map.toString());
        String signFromAPIResponse = map.get("sign").toString();
        if(signFromAPIResponse=="" || signFromAPIResponse == null){
            Util.log("API返回的数据签名数据不存在,有可能被第三方篡改!!!");
            return false;
        }
        Util.log("服务器回包里面的签名是:" + signFromAPIResponse);
        //清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名
        map.put("sign","");
        //将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
        String signForAPIResponse = Signature.getSign(map);
        if(!signForAPIResponse.equals(signFromAPIResponse)){
            //签名验不过,表示这个API返回的数据有可能已经被篡改了
            Util.log("API返回的数据签名验证不通过,有可能被第三方篡改!!!");
            return false;
        }
        Util.log("恭喜,API返回的数据签名验证通过!!!");
        return true;
    }
}
先讲到这里,所有参数都准备好了,下一步是组成xml
声明:工具类代码参考微信支付开发的demo,有些自己做了小改动。
posted @ 2015-09-10 15:35 休息食客 阅读(871) | 评论 (0)编辑 收藏

     摘要: java解析xml文件的方式有几种,下面介绍用dom4j方式解析1、先看一段xml内容 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  1 <configs>  2 &nb...  阅读全文
posted @ 2015-02-11 17:23 休息食客 阅读(412) | 评论 (0)编辑 收藏

linux发行版:CentOS release 6.5 (Final)
启动系统后,没有桌面,只是一个控制台,如果要启动桌面系统,如下步骤:
1、启动系统,登录
2、vi /etc/inittab
3、将最后一行的id:3:initdefault:中的3换成5,即id:5:initdefault:.
4、wq保存退出
5、重启系统即可。

说明:如果将桌面系统切换成控制台,反过来将5换成3重启即可。 此方法只在上面说的发行版测试通过。
posted @ 2015-02-11 11:01 休息食客 阅读(350) | 评论 (1)编辑 收藏

不允许将 NULL 值赋给 NOT NULL 列"TBSPACEID=3, TABLEID=34, COLNO=29"。

SELECT C.TABSCHEMA, C.TABNAME, C.COLNAME   FROM SYSCAT.TABLES AS T,SYSCAT.COLUMNS AS C WHERE T.TBSPACEID = 3 AND T.TABLEID = 34 AND C.COLNO = 29 AND C.TABSCHEMA = T.TABSCHEMA AND C.TABNAME = T.TABNAME

找出是哪一列不能插入空值。
posted @ 2015-02-05 15:50 休息食客 阅读(385) | 评论 (0)编辑 收藏

Java获取根目录路径有很多种方法,但是根据应用程序所部署的环境和中间件不同,获取的路径可能也不同。下面我提供一种方法,解决这个问题。

         String path = InterfaceConfig.class.getResource("").getPath().toString();//获取类所在路径
         if (path.contains(".jar")) {
             path = path.replace("/", File.separator);//将/换成\,如果是linux环境,还是/
             path = path.replace("file:", "");//去掉file
             path = path.replace("classes\\", "");//去掉classes\
             if (path.startsWith("\\")) {
                 path = path.substring(1);//去掉第一个\,如:、\D:\TongWeb...  ,在linux上没有这种情况
             }
             path = path.split("WEB-INF")[0]+"WEB-INF"+File.separator+"classes";
        } else {
             path = InterfaceConfig.class.getResource("/").getPath().toString();//获取根路径
        }
        File file = new File(path + File.separator + "InterfaceConfig.xml");

这段代码什么意思呢?
1、第一行是获取InterfaceConfig.class这个类所在的路径,这个InterfaceConfig.class可以换成你这段代码所在的类。
2、判断路径中是否包含.jar,就是说这段代码所在的类最终构建的时候是不是打入jar包里,如果在jar包里,就去掉一些内容,如file: ,classes\\,
    然后根据WEB-INF切割,并拼出根目录。
3、如果没有打入jar包,那更简单了,直接通过获取根路径方法就解决了。
4、最后读取classes路径下的InterfaceConfig.xml配置文件。

posted @ 2015-01-30 15:01 休息食客 阅读(1311) | 评论 (1)编辑 收藏

create or replace trigger preventdeleted502
before delete on d502_mzdetail
for each row
begin
if deleting then raise_application_error(-200001,'不允许删除数据!');
dbms_output.PUT_LINE('不允许删除数据!');
end if;
end;

解释说明:preventdeleted502为该触发器名称,d502_mzdetail为表名,对于表d502_mzdetail如果一有删除动作,马上提示溢出错误,同时打印错误信息,那么删除动作即刻停止!
posted @ 2014-12-25 10:15 休息食客 阅读(3480) | 评论 (0)编辑 收藏

我用的是CentOS6.5 32位
1、安装ftp
sudo yum install vsftpd   (注:如果你用的是Ubuntu,命令:sudo apt-get install vsftpd)

2、配置vsftpd.conf
sudo vim /etc/vsftpd.conf (注:这里的vim是编辑器,如果没有安装,请先sudo yum install vim安装这个编辑器,当然也可以用系统自动的vi)

#禁止匿名访问 
anonymous_enable=NO
#接受本地用户
local_enable=YES
#允许上传
write_enable=YES
#用户只能访问限制的目录
chroot_local_user=YES
#设置固定目录,在结尾添加。如果不添加这一行,各用户对应自己的目录,当然这个文件夹自己建
local_root=/home/ftp

3、添加用户
sudo useradd -d /home/ftp -M loub 
sudo passwd loub

4、给文件夹授权
sudo chmod a-w /home/ftp 
sudo mkdir /home/ftp/upload
sudo mkdir /home/ftp/download
sudo chmod -R 777 /home/ftp/upload
sudo chmod -R 777 /home/ftp/download

5、
命令:
sudo vim /etc/pam.d/vsftpd
注释掉
#auth    required pam_shells.so

6、重启服务
sudo service vsftpd restart

安装ftp服务器到这里就差不多了,然后在客户机上安装一个FileZilla软件,输入服务器ip,用户名和密码,端口默认21就行了。
如果想了解vsftpd更多信息网上有很多,但我觉得有这几个步骤就差不多了,能用就行,没必要搞清楚原理。

我用ftp遇到的问题,每次当我启动了CentOS后,然后用FileZilla连上服务器,就拒绝访问,因为CentOS上的ftp没有启动,于是输入
sudo /etc/init.d/vsftpd start 就会报错:500 oops :connot read config file....
这是因为没有激活vsftpd,还要设置运行级别,那么就用root用户登录
命令:su root
命令:chkconfig --level 35 vsftpd on
命令:service vsftpd restart
就可以用FileZilla连上了。
posted @ 2014-11-12 10:00 休息食客 阅读(683) | 评论 (0)编辑 收藏