First submission
commit
fa5cd5e337
@ -0,0 +1,180 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func generateRandomDeviceId(size int) string {
|
||||
tempStr := "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
deviceId := make([]byte, size)
|
||||
|
||||
_, err := rand.Read(deviceId)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for i := range deviceId {
|
||||
deviceId[i] = tempStr[deviceId[i]%byte(len(tempStr))]
|
||||
}
|
||||
|
||||
return string(deviceId)
|
||||
}
|
||||
|
||||
type Authorize struct {
|
||||
CUserId string `json:"cUserId"`
|
||||
Code int `json:"code"`
|
||||
DeviceId string `json:"deviceId"`
|
||||
Message string `json:"message"`
|
||||
SecurityToken string `json:"securityToken"`
|
||||
ServiceToken string `json:"serviceToken"`
|
||||
Sid string `json:"sid"`
|
||||
UserId int64 `json:"userId"`
|
||||
}
|
||||
|
||||
func mapToStruct(data map[string]interface{}) (Authorize, error) {
|
||||
jsonStr, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return Authorize{}, err
|
||||
}
|
||||
|
||||
var myStruct Authorize
|
||||
err = json.Unmarshal(jsonStr, &myStruct)
|
||||
if err != nil {
|
||||
return Authorize{}, err
|
||||
}
|
||||
|
||||
return myStruct, nil
|
||||
}
|
||||
|
||||
func Login(user, pwd string) (Authorize, error) {
|
||||
msgURL := fmt.Sprintf("https://account.xiaomi.com/pass/serviceLogin?sid=xiaomiio&_json=true")
|
||||
loginURL := "https://account.xiaomi.com/pass/serviceLoginAuth2"
|
||||
deviceID := generateRandomDeviceId(16)
|
||||
authorize := make(map[string]interface{})
|
||||
userAgent := "APP/com.xiaomi.mihome APPV/6.0.103 iosPassportSDK/3.9.0 iOS/14.4 miHSTS"
|
||||
client := &http.Client{}
|
||||
req, _ := http.NewRequest("GET", msgURL, nil)
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
req.Header.Set("Accept", "*/*")
|
||||
req.Header.Set("Accept-Language", "zh-tw")
|
||||
req.Header.Set("Cookie", fmt.Sprintf("deviceId=%s; sdkVersion=3.4.1", deviceID))
|
||||
resp, _ := client.Do(req)
|
||||
defer resp.Body.Close()
|
||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
||||
var result map[string]interface{}
|
||||
json.Unmarshal(bodyBytes[11:], &result)
|
||||
body := url.Values{}
|
||||
body.Set("qs", result["qs"].(string))
|
||||
body.Set("sid", result["sid"].(string))
|
||||
body.Set("_sign", result["_sign"].(string))
|
||||
body.Set("callback", result["callback"].(string))
|
||||
body.Set("user", user)
|
||||
pwdHash := md5.Sum([]byte(pwd))
|
||||
pwdHashStr := strings.ToUpper(hex.EncodeToString(pwdHash[:]))
|
||||
body.Set("hash", pwdHashStr)
|
||||
body.Set("_json", "true")
|
||||
loginReq, _ := http.NewRequest("POST", loginURL, strings.NewReader(body.Encode()))
|
||||
loginReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
loginResp, _ := client.Do(loginReq)
|
||||
defer loginResp.Body.Close()
|
||||
loginBodyBytes, _ := io.ReadAll(loginResp.Body)
|
||||
json.Unmarshal(loginBodyBytes[11:], &result)
|
||||
if result["code"].(float64) != 0 {
|
||||
authorize["code"] = result["code"]
|
||||
authorize["message"] = result["desc"]
|
||||
//return authorize
|
||||
}
|
||||
redirectURL := result["location"].(string)
|
||||
redirectReq, _ := http.NewRequest("GET", redirectURL, nil)
|
||||
redirectResp, _ := client.Do(redirectReq)
|
||||
defer redirectResp.Body.Close()
|
||||
cookies := redirectResp.Header["Set-Cookie"]
|
||||
for _, cookie := range cookies {
|
||||
cookieParts := strings.Split(strings.Split(cookie, "; ")[0], "=")
|
||||
authorize[cookieParts[0]] = cookieParts[1]
|
||||
}
|
||||
authorize["code"] = 0
|
||||
authorize["sid"] = "xiaomiio"
|
||||
authorize["userId"] = result["userId"]
|
||||
authorize["securityToken"] = result["ssecurity"]
|
||||
authorize["deviceId"] = deviceID
|
||||
authorize["message"] = "成功"
|
||||
return mapToStruct(authorize)
|
||||
}
|
||||
|
||||
func generateSignedNonce(secret, nonce string) string {
|
||||
hash := sha256.New()
|
||||
decodeString, _ := base64.StdEncoding.DecodeString(secret)
|
||||
hash.Write(decodeString)
|
||||
V, _ := base64.StdEncoding.DecodeString(nonce)
|
||||
hash.Write(V)
|
||||
return base64.StdEncoding.EncodeToString(hash.Sum(nil))
|
||||
}
|
||||
|
||||
func generateSignature(uri, signedNonce, nonce, data string) string {
|
||||
sign := uri + "&" + signedNonce + "&" + nonce + "&data=" + data
|
||||
decodeString, _ := base64.StdEncoding.DecodeString(signedNonce)
|
||||
mac := hmac.New(sha256.New, decodeString)
|
||||
mac.Write([]byte(sign))
|
||||
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
||||
}
|
||||
|
||||
func mapToJSON(data map[string]interface{}) (string, error) {
|
||||
jsonBytes, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(jsonBytes), nil
|
||||
}
|
||||
|
||||
func PostData(uri string, data map[string]interface{}, Certificate Authorize) []byte {
|
||||
|
||||
Certificate.UserId = 2251648609
|
||||
Certificate.ServiceToken = "x2K8nowPRvFEaeEKt2aj35xTgEZLTspxURrRIbbETcLJ5WLNdzxFrI1DfI3M3+/tvxJyfQMdaYu+8EfedWgSfB81T0P8R5zofX6GUd/jE2KlslBLyzn3vabqhHIL93ahoPUog1Q8pKBJJTRqOrL2pypDy1ODWkQ07jUC6fWqf+k="
|
||||
Certificate.Code = 0
|
||||
Certificate.Sid = "xiaomiio"
|
||||
Certificate.SecurityToken = "btZAHcCqLvQZp0eot8IlOQ=="
|
||||
Certificate.DeviceId = "3P5v99CdV4vwkpsS"
|
||||
|
||||
dataStr, err := mapToJSON(data)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
nonce := generateRandomDeviceId(16)
|
||||
nonce = "H9qOd9J9wRRMTXj0"
|
||||
signedNonce := generateSignedNonce(Certificate.SecurityToken, nonce)
|
||||
signature := generateSignature(uri, signedNonce, nonce, dataStr)
|
||||
|
||||
body := url.Values{}
|
||||
body.Set("_nonce", nonce)
|
||||
body.Set("data", dataStr)
|
||||
body.Set("signature", signature)
|
||||
|
||||
userAgent := "APP/com.xiaomi.mihome APPV/6.0.103 iosPassportSDK/3.9.0 iOS/14.4 miHSTS"
|
||||
client := &http.Client{}
|
||||
req, _ := http.NewRequest("POST", "https://api.io.mi.com/app"+uri, strings.NewReader(body.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
req.Header.Set("x-xiaomi-protocal-flag-cli", "PROTOCAL-HTTP2")
|
||||
req.Header.Set("Cookie", fmt.Sprintf("PassportDeviceId=%s;userId=%v;serviceToken=%s;", Certificate.DeviceId, Certificate.UserId, Certificate.ServiceToken))
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, _ := io.ReadAll(resp.Body)
|
||||
return respBody
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"mijia-go-sdk/api"
|
||||
)
|
||||
|
||||
func main() {
|
||||
user := "15542100924"
|
||||
pwd := "1XAII@wsk"
|
||||
result, _ := api.Login(user, pwd)
|
||||
marshal, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
Mi := api.NewMiJia(result)
|
||||
//Mi.Rooms()
|
||||
//Mi.Devices()
|
||||
//Mi.Scenes(0)
|
||||
//Mi.RunScene("1784216758920822784")
|
||||
|
||||
var data []map[string]interface{}
|
||||
|
||||
data = append(data, map[string]interface{}{
|
||||
"did": "538261193",
|
||||
"siid": 2,
|
||||
"piid": 1,
|
||||
})
|
||||
data = append(data, map[string]interface{}{
|
||||
"did": "538261193",
|
||||
"siid": 2,
|
||||
"piid": 2,
|
||||
})
|
||||
data = append(data, map[string]interface{}{
|
||||
"did": "538261193",
|
||||
"siid": 2,
|
||||
"piid": 3,
|
||||
})
|
||||
|
||||
Mi.GetDeviceVar(data)
|
||||
//Mi.Consumables(0)
|
||||
//Mi.Scenes(0)
|
||||
println(marshal)
|
||||
fmt.Println(result)
|
||||
}
|
Loading…
Reference in New Issue