Files
junhong_cmp_fiber/docs/7月迭代/新需求.md
2026-07-16 15:08:07 +08:00

23 KiB
Raw Blame History

处理回调的代码

package main

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"strconv"

	"strings"
	"time"

	ranNumLib "math/rand"

	"github.com/google/uuid"
)

// XML请求体结构
type ContractRoot struct {
	XMLName            xml.Name `xml:"ContractRoot"`
	Type               string   `xml:"TYPE"`
	GroupTransactionID string   `xml:"GROUP_TRANSACTIONID"`
	StatusInfo         string   `xml:"STATUSINFO"`
	AccNbr             string   `xml:"ACCNBR"`
	ICCID              string   `xml:"ICCID"`
	SendDt             string   `xml:"SENDDT"`
	AcceptType         string   `xml:"ACCEPTTYPE"`
	AcceptMsg          string   `xml:"ACCEPTMSG"`
	StatusDt           string   `xml:"STATUSDT"`
	ResultMsg          string   `xml:"RESULTMSG"`
}

// 第三方推送数据结构
type PushData struct {
	Msg  string `json:"msg"`
	Code int    `json:"code"`
	Data struct {
		RequestID  string `json:"requestId"`
		RealStatus bool   `json:"realStatus"`
		ICCID      string `json:"iccid"`
	} `json:"data"`
}

func parseCallback(jsonStr []byte) (string, string, error) {
	// 定义匿名结构体用于解析外层JSON
	var cb struct {
		Data string `json:"data"`
	}
	err := json.Unmarshal(jsonStr, &cb)
	if err != nil {
		return "", "", fmt.Errorf("failed to unmarshal outer JSON: %v", err)
	}

	// 定义匿名结构体用于解析内层数据
	var inner struct {
		DateChanged string `json:"dateChanged"`
		ICCID       string `json:"iccid"`
	}
	err = json.Unmarshal([]byte(cb.Data), &inner)
	if err != nil {
		return "", "", fmt.Errorf("failed to unmarshal inner data JSON: %v", err)
	}

	return inner.ICCID, inner.DateChanged, nil
}

// 5GCMP实名后推送到第三方平台
func pushToThirdParty(iccid string) (string, error) {
	// 构建推送数据
	pushData := PushData{
		Msg:  "查询成功",
		Code: 200,
	}
	pushData.Data.RequestID = uuid.New().String()
	pushData.Data.RealStatus = true
	pushData.Data.ICCID = iccid

	// 序列化为JSON
	jsonData, err := json.Marshal(pushData)
	if err != nil {
		return "", fmt.Errorf("序列化推送数据失败: %v", err)
	}

	// 发送HTTP POST请求
	pushURL := "http://jh.whjhft.com/gswlpushapi/recv.do?type=3"
	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	resp, err := client.Post(pushURL, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return "", fmt.Errorf("HTTP请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 读取响应
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("读取响应失败: %v", err)
	}

	return string(respBody), nil
}

// 获取日志文件路径
func getLogFilePath() string {
	// 创建logs目录
	logsDir := "logs"
	if err := os.MkdirAll(logsDir, 0755); err != nil {
		log.Printf("创建日志目录失败: %v", err)
	}

	// 按日期生成文件名
	dateStr := time.Now().Format("2006-01-02")
	fileName := fmt.Sprintf("5gcmp_callback_%s.log", dateStr)
	return filepath.Join(logsDir, fileName)
}

func GetQcRandNum() (ranNum string) {
	randomFloat := ranNumLib.Float64()
	if randomFloat < 0.5 {
		randomFloat = 1 - randomFloat
	}
	ranNum = fmt.Sprintf("%.16f", randomFloat)
	return
}

// 写入日志
func writeLog(content string) {
	logFile := getLogFilePath()

	// 打开或创建日志文件
	file, err := os.OpenFile(logFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		log.Printf("打开日志文件失败: %v", err)
		return
	}
	defer file.Close()

	// 写入日志内容
	if _, err := file.WriteString(content); err != nil {
		log.Printf("写入日志失败: %v", err)
	}
}

// 向管理平台发送删除实名请求
func DelRealName(iccid string) (res string) {
	account := Account{UserName: "18627991016", Password: "y123456"}
	sessionid := account.Login()
	realnameId := getRealnameIdByIccid(iccid, sessionid)
	if realnameId == "" {
		return
	}
	log.Printf("sessinid:%s,realnameId:%s", sessionid, realnameId)
	url := "http://jh.whjhft.com/realnamerecord/deleteById.do?responseFunction=initUpdate&id=" + realnameId + "&rfm=" + GetQcRandNum()
	data := fmt.Sprintf("status=1&iccidMark=%s", iccid)
	req, err := http.NewRequest("POST", url, strings.NewReader(data))
	if err != nil {
		log.Printf("创建请求失败: %v", err)
		return ""
	}
	client := &http.Client{
		Timeout: 10 * time.Second,
	}
	req.Header.Set("Cookie", fmt.Sprintf("JSESSIONID=%s", sessionid))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
	req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.37 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0")
	resp, err := client.Do(req)
	if err != nil {
		log.Printf("HTTP请求失败: %v", err)
		return
	}
	defer resp.Body.Close()
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Printf("读取响应失败: %v", err)
		return
	}
	log.Printf("删除实名响应: %s", respBody)
	res = string(respBody)
	return
}

func getRealnameIdByIccid(iccid, sessionid string) (realnameId string) {
	url := "http://jh.whjhft.com/realnamerecord/grid.do?responseFunction=grid&pageSize=15&pageNo=1&rfm=0." + GetQcRandNum()
	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	data := fmt.Sprintf("status=1&iccidMark=%s", iccid)

	req, err := http.NewRequest("POST", url, strings.NewReader(data))
	if err != nil {
		log.Printf("创建请求失败: %v", err)
		return
	}
	req.Header.Set("Cookie", fmt.Sprintf("JSESSIONID=%s", sessionid))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
	req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.37 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0")
	resp, err := client.Do(req)
	if err != nil {
		log.Printf("HTTP请求失败: %v", err)
		return
	}
	defer resp.Body.Close()
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Printf("读取响应失败: %v", err)
		return
	}

	var JSONData struct {
		Code string `json:"code"`
		Data struct {
			PageNo          int `json:"pageNo"`
			PageCount       int `json:"pageCount"`
			PageSize        int `json:"pageSize"`
			PageStartOffset int `json:"pageStartOffset"`
			Total           int `json:"total"`
			Rows            []struct {
				MybatisRecordCount int    `json:"mybatisRecordCount"`
				OrderNo            string `json:"orderNo"`
				JSONUpdateFlag     string `json:"jsonUpdateFlag"`
				ID                 string `json:"id"`
				IccidMark          string `json:"iccidMark"`
				Phone              string `json:"phone"`
				AccountID          string `json:"accountId"`
				AccountName        string `json:"accountName"`
				Status             int    `json:"status"`
				CreateName         string `json:"createName"`
				CreateDate         string `json:"createDate"`
				StatusStr          string `json:"statusStr"`
			} `json:"rows"`
			Framework string `json:"framework"`
			Data      string `json:"data"`
			Count     int    `json:"count"`
			Limit     int    `json:"limit"`
			Page      int    `json:"page"`
			Layui     bool   `json:"layui"`
		} `json:"data"`
		CurrentSessionUserResourceIdsIndex []string `json:"current_session_user_resource_ids_index"`
		AppResultKey                       string   `json:"app_result_key"`
		SystemResultKey                    string   `json:"system_result_key"`
	}
	json.Unmarshal(respBody, &JSONData)
	if JSONData.AppResultKey == "0" && JSONData.SystemResultKey == "0" && JSONData.Data.Count > 0 {
		realnameId = JSONData.Data.Rows[0].ID
	}

	log.Printf("响应体: %s", respBody)
	return
}

func getIccidByMsisdn(msisdn, sessionid string) (iccid string) {
	url := "http://jh.whjhft.com/realnamerecord/grid.do?responseFunction=grid&pageSize=15&pageNo=1&rfm=" + GetQcRandNum()
	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	data := fmt.Sprintf("status=1&phone=%s", msisdn)

	req, err := http.NewRequest("POST", url, strings.NewReader(data))
	if err != nil {
		log.Printf("创建请求失败: %v", err)
		return
	}
	req.Header.Set("Cookie", fmt.Sprintf("JSESSIONID=%s", sessionid))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
	req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.37 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0")
	resp, err := client.Do(req)
	if err != nil {
		log.Printf("HTTP请求失败: %v", err)
		return
	}
	defer resp.Body.Close()
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Printf("读取响应失败: %v", err)
		return
	}
	var JSONData struct {
		Code string `json:"code"`
		Data struct {
			Rows []struct {
				IccidMark string `json:"iccidMark"`
			} `json:"rows"`
			Count int `json:"count"`
		} `json:"data"`
		AppResultKey    string `json:"app_result_key"`
		SystemResultKey string `json:"system_result_key"`
	}
	json.Unmarshal(respBody, &JSONData)
	if JSONData.AppResultKey == "0" && JSONData.SystemResultKey == "0" && JSONData.Data.Count > 0 {
		iccid = JSONData.Data.Rows[0].IccidMark
	}
	log.Printf("响应体: %s", respBody)
	return
}

func ModifyDate(iccid, dateChanged string) {
	var jsonData = map[string]interface{}{
		"iccid":       iccid,
		"dateChanged": dateChanged,
	}
	jsonDataBs, _ := json.Marshal(jsonData)

	// 创建请求
	req, err := http.NewRequest("POST", "http://127.0.0.1:3000/api/v1/inventory/realname/inner_callback", bytes.NewReader(jsonDataBs))
	if err != nil {
		writeLog(fmt.Sprintf("创建请求失败:[%s] [%s]实名时间[%s]失败\r\n", "http://127.0.0.1:3000/api/v1/inventory/realname/inner_callback", iccid, dateChanged))
		return
	}

	// 设置Content-Type为x-www-form-urlencoded
	req.Header.Set("Content-Type", "application/json")

	// 发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		writeLog(fmt.Sprintf("请求接口:[%s] [%s]实名时间[%s]失败\r\n", "http://127.0.0.1:3000/api/v1/inventory/realname/inner_callback", iccid, dateChanged))
		return
	}
	defer resp.Body.Close()

	// 读取响应内容
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		writeLog(fmt.Sprintf("请求接口:[%s] [%s]实名时间[%s]失败\r\n", "http://127.0.0.1:3000/api/v1/inventory/realname/inner_callback", iccid, dateChanged))
		return
	}

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		fmt.Printf("请求失败,状态码: %d, 响应: %s\n", resp.StatusCode, string(respBody))
		writeLog(fmt.Sprintf("请求接口:[%s] [%s]实名时间[%s]失败\r\n", "http://127.0.0.1:3000/api/v1/inventory/realname/inner_callback", iccid, dateChanged))
		return
	}

	writeLog(fmt.Sprintf("请求接口:[%s] [%s]实名时间[%s]成功,[%s]\r\n", "http://127.0.0.1:3000/api/v1/inventory/realname/inner_callback", iccid, dateChanged, string(respBody)))

}

// 处理回调请求
func handleCallback(w http.ResponseWriter, r *http.Request) {
	// 记录请求开始时间
	startTime := time.Now()
	timestamp := startTime.Format("2006-01-02 15:04:05")

	// 构建日志内容
	var logBuilder strings.Builder
	logBuilder.WriteString("\n========================================\n")
	logBuilder.WriteString(fmt.Sprintf("请求时间: %s\n", timestamp))
	logBuilder.WriteString(fmt.Sprintf("请求方法: %s\n", r.Method))
	logBuilder.WriteString(fmt.Sprintf("完整URL: %s\n", r.URL.String()))
	logBuilder.WriteString(fmt.Sprintf("请求路径: %s\n", r.URL.Path))
	logBuilder.WriteString(fmt.Sprintf("查询参数: %s\n", r.URL.RawQuery))
	logBuilder.WriteString(fmt.Sprintf("客户端IP: %s\n", r.RemoteAddr))

	// 记录请求头
	logBuilder.WriteString("--- 请求头 ---\n")
	for name, values := range r.Header {
		for _, value := range values {
			logBuilder.WriteString(fmt.Sprintf("%s: %s\n", name, value))
		}
	}

	// 记录请求体
	logBuilder.WriteString("--- 请求体 ---\n")
	body, err := io.ReadAll(r.Body)
	if err != nil {
		logBuilder.WriteString(fmt.Sprintf("读取请求体失败: %v\n", err))
	} else {
		if len(body) > 0 {
			logBuilder.WriteString(fmt.Sprintf("%s\n", string(body)))
		} else {
			logBuilder.WriteString("(空请求体)\n")
		}
	}

	// 处理XML请求体和第三方推送
	var pushResponse string

	log.Printf("body:%s\r\n", string(body))

	if len(body) > 0 {
		// 尝试解析XML
		var contractRoot ContractRoot
		if err := xml.Unmarshal(body, &contractRoot); err == nil {
			logBuilder.WriteString("--- XML解析结果 ---\n")
			logBuilder.WriteString(fmt.Sprintf("TYPE: %s\n", contractRoot.Type))
			logBuilder.WriteString(fmt.Sprintf("ICCID: %s\n", contractRoot.ICCID))
			logBuilder.WriteString(fmt.Sprintf("STATUSINFO: %s\n", contractRoot.StatusInfo))

			// 如果TYPE=1表示实名认证成功需要推送到第三方
			if strings.Contains(contractRoot.AcceptMsg, "已完成实名信息补录") && contractRoot.ICCID != "" && contractRoot.ResultMsg == "成功" {
				logBuilder.WriteString("--- 第三方推送 ---\n")
				logBuilder.WriteString(fmt.Sprintf("触发条件: TYPE=%s (实名认证成功)\n", contractRoot.Type))
				logBuilder.WriteString(fmt.Sprintf("推送ICCID: %s\n", contractRoot.ICCID))
				logBuilder.WriteString("推送地址: http://jh.whjhft.com/gswlpushapi/recv.do?type=3\n")

				timestampStr := strconv.FormatInt(time.Now().Unix(), 10)
				ModifyDate(contractRoot.ICCID, timestampStr)

				// 执行推送
				if resp, err := pushToThirdParty(contractRoot.ICCID); err != nil {
					logBuilder.WriteString(fmt.Sprintf("推送失败: %v\n", err))
					pushResponse = fmt.Sprintf("推送失败: %v", err)
				} else {
					logBuilder.WriteString(fmt.Sprintf("推送成功,响应: %s\n", resp))
					pushResponse = resp
				}
			} else if strings.Contains(contractRoot.AcceptMsg, "已完成实名信息清除") && contractRoot.ICCID != "" && contractRoot.ResultMsg == "成功" {
				logBuilder.WriteString("--- 第三方推送删除实名 ---\n")
				res := DelRealName(contractRoot.ICCID)
				logBuilder.WriteString(fmt.Sprintf("删除实名响应: %s\n", res))
			} else {
				logBuilder.WriteString("--- 第三方推送 ---\n")
				logBuilder.WriteString(fmt.Sprintf("跳过推送: TYPE=%s,%s,%s (非实名认证成功)\n", contractRoot.Type, contractRoot.AcceptMsg, contractRoot.ResultMsg))
			}
		} else {
			logBuilder.WriteString(fmt.Sprintf("XML解析失败: %v\n", err))
		}
	}

	// 记录处理时间
	processTime := time.Since(startTime)
	logBuilder.WriteString(fmt.Sprintf("处理耗时: %v\n", processTime))
	logBuilder.WriteString("========================================\n")

	// 写入日志文件
	writeLog(logBuilder.String())

	// 同时输出到控制台
	fmt.Print(logBuilder.String())

	// 返回成功响应
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)

	// 构建响应数据
	responseData := map[string]interface{}{
		"code":      200,
		"msg":       "success",
		"timestamp": timestamp,
	}

	// 如果有推送响应,添加到响应中
	if pushResponse != "" {
		responseData["pushResponse"] = pushResponse
	}

	respJSON, _ := json.Marshal(responseData)
	w.Write(respJSON)
}

// 获取管理平台登录凭证
func (ac Account) Login() (sessionid string) {
	var password string
	password = ac.Password
	var requestBody bytes.Buffer
	multipartWriter := multipart.NewWriter(&requestBody)
	multipartWriter.WriteField("username", ac.UserName)
	multipartWriter.WriteField("password", password)
	multipartWriter.Close()
	req, _ := http.NewRequest("POST", "http://jh.whjhft.com/pages/login.do", &requestBody)
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0")
	req.Header.Set("Content-Type", multipartWriter.FormDataContentType())
	//client1 := http.DefaultClient
	client1 := &http.Client{
		CheckRedirect: func(req1 *http.Request, via []*http.Request) error {

			strs := strings.Split(req1.URL.Path, ";")
			log.Printf("%s\r\n", req1.URL.Path)
			if len(strs) == 2 {
				strs1 := strings.Split(strs[1], "=")
				if len(strs1) == 2 {
					sessionid = strs1[1]
				}
			}
			// fmt.Printf("Redirect from '%s' to '%s'\n", via[0].URL, req1.URL.Path)
			return nil
		},
	}
	resp, err := client1.Do(req)
	if err != nil {
		fmt.Println("Failed to send request:", err)
		return
	}
	defer resp.Body.Close()

	// 处理响应
	_, err = ioutil.ReadAll(resp.Body)

	if err != nil {
		fmt.Println("Failed to read response:", err)
		return
	}
	//fmt.Println("Response:", string(respBody))
	return
}

// 移动实名回调
func ChinaMobileCallback(w http.ResponseWriter, r *http.Request) {
	// 记录请求开始时间
	startTime := time.Now()
	timestamp := startTime.Format("2006-01-02 15:04:05")

	// 构建日志内容
	var logBuilder strings.Builder
	logBuilder.WriteString("\n========================================\n")
	logBuilder.WriteString("【移动实名回调】\n")
	logBuilder.WriteString(fmt.Sprintf("请求时间: %s\n", timestamp))
	logBuilder.WriteString(fmt.Sprintf("请求方法: %s\n", r.Method))
	logBuilder.WriteString(fmt.Sprintf("完整URL: %s\n", r.URL.String()))
	logBuilder.WriteString(fmt.Sprintf("请求路径: %s\n", r.URL.Path))
	logBuilder.WriteString(fmt.Sprintf("查询参数: %s\n", r.URL.RawQuery))
	logBuilder.WriteString(fmt.Sprintf("客户端IP: %s\n", r.RemoteAddr))

	// 记录请求头
	logBuilder.WriteString("--- 请求头 ---\n")
	for name, values := range r.Header {
		for _, value := range values {
			logBuilder.WriteString(fmt.Sprintf("%s: %s\n", name, value))
		}
	}

	// 记录请求体
	logBuilder.WriteString("--- 请求体 ---\n")
	body, err := io.ReadAll(r.Body)
	if err != nil {
		logBuilder.WriteString(fmt.Sprintf("读取请求体失败: %v\n", err))
	} else {
		if len(body) > 0 {
			logBuilder.WriteString(fmt.Sprintf("%s\n", string(body)))
			var JSONData struct {
				Status  string `json:"status"`
				Message string `json:"message"`
				Result  []struct {
					RegStatus string `json:"regStatus"`
					BusiSeq   string `json:"busiSeq"`
					Msisdn    string `json:"msisdn"`
					Iccid     string `json:"iccid"`
				} `json:"result"`
			}
			json.Unmarshal(body, &JSONData)
			if JSONData.Status == "0" && JSONData.Message == "正确" && len(JSONData.Result) > 0 && JSONData.Result[0].RegStatus == "00000" {
				iccid := JSONData.Result[0].Iccid
				if iccid == "" {
					msisdn := JSONData.Result[0].Msisdn //接入号
					account := Account{UserName: "18627991016", Password: "y123456"}
					sessionid := account.Login()
					iccid = getIccidByMsisdn(msisdn, sessionid)
				}
				if iccid == "" {
					return
				}

				//推送修改过期时间
				timestampStr := strconv.FormatInt(time.Now().Unix(), 10)
				ModifyDate(iccid, timestampStr)

				logBuilder.WriteString("--- 第三方推送 ---\n")
				logBuilder.WriteString(fmt.Sprintf("推送ICCID: %s\n", iccid))
				logBuilder.WriteString("推送地址: http://jh.whjhft.com/gswlpushapi/recv.do?type=3\n")

				// 执行推送实名状态
				if resp, err := pushToThirdParty(iccid); err != nil {
					logBuilder.WriteString(fmt.Sprintf("推送失败: %v\n", err))
				} else {
					logBuilder.WriteString(fmt.Sprintf("推送成功,响应: %s\n", resp))
				}
				logBuilder.WriteString("--- 第三方推送 ---\n")

			} else {
				logBuilder.WriteString("(实名认证失败)\n")
			}

		} else {
			logBuilder.WriteString("(空请求体)\n")
		}
	}
	defer r.Body.Close()

	// 记录处理时间
	processTime := time.Since(startTime)
	logBuilder.WriteString(fmt.Sprintf("处理耗时: %v\n", processTime))
	logBuilder.WriteString("========================================\n")

	// 写入日志文件
	writeLog(logBuilder.String())

	// 同时输出到控制台
	fmt.Print(logBuilder.String())

	// 返回200 OK响应
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)

	// 构建响应数据
	responseData := map[string]interface{}{
		"code":      200,
		"msg":       "success",
		"timestamp": timestamp,
	}

	respJSON, _ := json.Marshal(responseData)
	w.Write(respJSON)
}

// 联通解除实名回调
func UniRealnameRemove(w http.ResponseWriter, r *http.Request) {
	// 记录请求开始时间
	startTime := time.Now()
	timestamp := startTime.Format("2006-01-02 15:04:05")

	// 构建日志内容
	var logBuilder strings.Builder
	logBuilder.WriteString("\n========================================\n")
	logBuilder.WriteString(fmt.Sprintf("请求时间: %s\n", timestamp))
	logBuilder.WriteString(fmt.Sprintf("请求方法: %s\n", r.Method))
	logBuilder.WriteString(fmt.Sprintf("完整URL: %s\n", r.URL.String()))
	logBuilder.WriteString(fmt.Sprintf("请求路径: %s\n", r.URL.Path))
	logBuilder.WriteString(fmt.Sprintf("查询参数: %s\n", r.URL.RawQuery))
	logBuilder.WriteString(fmt.Sprintf("客户端IP: %s\n", r.RemoteAddr))

	// 记录请求头
	logBuilder.WriteString("--- 请求头 ---\n")
	for name, values := range r.Header {
		for _, value := range values {
			logBuilder.WriteString(fmt.Sprintf("%s: %s\n", name, value))
		}
	}

	// 记录请求体
	logBuilder.WriteString("--- 请求体 ---\n")
	body, err := io.ReadAll(r.Body)
	if err != nil {
		logBuilder.WriteString(fmt.Sprintf("读取请求体失败: %v\n", err))
	} else {
		if len(body) > 0 {
			logBuilder.WriteString(fmt.Sprintf("%s\n", string(body)))
		} else {
			logBuilder.WriteString("(空请求体)\n")
		}
	}
	defer r.Body.Close()

	// 解析回调数据
	iccid, dateChanged, err := parseCallback(body)
	if err != nil {
		logBuilder.WriteString(fmt.Sprintf("解析回调数据失败: %v\n", err))
	} else {
		if len(iccid) == 20 {
			//取前面19位
			iccid = iccid[:19]
			//删除实名
			res := DelRealName(iccid)
			logBuilder.WriteString(fmt.Sprintf("删除实名响应: %s\n", res))
		}
		logBuilder.WriteString(fmt.Sprintf("解析回调数据成功: ICCID=%s, DateChanged=%s\n", iccid, dateChanged))
	}

	// 写入日志文件
	writeLog(logBuilder.String())

	// 同时输出到控制台
	fmt.Print(logBuilder.String())

	// 构建响应数据
	responseData := map[string]interface{}{
		"code":      200,
		"msg":       "success",
		"timestamp": timestamp,
	}

	respJSON, _ := json.Marshal(responseData)
	w.Write(respJSON)
}

func main() {
	// 注册路由
	// res := DelRealName("8986112422108176397")
	// log.Printf("删除实名响应: %s", res)

	http.HandleFunc("/5gcmp/callback/realname", handleCallback)
	http.HandleFunc("/unicom/callback/realname/remove", UniRealnameRemove)
	http.HandleFunc("/mobile/callback/realname", ChinaMobileCallback)

	// 启动服务器
	port := ":16159"
	fmt.Printf("5GCMP回调服务器启动成功\n")
	fmt.Printf("监听端口: %s\n", port)
	fmt.Printf("电信回调地址: %s/5gcmp/callback/realname\n", port)
	fmt.Printf("联通回调地址: %s/unicom/callback/realname/remove\n", port)
	fmt.Printf("移动回调地址: %s/mobile/callback/realname\n", port)
	fmt.Printf("日志目录: logs/\n")
	fmt.Printf("按 Ctrl+C 停止服务器\n\n")

	if err := http.ListenAndServe(port, nil); err != nil {
		log.Fatalf("启动服务器失败: %v", err)
	}
}

type Account struct {
	UserName string
	Password string
}

优化轮询以及添加事件/触发式 数据同步

目前我们系统过于依赖轮询系统,且轮询系统的黑盒属性过于严重 所以现在想加入事件触发以及实名回调,目前已知的可配置实名回调只有移动,联通,电信三个运营商,广电是没有实名回调的,上方是之前已经实现过的实名回调

需求差不多是这么个需求,主要就是想让数据同步这一块的及时率达到一种很快的地步,看是怎么埋点,而且开放接口的埋点还需要特殊处理,不然的话代理拿着我们的开放接口乱调用的话就等于外置了一个轮询系统了