pomia 发表于 2015-4-23 11:49:47

如何用C语言实现OpenAPI的用户登录请求和应答

下面的代码,仅给大家示例如何组包OpenAPI请求和解析OpenAPI应答。因代码是C++和C语言混合编写的,想用纯C代码实现的人,请参考改写。
http协议的C语言实现,请大家自己去网上找参考代码,这里就不贴了。代码中的Json解析是C++实现,有想用CJson做解析的朋友,请自行改写。
OpenAPI的用户登录:
/* OpenAPI错误码返回信息 */typedef struct _errorInfo_st {    int error;    string errorMessage;} errorInfo_st;
/* 用户登录返回信息 */typedef struct _userLoginResult_st {    errorInfo_st errorInfo;    string uid;    string token;    long expireAt;} userLoginResult_st;
userLoginResult_st UserLogin(const char *appID, const char *userName, const char *password){    int responseCode = 0;    int answerLen = 0;    char *answer = NULL;    char httpBody = { 0 };    char httpHeadCustom = { 0 };    userLoginResult_st userLoginResult = {};
    if (!appID || !userName || !password || !appID || !userName || !password) {      userLoginResult.errorInfo.error = ERROR_INVALID_PARAM;      userLoginResult.errorInfo.errorMessage = "Invalid param(s).";      return userLoginResult;    }
    snprintf(httpHeadCustom, sizeof(httpHeadCustom),             "Content-Type: application/json\r\n"             "X-Gizwits-Application-Id: %s\r\n", appID);    snprintf(httpBody, sizeof(httpBody),             "{\"username\":\"%s\",\"password\":\"%s\"}", userName, password);
    answer = http_request(GWifiConfig::sharedInstance()->GetOpenAPIDomain(), GWifiConfig::sharedInstance()->GetOpenAPIPort(), HTTP_TIMEOUT, HTTP_POST, "/app/login", httpHeadCustom, httpBody, &responseCode, &answerLen);    if (answer) {      Value jsonRoot = Value(nullValue);      Reader jsonReader = Reader();
      try {            jsonReader.parse(answer, answer + answerLen, jsonRoot);
            if('{' == answer && jsonRoot.isObject()) {                userLoginResult.errorInfo.error = jsonRoot["error_code"].asInt();                userLoginResult.errorInfo.errorMessage = jsonRoot["error_message"].asString();                userLoginResult.uid = jsonRoot["uid"].asString();                userLoginResult.token = jsonRoot["token"].asString();                userLoginResult.expireAt = jsonRoot["expire_at"].asInt();            }      } catch (exception e) {            logMsgEx(LV_ERROR, __func__, "Cause parse exception - %s", e.what());      }
      free(answer);    } else {      userLoginResult.errorInfo.error = ERROR_HTTP_FAIL;      userLoginResult.errorInfo.errorMessage = "Http request failed: " + (errno ? string(strerror(errno)) : "");      logMsg(LV_WARN, "User %s login failed, responseCode:%d", userName, responseCode);    }
    //取到才uid跟token才视为成功    if (userLoginResult.uid.empty() || userLoginResult.token.empty()) {      if (ERROR_NONE == userLoginResult.errorInfo.error) {            userLoginResult.errorInfo.error = ERROR_HTTP_FAIL;            userLoginResult.errorInfo.errorMessage = "Http response error format.";      }      logMsg(LV_ERROR, "User %s login failed, error:%d, errorMessage:%s",               userName, userLoginResult.errorInfo.error, userLoginResult.errorInfo.errorMessage.c_str());    } else {      logMsg(LV_WARN, "User %s login success, uid:%s, token:%s, expire_at:%ld",               userName, userLoginResult.uid.c_str(), userLoginResult.token.c_str(), userLoginResult.expireAt);    }
    if (userLoginResult.errorInfo.errorMessage.length() && !userLoginResult.errorInfo.error) {      userLoginResult.errorInfo.error = ERROR_GENERAL;    }
    return userLoginResult;}

pomia 发表于 2015-4-23 11:50:52

OpenAPI的获取设备绑定列表:

/* 设备信息结构体 */
typedef struct _devDetailInfo_st {
    errorInfo_st errorInfo;
    string productKey; // 设备类型标识
    string did; // 设备唯一识别码
    string mac;// 设备mac地址
    string passCode; // 设备验证码
    string host; // m2m域名
    string remark; // 设备昵称
    int port; // m2m端口
    int isOnline; // 设备是否在线
    int isDisabled; //设备已注销
    int type; // 设备类型,0:普通设备, 1:中控设备
} devDetailInfo_st;

/* 绑定设备列表返回结果 */
typedef struct _getBoundDevResult_st {
    errorInfo_st errorInfo;
    vector<devDetailInfo_st> devices;
} getBoundDevResult_st;

getBoundDevResult_st GetNumBoundDevicesFromIndex(const char *appID, const char *token, int num, int index, const char *showDisabled)
{
    int responseCode = 0;
    int answerLen = 0;
    char *answer = NULL;
    char httpDest = { 0 };
    char httpHeadCustom = { 0 };
    getBoundDevResult_st getBoundDevResult = {ERROR_INVALID_PARAM, "Invalid param(s)."};
   
    if (!appID || !token || num <= 0|| index < 0) return getBoundDevResult;
   
    snprintf(httpDest, sizeof(httpDest), "/app/bindings?show_disabled=%s&limit=%d&skip=%d",
             showDisabled, num, index);
    snprintf(httpHeadCustom, sizeof(httpHeadCustom),
             "Content-Type: application/json\r\n"
             "X-Gizwits-Application-Id: %s\r\n"
             "X-Gizwits-User-token: %s\r\n", appID, token);
   
    answer = http_request(GWifiConfig::sharedInstance()->GetOpenAPIDomain(), GWifiConfig::sharedInstance()->GetOpenAPIPort(), HTTP_TIMEOUT, HTTP_GET, httpDest, httpHeadCustom, NULL, &responseCode, &answerLen);
    if (answer) {
      Value jsonRoot = Value(nullValue);
      Reader jsonReader = Reader();
      
      try {
            jsonReader.parse(answer, answer + answerLen, jsonRoot);
            
            if('{' == answer && jsonRoot.isObject()) {
                getBoundDevResult.errorInfo.error = jsonRoot["error_code"].asInt();
                getBoundDevResult.errorInfo.errorMessage = jsonRoot["error_message"].asString();
               
                Value jsonValue = jsonRoot["devices"];
                if (jsonValue.isArray()) {
                  for (ValueIterator i = jsonValue.begin(); i != jsonValue.end(); ++i) {
                        devDetailInfo_st device = {};
                        device.productKey = (*i)["product_key"].asString();
                        device.did = (*i)["did"].asString();
                        device.mac = (*i)["mac"].asString();
                        device.passCode = (*i)["passcode"].asString();
                        device.host = (*i)["host"].asString();
                        device.port = (*i)["port"].asInt();
                        device.isOnline = (*i)["is_online"].asBool();
                        device.remark = (*i)["remark"].asString();
                        device.isDisabled = (*i)["is_disabled"].asBool();
                        if ((*i)["type"].isString()) {
                            if ((*i)["type"].asString() == string("center_control")) {
                              device.type = 1;
                            }
                        }
                        getBoundDevResult.devices.push_back(device);
                  }
                  
                  getBoundDevResult.errorInfo.error = ERROR_NONE;
                  getBoundDevResult.errorInfo.errorMessage = string();
                  logMsg(LV_WARN, "Get %d devices from %s success", getBoundDevResult.devices.size(), GWifiConfig::sharedInstance()->GetOpenAPIDomain());
                } else {
                  logMsg(LV_WARN, "Get devices from %s failed, can't find jsonKey(devices)", GWifiConfig::sharedInstance()->GetOpenAPIDomain());
                }
            } else {
                logMsg(LV_WARN, "Get devices from %s failed, parse json error", GWifiConfig::sharedInstance()->GetOpenAPIDomain());
            }
      } catch (exception e) {
            logMsgEx(LV_ERROR, __func__, "Cause parse exception - %s", e.what());
      }
      
      free(answer);
    } else {
      getBoundDevResult.errorInfo.error = ERROR_HTTP_FAIL;
      getBoundDevResult.errorInfo.errorMessage = "Http request failed: " + (errno ? string(strerror(errno)) : "");
      logMsg(LV_WARN, "Get devices from %s failed, responseCode:%d", GWifiConfig::sharedInstance()->GetOpenAPIDomain(), responseCode);
    }
   
    if (ERROR_INVALID_PARAM == getBoundDevResult.errorInfo.error) {
      getBoundDevResult.errorInfo.error = ERROR_HTTP_FAIL;
      getBoundDevResult.errorInfo.errorMessage = "Http response error format.";
    }
   
    if (getBoundDevResult.errorInfo.errorMessage.length() && !getBoundDevResult.errorInfo.error) {
      getBoundDevResult.errorInfo.error = ERROR_GENERAL;
    }
   
    return getBoundDevResult;
}

Herry 发表于 2015-4-23 12:06:14

一级棒!

dwli 发表于 2015-4-24 21:58:21

这可真是所谓的开源啊!代码都贴出来了啊

johnvuong1999 发表于 2015-6-11 09:21:41

非常棒,谢谢分型。
页: [1]
查看完整版本: 如何用C语言实现OpenAPI的用户登录请求和应答