/* * @Descripttion:实名认证 * @version: * @Author: Neo,Huang * @Date: 2021-04-17 11:04:16 * @LastEditors: Neo,Huang * @LastEditTime: 2022-04-12 20:27:43 */ package nppa import ( "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/sha256" "encoding/base64" "encoding/hex" "encoding/json" "fmt" "io" "io/ioutil" "log" "net/http" "net/url" "sort" "strconv" "strings" "sync" "time" "box-3rdServer/utils" "github.com/bitly/go-simplejson" ) type ConfApp struct { aId int appId string appName string bizId string secretKey string } var mapAidToConf sync.Map var mapChannelToConf sync.Map // 初始化 func initConf() { path := utils.GetConfigPath() j := utils.LoadJsonFile(path + "NppaAppConfig.json") tmpMapAidToConf := make(map[int]*ConfApp) mapAppNameToConf := make(map[string]*ConfApp) for _, v := range j.MustArray() { item, _ := v.(map[string]interface{}) val, ok := item["aId"] if !ok { continue } aId := utils.JsonNumberToInt(val) conf := &ConfApp{aId: aId} val, ok = item["appId"] if ok { conf.appId = val.(string) } val, ok = item["appName"] if ok { conf.appName = val.(string) } val, ok = item["bizId"] if ok { conf.bizId = val.(string) } val, ok = item["secretKey"] if ok { conf.secretKey = val.(string) } tmpMapAidToConf[aId] = conf mapAppNameToConf[conf.appName] = conf } j = utils.LoadJsonFile(path + "NppaChannelConfig.json") mapChannelToAid := make(map[int]int) mapChannelToAppName := make(map[int]string) for _, v := range j.MustArray() { item, _ := v.(map[string]interface{}) val, ok := item["channel"] if !ok { continue } channel := utils.JsonNumberToInt(val) val, ok = item["aId"] if ok { mapChannelToAid[channel] = utils.JsonNumberToInt(val) } val, ok = item["appName"] if ok { mapChannelToAppName[channel] = val.(string) } } mapAidToConf.Range(func(k, v interface{}) bool { _, ok := tmpMapAidToConf[k.(int)] if !ok { mapAidToConf.Delete(k) } return true }) for k, v := range tmpMapAidToConf { mapAidToConf.Store(k, v) } mapTmp := make(map[int]*ConfApp) for k, v := range mapChannelToAid { conf, ok := tmpMapAidToConf[v] if ok { mapTmp[k] = conf } } mapChannelToConf.Range(func(k, v interface{}) bool { _, ok := mapTmp[k.(int)] if !ok { mapChannelToConf.Delete(k) } return true }) for k, v := range mapTmp { mapChannelToConf.Store(k, v) } } // 配置更新 func ConfUpdate() { initConf() } // 渠道配置 func ConfGetInfoByAid(aid int) map[string]string { v, ok := mapAidToConf.Load(aid) if !ok { return nil } conf := v.(*ConfApp) info := make(map[string]string) info["appId"] = conf.appId info["bizId"] = conf.bizId info["secretKey"] = conf.secretKey info["timestamps"] = fmt.Sprintf("%v", time.Now().UnixNano()/1e6) return info } // 渠道配置 func ConfGetInfoByChannel(chn int) map[string]string { v, ok := mapChannelToConf.Load(chn) if !ok { return nil } conf := v.(*ConfApp) info := make(map[string]string) info["appId"] = conf.appId info["bizId"] = conf.bizId info["secretKey"] = conf.secretKey info["timestamps"] = fmt.Sprintf("%v", time.Now().UnixNano()/1e6) return info } // 创建请求消息body func MakeRequestBody(m map[string]interface{}, secretKey string) string { pack, _ := json.Marshal(m) key, _ := hex.DecodeString(secretKey) block, err := aes.NewCipher(key) if err != nil { return "" } aesGcm, err := cipher.NewGCM(block) if err != nil { return "" } // 向量 nonce := make([]byte, aesGcm.NonceSize()) if _, err := io.ReadFull(rand.Reader, nonce); err != nil { return "" } cipherText := aesGcm.Seal(nonce, nonce, pack, nil) // encode as base64 string encoded := base64.StdEncoding.EncodeToString(cipherText) ret := make(map[string]string) ret["data"] = encoded pack, _ = json.Marshal(ret) return string(pack) } // 签名 func MakeRequestSign(heads map[string]string, params map[string]string, body string) string { var kvs utils.Kvs kvs = append(kvs, &utils.Kv{Key: "appId", Value: heads["appId"]}) kvs = append(kvs, &utils.Kv{Key: "bizId", Value: heads["bizId"]}) kvs = append(kvs, &utils.Kv{Key: "timestamps", Value: heads["timestamps"]}) for k, v := range params { kvs = append(kvs, &utils.Kv{Key: k, Value: url.QueryEscape(v)}) } sort.Sort(kvs) key := "" for i := 0; i < kvs.Len(); i++ { key += kvs[i].Key + kvs[i].Value } strEncode := heads["secretKey"] + key + body h2 := sha256.New() h2.Write([]byte(strEncode)) hashed := h2.Sum(nil) sign := hex.EncodeToString(hashed) // log.Println(fmt.Sprintf("MakeRequestSign strEncode[%s] sign[%s]", strEncode, sign)) return sign } // 请求 网络游戏防沉迷实名认证系统 func Send2Nppa(method string, url string, heads map[string]string, params map[string]string, body string) ([]byte, error) { if len(params) > 0 { url += "?" for k, v := range params { url += k + "=" + v + "&" } url = url[:len(url)-1] } req, err1 := http.NewRequest(method, url, strings.NewReader(body)) if err1 != nil { return nil, err1 } req.Header.Set("Content-Type", "application/json;charset=utf-8") req.Header.Set("appId", heads["appId"]) req.Header.Set("bizId", heads["bizId"]) req.Header.Set("timestamps", heads["timestamps"]) req.Header.Set("sign", heads["sign"]) client := &http.Client{} resp, err2 := client.Do(req) if err2 != nil { return nil, err2 } defer resp.Body.Close() return ioutil.ReadAll(resp.Body) } // 测试签名 func TestSign() string { mapBody := make(map[string]interface{}) mapBody["id"] = "test-id" mapBody["name"] = "test-name" mapInfo := make(map[string]string) mapInfo["appId"] = "test-appId" mapInfo["bizId"] = "test-bizId" mapInfo["secretKey"] = "2836e95fcd10e04b0069bb1ee659955b" mapInfo["timestamps"] = "1584949895758" body := MakeRequestBody(mapBody, mapInfo["secretKey"]) sign := MakeRequestSign(mapInfo, nil, body) // log.Println(fmt.Sprintf("TestSign sign[%s]", sign)) return sign } // 获取玩家嘉米实名认证信息 func GetJiamiIdInfo(uid int) map[string]string { project := utils.GetProject() idInfo := make(map[string]string) // 麻将 if project == "mahjong" { idInfo = GetMahjongIdInfo(uid) } else if project == "H5ddz" { idInfo = GetH5ddzIdInfo(uid) } return idInfo } func GetMahjongIdInfo(uid int) map[string]string { idInfo := make(map[string]string) idInfo["name"] = utils.GetPlayerInfoFromRedis(uid, "jmIDName") idInfo["idNum"] = utils.GetPlayerInfoFromRedis(uid, "jmIDCard") idInfo["chn"] = utils.GetPlayerInfoFromRedis(uid, "channel") return idInfo } func GetH5ddzIdInfo(uid int) map[string]string { idInfo := make(map[string]string) info := utils.GetPlayerInfoFromRedis(uid, "info") j, err := simplejson.NewJson([]byte(info)) if err != nil { log.Println("GetH5ddzIdInfo err:", err) return idInfo } idInfo["name"], _ = j.Get("antiAddiData").Get("identityName").String() idInfo["idNum"], _ = j.Get("antiAddiData").Get("identity").String() strChannel, _ := j.Get("channel").Int() idInfo["chn"] = strconv.Itoa(strChannel) return idInfo }