callback interface
- Set and verify the callback address;
- Callback message format description;
- Methods for testing callback functions;
Set callback address
Function description
- Set and verify callback address
Operation path
Step1: Log in to the console
Step2: Enter the application template
Step3: Select [SMS Settings] from the menu on the right
Step4: Click to select the callback interface you want to use

Set callback address
Fill in the callback address in the console. The callback address must end with http:// or https:// At the beginning, custom ports are not supported. After filling in the callback address, it must be verified before it can be used. Verification rules:Jiguangwill give callback URL initiate a GET Requests a parameter with a random 8-digit string echostr, developers need to Response Body output as it is echostr value.
Callback method description
When there is a callback message, it will be used HTTP POST method to fill in the callback to the developer URL Submit notification message. It should be noted that if the callback fails, thenJiguangWill try again after a certain interval, up to three times. The time intervals for retrying callbacks are 3 minutes, 1 hour, and 12 hours respectively.
The basic parameters of the callback are as follows
| KEY |
REQUIRE |
DESCRIPTION |
| nonce |
Long |
Random long integer |
| signature |
String |
signature, combination appKey、appMasterSecret、nonce、timestamp generate |
| timestamp |
Long |
Current timestamp, millisecond value |
| type |
String |
notification type (SMS_REPORT/SMS_REPLY) |
| data |
String |
notification content,json String, developers can use type Deserialization data |
signatureGenerate verification rules
- Will appKey、appMasterSecret、nonce、timestamp Substitute the value into the generated string appKey={appKey}&appMasterSecret={appMasterSecret}&nonce={nonce}&timestamp={timestamp};
- Run on the generated string sha1 encryption;
- The developer takes the received signature Compare it with the signature generated by your own local code according to the same rules. If they are consistent, you can determine that this callback comes fromJiguang。
Downstream message delivery status callback parameters
| CODE |
TYPE |
DESCRIPTION |
| msgId |
String |
API Returned when calling msg_id |
| status |
Integer |
Send status return code |
| receiveTime |
Timestamp |
SMS delivery time |
| phone |
String |
SMS delivered to mobile phone number |
Send status return code
| CODE |
DESCRIPTION |
| 4001 |
Sent successfully |
| 4002 |
The called mobile phone number iscarriersBlacklist, need to contactcarriersdeal with |
| 4003 |
Mobile phone terminal problems, mobile phone shutdown, shutdown, etc. Please confirm whether the mobile phone status is normal |
| 4004 |
The called mobile phone number is empty. Please verify whether the mobile phone number is legal. |
| 4005 |
Insufficient remaining space for sending text messages |
| 4006 |
Send overclocking, send frequency exceedingcarrierslimit |
| 4007 |
Unanswered, voice message status, voice message call successful, user did not answer or refused to answer |
| 4008 |
The user is busy, voice message status, the called user is busy |
| 4009 |
Unable to connect, voice message status, not in the service area, no signal on the mobile phone, or the phone is forwarded to the incoming call reminder, etc. |
| 4010 |
Sensitive word interception, caused by the presence of sensitive words in the text message contentcarriersintercept |
| 4100 |
Other errors |
Upstream message content callback parameters
| CODE |
TYPE |
DESCRIPTION |
| phone |
String |
Calling number (user’s mobile phone number) |
| replyTime |
Date |
The message was delivered toJiguangplatform time |
| content |
String |
The message content of the user's reply |
Template review result callback parameters
| CODE |
TYPE |
DESCRIPTION |
| tempId |
Integer |
Template ID |
| status |
Integer |
Template status, 1 means passed the review, 2 means failed. |
| refuseReason |
String |
Reasons for failure to pass the review |
Signature review result callback parameters
| CODE |
TYPE |
DESCRIPTION |
| signId |
Integer |
Signature ID |
| status |
Integer |
Signature status, 1 means approved, 2 means failed. |
| refuseReason |
String |
Reasons for failure to pass the review |
callback test
Function description
- Two methods are provided for testing callback functionality:
- Console callback setting page test;
- curl simulation POST callback request;
Console callback settings page test
The developer clicks the test button in the callback settings page,JiguangA callback will be initiated to call back the fixed test data to the callback address provided by the developer. Developers can determine whether the callback request is successful by checking whether the callback request is received and whether the received data is consistent with the table below.

Uplink SMS sending content callback test data
| KEY |
VALUE |
| content |
TD |
| phone |
13000000000 |
| replyTime |
1492150740292 |
Downlink SMS sending status callback test data
| KEY |
VALUE |
| msgId |
1857496 |
| phone |
13000000000 |
| receiveTime |
1492150740292 |
| status |
4001 |
Template review results callback test data
| KEY |
VALUE |
| tempId |
57496 |
| status |
1 |
| refuseReason |
null |
Signature review result callback test data
| KEY |
VALUE |
| signId |
123 |
| status |
1 |
| refuseReason |
null |
curl simulation POST callback request
exist linux It is very convenient to use curl Command initiated HTTP POST Request, at windows Need to install curl Tool software. The following is curl Example of mocking callbacks
Upstream message content callback
curl -d "nonce=7659972084945889195&timestamp=1492150740274&signature=007eff6a105503211b472802eecc42465582ba70&type=SMS_REPLY&data={\"content\":\"TD\",\"phone\":\"13720481024\",\"replyTime\":1492150740292}" "http://localhost:8088/callback"
curl -d "nonce=7659972084945889195&timestamp=1492150740274&signature=007eff6a105503211b472802eecc42465582ba70&type=SMS_REPLY&data={\"content\":\"TD\",\"phone\":\"13720481024\",\"replyTime\":1492150740292}" "http://localhost:8088/callback"
This code block is shown in the floating window
Downstream message sending status callback
curl -d "nonce=7659972084945889195&timestamp=1492150740274&signature=007eff6a105503211b472802eecc42465582ba70&type=SMS_REPORT&data={\"msgId\":\"1652496\",\"phone\":\"15822889320\",\"receiveTime\":1492150741392,\"status\":4001}" "http://localhost:8088/callback"
curl -d "nonce=7659972084945889195&timestamp=1492150740274&signature=007eff6a105503211b472802eecc42465582ba70&type=SMS_REPORT&data={\"msgId\":\"1652496\",\"phone\":\"15822889320\",\"receiveTime\":1492150741392,\"status\":4001}" "http://localhost:8088/callback"
This code block is shown in the floating window
Template review result callback
curl -d "nonce=7659972084945889195&timestamp=1492150740274&signature=007eff6a105503211b472802eecc42465582ba70&type=SMS_TEMPLATE&data={\"tempId\":57496,\"status\":1,\"refuseReason\":null}" "http://localhost:8088/callback"
curl -d "nonce=7659972084945889195&timestamp=1492150740274&signature=007eff6a105503211b472802eecc42465582ba70&type=SMS_TEMPLATE&data={\"tempId\":57496,\"status\":1,\"refuseReason\":null}" "http://localhost:8088/callback"
This code block is shown in the floating window
Signature review result callback
curl -d "nonce=7659972084945889195&timestamp=1492150740274&signature=007eff6a105503211b472802eecc42465582ba70&type=SMS_SIGN&data={\"signId\":57496,\"status\":1,\"refuseReason\":null}" "http://localhost:8088/callback"
curl -d "nonce=7659972084945889195&timestamp=1492150740274&signature=007eff6a105503211b472802eecc42465582ba70&type=SMS_SIGN&data={\"signId\":57496,\"status\":1,\"refuseReason\":null}" "http://localhost:8088/callback"
This code block is shown in the floating window
HttpClient simulation POST callback request
The following is Java language use apache HttpClient An example of component simulation callback, the following needs to be introduced before use jar Bag:
pom.xml
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
This code block is shown in the floating window
CallbackTest.java
package cn.jiguang.sms.dev.sample;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
/**
* Created by jiguang on 2017/4/14.
*/
public class CallbackTest {
private final static String URL = "http://localhost:8088/callback"; // 开发者将自己的回调URL写入
private final static String APPKEY = "dev_sample_appKey"; // 开发者将自己的appKey写入
private final static String APPMASTERSECRET = "dev_sample_appMasterSecret"; // 开发者将自己的appMasterSecret写入
public static void main(String[] args) throws IOException {
long nonce = new Random().nextLong();
long timestamp = System.currentTimeMillis();
String str = String.format("appKey=%s&appMasterSecret=%s&nonce=%s&timestamp=%s",
APPKEY, APPMASTERSECRET, nonce, timestamp);
String signature = encrypt(str);
Map<String, Object> params = new HashMap<>();
params.put("nonce", nonce);
params.put("timestamp", timestamp);
params.put("signature", signature);
// 测试用户回复消息回调
ReplyMessage replyMessage = new ReplyMessage();
replyMessage.setPhone("13720481024");
replyMessage.setReplyTime(new Date());
replyMessage.setContent("TD");
params.put("data", JSON.toJSONString(replyMessage));
params.put("type", "SMS_REPLY");
System.out.println("post params: " + JSON.toJSONString(params));
sendPost(URL, params);
// 测试短信送达状态回调
ReportMessage reportMessage = new ReportMessage();
reportMessage.setMsgId("1652496");
reportMessage.setStatus(4001);
reportMessage.setPhone("15822889320");
reportMessage.setReceiveTime(new Date());
params.put("data", JSON.toJSONString(reportMessage));
params.put("type", "SMS_REPORT");
System.out.println("post params: " + JSON.toJSONString(params));
sendPost(URL, params);
// 测试短信模板审核结果回调
TemplateMessage templateMessage = new TemplateMessage();
templateMessage.setTempId(57496);
templateMessage.setStatus(1);
templateMessage.setRefuseReason(null);
params.put("data", JSON.toJSONString(templateMessage));
params.put("type", "SMS_TEMPLATE");
System.out.println("post params: " + JSON.toJSONString(params));
sendPost(URL, params);
}
private static void sendPost(String url, Map<String, Object> params) throws IOException {
HttpClient httpClient = HttpClients.custom().build();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> formParams = new ArrayList<>();
for (Map.Entry<String, Object> entry : params.entrySet()) {
formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
}
UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formParams, "UTF-8");
httpPost.setEntity(uefEntity);
HttpResponse response = httpClient.execute(httpPost);
System.out.println("response: " + JSON.toJSONString(response));
}
private static class ReplyMessage {
private String phone;
private Date replyTime;
private String content;
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getReplyTime() {
return replyTime;
}
public void setReplyTime(Date replayTime) {
this.replyTime = replayTime;
}
}
private static class ReportMessage {
private String msgId;
private Integer status;
private String phone;
private Date receiveTime;
public String getMsgId() {
return msgId;
}
public void setMsgId(String msgId) {
this.msgId = msgId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Date getReceiveTime() {
return receiveTime;
}
public void setReceiveTime(Date receiveTime) {
this.receiveTime = receiveTime;
}
}
private static class TemplateMessage {
private Integer tempId;
private Integer status;
private String refuseReason;
public Integer getTempId() {
return tempId;
}
public void setTempId(Integer tempId) {
this.tempId = tempId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getRefuseReason() {
return refuseReason;
}
public void setRefuseReason(String refuseReason) {
this.refuseReason = refuseReason;
}
}
/**
* SHA1加密
*
* @param strSrc 明文
* @return 加密之后的密文
*/
public static String encrypt(String strSrc) {
MessageDigest md = null;
String strDes = null;
byte[] bt = strSrc.getBytes();
try {
md = MessageDigest.getInstance("SHA-1");// 将此换成SHA-1、SHA-512、SHA-384等参数
md.update(bt);
strDes = bytes2Hex(md.digest()); // to HexString
} catch (NoSuchAlgorithmException e) {
return null;
}
return strDes;
}
/**
* byte数组转换为16进制字符串
*
* @param bts 数据源
* @return 16进制字符串
*/
private static String bytes2Hex(byte[] bts) {
String des = "";
String tmp = null;
for (int i = 0; i < bts.length; i++) {
tmp = (Integer.toHexString(bts[i] & 0xFF));
if (tmp.length() == 1) {
des += "0";
}
des += tmp;
}
return des;
}
}
package cn.jiguang.sms.dev.sample;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
public class CallbackTest {
private final static String URL = "http://localhost:8088/callback";
private final static String APPKEY = "dev_sample_appKey";
private final static String APPMASTERSECRET = "dev_sample_appMasterSecret";
public static void main(String[] args) throws IOException {
long nonce = new Random().nextLong();
long timestamp = System.currentTimeMillis();
String str = String.format("appKey=%s&appMasterSecret=%s&nonce=%s&timestamp=%s",
APPKEY, APPMASTERSECRET, nonce, timestamp);
String signature = encrypt(str);
Map<String, Object> params = new HashMap<>();
params.put("nonce", nonce);
params.put("timestamp", timestamp);
params.put("signature", signature);
ReplyMessage replyMessage = new ReplyMessage();
replyMessage.setPhone("13720481024");
replyMessage.setReplyTime(new Date());
replyMessage.setContent("TD");
params.put("data", JSON.toJSONString(replyMessage));
params.put("type", "SMS_REPLY");
System.out.println("post params: " + JSON.toJSONString(params));
sendPost(URL, params);
ReportMessage reportMessage = new ReportMessage();
reportMessage.setMsgId("1652496");
reportMessage.setStatus(4001);
reportMessage.setPhone("15822889320");
reportMessage.setReceiveTime(new Date());
params.put("data", JSON.toJSONString(reportMessage));
params.put("type", "SMS_REPORT");
System.out.println("post params: " + JSON.toJSONString(params));
sendPost(URL, params);
TemplateMessage templateMessage = new TemplateMessage();
templateMessage.setTempId(57496);
templateMessage.setStatus(1);
templateMessage.setRefuseReason(null);
params.put("data", JSON.toJSONString(templateMessage));
params.put("type", "SMS_TEMPLATE");
System.out.println("post params: " + JSON.toJSONString(params));
sendPost(URL, params);
}
private static void sendPost(String url, Map<String, Object> params) throws IOException {
HttpClient httpClient = HttpClients.custom().build();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> formParams = new ArrayList<>();
for (Map.Entry<String, Object> entry : params.entrySet()) {
formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
}
UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formParams, "UTF-8");
httpPost.setEntity(uefEntity);
HttpResponse response = httpClient.execute(httpPost);
System.out.println("response: " + JSON.toJSONString(response));
}
private static class ReplyMessage {
private String phone;
private Date replyTime;
private String content;
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getReplyTime() {
return replyTime;
}
public void setReplyTime(Date replayTime) {
this.replyTime = replayTime;
}
}
private static class ReportMessage {
private String msgId;
private Integer status;
private String phone;
private Date receiveTime;
public String getMsgId() {
return msgId;
}
public void setMsgId(String msgId) {
this.msgId = msgId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Date getReceiveTime() {
return receiveTime;
}
public void setReceiveTime(Date receiveTime) {
this.receiveTime = receiveTime;
}
}
private static class TemplateMessage {
private Integer tempId;
private Integer status;
private String refuseReason;
public Integer getTempId() {
return tempId;
}
public void setTempId(Integer tempId) {
this.tempId = tempId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getRefuseReason() {
return refuseReason;
}
public void setRefuseReason(String refuseReason) {
this.refuseReason = refuseReason;
}
}
public static String encrypt(String strSrc) {
MessageDigest md = null;
String strDes = null;
byte[] bt = strSrc.getBytes();
try {
md = MessageDigest.getInstance("SHA-1");
md.update(bt);
strDes = bytes2Hex(md.digest());
} catch (NoSuchAlgorithmException e) {
return null;
}
return strDes;
}
private static String bytes2Hex(byte[] bts) {
String des = "";
String tmp = null;
for (int i = 0; i < bts.length; i++) {
tmp = (Integer.toHexString(bts[i] & 0xFF));
if (tmp.length() == 1) {
des += "0";
}
des += tmp;
}
return des;
}
}
This code block is shown in the floating window