package com.lzl.util.sms; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import com.lzl.util.RedisTool; public class SmsUtil { private static Logger logger = Logger.getLogger(SmsUtil.class); /** * 微米帳號的接口UID */ private static String uid = "******"; /** * 微米帳號的接口密碼 */ private static String pas = "******"; /** * 微米帳號的模板ID */ private static String cid = "******"; /** * 接口返回類型:json、xml、txt。默認值爲txt */ private static String type = "json"; /** * 有效期(單位min) */ private static String p2 = "1"; /** * @author yangxy,litj * @note 微米短信發送 * @return {"code":0,"msg":"短信接口調用成功"} */ public static void send(String toTelephone, String verification) { Map<String, String> para = new HashMap<String, String>(); para.put("uid", uid); para.put("pas", pas); para.put("cid", cid); para.put("type", type); para.put("p2", p2); /** * 目標手機號碼,多個以「,」分隔,例如1391*******,138******** */ para.put("mob", toTelephone); /** * 驗證碼字符串 */ para.put("p1", verification); logger.info((HttpClientHelper.convertStreamToString(HttpClientHelper .post("http://api.weimi.cc/2/sms/send.html", para), "UTF-8"))); } /** * @author yangxy,litj * @note 微米帳號查詢短信剩餘 * @return {"sms-left":6803,"sms-sent":7,"sms-total":6810,"mms-left":5,"mms-sent" * :0,"mms-total":5,"msg":"帳戶短信彩信餘額"} * * @detail sms-left:短信剩餘條數 * @detail sms-sent:短信已發條數 * @detail sms-total:短信總條數 * @detail mms-left:彩信剩餘條數 * @detail mms-sent:彩信已發條數 * @detail mms-total:彩信總條數 * */ public static String account() { Map<String, String> para = new HashMap<String, String>(); /** * 微米帳號的接口UID */ para.put("uid", uid); /** * 微米帳號的接口密碼 */ para.put("pas", pas); /** * 接口返回類型:json、xml、txt。默認值爲txt */ para.put("type", type); return HttpClientHelper.convertStreamToString(HttpClientHelper.get( "http://api.weimi.cc/2/account/balance.html", para), "UTF-8"); } /** * 發送短信,並緩存在REDIS,1分鐘之內僅獲取緩存驗證碼 */ public static String sendSms(String toTelephone) { int dbIndex = 1;// 1庫用來存儲短信驗證碼 int expireSec = 60;// 1分鐘過時 String vCode = (String) RedisTool.get(toTelephone, dbIndex); if (StringUtils.isBlank(vCode)) { vCode = String.valueOf(Math.round(Math.random() * 8999 + 1000)); RedisTool.setWithExpire(toTelephone, vCode, expireSec, dbIndex); SmsUtil.send(toTelephone, vCode); logger.info("驗證碼發送序列爲:" + vCode + "|" + "手機號爲:" + toTelephone); } return vCode; } public static void main(String[] a) { // 發送短信 SmsUtil.sendSms("18184399267"); // 查詢剩餘短信數量 System.out.println(account()); } }
備註:html
參數uid和pas都是在註冊微米帳戶之後系統自動分配的;cid是短信模板ID號,是在提交短信模板審覈之後纔有的,指定了發送短信的模板,例如:【三隻象商城】您的驗證碼是:4569,1分鐘內有效。如非您本人操做,可忽略本消息。java
附HttpClientHelper.javaapache
package com.lzl.util.sms; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; public class HttpClientHelper { static { System.setProperty("java.net.useSystemProxies", "true"); } public enum REQUEST_METHOD { GET, POST, MULTIPART_FORM_DATA } public static InputStream get(String urlToRequest, Map<String, String> parameters) { return invokeRequest(urlToRequest, REQUEST_METHOD.GET, parameters); } public static InputStream post(String urlToRequest, Map<String, String> parameters) { return invokeRequest(urlToRequest, REQUEST_METHOD.POST, parameters); } public static String requestBodyString(String urlToRequest, Map<String, String> parameters) { return convertStreamToString( invokeRequest(urlToRequest, REQUEST_METHOD.GET, parameters), "utf-8"); } public static String postBodyString(String urlToRequest, Map<String, String> parameters) { return convertStreamToString( invokeRequest(urlToRequest, REQUEST_METHOD.POST, parameters), "utf-8"); } public static InputStream invokeRequest(String urlToRequest, REQUEST_METHOD method, Map<String, String> parameters) { if (urlToRequest == null || urlToRequest.trim().length() == 0) return null; if (parameters == null) { parameters = new HashMap<String, String>(); } String urlParameters = constructURLString(parameters); if ((method == null || REQUEST_METHOD.GET.equals(method)) && urlParameters.length() < 900 && urlParameters.length() > 0) { if (urlToRequest.indexOf("?") == -1) urlToRequest += "?" + urlParameters; else urlToRequest += "&" + urlParameters; method = REQUEST_METHOD.GET; } InputStream in = null; try { URL url = new URL(urlToRequest); System.out.println("Reuqest URL:::" + urlToRequest); HttpURLConnection con = (HttpURLConnection) url.openConnection(); OutputStream out; byte[] buff; if (REQUEST_METHOD.GET.equals(method)) { con.setRequestMethod("GET"); con.setDoOutput(false); con.setDoInput(true); con.connect(); in = con.getInputStream(); } else if (REQUEST_METHOD.MULTIPART_FORM_DATA.equals(method)) { con.setRequestMethod("POST"); con.setDoOutput(true); con.setDoInput(true); con.setUseCaches(false); con.setDefaultUseCaches(false); String boundary = MultipartFormOutputStream.createBoundary(); // The following request properties were recommended by the MPF // class con.setRequestProperty("Accept", "*/*"); con.setRequestProperty("Content-Type", MultipartFormOutputStream.getContentType(boundary)); con.setRequestProperty("Connection", "Keep-Alive"); con.setRequestProperty("Cache-Control", "no-cache"); con.connect(); MultipartFormOutputStream mpout = new MultipartFormOutputStream( con.getOutputStream(), boundary); // First, write out the parameters for (Map.Entry<String, String> entry : parameters.entrySet()) { mpout.writeField(entry.getKey(), entry.getValue()); } // Now write the image String mimeType = "image/jpg"; String fullFilePath = parameters.get("file_path"); if (fullFilePath.endsWith("gif")) { mimeType = "image/gif"; } else if (fullFilePath.endsWith("png")) { mimeType = "image/png"; } else if (fullFilePath.endsWith("tiff")) { mimeType = "image/tiff"; } mpout.writeFile("uploadFile", mimeType, new File(fullFilePath)); mpout.flush(); mpout.close(); // All done, get the InputStream in = con.getInputStream(); } else { con.setRequestMethod("POST"); con.setDoOutput(true); con.setDoInput(true); con.connect(); out = con.getOutputStream(); buff = urlParameters.getBytes("UTF8"); out.write(buff); out.flush(); out.close(); in = con.getInputStream(); } } catch (Exception e) { e.printStackTrace(); } return in; } /** * Expand the map of parameters to construct a URL string * * @param parameters * @return */ private static String constructURLString(Map<String, String> parameters) { StringBuffer url = new StringBuffer(); boolean first = true; for (Map.Entry<String, String> entry : parameters.entrySet()) { try { // type checking, we can get nulls in here if ((entry.getValue() == null) || (entry.getKey() == null)) { continue; } if (entry.getValue().length() == 0) { continue; } if (first) { first = false; } else { url.append("&"); } url.append(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue(), "UTF-8")); } catch (UnsupportedEncodingException ex) { ex.printStackTrace(); // No Fixing this, really throw new Error("Unsupported Encoding Exception", ex); } } return url.toString(); } public static String convertStreamToString(InputStream is, String encoding) { try { InputStreamReader input = new InputStreamReader(is, "UTF-8"); final int CHARS_PER_PAGE = 5000; // counting spaces final char[] buffer = new char[CHARS_PER_PAGE]; StringBuilder output = new StringBuilder(CHARS_PER_PAGE); try { for (int read = input.read(buffer, 0, buffer.length); read != -1; read = input .read(buffer, 0, buffer.length)) { output.append(buffer, 0, read); } } catch (IOException e) { e.printStackTrace(); } return output.toString(); } catch (IOException e) { e.printStackTrace(); } return ""; } } class MultipartFormOutputStream { /** * The line end characters. */ private static final String NEWLINE = "\r\n"; /** * The boundary prefix. */ private static final String PREFIX = "--"; /** * The output stream to write to. */ private DataOutputStream out = null; /** * The multipart boundary string. */ private String boundary = null; /** * Creates a new <code>MultiPartFormOutputStream</code> object using the * specified output stream and boundary. The boundary is required to be * created before using this method, as described in the description for the * <code>getContentType(String)</code> method. The boundary is only checked * for <code>null</code> or empty string, but it is recommended to be at * least 6 characters. (Or use the static createBoundary() method to create * one.) * * @param os * the output stream * @param boundary * the boundary * @see #createBoundary() * @see #getContentType(String) */ MultipartFormOutputStream(OutputStream os, String boundary) { if (os == null) { throw new IllegalArgumentException("Output stream is required."); } if (boundary == null || boundary.length() == 0) { throw new IllegalArgumentException("Boundary stream is required."); } this.out = new DataOutputStream(os); this.boundary = boundary; } /** * Writes an boolean field value. * * @param name * the field name (required) * @param value * the field value * @throws java.io.IOException * on input/output errors */ public void writeField(String name, boolean value) throws java.io.IOException { writeField(name, new Boolean(value).toString()); } /** * Writes an double field value. * * @param name * the field name (required) * @param value * the field value * @throws java.io.IOException * on input/output errors */ public void writeField(String name, double value) throws java.io.IOException { writeField(name, Double.toString(value)); } /** * Writes an float field value. * * @param name * the field name (required) * @param value * the field value * @throws java.io.IOException * on input/output errors */ public void writeField(String name, float value) throws java.io.IOException { writeField(name, Float.toString(value)); } /** * Writes an long field value. * * @param name * the field name (required) * @param value * the field value * @throws java.io.IOException * on input/output errors */ public void writeField(String name, long value) throws java.io.IOException { writeField(name, Long.toString(value)); } /** * Writes an int field value. * * @param name * the field name (required) * @param value * the field value * @throws java.io.IOException * on input/output errors */ public void writeField(String name, int value) throws java.io.IOException { writeField(name, Integer.toString(value)); } /** * Writes an short field value. * * @param name * the field name (required) * @param value * the field value * @throws java.io.IOException * on input/output errors */ public void writeField(String name, short value) throws java.io.IOException { writeField(name, Short.toString(value)); } /** * Writes an char field value. * * @param name * the field name (required) * @param value * the field value * @throws java.io.IOException * on input/output errors */ public void writeField(String name, char value) throws java.io.IOException { writeField(name, new Character(value).toString()); } /** * Writes an string field value. If the value is null, an empty string is * sent (""). * * @param name * the field name (required) * @param value * the field value * @throws java.io.IOException * on input/output errors */ public void writeField(String name, String value) throws java.io.IOException { if (name == null) { throw new IllegalArgumentException("Name cannot be null or empty."); } if (value == null) { value = ""; } /* * --boundary\r\n Content-Disposition: form-data; name="<fieldName>"\r\n * \r\n <value>\r\n */ // write boundary out.writeBytes(PREFIX); out.writeBytes(boundary); out.writeBytes(NEWLINE); // write content header out.writeBytes("Content-Disposition: form-data; name=\"" + name + "\""); out.writeBytes(NEWLINE); out.writeBytes(NEWLINE); // write content out.writeBytes(value); out.writeBytes(NEWLINE); out.flush(); } /** * Writes a file's contents. If the file is null, does not exists, or is a * directory, a <code>java.lang.IllegalArgumentException</code> will be * thrown. * * @param name * the field name * @param mimeType * the file content type (optional, recommended) * @param file * the file (the file must exist) * @throws java.io.IOException * on input/output errors */ public void writeFile(String name, String mimeType, File file) throws java.io.IOException { if (file == null) { throw new IllegalArgumentException("File cannot be null."); } if (!file.exists()) { throw new IllegalArgumentException("File does not exist."); } if (file.isDirectory()) { throw new IllegalArgumentException("File cannot be a directory."); } writeFile(name, mimeType, file.getCanonicalPath(), new FileInputStream( file)); } /** * Writes a input stream's contents. If the input stream is null, a * <code>java.lang.IllegalArgumentException</code> will be thrown. * * @param name * the field name * @param mimeType * the file content type (optional, recommended) * @param fileName * the file name (required) * @param is * the input stream * @throws java.io.IOException * on input/output errors */ public void writeFile(String name, String mimeType, String fileName, InputStream is) throws java.io.IOException { if (is == null) { throw new IllegalArgumentException("Input stream cannot be null."); } if (fileName == null || fileName.length() == 0) { throw new IllegalArgumentException( "File name cannot be null or empty."); } /* * --boundary\r\n Content-Disposition: form-data; name="<fieldName>"; * filename="<filename>"\r\n Content-Type: <mime-type>\r\n \r\n * <file-data>\r\n */ // write boundary out.writeBytes(PREFIX); out.writeBytes(boundary); out.writeBytes(NEWLINE); // write content header out.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"; filename=\"" + fileName + "\""); out.writeBytes(NEWLINE); if (mimeType != null) { out.writeBytes("Content-Type: " + mimeType); out.writeBytes(NEWLINE); } out.writeBytes(NEWLINE); // write content byte[] data = new byte[1024]; int r = 0; while ((r = is.read(data, 0, data.length)) != -1) { out.write(data, 0, r); } // close input stream, but ignore any possible exception for it try { is.close(); } catch (Exception e) { } out.writeBytes(NEWLINE); out.flush(); } /** * Writes the given bytes. The bytes are assumed to be the contents of a * file, and will be sent as such. If the data is null, a * <code>java.lang.IllegalArgumentException</code> will be thrown. * * @param name * the field name * @param mimeType * the file content type (optional, recommended) * @param fileName * the file name (required) * @param data * the file data * @throws java.io.IOException * on input/output errors */ void writeFile(String name, String mimeType, String fileName, byte[] data) throws java.io.IOException { if (data == null) { throw new IllegalArgumentException("Data cannot be null."); } if (fileName == null || fileName.length() == 0) { throw new IllegalArgumentException( "File name cannot be null or empty."); } /* * --boundary\r\n Content-Disposition: form-data; name="<fieldName>"; * filename="<filename>"\r\n Content-Type: <mime-type>\r\n \r\n * <file-data>\r\n */ // write boundary out.writeBytes(PREFIX); out.writeBytes(boundary); out.writeBytes(NEWLINE); // write content header out.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"; filename=\"" + fileName + "\""); out.writeBytes(NEWLINE); if (mimeType != null) { out.writeBytes("Content-Type: " + mimeType); out.writeBytes(NEWLINE); } out.writeBytes(NEWLINE); // write content out.write(data, 0, data.length); out.writeBytes(NEWLINE); out.flush(); } /** * Flushes the stream. Actually, this method does nothing, as the only write * methods are highly specialized and automatically flush. */ public void flush() { // out.flush(); } /** * Closes the stream. <br /> * <br /> * <b>NOTE:</b> This method <b>MUST</b> be called to finalize the multipart * stream. * * @throws java.io.IOException * on input/output errors */ public void close() throws java.io.IOException { // write final boundary out.writeBytes(PREFIX); out.writeBytes(boundary); out.writeBytes(PREFIX); out.writeBytes(NEWLINE); out.flush(); out.close(); } /** * Gets the multipart boundary string being used by this stream. * * @return the boundary */ public String getBoundary() { return this.boundary; } /** * Creates a new <code>java.net.URLConnection</code> object from the * specified <code>java.net.URL</code>. This is a convenience method which * will set the <code>doInput</code>, <code>doOutput</code>, * <code>useCaches</code> and <code>defaultUseCaches</code> fields to the * appropriate settings in the correct order. * * @return a <code>java.net.URLConnection</code> object for the URL * @throws java.io.IOException * on input/output errors */ public static URLConnection createConnection(URL url) throws java.io.IOException { URLConnection urlConn = url.openConnection(); if (urlConn instanceof HttpURLConnection) { HttpURLConnection httpConn = (HttpURLConnection) urlConn; httpConn.setRequestMethod("POST"); } urlConn.setDoInput(true); urlConn.setDoOutput(true); urlConn.setUseCaches(false); urlConn.setDefaultUseCaches(false); return urlConn; } /** * Creates a multipart boundary string by concatenating 20 hyphens (-) and * the hexadecimal (base-16) representation of the current time in * milliseconds. * * @return a multipart boundary string * @see #getContentType(String) */ public static String createBoundary() { return "--------------------" + Long.toString(System.currentTimeMillis(), 16); } /** * Gets the content type string suitable for the * <code>java.net.URLConnection</code> which includes the multipart boundary * string. <br /> * <br /> * This method is static because, due to the nature of the * <code>java.net.URLConnection</code> class, once the output stream for the * connection is acquired, it's too late to set the content type (or any * other request parameter). So one has to create a multipart boundary * string first before using this class, such as with the * <code>createBoundary()</code> method. * * @param boundary * the boundary string * @return the content type string * @see #createBoundary() */ public static String getContentType(String boundary) { return "multipart/form-data; boundary=" + boundary; } }