Total Pageviews

2016/08/08

How to send SMS via 三竹簡訊

Requirement
Our web application has SMS (short message service) requirement. Our customer asks to send short message by 三竹簡訊.

Based on its documentation, it provide 8 ways to send short message, and we choose approach 4th.


Here has an diagram to describe 三竹資訊's architecture:


We will use Http Get method to send user name, password, phone number and short message to SmGateway:


And it will return response to your source code:


The status code and its description are as follows:



How-to
The process looks like:


Here has the sample code.
This enumeration contains the status code and its description:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package albert.practice.sms;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
public enum SmsStatusCodeEnum {

    STATUS_STAR("*", "系統發生錯誤,請聯絡三竹資訊窗口人員"),
    STATUS_a("a", "簡訊發送功能暫時停止服務,請稍候再試"),
    STATUS_b("b", "簡訊發送功能暫時停止服務,請稍候再試"),
    STATUS_c("c", "請輸入帳號"),
    STATUS_d("d", "請輸入密碼"),
    STATUS_e("e", "帳號、密碼錯誤"),
    STATUS_f("f", "帳號已過期"),
    STATUS_h("h", "帳號已被停用"),
    STATUS_k("k", "無效的連線位址"),
    STATUS_m("m", "必須變更密碼,在變更密碼前,無法使用簡訊發送服務"),
    STATUS_n("n", "密碼已逾期,在變更密碼前,將無法使用簡訊發送服務"),
    STATUS_p("p", "沒有權限使用外部Http程式"),
    STATUS_r("r", "系統暫停服務,請稍後再試"),
    STATUS_s("s", "帳務處理失敗,無法發送簡訊"),
    STATUS_t("t", "簡訊已過期"),
    STATUS_u("u", "簡訊內容不得為空白"),
    STATUS_v("v", "無效的手機號碼"),
    STATUS_0("0", "預約傳送中"),
    STATUS_1("1", "已送達業者"),
    STATUS_2("2", "已送達業者"),
    STATUS_3("3", "已送達業者"),
    STATUS_4("4", "已送達手機"),
    STATUS_5("5", "內容有錯誤"),
    STATUS_6("6", "門號有錯誤"),
    STATUS_7("7", "簡訊已停用"),
    STATUS_8("8", "逾時無送達"),
    STATUS_9("9", "預約已取消");

    @Getter
    private String code;

    @Getter
    private String description;

}

This utility class is used to send short message:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package albert.practice.sms;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang.StringUtils;

import com.google.common.collect.Lists;

/**
 * username = 使用者帳號。SmGateway資料庫表格SMUser中需有此使用者,且狀態為啟用。 <br>
 * password = 使用者密碼 <br>
 * dstaddr = 受訊方手機號碼 <br>
 * DestName = 收訊人名稱。若其他系統需要與簡訊資料進行系統整合,此欄位可填入來源系統所產生的Key值,以對應回來源資料庫 <br>
 * dlvtime = 簡訊預約時間。格式為YYYY-MM-DD HH:NN:SS或YYYYMMDDHHNNSS,或是整數值代表幾秒後傳送。<br>
 * vldtime = 簡訊有效期限。格式為YYYY-MM-DD HH:NN:SS或YYYYMMDDHHNNSS,或是整數值代表傳送後幾秒後內有效。 <br>
 * smbody = 簡訊內容。必須為BIG-5編碼,長度70個中文字或是160個英數字。若有換行的需求,請填入ASCII Code 6代表換行。 <br>
 */
@Slf4j
public class SmsUtils {

    private final static String USER_AGENT = "Mozilla/5.0";

    private final String SMS_URL = "http://xxx/SmSendGet.asp?";
    private final String USER_NAME = "Test001";
    private final String PASSWORD = "TestPwd";

    public static void main(String[] args) throws Exception {
        String phone = "09";
        String smBody = "您的驗證碼為○○○○○○,請於收到簡訊10分鐘內完成驗證。";
        new SmsUtils().sendSms(phone, smBody);
    }

    public void sendSms(String phoneNumber, String body) throws Exception {
        body = URLEncoder.encode(body, "Big5");
        sendGet(phoneNumber, body);
    }

    private void sendGet(String phoneNumber, String body) throws IOException {

        StringBuilder url = new StringBuilder();
        url.append(SMS_URL);
        url.append("username=").append(USER_NAME);
        url.append("&password=").append(PASSWORD);
        url.append("&dstaddr=").append(phoneNumber);
        url.append("&smbody=").append(body);

        URL obj = null;
        BufferedReader bufferedReader = null;
        try {
            obj = new URL(url.toString());
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();

            // optional default is GET
            con.setRequestMethod("GET");

            // add request header
            con.setRequestProperty("User-Agent", USER_AGENT);

            int responseCode = con.getResponseCode();

            log.debug("\nSending 'GET' request to URL : " + url);
            log.debug("Response Code : " + responseCode);

            bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine = "";
            StringBuffer response = new StringBuffer();

            while ((inputLine = bufferedReader.readLine()) != null) {
                response.append(inputLine);
            }

            // print result
            String responseStr = response.toString();
            log.debug(responseStr);

            int from = responseStr.indexOf("statuscode=");
            int to = responseStr.indexOf("AccountPoint=");
            String tmpStr = StringUtils.substring(responseStr, from, to);

            // 取得status code
            String statusCode = StringUtils.substring(tmpStr, tmpStr.length() - 1, tmpStr.length());
            log.info("statusCode = " + statusCode);

            // 將status code 轉成 中文訊息
            String executionResult = getDescription(statusCode);
            log.info("executionResult = " + executionResult);

            List<String> successList = Lists.newArrayList("0", "1", "2", "3", "4"); // 成功的SATUSCODE
            if (!successList.contains(statusCode)) {
                throw new RuntimeException(executionResult);
            }

        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (bufferedReader != null) {
                bufferedReader.close();
            }
        }
    }

    /**
     * 將status code 轉成 中文訊息
     * 
     * @param statusCode
     * @return 中文訊息
     */
    private String getDescription(String statusCode) {
        String description = "";
        for (SmsStatusCodeEnum smsStatusCode : SmsStatusCodeEnum.values()) {
            if (smsStatusCode.getCode().equals(statusCode)) {
                description = smsStatusCode.getDescription();
            }
        }
        return description;
    }
}









No comments: