微信APP支付(Java后台生成签名具体步骤)
生活随笔
收集整理的這篇文章主要介紹了
微信APP支付(Java后台生成签名具体步骤)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
?
?
public class PayCommonUtil { //定義簽名,微信根據(jù)參數(shù)字段的ASCII碼值進行排序 加密簽名,故使用SortMap進行參數(shù)排序public static String createSign(String characterEncoding,SortedMap<String,String> parameters){
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
Object v = entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + ConstantUtil.PARTNER_KEY);//最后加密時添加商戶密鑰,由于key值放在最后,所以不用添加到SortMap里面去,單獨處理,編碼方式采用UTF-8
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}?//將封裝好的參數(shù)轉(zhuǎn)換成Xml格式類型的字符串
public static String getRequestXml(SortedMap<String,String> parameters){
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set es = 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".equalsIgnoreCase(k)){
}
else if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)) {
sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
}
else {
sb.append("<"+k+">"+v+"</"+k+">");
}
}
sb.append("<"+"sign"+">"+"<![CDATA["+parameters.get("sign")+"]]></"+"sign"+">");
sb.append("</xml>");
return sb.toString();
}
}?//微信Md5加密工具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" };
}?//微信返回的結(jié)果為Xml格式的字符串,XmlUtil主要用于解析結(jié)果public class XMLUtil {
/**
* 解析xml,返回第一級元素鍵值對。如果第一級元素有子節(jié)點,則此節(jié)點的值是子節(jié)點的xml數(shù)據(jù)。
* @param strxml
* @return
* @throws JDOMException
* @throws IOException
*/
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if(null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if(children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = XMLUtil.getChildrenText(children);
}
m.put(k, v);
}
//關(guān)閉流
in.close();
return m;
}
/**
* 獲取子結(jié)點的xml
* @param children
* @return String
*/
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if(!children.isEmpty()) {
Iterator it = children.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if(!list.isEmpty()) {
sb.append(XMLUtil.getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
}
return sb.toString();
}
/**
* 獲取xml編碼字符集
* @param strxml
* @return
* @throws IOException
* @throws JDOMException
*/
public static String getXMLEncoding(String strxml) throws JDOMException, IOException {
InputStream in = HttpClientUtil.String2Inputstream(strxml);
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
in.close();
return (String)doc.getProperty("encoding");
}
}?//發(fā)送httpspublic class CommonUtil {
private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
/**
* 發(fā)送https請求
* @param requestUrl 請求地址
* @param requestMethod 請求方式(GET、POST)
* @param outputStr 提交的數(shù)據(jù)
* @return 返回微信服務(wù)器響應(yīng)的信息
*/
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
try {
// 創(chuàng)建SSLContext對象,并使用我們指定的信任管理器初始化
MyX509TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 從上述SSLContext對象中得到SSLSocketFactory對象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 設(shè)置請求方式(GET/POST)
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 當outputStr不為null時向輸出流寫數(shù)據(jù)
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意編碼格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 從輸入流讀取返回內(nèi)容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 釋放資源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
log.error("連接超時:{}", ce);
} catch (Exception e) {
log.error("https請求異常:{}", e);
}
return null;
}
/**
* 獲取接口訪問憑證
*
* @param appid 憑證
* @param appsecret 密鑰
* @return
*//*
public static Token getToken(String appid, String appsecret) {
Token token = null;
String requestUrl = ConfigUtil.TOKEN_URL.replace("APPID", appid).replace("APPSECRET", appsecret);
// 發(fā)起GET請求獲取憑證
JSONObject jsonObject = JSONObject.fromObject(httpsRequest(requestUrl, "GET", null));
if (null != jsonObject) {
try {
token = new Token();
token.setAccessToken(jsonObject.getString("access_token"));
token.setExpiresIn(jsonObject.getInt("expires_in"));
} catch (JSONException e) {
token = null;
// 獲取token失敗
log.error("獲取token失敗 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
}
}
return token;
}
public static String urlEncodeUTF8(String source){
String result = source;
try {
result = java.net.URLEncoder.encode(source,"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}*/
}?重點:封裝參數(shù)調(diào)用統(tǒng)一下單接口,生成prepay_id(預(yù)支付訂單Id)/**
* 微信支付
* @param orderId 訂單編號
* @param actualPay 實際支付金額
* @return
*/
private String generateOrderInfoByWeiXinPay(String orderId, float actualPay,HttpServletRequest request,HttpServletResponse response) throws Exception{
String notify_url = propertiesService.WEI_XIN_NOTIFY_URL;//回調(diào)地址
String uuid = IdGen.uuid();
System.out.print("uuid" + uuid);
SortedMap<String, String> signParams = new TreeMap<String, String>();
signParams.put("appid", ConstantUtil.APP_ID);//app_id
signParams.put("body","測試");//商品參數(shù)信息
signParams.put("mch_id", ConstantUtil.PARTNER);//微信商戶賬號
signParams.put("nonce_str", uuid);//32位不重復(fù)的編號
signParams.put("notify_url", notify_url);//回調(diào)頁面
signParams.put("out_trade_no", orderId);//訂單編號
signParams.put("spbill_create_ip",request.getRemoteAddr() );//請求的實際ip地址
signParams.put("total_fee","1");//支付金額 單位為分
signParams.put("trade_type", "APP");付款類型為APP
String sign = PayCommonUtil.createSign("UTF-8", signParams);//生成簽名
signParams.put("sign", sign);
signParams.remove("key");//調(diào)用統(tǒng)一下單無需key(商戶應(yīng)用密鑰)
String requestXml = PayCommonUtil.getRequestXml(signParams);//生成Xml格式的字符串
String result = CommonUtil.httpsRequest (ConstantUtil.UNIFIED_ORDER_URL, "POST", requestXml);//以post請求的方式調(diào)用統(tǒng)一下單接口(注:ConstantUtil.UNIFIED_ORDER_URL=https://api.mch.weixin.qq.com/pay/unifiedorder;)?返回的result成功結(jié)果取出prepay_id:Map map = XMLUtil.doXMLParse(result);
String return_code=(String) map.get("return_code");
String prepay_id =null;
String returnSign=null;
String returnNonce_str=null;
if (return_code.contains("SUCCESS")){
prepay_id=(String) map.get("prepay_id");//獲取到prepay_id
}
StringBuffer weiXinVo=new StringBuffer();
long currentTimeMillis = System.currentTimeMillis();//生成時間戳
long second = currentTimeMillis / 1000L;(轉(zhuǎn)換成秒)
String seconds = String.valueOf(second).substring(0, 10);(截取前10位)
SortedMap<String, String> signParam = new TreeMap<String, String>();
signParam.put("appid", ConstantUtil.APP_ID);//app_id
signParam.put("partnerid", ConstantUtil.PARTNER);//微信商戶賬號
signParam.put("prepayid", prepay_id);//預(yù)付訂單id
signParam.put("package", "Sign=WXPay");//默認sign=WXPay
signParam.put("noncestr", uuid);//自定義不重復(fù)的長度不長于32位
signParam.put("timestamp",seconds);//北京時間時間戳
String signAgain = PayCommonUtil.createSign("UTF-8", signParam);//再次生成簽名
signParams.put("sign", signAgain);
weiXinVo.append("appid=").append(ConstantUtil.APP_ID).append("&partnerid=").append(ConstantUtil.PARTNER).append("&prepayid=").append(prepay_id).append("&package=Sign=WXPay").append("&noncestr=").append(uuid).append("×tamp=").append(seconds).append("&sign=").append(signAgain);//拼接參數(shù)返回給移動端
return weiXinVo.toString();??(注:感謝IOS團隊的聯(lián)調(diào)支持)
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/xu-xiang/p/5797575.html
總結(jié)
以上是生活随笔為你收集整理的微信APP支付(Java后台生成签名具体步骤)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Myeclipse启动报错: Inva
- 下一篇: 如何让类对象只在栈(堆)上分配空间?(转