<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    休息食客

    隨心而動

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      16 隨筆 :: 7 文章 :: 2 評論 :: 0 Trackbacks
    開發之前,最好有一些微信開發的經驗,先看一下文檔,了解一下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 on 2015-09-10 15:35 休息食客 閱讀(878) 評論(0)  編輯  收藏 所屬分類: java
    主站蜘蛛池模板: 波多野结衣久久高清免费 | 国产日产亚洲系列最新| 亚洲日韩AV一区二区三区四区 | 国产成人免费AV在线播放 | 亚洲国产美女视频| 88xx成人永久免费观看| 老司机亚洲精品影院无码| 久久免费视频精品| 亚洲AV本道一区二区三区四区| 国产一精品一AV一免费| 亚洲AV无码成人精品区在线观看| 一级毛片**免费看试看20分钟 | 亚洲爽爽一区二区三区| 成人久久免费网站| 亚洲AV第一页国产精品| 30岁的女人韩剧免费观看| 亚洲中文字幕一二三四区苍井空 | 中文字幕不卡高清免费| 亚洲AV成人精品网站在线播放| 99热在线观看免费| 久久精品国产99国产精品亚洲| 毛片a级毛片免费观看免下载| 日本亚洲中午字幕乱码| 久久久久亚洲av成人无码电影 | 妞干网手机免费视频| 日韩免费码中文在线观看| 亚洲国产精品嫩草影院在线观看| 免费精品无码AV片在线观看| 亚洲精品伊人久久久久| 青青青国产色视频在线观看国产亚洲欧洲国产综合 | 红杏亚洲影院一区二区三区| 免费观看91视频| 中文字幕无码亚洲欧洲日韩| 亚洲av无码国产精品色在线看不卡| 91在线视频免费观看| 亚洲无人区视频大全| 又粗又大又硬又爽的免费视频 | 亚洲国产成人精品久久| 一级毛片直播亚洲| 久久永久免费人妻精品下载| 亚洲人成电影网站色|