JAVA 調用第三方短信平台接口發送短信


做了幾個調用三方短信平台發送短信的例子,大部分需要 攜帶參數,向指定URL發送請求

回顧對接第一個平台時痛苦的亂碼經歷,這里放一份代碼,算是個模版,再用到的時候過來copy一下就OK。

在進入主題之前,考慮一個編碼的問題:

1、unicode,utf8,gbk,gb2312之類的指的到底是什么?為什么需要它們?

字符編碼中ASCII、Unicode和UTF-8的區別 - 風行風中 - 博客園 (cnblogs.com)

GB2312、GBK、GB18030 這幾種字符集的主要區別是什么? - 知乎 (zhihu.com)

  • 簡單來說,計算機只能識別0和1組成的二進制,所以為了顯示某一個字符,必須指定字符與二進制表示的對應關系。
  • 各種各樣的字符會組合成一個集合,集合被稱為字符表,
  • 給字符表里的字符編上一個數字,也就是字符集合到一個整數集合的映射,這個整數集合叫做字符集,而按照字符二進制表示標准進行的實現叫做編碼,我們需要它們的結合來讓屏幕顯示出我們看得懂的內容。
  • 編碼其實就是一種映射關系,將字節表示的值映射到字符集中的符號。
  • unicode是一種字符集,涵蓋了世界上所有的字符,utf8是一種用於unicode的編碼方式
  • gb2312是國內針對 ASCII 擴展的字符集,通常我們把編碼方案也叫做gb2312。GBK是對gb2312做的擴展。

​ 也就是說,gbk,gb2312和 utf8 不是一個派系的。

2、程序運行時,處於內存中的字符串是不是也具有指定的編碼?如果沒有,為什么有時候在獲取字節數組時還要指定編碼方式?

這里我看了一些文章,有了自己的理解,但是不知道理解的是否正確,先不列出來了


Get請求

  • getResponse 內將數據寫入請求的方式
  • 組織數據時對content進行URL編碼
  • 正確設置content-type
//調用處捕獲異常處理發送失敗的情況,所以代碼內不合預期的情況都是直接拋Exception
      public void send(String to, String content) throws Exception {				
    	 //username,password,content,to...參數的非空 及 格式判斷		
	 String apiRspStr = getResponse(to,content); //構建請求,獲取響應		
	 String result = resolve(apiRspStr); //解析響應數據(kv,json,html...),
  						   //成功時返回代碼,失敗時返回錯誤消息
	 if(!"0".equals(result)) {          //"0" 需要按平台文檔替換
	    throw new Exception("消息發送失敗:" + result); 
	  }	
	}
	
	private String getResponse(String to, String content) throws Exception {
		URLConnection con = null;
		OutputStreamWriter out = null;
		BufferedReader br = null;		
		String sendSmsData;
		
		try {
		    sendSmsData = organizationData(to,content);
		    log.info("請求參數為:" + sendSmsData);
		} catch (Exception e) {
			log.error("組織請求數據時出現錯誤", e);
			throw e;
		}
	             
		try {
	        URL requestUrl = new URL(getUrl());
	        con = requestUrl.openConnection();
	        con.setDoOutput(true);
	        con.setRequestProperty("Pragma", "no-cache");
	        con.setRequestProperty("Cache-Control", "no-cache");
	        con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=gb2312");  // 按短信平台的要求設置 charset的值
	
	        out = new OutputStreamWriter(con.getOutputStream());	       
	        out.write(sendSmsData);
	        out.flush();
	        out.close();
	
	        br = new BufferedReader(new InputStreamReader(con.getInputStream()));
	        String line = "";
	        StringBuffer buf = new StringBuffer();
	        while ( (line = br.readLine()) != null ) {
	            buf.append(line);
	        }
	        String responseStr = buf.toString();
	        log.info("響應數據:" + responseStr);	                               
		return responseStr;
	    } catch (IOException e) {
	        e.printStackTrace();
	        log.error("獲取響應失敗", e);
	        throw e;
	    } finally {		
		try {
		  if(out != null) {				
		      out.close();
		    }
		}catch(Exception e) {}			
		try {
		  if(br != null) {				
		    br.close();
		    }
		}catch(Exception e) {}						
	    }
	}
	
	private String organizationData(String to, String content) throws Exception {
	    StringBuilder sendBuilder = new StringBuilder();
	    sendBuilder.append("username=");//用戶登錄名
	    sendBuilder.append(getUserName());
        
	    sendBuilder.append("&password=");//密碼需要按平台要求處理;
	    sendBuilder.append(hashpwd());
	    	    	    
	    sendBuilder.append("&mobiles=");//接收手機號,限定不允許
	    sendBuilder.append(to);
	    
	    sendBuilder.append("&content=");        		
	    sendBuilder.append(URLEncoder.encode(content, "GB2312"));
				
	    return sendBuilder.toString();
	}
	
	// resolve方法 依賴於短信平台返回結果的標准,這里提供的內容脫離平台就沒有意義
	//示例代碼內 發送成功result為0,發送失敗會返回各種含義的數字,description是中文描述
	private String resolve(String rspStr) throws Exception { //rspStr: result=0&description=%B7%A2%CB%CD%B3%C9%B9%A6&faillist=
		
		String[] resultArray = rspStr.split("&");
		Map kv = new HashMap();
		for(String array : resultArray) {
			String[] elementArray = array.split("=");
			if(elementArray.length == 2) {
				kv.put(elementArray[0], elementArray[1]);
			}							
		}				
		if(kv.isEmpty()) {
			log.error("rspStr: " + rspStr);
			throw new Exception("解析返回數據時未得到結果");
		}		
		String result = "";		
		if("0".equals(kv.get("result").toString())) {
			result = "0";
			return result;
		}		
		result = URLDecoder.decode(kv.get("description").toString(),"gb2312") ;
		return result;
	}

Post請求

  • 短信內容要用URL編碼
  • 寫入請求體的數據以 List<NameValuePair> 形式組織
 public void sendSmsPost(MsgData msgData){
			
        String respContent;//響應報文
        CloseableHttpClient httpClient = null;
        try{          
            httpClient = HttpClients.createDefault();  //創建連接對象           
            HttpPost httpPost = new HttpPost(smsUrl);  //創建post對象            
            Map params = new HashMap();                //構建請求參數
           
            String phone = msgData.getMsgTo(); //接收手機號
            String text = msgData.getContent(); //發送內容            
            String gbkText = URLEncoder.encode(msgData.getContent().trim(), "GBK");
            System.out.println("短信內容GBK:" + gbkText);
            params.put("username",username);//登錄用戶名
            params.put("password",password);//登錄用戶密碼         
            params.put("to",phone); //消息接收手機號碼
            params.put("text",gbkText);   
            
            List<NameValuePair> postParams = getParams(params);
            
            httpPost.setHeader("Content-Type","application/x-www-form-urlencoded;charset=gbk");
            httpPost.setEntity(new UrlEncodedFormEntity(postParams));
            //發送http請求,獲取返回結果
            HttpResponse httpResponse = httpClient.execute(httpPost);
            if(httpResponse.getStatusLine().getStatusCode() == 200){
                //解析數據
                respContent = EntityUtils.toString(httpResponse.getEntity());
                System.out.println("響應數據:" + respContent);
            }else {
                //請求失敗
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if(httpClient != null){
                    httpClient.close();
                }
            }catch (Exception e2){
                e2.printStackTrace();
            }
        }      
    }

    /**
     * 參數解析
     * @param map
     * @return
     */
    public static List<NameValuePair> getParams(Map<String, String> map){
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        for (Map.Entry<String, String> e : entrySet) {
            String name = e.getKey();
            String value = e.getValue();
            NameValuePair pair = new BasicNameValuePair(name, value);
            params.add(pair);
        }
        return params;
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM