回调接口
 
      最近更新:2021-12-15
    
 
    展开全部
    
 回调接口
- 设置并校验回调地址;
- 回调消息格式说明;
- 测试回调功能的方法;
设置回调地址
功能说明
- 设置并校验回调地址
操作路径
Step1:登入控制台
Step2:进入应用模版
Step3:右侧菜单中选择[短信设置]
Step4:点击选择需要使用的回调接口
设置回调地址
在控制台填写回调地址,回调地址必须以 http:// 或 https:// 开头,不支持自定义端口。填写回调地址后需校验通过后才可以使用,校验规则:极光将给回调 URL 发起一个 GET 请求并附带一个 8 位随机字符串的参数 echostr,开发者需要在 Response Body 里原样输出 echostr 的值。
回调消息格式
回调方式说明
当有回调消息时,将采用 HTTP POST 的方式向开发者填写的回调 URL 提交通知消息。需要注意的是,如果回调失败,那么极光将会在一定的时间间隔后重试,最多重试三次。重试回调的时间间隔分别是 3 分钟、1 小时、12 小时。
回调的基础参数如下
| KEY | REQUIRE | DESCRIPTION | 
|---|---|---|
| nonce | Long | 随机长整数 | 
| signature | String | 签名,结合 appKey、appMasterSecret、nonce、timestamp 生成 | 
| timestamp | Long | 当前时间戳,毫秒值 | 
| type | String | 通知类型(SMS_REPORT/SMS_REPLY) | 
| data | String | 通知内容,json 字符串,开发者可以根据 type 反序列化 data | 
signature生成校验规则
- 将 appKey、appMasterSecret、nonce、timestamp 的值代入生成字符串 appKey={appKey}&appMasterSecret={appMasterSecret}&nonce={nonce}&timestamp={timestamp};
- 对生成的字符串进行 sha1 加密;
- 开发者把接收到的 signature 和自己本地代码按照同样规则生成的签名作对比,如果一致,则可以认定此回调来自极光。
下行消息送达状态回调参数
| CODE | TYPE | DESCRIPTION | 
|---|---|---|
| msgId | String | API 调用的时候返回的 msg_id | 
| status | Integer | 发送状态返回码 | 
| receiveTime | Timestamp | 短信送达时间 | 
| phone | String | 短信送达手机号 | 
发送状态返回码
| CODE | DESCRIPTION | 
|---|---|
| 4001 | 发送成功 | 
| 4002 | 被叫手机号码为运营商黑名单,需联系运营商处理 | 
| 4003 | 手机终端问题,手机关机、停机等,请确认手机状态是否正常 | 
| 4004 | 被叫手机号码为空号,请核实手机号码是否合规 | 
| 4005 | 可发送短信余量不足 | 
| 4006 | 发送超频,发送频率超过运营商限制 | 
| 4007 | 未应答,语音短信状态,语音短信呼叫成功,用户未接听或拒绝接听 | 
| 4008 | 用户正忙,语音短信状态,被叫用户正忙 | 
| 4009 | 无法接通,语音短信状态,不在服务区、手机无信号或电话被转入来电提醒等 | 
| 4010 | 敏感词拦截,因短信内容存在敏感词导致运营商拦截 | 
| 4100 | 其他错误 | 
上行消息内容回调参数
| CODE | TYPE | DESCRIPTION | 
|---|---|---|
| phone | String | 主叫号码(用户手机号码) | 
| replyTime | Date | 消息送达到极光平台的时间 | 
| content | String | 用户回复的消息内容 | 
模板审核结果回调参数
| CODE | TYPE | DESCRIPTION | 
|---|---|---|
| tempId | Integer | 模板ID | 
| status | Integer | 模板状态,1代表审核通过,2代表审核不通过 | 
| refuseReason | String | 审核不通过的原因 | 
签名审核结果回调参数
| CODE | TYPE | DESCRIPTION | 
|---|---|---|
| signId | Integer | 签名ID | 
| status | Integer | 签名状态,1代表审核通过,2代表审核不通过 | 
| refuseReason | String | 审核不通过的原因 | 
回调测试
功能说明
- 提供两种测试回调功能的方法:
- 控制台回调设置页面测试;
- curl 模拟 POST 回调请求;
控制台回调设置页面测试
开发者点击回调设置页面中的测试按钮,极光将发起一次回调,将固定的测试数据回调到开发者提供的回调地址上。开发者可以通过检查是否收到回调请求,且接收到的数据是否与下面表格中一致以判断回调请求是否成功。
上行短信发送内容回调测试数据
| KEY | VALUE | 
|---|---|
| content | TD | 
| phone | 13000000000 | 
| replyTime | 1492150740292 | 
下行短信发送状态回调测试数据
| KEY | VALUE | 
|---|---|
| msgId | 1857496 | 
| phone | 13000000000 | 
| receiveTime | 1492150740292 | 
| status | 4001 | 
模板审核结果回调测试数据
| KEY | VALUE | 
|---|---|
| tempId | 57496 | 
| status | 1 | 
| refuseReason | null | 
签名审核结果回调测试数据
| KEY | VALUE | 
|---|---|
| signId | 123 | 
| status | 1 | 
| refuseReason | null | 
curl 模拟 POST 回调请求
在 linux 上可以很方便的使用 curl 命令发起 HTTP POST 请求,在 windows 下需要安装 curl 工具软件。以下是 curl 模拟回调的示例
上行消息内容回调
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"
        
        此代码块在浮窗中显示
      下行消息发送状态回调
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"
        
        此代码块在浮窗中显示
      模板审核结果回调
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"
        
        此代码块在浮窗中显示
      签名审核结果回调
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"
        
        此代码块在浮窗中显示
      HttpClient 模拟 POST 回调请求
以下是 Java 语言使用 apache HttpClient 组件模拟回调的示例,使用前需引入以下 jar 包:
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>   
        
        此代码块在浮窗中显示
      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.*;  
 
/**  
 * 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;
    }
}
        
        此代码块在浮窗中显示
      文档内容是否对您有帮助?
  
   
 