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;
    }

posted @ 2021-08-16 15:09  化云随风去  阅读(1194)  评论(0编辑  收藏  举报