730 lines
23 KiB
Markdown
730 lines
23 KiB
Markdown
> 本文保留新增需求讨论和示例代码,不作为技术实施结论。最终口径以 [标准评审稿](../7月迭代技术方案-标准评审稿.md) 及对应新增需求独立稿为准。
|
||
|
||
处理回调的代码
|
||
```golang
|
||
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
|
||
}
|
||
|
||
```
|
||
|
||
|
||
优化轮询以及添加事件/触发式 数据同步
|
||
|
||
目前我们系统过于依赖轮询系统,且轮询系统的黑盒属性过于严重
|
||
所以现在想加入事件触发以及实名回调,目前已知的可配置实名回调只有移动,联通,电信三个运营商,广电是没有实名回调的,上方是之前已经实现过的实名回调
|
||
|
||
需求差不多是这么个需求,主要就是想让数据同步这一块的及时率达到一种很快的地步,看是怎么埋点,而且开放接口的埋点还需要特殊处理,不然的话代理拿着我们的开放接口乱调用的话就等于外置了一个轮询系统了
|