Java呼叫微信掃碼支付介面(模式二)
前些天幫朋友實現了一個微信掃碼的介面,在之前也是不會搞這個東西,抱著試試的心態就開始看各種文件和blogs,大多數人都在吐槽微信給的java呼叫微信介面文件太含糊,而且網上的查到的資料也不詳細,只有大概的開發流程沒有太多細節上的講解,最後還是花了一些錢買了一套視訊和demo(理清了我的思路),最後完成了開發,如果有同學需要的話可以給我留言,我將免費提供幫助(可能不能及時回覆)。
(在這之間我們需要申請商家號)首先我們要理清思路要怎麼進行掃碼介面呼叫開發:
圖自己畫的不太好,見諒。
從圖中可以看出微信掃碼支付的大概流程,首先是下單,我們需要拼接一個xml(包含商戶平臺ID,價格,隨機數等資訊)傳送給微信介面,首先我們要知道,我們和微信介面之間的資訊傳遞都需要使用xml,所以在開發中xml資訊的拼接和解析是至關重要的。
①
傳送統一下單的xml,首先我們應該知道需要將哪些資訊拼接成xml資訊:
這個是我們的一些必須清單:
APP_ID
這個APP_ID我就填錯了(當時沒找到APP_ID),一直報空指標錯誤。
MCH_ID這個是商家號:
就是我塗鴉的那個部分,申請過商戶平臺賬號後會給你分配一個賬號。
API_KEY:
在這個頁面可以檢視API_KEY,如果忘了就重置一下。
NOTIFY_URL:這個是回撥地址(支付成功後,微信介面返回給我們的url,一定要是公網可以訪問的,不能是我們的本地localhost)。
CREATE_IP:這個東西可有可無,隨便填寫一個ip就行了。
//返回可生成二維碼的urlCode,這裡面用到了一些工具(拼接解析xml和傳送http請求)
String out_trade_no = "" + System.currentTimeMillis(); //訂單號
// 賬號資訊
String appid = PayConfigUtil.APP_ID; // appid
//String appsecret = PayConfigUtil.APP_SECRET; // appsecret
String mch_id = PayConfigUtil.MCH_ID; // 商業號
String key = PayConfigUtil.API_KEY; // key
String currTime = PayToolUtil.getCurrTime();
String strTime = currTime.substring(8, currTime.length());
String strRandom = PayToolUtil.buildRandom(4) + "";
String nonce_str = strTime + strRandom;
// 獲取發起電腦 ip
String spbill_create_ip = PayConfigUtil.CREATE_IP;
// 回撥介面
String notify_url = PayConfigUtil.NOTIFY_URL;
String trade_type = "NATIVE";
SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
packageParams.put("appid", appid);
//packageParams.put("appsecret", appsecret);
packageParams.put("mch_id", mch_id);
//隨機字串
packageParams.put("nonce_str", nonce_str);
packageParams.put("body", "報名費用"); //(調整為自己的名稱)
packageParams.put("out_trade_no", out_trade_no);
if(productId.equals("1")) {
packageParams.put("total_fee", "1");//一級費用240元,價格的單位為分
}else if(productId.equals("2")) {
packageParams.put("total_fee", "28000");
}else if(productId.equals("3")) {
packageParams.put("total_fee", "32000");
}else if(productId.equals("4")) {
packageParams.put("total_fee", "36000");
}else if(productId.equals("5")) {
packageParams.put("total_fee", "42000");
}else{
packageParams.put("total_fee", "48000");
}
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", notify_url);
packageParams.put("trade_type", trade_type);
String sign = PayToolUtil.createSign("UTF-8", packageParams,key);
packageParams.put("sign", sign);
String requestXML = PayToolUtil.getRequestXml(packageParams);
requestXML= requestXML.replaceAll("__", "_");
System.out.println("請求xml:"+requestXML);
//記錄請求商戶訂單號
Map<String,String> out_map = XMLUtil4jdom.doXMLParse(requestXML);
String out_no = (String) out_map.get("out_trade_no");
System.out.println("第一次商戶號:"+out_no);
//接下來儲存商戶訂單號和使用者(身份證號)對應關係
//////////////這裡執行資料庫邏輯////////////////////
String resXml = HttpUtil.postData(PayConfigUtil.UFDODER_URL, requestXML);
System.out.println("響應xml:"+resXml);
Map<String,String>map = XMLUtil4jdom.doXMLParse(resXml);
String urlCode = (String) map.get("code_url"); //code_url
//System.out.println(urlCode);
return urlCode;
我們需要知道首先我們應該將需要傳送的資訊放入map中,然後將它們拼接成xml,然後傳送給微信,然後接收來自微信的xml,我們解析這個xml,獲得url_code,就是生成二維碼的content,然後使用谷歌的生成程式碼zxing進行生成二維碼,最後將生成的二維碼通過你想要的方式傳送給前臺。
——————————————————————————————
接下來就是掃碼過後進行資訊的回調了(例如對使用者下單進行資料庫操作),可以使用外部訂單號來唯一標識訂單和使用者。
需要對微信介面回撥的資料(xml)進行解析,比對result_code結果,如果是SUCCESS就是支付成功,如果是FALSE就是支付失敗。
//讀取引數
//System.out.println("haha");
InputStream inputStream ;
StringBuffer sb = new StringBuffer();
inputStream = request.getInputStream();
String s ;
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
while ((s = in.readLine()) != null){
sb.append(s);
}
in.close();
inputStream.close();
System.out.println("回撥xml:"+sb.toString());//測試
//解析xml成map
Map<String, String> m = new HashMap<String, String>();
try {
m = XMLUtil4jdom.doXMLParse(sb.toString());
} catch (JDOMException e) {
e.printStackTrace();
}
SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
Iterator it = m.keySet().iterator();
while (it.hasNext()) {
String parameter = (String) it.next();
String parameterValue = m.get(parameter);
String v = "";
if(null != parameterValue) {
v = parameterValue.trim();
}
packageParams.put(parameter, v);
}
// 賬號資訊
String key = PayConfigUtil.API_KEY; // key
//判斷簽名是否正確
if(PayToolUtil.isTenpaySign("UTF-8", packageParams,key)) {
//------------------------------
//處理業務開始
//------------------------------
String resXml = "";
if("SUCCESS".equals((String)packageParams.get("result_code"))){
String fee = (String)packageParams.get("total_fee");
int level;
if(fee.equals("24000")) {
level = 1;
}else if(fee.equals("28000")) {
level = 2;
}else if(fee.equals("32000")) {
level = 3;
}else if(fee.equals("36000")) {
level = 4;
}else if(fee.equals("42000")) {
level = 5;
}else{
level = 6;
}
// 這裡是支付成功
//接下來對資料庫進行操作 ,先查詢訂單號對應的身份證號
String out_no = (String)packageParams.get("out_trade_no");
System.out.println("商家訂單號:"+out_no);
// Connection conn = DBUtils.getConnection();
// String sql="insert into uers values(?,?)";
//
// try {
// PreparedStatement pstmt=(PreparedStatement) conn.prepareStatement(sql);
// pstmt.setInt(0, 321333);
// pstmt.setInt(1,level);
// } catch (SQLException e) {
// e.printStackTrace();
// }
//通知微信.非同步確認成功.必寫.不然會一直通知後臺.八次之後就認為交易失敗了.
resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
} else {
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
+ "<return_msg><![CDATA[報文為空]]></return_msg>" + "</xml> ";
}
//------------------------------
//處理業務完畢
//------------------------------
BufferedOutputStream out = new BufferedOutputStream(
response.getOutputStream());
out.write(resXml.getBytes());
System.out.println("success");
out.flush();
out.close();
}
這些是用到的工具類:
關於工具類有點多,這裡就不一一給出了,如果有需要的小夥伴可以留言你的郵箱,我會一一發給你們(可能不及時),如果有不懂的地方也可以和我進行探討(QQ:1399405683),我會給你們講解。
這個例子是自己第一次做的,所以有很多不好的地方,所以還請包含。
限於篇幅,就講到這裡,如有錯誤歡迎指正。