feat: 发送养护订阅消息
This commit is contained in:
@@ -28,6 +28,7 @@ service-account:
|
|||||||
app-id: wxc236cddde8e7f863
|
app-id: wxc236cddde8e7f863
|
||||||
app-secret: 26c1fcecfc98a748d8916355623c975c
|
app-secret: 26c1fcecfc98a748d8916355623c975c
|
||||||
|
|
||||||
|
# 微信支付
|
||||||
wechat-pay:
|
wechat-pay:
|
||||||
mch-id: 1735188493 # 商户号
|
mch-id: 1735188493 # 商户号
|
||||||
mch-certificate-serial-number: 3725BFCA9CA3AF819AEC5D0CB7D3540BBC67F2CF # 商户证书序列号
|
mch-certificate-serial-number: 3725BFCA9CA3AF819AEC5D0CB7D3540BBC67F2CF # 商户证书序列号
|
||||||
@@ -37,6 +38,7 @@ wechat-pay:
|
|||||||
public-key-path: /Users/blizzard/privateFolder/cert/pub_key.pem # 商户APIv3密钥对应的公钥
|
public-key-path: /Users/blizzard/privateFolder/cert/pub_key.pem # 商户APIv3密钥对应的公钥
|
||||||
notify-url: https://prod.sundynix.cn/api/wechatpay/notify # 微信支付结果通知回调地址
|
notify-url: https://prod.sundynix.cn/api/wechatpay/notify # 微信支付结果通知回调地址
|
||||||
|
|
||||||
|
#百度植物识别
|
||||||
baidu-img-classify:
|
baidu-img-classify:
|
||||||
api-key: hpBfjwy8ifv3qswYGYjUCNKN
|
api-key: hpBfjwy8ifv3qswYGYjUCNKN
|
||||||
secret-key: i5aXZdM4XZVuDroBslL0f3uIuwbAyXFS
|
secret-key: i5aXZdM4XZVuDroBslL0f3uIuwbAyXFS
|
||||||
|
|||||||
+26
-39
@@ -1,41 +1,28 @@
|
|||||||
package initialize
|
package initialize
|
||||||
|
|
||||||
//func InitTimer() {
|
import (
|
||||||
// go func() {
|
"fmt"
|
||||||
// var option []cron.Option
|
"sundynix-go/global"
|
||||||
// option = append(option, cron.WithSeconds())
|
"sundynix-go/task"
|
||||||
//
|
|
||||||
// //任务一:每天凌晨00:01点执行 生成今日养护任务
|
"github.com/robfig/cron/v3"
|
||||||
// _, err := global.Timer.AddTaskByFuncWithSecond("GenerateToday", "0 1 0 * * *", func() {
|
"go.uber.org/zap"
|
||||||
// err := task.GeneratorTodayCare()
|
)
|
||||||
// if err != nil {
|
|
||||||
// fmt.Println("定时生成今日养护任务失败:", err)
|
func InitTimer() {
|
||||||
// }
|
go func() {
|
||||||
// }, "定时生成今日带养护记录", option...)
|
var option []cron.Option
|
||||||
// if err != nil {
|
option = append(option, cron.WithSeconds())
|
||||||
// fmt.Println("添加定时任务失败:", err)
|
|
||||||
// }
|
// 任务一:每天8点30执行 发送植物养护提醒
|
||||||
//
|
_, err := global.Timer.AddTaskByFuncWithSecond("SendCareRemind", "0 30 8 * * *", func() {
|
||||||
// // 任务二:每天凌晨00:16执行 定时更新未完成的任务
|
err1 := task.SendCareMsg()
|
||||||
// _, err2 := global.Timer.AddTaskByFuncWithSecond("UpdateExpireCare", "0 16 0 * * *", func() {
|
if err1 != nil {
|
||||||
// err3 := task.UpdateExpireCare()
|
global.Logger.Error("定时发送植物养护提醒失败", zap.Error(err1))
|
||||||
// if err3 != nil {
|
}
|
||||||
// fmt.Println("定时更新未完成任务失败:", err)
|
}, "定时发送植物养护提醒", option...)
|
||||||
// }
|
if err != nil {
|
||||||
// }, "定时更新未完成任务", option...)
|
fmt.Println("添加定时任务失败:", err)
|
||||||
// if err2 != nil {
|
}
|
||||||
// fmt.Println("添加定时任务失败:", err)
|
}()
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// // 任务三:每天8点执行 发送植物养护提醒
|
|
||||||
// _, err4 := global.Timer.AddTaskByFuncWithSecond("SendCareRemind", "0 0 8 * * *", func() {
|
|
||||||
// err5 := task.SendCareMsg()
|
|
||||||
// if err5 != nil {
|
|
||||||
// global.Logger.Error("定时发送植物养护提醒失败", zap.Error(err5))
|
|
||||||
// }
|
|
||||||
// }, "定时发送植物养护提醒", option...)
|
|
||||||
// if err4 != nil {
|
|
||||||
// fmt.Println("添加定时任务失败:", err)
|
|
||||||
// }
|
|
||||||
// }()
|
|
||||||
//}
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func main() {
|
|||||||
initialize.Redis()
|
initialize.Redis()
|
||||||
|
|
||||||
// timer
|
// timer
|
||||||
//initialize.InitTimer()
|
initialize.InitTimer()
|
||||||
// httpclient 主动初始化 HTTP Client(可选,也可依赖懒加载)饿汉加载
|
// httpclient 主动初始化 HTTP Client(可选,也可依赖懒加载)饿汉加载
|
||||||
httpclient.InitHttpClient()
|
httpclient.InitHttpClient()
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
|
|
||||||
type ClassifyRecord struct {
|
type ClassifyRecord struct {
|
||||||
global.BaseModel
|
global.BaseModel
|
||||||
UserId string `gorm:"uniqueIndex" json:"userId"`
|
UserId string `gorm:"index;" json:"userId"`
|
||||||
LogId uint64 `gorm:"uniqueIndex" json:"logId"`
|
LogId uint64 `gorm:"index;" json:"logId"`
|
||||||
AllResults ResultsArray `gorm:"type:json" json:"allResults"`
|
AllResults ResultsArray `gorm:"type:json" json:"allResults"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+112
-115
@@ -1,117 +1,114 @@
|
|||||||
package task
|
package task
|
||||||
|
|
||||||
//
|
import (
|
||||||
//import (
|
"bytes"
|
||||||
// "bytes"
|
"encoding/json"
|
||||||
// "encoding/json"
|
"fmt"
|
||||||
// "fmt"
|
"io"
|
||||||
// "io"
|
"sundynix-go/global"
|
||||||
// "sundynix-go/global"
|
"sundynix-go/model/plant"
|
||||||
// "sundynix-go/model/plant"
|
"sundynix-go/model/system"
|
||||||
// "sundynix-go/model/system"
|
"sundynix-go/pkg/httpclient"
|
||||||
// "sundynix-go/pkg/httpclient"
|
"sundynix-go/utils/timer"
|
||||||
// "sundynix-go/utils/wechat"
|
"sundynix-go/utils/wechat"
|
||||||
// "time"
|
"time"
|
||||||
//)
|
)
|
||||||
//
|
|
||||||
//type TemplateDataItem struct {
|
type TemplateDataItem struct {
|
||||||
// Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//// SendMessagePayload 是我们发送给微信服务器的消息体
|
// SendMessagePayload 是我们发送给微信服务器的消息体
|
||||||
//type SendMessagePayload struct {
|
type SendMessagePayload struct {
|
||||||
// TemplateID string `json:"template_id"`
|
TemplateID string `json:"template_id"`
|
||||||
// Page string `json:"page"`
|
Page string `json:"page"`
|
||||||
// Touser string `json:"touser"`
|
Touser string `json:"touser"`
|
||||||
// Data map[string]TemplateDataItem `json:"data"`
|
Data map[string]TemplateDataItem `json:"data"`
|
||||||
// MiniProgramState string `json:"miniprogram_state"` //跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
|
MiniProgramState string `json:"miniprogram_state"` //跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
|
||||||
// Lang string `json:"lang"`
|
Lang string `json:"lang"`
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//// SendMessageResponse 是发送消息的响应体
|
// SendMessageResponse 是发送消息的响应体
|
||||||
//type SendMessageResponse struct {
|
type SendMessageResponse struct {
|
||||||
// Errcode int `json:"errcode"`
|
Errcode int `json:"errcode"`
|
||||||
// Errmsg string `json:"errmsg"`
|
Errmsg string `json:"errmsg"`
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//// SendCareMsg 发送提醒消息
|
// SendCareMsg 发送提醒消息
|
||||||
//func SendCareMsg() error {
|
func SendCareMsg() error {
|
||||||
// httpUrl := "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + wechat.GetMiniAccessToken()
|
httpUrl := "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + wechat.GetMiniAccessToken()
|
||||||
//
|
//1.查询出今日的养护任务
|
||||||
// //1.查询出今日的养护任务
|
now := time.Now()
|
||||||
// now := time.Now()
|
today := timer.GetZeroTime()
|
||||||
// today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
|
endOfToday := today.Add(24 * time.Hour)
|
||||||
// var tasks []*plant.TodayCare
|
var tasks []*plant.CareTask
|
||||||
// err := global.DB.Where("expected_date = ? and status in (1,4)", today).Find(&tasks).Error
|
err := global.DB.Where("status = 1 and due_date < ?", endOfToday).Order("due_date ASC").Find(&tasks).Error
|
||||||
// if err != nil {
|
if len(tasks) > 0 {
|
||||||
// return err
|
// 将tasks分组,key为用户id 保证无论用户有多少植物,只给用户发送一条消息
|
||||||
// }
|
tasksMap := make(map[string][]*plant.CareTask)
|
||||||
// if len(tasks) > 0 {
|
for _, task := range tasks {
|
||||||
// // 将tasks分组,key为用户id 保证无论用户有多少植物,只给用户发送一条消息
|
tasksMap[task.UserId] = append(tasksMap[task.UserId], task)
|
||||||
// tasksMap := make(map[string][]*plant.TodayCare)
|
}
|
||||||
// for _, task := range tasks {
|
for userId, cares := range tasksMap {
|
||||||
// tasksMap[task.UserId] = append(tasksMap[task.UserId], task)
|
//1.查询用户
|
||||||
// }
|
var user system.User
|
||||||
// for userId, cares := range tasksMap {
|
err = global.DB.Where("id = ?", userId).First(&user).Error
|
||||||
// //1.查询用户
|
if err != nil {
|
||||||
// var user system.User
|
return err
|
||||||
// err = global.DB.Where("id = ?", userId).First(&user).Error
|
}
|
||||||
// if err != nil {
|
if user.MiniOpenId != "" {
|
||||||
// return err
|
//2.用户该养护的植物
|
||||||
// }
|
plantId := cares[0].PlantId
|
||||||
// if user.MiniOpenId != "" {
|
var myPlant plant.MyPlant
|
||||||
// //2.用户该养护的植物
|
err = global.DB.Where("id = ?", plantId).First(&myPlant).Error
|
||||||
// plantId := cares[0].PlantId
|
if err != nil {
|
||||||
// var myPlant plant.MyPlant
|
return err
|
||||||
// err = global.DB.Where("id = ?", plantId).First(&myPlant).Error
|
}
|
||||||
// if err != nil {
|
//3.构造请求参数 发送订阅消息
|
||||||
// return err
|
payload := SendMessagePayload{
|
||||||
// }
|
TemplateID: "R7fh3NDpuV8DYqI83HpEQvC8mLJy5xMWFl1qeGN9JIo",
|
||||||
// //3.构造请求参数 发送订阅消息
|
Page: "pages/garden/index",
|
||||||
// payload := SendMessagePayload{
|
Touser: user.MiniOpenId,
|
||||||
// TemplateID: "inVOG9qy5NylOivO4Xb9H1db6PQlfv5doNNVhh_3iFE",
|
Data: map[string]TemplateDataItem{
|
||||||
// Page: "pages/garden/index",
|
"thing2": {
|
||||||
// Touser: user.MiniOpenId,
|
Value: myPlant.Name + "等",
|
||||||
// Data: map[string]TemplateDataItem{
|
},
|
||||||
// "thing2": {
|
"time3": {
|
||||||
// Value: myPlant.Name + "等",
|
// 今天的九点
|
||||||
// },
|
Value: time.Date(now.Year(), now.Month(), now.Day(), 8, 30, 0, 0, time.Local).Format("2006-01-02"),
|
||||||
// "time3": {
|
},
|
||||||
// // 今天的九点
|
},
|
||||||
// Value: time.Date(now.Year(), now.Month(), now.Day(), 9, 0, 0, 0, time.Local).Format("2006-01-02"),
|
//MiniProgramState: "formal",
|
||||||
// },
|
MiniProgramState: "trial",
|
||||||
// },
|
Lang: "zh_CN",
|
||||||
// MiniProgramState: "formal",
|
}
|
||||||
// //MiniProgramState: "trial",
|
payloadBytes, err := json.Marshal(payload)
|
||||||
// Lang: "zh_CN",
|
if err != nil {
|
||||||
// }
|
return err
|
||||||
// payloadBytes, err := json.Marshal(payload)
|
}
|
||||||
// if err != nil {
|
myHttpClient := httpclient.GetClient()
|
||||||
// return err
|
resp, err := myHttpClient.Post(httpUrl, "application/json", bytes.NewBuffer(payloadBytes))
|
||||||
// }
|
if err != nil {
|
||||||
// myHttpClient := httpclient.GetClient()
|
return err
|
||||||
// resp, err := myHttpClient.Post(httpUrl, "application/json", bytes.NewBuffer(payloadBytes))
|
}
|
||||||
// if err != nil {
|
defer resp.Body.Close()
|
||||||
// return err
|
body, err := io.ReadAll(resp.Body)
|
||||||
// }
|
if err != nil {
|
||||||
// defer resp.Body.Close()
|
return fmt.Errorf("读取订阅消息响应失败: %v", err)
|
||||||
// body, err := io.ReadAll(resp.Body)
|
}
|
||||||
// if err != nil {
|
|
||||||
// return fmt.Errorf("读取订阅消息响应失败: %v", err)
|
var smr SendMessageResponse
|
||||||
// }
|
err = json.Unmarshal(body, &smr)
|
||||||
//
|
if err != nil {
|
||||||
// var smr SendMessageResponse
|
return fmt.Errorf("解析订阅消息响应失败: %v, body: %s", err, string(body))
|
||||||
// err = json.Unmarshal(body, &smr)
|
}
|
||||||
// if err != nil {
|
|
||||||
// return fmt.Errorf("解析订阅消息响应失败: %v, body: %s", err, string(body))
|
if smr.Errcode != 0 {
|
||||||
// }
|
return fmt.Errorf("微信服务器返回错误: errcode=%d, errmsg=%s", smr.Errcode, smr.Errmsg)
|
||||||
//
|
}
|
||||||
// if smr.Errcode != 0 {
|
global.Logger.Info("订阅消息发送成功!")
|
||||||
// return fmt.Errorf("微信服务器返回错误: errcode=%d, errmsg=%s", smr.Errcode, smr.Errmsg)
|
}
|
||||||
// }
|
}
|
||||||
// global.Logger.Info("订阅消息发送成功!")
|
}
|
||||||
// }
|
return nil
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
// return nil
|
|
||||||
//}
|
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ func TimeInterval(targetTime time.Time) string {
|
|||||||
case totalMinutes >= 60: // 1小时 = 60分钟
|
case totalMinutes >= 60: // 1小时 = 60分钟
|
||||||
hours := totalMinutes / 60
|
hours := totalMinutes / 60
|
||||||
return fmt.Sprintf("%d小时前", hours)
|
return fmt.Sprintf("%d小时前", hours)
|
||||||
|
case totalMinutes < 1:
|
||||||
|
return "刚刚"
|
||||||
default: // 不足1小时
|
default: // 不足1小时
|
||||||
return fmt.Sprintf("%d分钟前", totalMinutes)
|
return fmt.Sprintf("%d分钟前", totalMinutes)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
|
||||||
"sundynix-go/global"
|
"sundynix-go/global"
|
||||||
|
"sundynix-go/pkg/httpclient"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
@@ -20,7 +20,8 @@ func GetMiniAccessToken() string {
|
|||||||
// 从微信服务器获取
|
// 从微信服务器获取
|
||||||
//重新从微信服务器获取
|
//重新从微信服务器获取
|
||||||
url := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + global.Config.MiniProgram.AppId + "&secret=" + global.Config.MiniProgram.AppSecret
|
url := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + global.Config.MiniProgram.AppId + "&secret=" + global.Config.MiniProgram.AppSecret
|
||||||
resp, err := http.Get(url)
|
myHttpClient := httpclient.GetClient()
|
||||||
|
resp, err := myHttpClient.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error making GET request: %s", err)
|
log.Fatalf("Error making GET request: %s", err)
|
||||||
}
|
}
|
||||||
@@ -46,8 +47,6 @@ func GetMiniAccessToken() string {
|
|||||||
global.Redis.Set(context.Background(), "mini_access_token", ak, time.Duration(ex)*time.Second) //秒
|
global.Redis.Set(context.Background(), "mini_access_token", ak, time.Duration(ex)*time.Second) //秒
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Fatalf("Error getting access token from Redis: %s", err)
|
log.Fatalf("Error getting access token from Redis: %s", err)
|
||||||
} else {
|
|
||||||
return ak
|
|
||||||
}
|
}
|
||||||
return ak
|
return ak
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user