package models import ( "crypto/md5" "encoding/hex" "encoding/json" "fmt" "github.com/go-admin-team/go-admin-core/logger" "go-admin/common/database" "io" "net/http" "net/url" "time" ) const ( MusicProductID = 2 MaxRetries = 3 LoginType = "3" ServiceId = "698039049108516515" MiGuSubscriptionUrl = "http://hz.migu.cn/order/rest/201906/all/bjhy/and/package/query.do" MiGuLoginUrl = "http://hz.migu.cn/order/rest/login/secret/url.do" SignSecretKey = "1524b4ed9eef4cdca934056499a1dd14" // 签名密钥 LoginSecretKey = "913efe5c6f274c278988af817f9d1c7d" // 登陆密钥 ) type MonthlySubscriptionReq struct { ChannelCode string `json:"channelCode"` Timestamp string `json:"timestamp"` Signature string `json:"signature"` Token string `json:"token"` ServiceId string `json:"serviceId"` } type MonthlySubscriptionResp struct { ResCode string `json:"resCode"` ResMsg string `json:"resMsg"` Status string `json:"status"` ValidTime string `json:"validTime"` } func generateSignature(channelCode, timestamp string) string { data := channelCode + timestamp + SignSecretKey hash := md5.Sum([]byte(data)) return hex.EncodeToString(hash[:]) } func MonthlySubscriptionQuery(token, serviceId, channelCode string) (MonthlySubscriptionResp, error) { fmt.Println("MonthlySubscriptionQuery start") logger.Info("MonthlySubscriptionQuery start") var respData MonthlySubscriptionResp timestamp := time.Now().Format("20060102150405") signature := generateSignature(channelCode, timestamp) reqBody := MonthlySubscriptionReq{ ChannelCode: channelCode, Timestamp: timestamp, Signature: signature, Token: token, ServiceId: serviceId, } jsonData, err := json.Marshal(reqBody) if err != nil { fmt.Println("Error marshalling request body:", err) return respData, err } fmt.Println("MonthlySubscriptionQuery req:", string(jsonData)) logger.Info("MonthlySubscriptionQuery req:", string(jsonData)) client := &http.Client{} req, err := http.NewRequest("GET", MiGuSubscriptionUrl+"?data="+url.QueryEscape(string(jsonData)), nil) if err != nil { fmt.Println("Error creating HTTP request:", err) logger.Error("Error creating HTTP request:", err) return respData, err } req.Header.Set("Content-Type", "application/json; charset=utf-8") resp, err := client.Do(req) if err != nil { fmt.Println("Error making HTTP request:", err) logger.Error("Error making HTTP request:", err) return respData, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) logger.Error("Error reading response body:", err) return respData, err } fmt.Println("MonthlySubscriptionQuery resp:", string(body)) logger.Info("MonthlySubscriptionQuery resp:", string(body)) err = json.Unmarshal(body, &respData) if err != nil { fmt.Println("Error unmarshalling response body:", err) logger.Error("Error unmarshalling response body:", err) return respData, err } fmt.Println("MonthlySubscriptionQuery end") logger.Info("MonthlySubscriptionQuery end") return respData, nil } type LoginRequest struct { ChannelCode string `json:"channelCode"` Timestamp string `json:"timestamp"` Signature string `json:"signature"` LoginType string `json:"loginType"` CallBackUrl string `json:"callBackUrl,omitempty"` Key string `json:"key,omitempty"` Msisdn string `json:"msisdn,omitempty"` } type LoginResponse struct { ResCode string `json:"resCode"` ResMsg string `json:"resMsg"` Token string `json:"token"` } func Login(channelCode, loginType, callBackUrl, msisdn string) (LoginResponse, error) { fmt.Println("login start") logger.Info("login start") var respData LoginResponse timestamp := time.Now().Format("20060102150405") signature := generateSignature(channelCode, timestamp) reqBody := LoginRequest{ ChannelCode: channelCode, Timestamp: timestamp, Signature: signature, LoginType: loginType, } if loginType == "1" && callBackUrl != "" { reqBody.CallBackUrl = callBackUrl } else if loginType == "3" { reqBody.Key = LoginSecretKey reqBody.Msisdn = msisdn } jsonData, err := json.Marshal(reqBody) if err != nil { fmt.Println("Error marshalling request body:", err) return respData, err } fmt.Println("login req:", string(jsonData)) logger.Info("login req:", string(jsonData)) client := &http.Client{} req, err := http.NewRequest("GET", MiGuLoginUrl+"?data="+url.QueryEscape(string(jsonData)), nil) if err != nil { fmt.Println("Error creating HTTP request:", err) logger.Error("Error creating HTTP request:", err) return respData, err } req.Header.Set("Content-Type", "application/json; charset=utf-8") resp, err := client.Do(req) if err != nil { fmt.Println("Error making HTTP request:", err) logger.Error("Error making HTTP request:", err) return respData, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) logger.Error("Error reading response body:", err) return respData, err } fmt.Println("login resp:", string(body)) logger.Info("login resp:", string(body)) err = json.Unmarshal(body, &respData) if err != nil { fmt.Println("Error unmarshalling response body:", err) logger.Error("Error unmarshalling response body:", err) return respData, err } fmt.Println("login end") logger.Info("login end") return respData, nil } // CheckMusicOrderState 定时任务,检查咪咕音乐的订单是否有退订 func CheckMusicOrderState() { logger.Info("****** CheckMusicOrderState start ******") fmt.Println("****** CheckMusicOrderState start ******") if database.Db == nil { logger.Error("Database connection is nil") fmt.Println("Database connection is nil") return } // 查询订单列表中未退订的用户,查询其是否退订;如果退订,则更新退订时间 var orderList []MgOrder err := database.Db.Where("state = 1"). Where("product_id = ?", MusicProductID). Order("created_at desc"). Find(&orderList).Error if err != nil { fmt.Println("query mg_order err:", err.Error()) logger.Error("query mg_order err:", err.Error()) return } fmt.Println("orderList size is:", len(orderList)) logger.Info("orderList size is:", len(orderList)) for _, order := range orderList { var token string // 登录接口调用 if !attemptLogin(&token, order) { continue } // 订阅状态查询 if !checkSubscriptionStatus(token, order) { continue } } fmt.Println("****** CheckMusicOrderState end ******") logger.Info("****** CheckMusicOrderState end ******") } func attemptLogin(token *string, order MgOrder) bool { for j := 0; j < MaxRetries; j++ { resp, err := Login(order.ChannelCode, LoginType, "", order.PhoneNumber) if err != nil || resp.ResCode != "000000" { if err != nil { fmt.Println("Login failed:", err.Error()) logger.Error("Login failed:", err.Error()) } else { fmt.Println("Login failed, loginResp:", resp) logger.Error("Login failed, loginResp:", resp) } if j < MaxRetries-1 { continue } return false } *token = resp.Token return true } return false } func checkSubscriptionStatus(token string, order MgOrder) bool { for j := 0; j < MaxRetries; j++ { resp, err := MonthlySubscriptionQuery(token, ServiceId, order.ChannelCode) if err != nil || resp.ResCode != "000000" { if err != nil { fmt.Println("MonthlySubscriptionQuery failed:", err.Error()) logger.Error("MonthlySubscriptionQuery failed:", err.Error()) } else { fmt.Println("MonthlySubscriptionQuery failed, MonthlySubscriptionResp:", resp.ResCode) logger.Error("MonthlySubscriptionQuery failed, MonthlySubscriptionResp:", resp.ResCode) } if j < MaxRetries-1 { continue } return false } if resp.Status == "0" { return true } else if resp.Status == "1" { if order.State == SubscribeOK { subscribeTime := order.CreatedAt unsubTime := time.Now().Format("2006-01-02 15:04:05") cancelFlag := 0 if IsWithinOneHourCancel(subscribeTime, unsubTime) { cancelFlag = 1 } err = database.Db.Table("mg_order").Where("order_serial = ?", order.OrderSerial).Updates(map[string]interface{}{ "state": UnsubscribeOK, "is_one_hour_cancel": cancelFlag, "unsubscribe_time": unsubTime, "updated_at": time.Now(), }).Error if err != nil { fmt.Println("Failed to update order:", err.Error()) logger.Error("Failed to update order:", err.Error()) } return false } } } return false }