參數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,有些自己做了小改動。