Administrator
Administrator
发布于 2024-12-06 / 11 阅读
0
0

C语言对接短信

C语言在魔方财务系统中集成零零七云计算短信服务详解

目录

  1. 简介
  2. 前提条件
  3. 安装与配置
  4. API接口对接
  5. 错误处理
  6. 实用C语言代码示例
  7. 附录:常见错误码说明
  8. 总结

简介

本文档详细介绍了如何使用C语言在魔方财务系统中集成零零七云计算(007IDC)提供的短信服务。通过系统调用,实现国内/国际短信通知、短信验证、用户请求验证等功能。文档涵盖了插件对接的前提条件、安装配置步骤、API接口的详细说明及C语言代码示例,帮助开发者高效地完成短信服务的集成。


前提条件

在开始集成之前,请确保满足以下条件:

  1. 购买短信资源包:在启用该应用之前,请确保已在零零七云计算(007IDC)购买了短信资源包。
  2. 获取账号信息
    • 短信服务地址:访问零零七云计算(007IDC)的短信服务购买页面(新用户注册点击注册)。
    • 平台账号密码:获取零零七云计算(007IDC)平台的账号和密码。
    • 短信额度:大量短信额度价格可商量,不能过低。如有问题,请联系客服经理:1485174354。

安装与配置

购买并配置短信插件

  1. 购买插件

    • 购买插件后,登录魔方财务后台。
    • 导航至 系统 > 短信邮件设置 > 接口设置 > 短信设置 管理页面。
    • 找到 零零七云计算·云通信,点击右侧 安装 按钮进行安装。
  2. 配置插件

    • 安装完成后,点击右侧 配置 按钮。
    • 填写相关配置信息,包括 appkeyappCodeappSecret 等。
    • 保存配置。
  3. 配置短信模板

    • 打开 短信模板 页面,将供应商切换为 零零七短信平台
    • 勾选需要使用的短信模板并提交审核。
  4. 发送设置

    • 审核通过后,点击 发送设置 页面,将供应商切换为 零零七短信平台
    • 保存设置后,点击 测试发送 以验证配置是否成功。

手动安装(如自动安装失败)

  1. 点击应用商店上方的 我的 按钮,找到该插件。
  2. 点击 安装下载 按钮,进行立即安装或重新下载。

API接口对接

零零七云计算提供多种API接口,用于发送短信、接收状态报告、查询余额等。以下详细介绍各个API接口的使用方法及C语言实现方式。

1. 一对多群发短信

接口地址http://sms.007idc.cn:9090/sms/batch/v1

请求方式POST

请求头

  • Content-Type: application/json

请求参数

参数名称 参数说明 备注
appkey 应用key-登录账号 *必填,由供应商提供
appcode 应用代码-默认1000 *必填,由供应商提供,默认为1000
sign 短信签名验证MD5(appkey+appsecret+timestamp) *必填,秘钥 appsecret 由供应商提供,由 appkey + appsecret + timestamp 经过 MD5 加密后的32位16进制小写字符串(拼接过程不包括 +
phone 手机号码 *必填,多个号码用半角英文逗号隔开,一次最多不能超过1000个
msg 下发短信内容 *必填,短信内容长度不超过1000个字(包括1000字),每个英文或阿拉伯字符算1个字
timestamp 时间戳 *必填,时间戳(精确到毫秒),当前时间5分钟内请求有效
extend 扩展号 选填,可为空数字,如:001,119等,通道本身主叫号加上用户自己分配扩展号的总长度不能超过20位

请求示例

{
  "sign": "de7cb2fb99756c06214fc78252d36484",
  "timestamp": "1520496753938",
  "phone": "15100000055,15100000044",
  "extend": "123",
  "appcode": "test",
  "appkey": "test",
  "msg": "你好,测试"
}

响应信息说明

  • 请求成功
{
  "code": "00000",
  "desc": "提交成功",
  "uid": "8b159b0036d0402e93b39fee102eedf2",
  "result": [
    {
      "status": "00000",
      "phone": "15100000055",
      "desc": "提交成功"
    },
    {
      "status": "00000",
      "phone": "15100000044",
      "desc": "提交成功"
    }
  ]
}
  • 请求异常
{
  "code": "F0006",
  "desc": "appkey不存在",
  "uid": "6e31047a352346f18a0eb2daadb9f217",
  "result": []
}

2. 一对一内容群发

接口地址http://sms.007idc.cn:9090/sms/distinct/v1

请求方式POST

请求头

  • Content-Type: application/json

请求参数

参数名称 参数说明 备注
appkey 应用key-登录账号 *必填,由供应商提供
appcode 应用代码-默认1000 *必填,由供应商提供,默认为1000
sign 短信签名验证MD5(appkey+appsecret+timestamp) *必填,秘钥 appsecret 由供应商提供,由 appkey + appsecret + timestamp 经过 MD5 加密后的32位16进制小写字符串(拼接过程不包括 +
sms 个性化信息sms[] *必填,个性化信息,短信条数不能超过1000条
timestamp 时间戳 *必填,时间戳(精确到毫秒),当前时间5分钟内请求有效
number 数量 选填,可为空数字,范围1到1000,不在该范围采用默认值200

sms结构

字段 类型 说明
phone String *必填,手机号码
msg String *必填,短信内容长度不超过1000个字(包括1000字),每个英文或阿拉伯字符算1个字
extend String 选填,可为空数字,如:001,119等,通道本身主叫号加上用户自己分配扩展号的总长度不能超过20位

请求示例

{
  "appkey": "test",	 
  "appcode": "test",
  "sign": "de7cb2fb99756c06214fc78252d36484",
  "timestamp": "1520496753938",
  "sms": [
    {
      "msg": "短信内容1",
      "phone": "15100000055",
      "extend": ""
    },
    {
      "msg": "短信内容2",
      "phone": "15100000044",
      "extend": "11"
    }
  ]
}

响应信息说明

  • 请求成功
{
  "code": "00000",
  "desc": "提交成功",
  "result": [
    {
      "status": "00000",
      "phone": "15100000055",
      "desc": "提交成功",
      "uid": "8b159b0036d0402e93b39fee102eedf2"
    },
    {
      "status": "00000",
      "phone": "15100000044",
      "desc": "提交成功",
      "uid": "8b159b0036d0402e93b39fee102ee587"
    }
  ]
}
  • 请求异常
{
  "code": "F0006",
  "desc": "appkey不存在",
  "uid": "6e31047a352346f18a0eb2daadb9f217",
  "result": []
}

3. 状态报告平台推送

推送地址:由接收方提供,平台绑定后推送该地址。

推送格式

[
  {
    "appkey": "huoguo",
    "desc": "DELIVRD",
    "phone": "15200000006",
    "report_time": "2018-03-15 01:01:46",
    "status": "0",
    "uid": "143536bbc41e4ef69c779cbb125f7317"
  },
  {
    "appkey": "huoguo",
    "desc": "UNDELIV",
    "phone": "15200000007",
    "report_time": "2018-03-15 01:01:49",
    "status": "2",
    "uid": "b671244d5c534cf7a10f3b99c31aa086"
  }
]

字段说明

字段 类型 说明
appkey String 应用key
phone String 手机号码
status String 状态 0-成功 其他失败
desc String 状态码描述
uid String 短信唯一标识,对应提交响应返回的uid
report_time String 状态报告时间

推送规则

  • 存在多条状态报告时,一次最多推送100条。

  • 接收成功需要返回:

    {"code": "00000"}
    
  • 返回其他值视为接收异常,会尝试最多推送三次。


4. 状态报告用户自取

接口地址http://sms.007idc.cn:9090/sms/report/v1

请求方式GET

请求参数

参数名称 参数说明 备注
appkey 应用key-登录账号 *必填,由供应商提供
appcode 应用代码-默认1000 *必填,由供应商提供,默认为1000
sign 短信签名验证MD5(appkey+appsecret+timestamp) *必填,秘钥 appsecret 由供应商提供,由 appkey + appsecret + timestamp 经过 MD5 加密后的32位16进制小写字符串(拼接过程不包括 +
timestamp 时间戳 *必填,时间戳(精确到毫秒),当前时间5分钟内请求有效
number 数量 选填,可为空,数字,范围1到1000,不在该范围采用默认值200

请求示例

// URL示例
http://sms.007idc.cn:9090/sms/report/v1?appkey=test&appcode=1000&sign=de7cb2fb99756c06214fc78252d36484&timestamp=1520496753938&number=100

响应信息说明

  • 请求成功
[
  {
    "appkey": "huoguo",
    "desc": "DELIVRD",
    "phone": "15200000006",
    "report_time": "2018-03-15 01:01:46",
    "status": "0",
    "uid": "143536bbc41e4ef69c779cbb125f7317"
  },
  {
    "appkey": "huoguo",
    "desc": "UNDELIV",
    "phone": "15200000007",
    "report_time": "2018-03-15 01:01:49",
    "status": "2",
    "uid": "b671244d5c534cf7a10f3b99c31aa086"
  }
]
  • 无数据
{
  "code": "F0050",
  "desc": "无数据"
}
  • 请求异常
{
  "code": "F0006",
  "desc": "appkey不存在"
}

5. 上行平台推送

推送地址:由接收方提供,平台绑定后推送该地址。

推送格式

[
  {
    "appkey": "huoguo",
    "deliver_time": "2018-03-15 01:35:41",
    "extend": "123",
    "msg": "TD",
    "phone": "13900000200"
  },
  {
    "appkey": "huoguo",
    "deliver_time": "2018-03-15 01:35:41",
    "extend": "",
    "msg": "TD",
    "phone": "13900000200"
  }
]

字段说明

字段 类型 说明
appkey String 应用key
phone String 手机号码
msg String 上行回复内容
extend String 扩展号,对应发送填写的extend
deliver_time String 上行回复时间

推送规则

  • 存在多条上行时,一次最多推送10条。

  • 接收成功需要返回:

    {"code": "00000"}
    
  • 返回其他值视为接收异常,会尝试最多推送三次。


6. 上行用户自取

接口地址http://sms.007idc.cn:9090/sms/mo/v1

请求方式GET

请求参数

参数名称 参数说明 备注
appkey 应用key-登录账号 *必填,由供应商提供
appcode 应用代码-默认1000 *必填,由供应商提供,默认为1000
sign 短信签名验证MD5(appkey+appsecret+timestamp) *必填,秘钥 appsecret 由供应商提供,由 appkey + appsecret + timestamp 经过 MD5 加密后的32位16进制小写字符串(拼接过程不包括 +
timestamp 时间戳 *必填,时间戳(精确到毫秒),当前时间5分钟内请求有效
number 数量 选填,可为空,数字,范围1到1000,不在该范围采用默认值200

请求示例

// URL示例
http://sms.007idc.cn:9090/sms/mo/v1?appkey=test&appcode=1000&sign=de7cb2fb99756c06214fc78252d36484&timestamp=1520496753938&number=100

响应信息说明

  • 请求成功
[
  {
    "appkey": "huoguo",
    "deliver_time": "2018-03-15 01:35:41",
    "extend": "123",
    "msg": "TD",
    "phone": "13900000200"
  },
  {
    "appkey": "huoguo",
    "deliver_time": "2018-03-15 01:35:41",
    "extend": "",
    "msg": "TD",
    "phone": "13900000200"
  }
]
  • 无数据
{
  "code": "F0050",
  "desc": "无数据"
}
  • 请求异常
{
  "code": "F0006",
  "desc": "appkey不存在"
}

7. 查询余额

接口地址http://sms.007idc.cn:9090/sms/balance/v1

请求方式GET

请求参数

参数名称 参数说明 备注
appkey 应用key-登录账号 *必填,由供应商提供
appcode 应用代码-默认1000 *必填,由供应商提供,默认为1000
sign 短信签名验证MD5(appkey+appsecret+timestamp) *必填,秘钥 appsecret 由供应商提供,由 appkey + appsecret + timestamp 经过 MD5 加密后的32位16进制小写字符串(拼接过程不包括 +
timestamp 时间戳 *必填,时间戳(精确到毫秒),当前时间5分钟内请求有效

请求示例

// URL示例
http://sms.007idc.cn:9090/sms/balance/v1?appkey=test&appcode=1000&sign=de7cb2fb99756c06214fc78252d36484&timestamp=1520496753938

响应信息说明

  • 请求成功
{
  "appkey": "test",
  "balance": "50",
  "balance_time": "2018-03-15 01:01:46"
}
  • 请求异常
{
  "code": "F0006",
  "desc": "appkey不存在"
}

错误处理

所有API接口在请求失败时,会返回相应的错误码和描述。以下是常见错误码说明:

返回代码 错误码描述
00000 提交成功
F0001 参数 appkey 未填写
F0002 参数 appcode 未填写
F0003 参数 phone 未填写
F0004 参数 sign 未填写
F0005 参数 timestamp 未填写
F0006 appkey 不存在
F0007 账号已经关闭
F0008 sign 检验错误
F0009 账号下没有业务
F0010 业务不存在
F0011 手机号码超过1000个
F0012 timestamp 不是数字
F0013 timestamp 过期超过5分钟
F0014 请求IP不在白名单内
F0015 余额不足
F0016 手机号码无效
F0017 没有可用的业务
F0022 参数 msg 未填写
F0023 msg 超过了1000个字
F0024 extend 不是纯数字
F0025 内容签名未报备/无签名
F0039 参数 sms 未填写
F0040 参数 sms 格式不正确
F0041 短信条数超过1000条
F0050 无数据
F0100 未知错误

错误处理示例

在C语言中,处理API返回的错误码需要解析JSON响应,并根据 code 字段进行相应的处理。


实用C语言代码示例

以下示例使用C语言和libcurl库进行HTTP请求,使用cJSON库解析JSON数据,并通过OpenSSL库计算MD5签名。请确保在编译时链接相应的库(如 -lcurl -lcjson -lssl -lcrypto)。

前置准备

  1. 安装必要库

    sudo apt-get update
    sudo apt-get install libcurl4-openssl-dev libssl-dev
    sudo apt-get install libcjson-dev
    
  2. 包含头文件

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <curl/curl.h>
    #include <cjson/cJSON.h>
    #include <openssl/md5.h>
    #include <time.h>
    

1. 一对多群发短信示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <cjson/cJSON.h>
#include <openssl/md5.h>
#include <time.h>

// Function to compute MD5 hash
void compute_md5(const char *str, char *output) {
    unsigned char digest[MD5_DIGEST_LENGTH];
    MD5((unsigned char*)str, strlen(str), digest);
    for(int i = 0; i < MD5_DIGEST_LENGTH; i++) {
        sprintf(&output[i*2], "%02x", (unsigned int)digest[i]);
    }
    output[32] = '\0';
}

// Function to get current timestamp in milliseconds
long long current_timestamp_ms() {
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return (long long)(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;
}

// Callback function to handle response data
size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    char **response_ptr = (char**)userp;
    *response_ptr = realloc(*response_ptr, realsize + 1);
    if(*response_ptr == NULL) {
        fprintf(stderr, "Not enough memory (realloc returned NULL)\n");
        return 0;
    }
    memcpy(*response_ptr, contents, realsize);
    (*response_ptr)[realsize] = '\0';
    return realsize;
}

int main() {
    CURL *curl;
    CURLcode res;
    char *response = NULL;

    // Configuration
    const char *appkey = "your_appkey";
    const char *appsecret = "your_appsecret";
    const char *appcode = "1000";
    const char *sign_format = "%s%s%lld";
    long long timestamp = current_timestamp_ms();
    
    // Compute sign
    char sign_input[256];
    snprintf(sign_input, sizeof(sign_input), sign_format, appkey, appsecret, timestamp);
    char sign[33];
    compute_md5(sign_input, sign);
    
    // Prepare JSON payload
    cJSON *json = cJSON_CreateObject();
    cJSON_AddStringToObject(json, "appkey", appkey);
    cJSON_AddStringToObject(json, "appcode", appcode);
    cJSON_AddStringToObject(json, "sign", sign);
    cJSON_AddStringToObject(json, "phone", "15100000055,15100000044");
    cJSON_AddStringToObject(json, "msg", "【零零七】 您的验证码是124154");
    cJSON_AddStringToObject(json, "timestamp", "1520496753938"); // Replace with actual timestamp
    
    char *json_data = cJSON_PrintUnformatted(json);
    cJSON_Delete(json);
    
    // Initialize CURL
    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();
    if(curl) {
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        
        curl_easy_setopt(curl, CURLOPT_URL, "http://sms.007idc.cn:9090/sms/batch/v1");
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        
        // Set callback to capture response
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
        
        // Perform the request
        res = curl_easy_perform(curl);
        
        // Check for errors
        if(res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        } else {
            // Parse JSON response
            cJSON *json_response = cJSON_Parse(response);
            if(json_response == NULL) {
                fprintf(stderr, "Error parsing JSON response\n");
            } else {
                cJSON *code = cJSON_GetObjectItem(json_response, "code");
                if(cJSON_IsString(code) && (code->valuestring != NULL)) {
                    printf("Response Code: %s\n", code->valuestring);
                    if(strcmp(code->valuestring, "00000") == 0) {
                        printf("短信发送成功\n");
                    } else {
                        // Handle error based on code
                        printf("短信发送失败,错误码: %s\n", code->valuestring);
                    }
                }
                cJSON_Delete(json_response);
            }
        }
        
        // Cleanup
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
    free(json_data);
    free(response);
    return 0;
}

说明

  1. 计算MD5签名:使用OpenSSL库的 MD5 函数计算签名。
  2. 获取当前时间戳:使用 clock_gettime 获取当前时间的毫秒级时间戳。
  3. 构建JSON请求体:使用cJSON库构建JSON格式的请求体。
  4. 发送HTTP POST请求:使用libcurl发送HTTP POST请求,并设置相应的头部信息。
  5. 处理响应:接收并解析JSON格式的响应,检查返回码 code,判断短信是否发送成功。

2. 一对一内容群发短信示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <cjson/cJSON.h>
#include <openssl/md5.h>
#include <time.h>

// Function to compute MD5 hash
void compute_md5(const char *str, char *output) {
    unsigned char digest[MD5_DIGEST_LENGTH];
    MD5((unsigned char*)str, strlen(str), digest);
    for(int i = 0; i < MD5_DIGEST_LENGTH; i++) {
        sprintf(&output[i*2], "%02x", (unsigned int)digest[i]);
    }
    output[32] = '\0';
}

// Function to get current timestamp in milliseconds
long long current_timestamp_ms() {
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return (long long)(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;
}

// Callback function to handle response data
size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    char **response_ptr = (char**)userp;
    *response_ptr = realloc(*response_ptr, realsize + 1);
    if(*response_ptr == NULL) {
        fprintf(stderr, "Not enough memory (realloc returned NULL)\n");
        return 0;
    }
    memcpy(*response_ptr, contents, realsize);
    (*response_ptr)[realsize] = '\0';
    return realsize;
}

int main() {
    CURL *curl;
    CURLcode res;
    char *response = NULL;

    // Configuration
    const char *appkey = "your_appkey";
    const char *appsecret = "your_appsecret";
    const char *appcode = "1000";
    const char *sign_format = "%s%s%lld";
    long long timestamp = current_timestamp_ms();
    
    // Compute sign
    char sign_input[256];
    snprintf(sign_input, sizeof(sign_input), sign_format, appkey, appsecret, timestamp);
    char sign[33];
    compute_md5(sign_input, sign);
    
    // Prepare JSON payload
    cJSON *json = cJSON_CreateObject();
    cJSON_AddStringToObject(json, "appkey", appkey);
    cJSON_AddStringToObject(json, "appcode", appcode);
    cJSON_AddStringToObject(json, "sign", sign);
    cJSON_AddStringToObject(json, "timestamp", "1520496753938"); // Replace with actual timestamp
    
    // Create sms array
    cJSON *sms_array = cJSON_AddArrayToObject(json, "sms");
    
    // Add individual SMS messages
    cJSON *sms1 = cJSON_CreateObject();
    cJSON_AddStringToObject(sms1, "msg", "【测试】你好测试0");
    cJSON_AddStringToObject(sms1, "phone", "15100000410");
    cJSON_AddStringToObject(sms1, "extend", "0010");
    cJSON_AddItemToArray(sms_array, sms1);
    
    cJSON *sms2 = cJSON_CreateObject();
    cJSON_AddStringToObject(sms2, "msg", "【测试】你好测试1");
    cJSON_AddStringToObject(sms2, "phone", "15100000411");
    cJSON_AddStringToObject(sms2, "extend", "0011");
    cJSON_AddItemToArray(sms_array, sms2);
    
    char *json_data = cJSON_PrintUnformatted(json);
    cJSON_Delete(json);
    
    // Initialize CURL
    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();
    if(curl) {
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        
        curl_easy_setopt(curl, CURLOPT_URL, "http://sms.007idc.cn:9090/sms/distinct/v1");
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        
        // Set callback to capture response
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
        
        // Perform the request
        res = curl_easy_perform(curl);
        
        // Check for errors
        if(res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        } else {
            // Parse JSON response
            cJSON *json_response = cJSON_Parse(response);
            if(json_response == NULL) {
                fprintf(stderr, "Error parsing JSON response\n");
            } else {
                cJSON *code = cJSON_GetObjectItem(json_response, "code");
                if(cJSON_IsString(code) && (code->valuestring != NULL)) {
                    printf("Response Code: %s\n", code->valuestring);
                    if(strcmp(code->valuestring, "00000") == 0) {
                        printf("短信发送成功\n");
                    } else {
                        // Handle error based on code
                        printf("短信发送失败,错误码: %s\n", code->valuestring);
                    }
                }
                cJSON_Delete(json_response);
            }
        }
        
        // Cleanup
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
    free(json_data);
    free(response);
    return 0;
}

说明

  1. 构建SMS数组:通过cJSON库创建一个包含多个SMS消息的数组,每个消息包含 msgphoneextend 字段。
  2. 发送请求:与一对多群发类似,使用libcurl发送HTTP POST请求,设置相应的头部信息和JSON数据。
  3. 处理响应:解析JSON响应,检查返回码 code,判断短信是否发送成功。

3. 查询余额示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <cjson/cJSON.h>
#include <openssl/md5.h>
#include <time.h>

// Function to compute MD5 hash
void compute_md5(const char *str, char *output) {
    unsigned char digest[MD5_DIGEST_LENGTH];
    MD5((unsigned char*)str, strlen(str), digest);
    for(int i = 0; i < MD5_DIGEST_LENGTH; i++) {
        sprintf(&output[i*2], "%02x", (unsigned int)digest[i]);
    }
    output[32] = '\0';
}

// Function to get current timestamp in milliseconds
long long current_timestamp_ms() {
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return (long long)(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;
}

// Callback function to handle response data
size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    char **response_ptr = (char**)userp;
    *response_ptr = realloc(*response_ptr, realsize + 1);
    if(*response_ptr == NULL) {
        fprintf(stderr, "Not enough memory (realloc returned NULL)\n");
        return 0;
    }
    memcpy(*response_ptr, contents, realsize);
    (*response_ptr)[realsize] = '\0';
    return realsize;
}

int main() {
    CURL *curl;
    CURLcode res;
    char *response = NULL;

    // Configuration
    const char *appkey = "your_appkey";
    const char *appsecret = "your_appsecret";
    const char *appcode = "1000";
    const char *sign_format = "%s%s%lld";
    long long timestamp = current_timestamp_ms();
    
    // Compute sign
    char sign_input[256];
    snprintf(sign_input, sizeof(sign_input), sign_format, appkey, appsecret, timestamp);
    char sign[33];
    compute_md5(sign_input, sign);
    
    // Prepare URL with query parameters
    char url[512];
    snprintf(url, sizeof(url), "http://sms.007idc.cn:9090/sms/balance/v1?appkey=%s&appcode=%s&sign=%s&timestamp=%lld",
             appkey, appcode, sign, timestamp);
    
    // Initialize CURL
    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();
    if(curl) {
        // Set URL
        curl_easy_setopt(curl, CURLOPT_URL, url);
        
        // Set callback to capture response
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
        
        // Perform the request
        res = curl_easy_perform(curl);
        
        // Check for errors
        if(res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        } else {
            // Parse JSON response
            cJSON *json_response = cJSON_Parse(response);
            if(json_response == NULL) {
                fprintf(stderr, "Error parsing JSON response\n");
            } else {
                cJSON *balance = cJSON_GetObjectItem(json_response, "balance");
                cJSON *balance_time = cJSON_GetObjectItem(json_response, "balance_time");
                if(cJSON_IsString(balance) && (balance->valuestring != NULL) &&
                   cJSON_IsString(balance_time) && (balance_time->valuestring != NULL)) {
                    printf("账户余额: %s 条\n", balance->valuestring);
                    printf("余额更新时间: %s\n", balance_time->valuestring);
                } else {
                    cJSON *code = cJSON_GetObjectItem(json_response, "code");
                    cJSON *desc = cJSON_GetObjectItem(json_response, "desc");
                    if(cJSON_IsString(code) && (code->valuestring != NULL) &&
                       cJSON_IsString(desc) && (desc->valuestring != NULL)) {
                        printf("查询失败,错误码: %s, 描述: %s\n", code->valuestring, desc->valuestring);
                    } else {
                        printf("未知响应格式\n");
                    }
                }
                cJSON_Delete(json_response);
            }
        }
        
        // Cleanup
        curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
    free(response);
    return 0;
}

说明

  1. 构建URL:将必要的参数(appkeyappcodesigntimestamp)作为查询参数附加到URL中。
  2. 发送GET请求:使用libcurl发送HTTP GET请求。
  3. 处理响应:解析JSON响应,提取余额信息或错误信息。

编译与运行

使用以下命令编译上述示例代码:

gcc -o send_sms_batch send_sms_batch.c -lcurl -lcjson -lssl -lcrypto
gcc -o send_sms_distinct send_sms_distinct.c -lcurl -lcjson -lssl -lcrypto
gcc -o query_balance query_balance.c -lcurl -lcjson -lssl -lcrypto

然后运行相应的可执行文件:

./send_sms_batch
./send_sms_distinct
./query_balance

附录:常见错误码说明

以下是零零七云计算短信服务的常见错误码及其描述:

返回代码 错误码描述
00000 提交成功
F0001 参数 appkey 未填写
F0002 参数 appcode 未填写
F0003 参数 phone 未填写
F0004 参数 sign 未填写
F0005 参数 timestamp 未填写
F0006 appkey 不存在
F0007 账号已经关闭
F0008 sign 检验错误
F0009 账号下没有业务
F0010 业务不存在
F0011 手机号码超过1000个
F0012 timestamp 不是数字
F0013 timestamp 过期超过5分钟
F0014 请求IP不在白名单内
F0015 余额不足
F0016 手机号码无效
F0017 没有可用的业务
F0022 参数 msg 未填写
F0023 msg 超过了1000个字
F0024 extend 不是纯数字
F0025 内容签名未报备/无签名
F0039 参数 sms 未填写
F0040 参数 sms 格式不正确
F0041 短信条数超过1000条
F0050 无数据
F0100 未知错误

处理建议

  • 成功:代码 00000 表示短信提交成功。
  • 失败:其他代码表示不同类型的错误,应根据错误码描述进行相应的处理,如重新发送、提示用户错误信息等。

总结

本文档详细介绍了如何使用C语言在魔方财务系统中集成零零七云计算(007IDC)的短信服务。通过系统调用实现国内/国际短信通知、短信验证、用户请求验证等功能。文档涵盖了插件对接的前提条件、安装配置步骤、API接口的详细说明及C语言代码示例,帮助开发者高效地完成短信服务的集成。

关键点

  1. 安全性:确保 appkeyappsecret 的安全,避免泄露。
  2. 时间戳:所有请求均需包含精确到毫秒的时间戳,且必须在当前时间5分钟内。
  3. 签名计算:签名为 appkey + appsecret + timestamp 的MD5值,需为32位16进制小写字符串。
  4. 错误处理:根据返回的错误码进行相应的处理,确保程序的健壮性。
  5. 库依赖:使用libcurl进行HTTP请求,cJSON进行JSON处理,OpenSSL进行MD5签名计算。

建议

  • 测试:在正式使用前,建议通过提供的测试发送功能进行充分测试,确保接口对接正确。
  • 文档参考:详细阅读零零七云计算提供的官方文档,了解最新的接口变更和使用规范。
  • 日志记录:在实际应用中,建议记录发送日志和响应信息,便于后续的排查和维护。

通过本文档的指导,您将能够在C语言环境下高效地集成零零七云计算的短信服务,满足魔方财务系统的短信通知和验证需求。


评论