🐛 fix bug
This commit is contained in:
parent
26220f0276
commit
433ff17755
@ -15,7 +15,8 @@ WORKDIR /go/src/miniapp
|
||||
|
||||
COPY --from=0 /go/src/miniapp/server ./
|
||||
COPY --from=0 /go/src/miniapp/resource ./resource/
|
||||
COPY --from=0 /go/src/miniapp/config.yaml ./
|
||||
COPY --from=0 /go/src/miniapp/docker/config.docker.yaml ./docker/
|
||||
COPY --from=0 /go/src/miniapp/docker ./
|
||||
|
||||
EXPOSE 8888
|
||||
ENTRYPOINT ./server -c config.yaml
|
||||
ENTRYPOINT ./server -c docker/config.docker.yaml
|
||||
|
@ -1,8 +1,11 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.echol.cn/loser/logger/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/medivhzhan/weapp/v3"
|
||||
msg "github.com/medivhzhan/weapp/v3/subscribemessage"
|
||||
"miniapp/api"
|
||||
"miniapp/model/app"
|
||||
"miniapp/model/app/request"
|
||||
@ -86,6 +89,13 @@ func (u *UserApi) UpdateUser(ctx *gin.Context) {
|
||||
if p.Phone != "" {
|
||||
loginUser.Phone = p.Phone
|
||||
}
|
||||
if p.SurgeryTime != "" {
|
||||
//t, _ := time.Parse("2006-01-02", p.SurgeryTime)
|
||||
//format := t.UTC().Format("2006-01-02")
|
||||
loginUser.SurgeryTime = p.SurgeryTime
|
||||
}
|
||||
loginUser.IsSurgery = p.IsSurgery
|
||||
loginUser.HospitalId = p.HospitalId
|
||||
// 修改数据
|
||||
if err := userService.UpdateUserInfo(&loginUser); err != nil {
|
||||
log.Errorf("修改用户信息失败:%s", err.Error())
|
||||
@ -137,3 +147,46 @@ func (u *UserApi) GetInfo(ctx *gin.Context) {
|
||||
}
|
||||
r.OkWithData(userInfo, ctx)
|
||||
}
|
||||
|
||||
// SendMedicineRemind 发送用药提醒消息
|
||||
func (u *UserApi) SendMedicineRemind(ctx *gin.Context) {
|
||||
var req utils.SendRequest
|
||||
if err := ctx.ShouldBind(&req); err != nil {
|
||||
r.FailWithMessage("参数错误: "+err.Error(), ctx)
|
||||
return
|
||||
}
|
||||
|
||||
//app-id: wxaaf66dbb5c3983b3
|
||||
//app-secret: 0abba24dbff43febba1e551651f693b4
|
||||
//template-id: PgxoZOOSDgBcmIGd_EVLDnYUmL3eu6NQTAZCsHQeuWY
|
||||
|
||||
sdk := weapp.NewClient("wxaaf66dbb5c3983b3", "0abba24dbff43febba1e551651f693b4")
|
||||
|
||||
msgData := msg.SendRequest{
|
||||
ToUser: "o9Fq_6_cYKvOWnyUM3McC11hWsTI",
|
||||
TemplateID: "PgxoZOOSDgBcmIGd_EVLDnYUmL3eu6NQTAZCsHQeuWY",
|
||||
Page: "page/index/todo",
|
||||
MiniprogramState: msg.MiniprogramStateTrial,
|
||||
Data: msg.SendData{
|
||||
"thing1": msg.SendValue{Value: "眼药水"},
|
||||
"time2": msg.SendValue{Value: "20:00"},
|
||||
"short_thing17": msg.SendValue{Value: "一天4次"},
|
||||
"time15": msg.SendValue{Value: "2024-03-20 20:00"},
|
||||
},
|
||||
}
|
||||
|
||||
send, err := sdk.NewSubscribeMessage().Send(&msgData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = send.GetResponseError()
|
||||
if err != nil {
|
||||
fmt.Printf("微信返回错误: %#v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("返回结果: %#v", send)
|
||||
|
||||
r.Ok(ctx)
|
||||
}
|
||||
|
@ -1,203 +0,0 @@
|
||||
# miniapp Global Configuration
|
||||
|
||||
# jwt configuration
|
||||
jwt:
|
||||
signing-key: qmPlus
|
||||
expires-time: 7d
|
||||
buffer-time: 1d
|
||||
issuer: qmPlus
|
||||
# zap logger configuration
|
||||
zap:
|
||||
level: info
|
||||
format: console
|
||||
prefix: "[miniapp]"
|
||||
director: log
|
||||
show-line: true
|
||||
encode-level: LowercaseColorLevelEncoder
|
||||
stacktrace-key: stacktrace
|
||||
log-in-console: true
|
||||
|
||||
# redis configuration
|
||||
redis:
|
||||
db: 0
|
||||
addr: 177.7.0.14:6379
|
||||
password: ""
|
||||
|
||||
# email configuration
|
||||
email:
|
||||
to: xxx@qq.com
|
||||
port: 465
|
||||
from: xxx@163.com
|
||||
host: smtp.163.com
|
||||
is-ssl: true
|
||||
secret: xxx
|
||||
nickname: test
|
||||
|
||||
# system configuration
|
||||
system:
|
||||
env: public # Change to "develop" to skip authentication for development mode
|
||||
addr: 8888
|
||||
db-type: mysql
|
||||
oss-type: local # 控制oss选择走本地还是 七牛等其他仓 自行增加其他oss仓可以在 server.exe.exe/utils/upload/upload.go 中 NewOss函数配置
|
||||
use-redis: false # 使用redis
|
||||
use-multipoint: false
|
||||
# IP限制次数 一个小时15000次
|
||||
iplimit-count: 15000
|
||||
# IP限制一个小时
|
||||
iplimit-time: 3600
|
||||
|
||||
# captcha configuration
|
||||
captcha:
|
||||
key-long: 6
|
||||
img-width: 240
|
||||
img-height: 80
|
||||
open-captcha: 0 # 0代表一直开启,大于0代表限制次数
|
||||
open-captcha-timeout: 3600 # open-captcha大于0时才生效
|
||||
|
||||
# mysql connect configuration
|
||||
# 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master)
|
||||
mysql:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
|
||||
# pgsql connect configuration
|
||||
# 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master)
|
||||
pgsql:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
|
||||
db-list:
|
||||
- disable: true # 是否禁用
|
||||
type: "" # 数据库的类型,目前支持mysql、pgsql
|
||||
alias-name: "" # 数据库的名称,注意: alias-name 需要在db-list中唯一
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
|
||||
|
||||
# local configuration
|
||||
local:
|
||||
path: uploads/file
|
||||
store-path: uploads/file
|
||||
|
||||
# autocode configuration
|
||||
autocode:
|
||||
transfer-restart: true
|
||||
# root 自动适配项目根目录
|
||||
# 请不要手动配置,他会在项目加载的时候识别出根路径
|
||||
root: ""
|
||||
server: /server.exe.exe
|
||||
server-plug: /plugin/%s
|
||||
server-api: /api/v1/%s
|
||||
server-initialize: /initialize
|
||||
server-model: /model/%s
|
||||
server-request: /model/%s/request/
|
||||
server-router: /router/%s
|
||||
server-service: /service/%s
|
||||
web: /web/src
|
||||
web-api: /api
|
||||
web-form: /view
|
||||
web-table: /view
|
||||
|
||||
# qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址)
|
||||
qiniu:
|
||||
zone: ZoneHuaDong
|
||||
bucket: ""
|
||||
img-path: ""
|
||||
use-https: false
|
||||
access-key: ""
|
||||
secret-key: ""
|
||||
use-cdn-domains: false
|
||||
|
||||
# aliyun oss configuration
|
||||
aliyun-oss:
|
||||
endpoint: yourEndpoint
|
||||
access-key-id: yourAccessKeyId
|
||||
access-key-secret: yourAccessKeySecret
|
||||
bucket-name: yourBucketName
|
||||
bucket-url: yourBucketUrl
|
||||
base-path: yourBasePath
|
||||
|
||||
# tencent cos configuration
|
||||
tencent-cos:
|
||||
bucket: xxxxx-10005608
|
||||
region: ap-shanghai
|
||||
secret-id: your-secret-id
|
||||
secret-key: your-secret-key
|
||||
base-url: https://gin.vue.admin
|
||||
path-prefix: miniapp
|
||||
|
||||
# aws s3 configuration (minio compatible)
|
||||
aws-s3:
|
||||
bucket: xxxxx-10005608
|
||||
region: ap-shanghai
|
||||
endpoint: ""
|
||||
s3-force-path-style: false
|
||||
disable-ssl: false
|
||||
secret-id: your-secret-id
|
||||
secret-key: your-secret-key
|
||||
base-url: https://gin.vue.admin
|
||||
path-prefix: miniapp
|
||||
|
||||
# huawei obs configuration
|
||||
hua-wei-obs:
|
||||
path: you-path
|
||||
bucket: you-bucket
|
||||
endpoint: you-endpoint
|
||||
access-key: you-access-key
|
||||
secret-key: you-secret-key
|
||||
|
||||
# excel configuration
|
||||
excel:
|
||||
dir: ./resource/excel/
|
||||
|
||||
# timer task db clear table
|
||||
Timer:
|
||||
start: true
|
||||
spec: "@daily" # 定时任务详细配置参考 https://pkg.go.dev/github.com/robfig/cron/v3
|
||||
detail:
|
||||
- tableName: sys_operation_records
|
||||
compareField: created_at
|
||||
interval: 2160h
|
||||
- tableName: jwt_blacklists
|
||||
compareField: created_at
|
||||
interval: 168h
|
||||
|
||||
# 跨域配置
|
||||
# 需要配合 server.exe.exe/initialize/router.go -> `Router.Use(middleware.CorsByRules())` 使用
|
||||
cors:
|
||||
mode: whitelist # 放行模式: allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝
|
||||
whitelist:
|
||||
- allow-origin: example1.com
|
||||
allow-headers: content-type
|
||||
allow-methods: GET, POST
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
allow-credentials: true # 布尔值
|
||||
- allow-origin: example2.com
|
||||
allow-headers: content-type
|
||||
allow-methods: GET, POST
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
allow-credentials: true # 布尔值
|
@ -1,12 +1,12 @@
|
||||
package config
|
||||
|
||||
// MiniApp 微信小程序配置
|
||||
type MiniApp struct {
|
||||
AppId string `mapstructure:"app-id" yaml:"app-id"`
|
||||
AppSecret string `mapstructure:"app-secret" yaml:"app-secret"`
|
||||
TemplateID string `mapstructure:"template-id" yaml:"template-id"`
|
||||
}
|
||||
|
||||
// 微信小程序配置
|
||||
|
||||
// 微信支付配置
|
||||
type wechatPayConfig struct {
|
||||
MchId string `mapstructure:"mchId" yaml:"mchId"` // 商户号
|
||||
|
@ -79,12 +79,12 @@ mini-app:
|
||||
app-secret: 0abba24dbff43febba1e551651f693b4
|
||||
mysql:
|
||||
prefix: ""
|
||||
port: "3307"
|
||||
port: "3306"
|
||||
config: charset=utf8mb4&parseTime=True&loc=Local
|
||||
db-name: mini_app
|
||||
username: root
|
||||
db-name: jmyl
|
||||
username: jmyl
|
||||
password: Jmyl123123
|
||||
path: 47.116.50.126
|
||||
path: 101.35.50.11
|
||||
engine: ""
|
||||
log-mode: error
|
||||
max-idle-conns: 10
|
||||
@ -92,8 +92,8 @@ mysql:
|
||||
singular: false
|
||||
log-zap: false
|
||||
redis:
|
||||
addr: 47.116.50.126:6378
|
||||
password: "Jmyl123123"
|
||||
addr: 101.35.50.11:6379
|
||||
password: "loser7659"
|
||||
db: 0
|
||||
system:
|
||||
env: public
|
132
docker/config.docker.yaml
Normal file
132
docker/config.docker.yaml
Normal file
@ -0,0 +1,132 @@
|
||||
aliyun-oss:
|
||||
endpoint: oss-cn-chengdu.aliyuncs.com
|
||||
access-key-id: LTAI5tFHes6HBWJFUjuPwHso
|
||||
access-key-secret: qXuWtEJvYEQvj9yhkmLYfRxHShheYa
|
||||
bucket-name: jmyl-app
|
||||
bucket-url: https://jmyl-app.oss-cn-chengdu.aliyuncs.com
|
||||
base-path: miniapp
|
||||
autocode:
|
||||
server-model: /model/%s
|
||||
server-router: /router/%s
|
||||
server: /server.exe.exe
|
||||
server-api: /api/v1/%s
|
||||
server-plug: /plugin/%s
|
||||
server-initialize: /initialize
|
||||
root: C:\Users\Administrator\Desktop
|
||||
web-table: /view
|
||||
web: /web/src
|
||||
server-service: /service/%s
|
||||
server-request: /model/%s/request/
|
||||
web-api: /api
|
||||
web-form: /view
|
||||
transfer-restart: true
|
||||
captcha:
|
||||
key-long: 4
|
||||
img-width: 240
|
||||
img-height: 80
|
||||
open-captcha: 0
|
||||
open-captcha-timeout: 3600
|
||||
cors:
|
||||
mode: strict-whitelist
|
||||
whitelist:
|
||||
- allow-origin: example1.com
|
||||
allow-methods: POST, GET
|
||||
allow-headers: Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
allow-credentials: true
|
||||
- allow-origin: example2.com
|
||||
allow-methods: GET, POST
|
||||
allow-headers: content-type
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
allow-credentials: true
|
||||
db-list:
|
||||
- type: ""
|
||||
alias-name: ""
|
||||
prefix: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
path: ""
|
||||
engine: ""
|
||||
log-mode: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
singular: false
|
||||
log-zap: false
|
||||
disable: true
|
||||
email:
|
||||
to: xxx@qq.com
|
||||
from: xxx@163.com
|
||||
host: smtp.163.com
|
||||
secret: xxx
|
||||
nickname: test
|
||||
port: 465
|
||||
is-ssl: true
|
||||
excel:
|
||||
dir: ./resource/excel/
|
||||
jwt:
|
||||
signing-key: f2b1b2af-c8f1-43cf-88e4-40b0a64b5487
|
||||
expires-time: 7d
|
||||
buffer-time: 1d
|
||||
issuer: qmPlus
|
||||
local:
|
||||
path: uploads/file
|
||||
store-path: uploads/file
|
||||
mini-app:
|
||||
app-id: wxaaf66dbb5c3983b3
|
||||
app-secret: 0abba24dbff43febba1e551651f693b4
|
||||
mysql:
|
||||
prefix: ""
|
||||
port: "3307"
|
||||
config: charset=utf8mb4&parseTime=True&loc=Local
|
||||
db-name: mini_app
|
||||
username: root
|
||||
password: Jmyl123123
|
||||
path: 47.113.103.195
|
||||
engine: ""
|
||||
log-mode: error
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
singular: false
|
||||
log-zap: false
|
||||
redis:
|
||||
addr: 127.0.0.1:6379
|
||||
password: "Jmyl123123"
|
||||
db: 0
|
||||
system:
|
||||
env: public
|
||||
db-type: mysql
|
||||
oss-type: aliyun-oss
|
||||
router-prefix: ""
|
||||
addr: 8888
|
||||
iplimit-count: 15000
|
||||
iplimit-time: 3600
|
||||
use-multipoint: false
|
||||
use-redis: true
|
||||
timer:
|
||||
spec: '@daily'
|
||||
detail:
|
||||
- tableName: sys_operation_records
|
||||
compareField: created_at
|
||||
interval: 2160h
|
||||
- tableName: jwt_blacklists
|
||||
compareField: created_at
|
||||
interval: 168h
|
||||
start: true
|
||||
with_seconds: false
|
||||
zap:
|
||||
level: info
|
||||
prefix: '[miniapp]'
|
||||
format: console
|
||||
director: log
|
||||
encode-level: LowercaseColorLevelEncoder
|
||||
stacktrace-key: stacktrace
|
||||
max-age: 0
|
||||
show-line: true
|
||||
log-in-console: true
|
||||
|
||||
|
||||
|
||||
|
5
go.mod
5
go.mod
@ -15,13 +15,14 @@ require (
|
||||
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/glebarez/sqlite v1.8.0
|
||||
github.com/go-co-op/gocron v1.13.0
|
||||
github.com/go-oauth2/oauth2/v4 v4.5.2
|
||||
github.com/go-oauth2/redis/v4 v4.1.1
|
||||
github.com/go-redis/redis/v8 v8.11.4
|
||||
github.com/go-sql-driver/mysql v1.7.1
|
||||
github.com/gofrs/uuid/v5 v5.0.0
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.8+incompatible
|
||||
github.com/jordan-wright/email v0.0.0-20200824153738-3f5bafa1cd84
|
||||
@ -37,7 +38,7 @@ require (
|
||||
github.com/shirou/gopsutil/v3 v3.23.6
|
||||
github.com/songzhibin97/gkit v1.2.11
|
||||
github.com/spf13/viper v1.16.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/swaggo/files v1.0.1
|
||||
github.com/swaggo/gin-swagger v1.6.0
|
||||
github.com/swaggo/swag v1.16.2
|
||||
|
10
go.sum
10
go.sum
@ -137,6 +137,8 @@ github.com/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0
|
||||
github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E=
|
||||
github.com/glebarez/sqlite v1.8.0 h1:02X12E2I/4C1n+v90yTqrjRa8yuo7c3KeHI3FRznCvc=
|
||||
github.com/glebarez/sqlite v1.8.0/go.mod h1:bpET16h1za2KOOMb8+jCp6UBP/iahDpfPQqSaYLTLx8=
|
||||
github.com/go-co-op/gocron v1.13.0 h1:BjkuNImPy5NuIPEifhWItFG7pYyr27cyjS6BN9w/D4c=
|
||||
github.com/go-co-op/gocron v1.13.0/go.mod h1:GD5EIEly1YNW+LovFVx5dzbYVcIc8544K99D8UVRpGo=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@ -264,8 +266,9 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbu
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
@ -467,8 +470,8 @@ github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc=
|
||||
github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@ -480,8 +483,9 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
||||
|
@ -1,11 +1,10 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
"net/http"
|
||||
|
||||
"miniapp/global"
|
||||
"miniapp/middleware"
|
||||
@ -31,7 +30,7 @@ func Routers() *gin.Engine {
|
||||
Router.StaticFS(global.GVA_CONFIG.Local.StorePath, http.Dir(global.GVA_CONFIG.Local.StorePath)) // 为用户头像和文件提供静态地址
|
||||
// Router.Use(middleware.LoadTls()) // 如果需要使用https 请打开此中间件 然后前往 core/server.exe.exe.exe.go 将启动模式 更变为 Router.RunTLS("端口","你的cre/pem文件","你的key文件")
|
||||
// 跨域,如需跨域可以打开下面的注释
|
||||
// Router.Use(middleware.Cors()) // 直接放行全部跨域请求
|
||||
Router.Use(middleware.Cors()) // 直接放行全部跨域请求
|
||||
// Router.Use(middleware.CorsByRules()) // 按照配置的规则放行跨域请求
|
||||
//global.GVA_LOG.Info("use middleware cors")
|
||||
|
||||
|
2
main.go
2
main.go
@ -4,6 +4,7 @@ import (
|
||||
"go.uber.org/zap"
|
||||
"miniapp/client"
|
||||
"miniapp/oauth2"
|
||||
"miniapp/task"
|
||||
|
||||
"miniapp/core"
|
||||
"miniapp/global"
|
||||
@ -41,5 +42,6 @@ func main() {
|
||||
client.InitRedisClient()
|
||||
oauth2.InitOAuth2Server() // 初始化OAuth2服务
|
||||
initialize.InitKp() // 初始化关键词处理器
|
||||
task.InitTask() // 初始化定时任务
|
||||
core.RunWindowsServer()
|
||||
}
|
||||
|
@ -24,6 +24,9 @@ type ChangeUserInfo struct {
|
||||
Nickname string `json:"nickname" form:"nickname"` // 昵称
|
||||
Avatar string `json:"avatar" form:"avatar"` // 头像
|
||||
Phone string `json:"phone" form:"phone"` // 手机号
|
||||
IsSurgery int `json:"isSurgery" gorm:"default:0;comment:是否已经手术 0未手术 1已手术"`
|
||||
HospitalId int `json:"hospitalId" gorm:"comment:手术医院"`
|
||||
SurgeryTime string `json:"surgery_time" gorm:"comment:手术时间"`
|
||||
}
|
||||
|
||||
// ChangePassword 修改密码
|
||||
|
@ -34,7 +34,7 @@ type UserVO struct {
|
||||
IsSurgery int `json:"isSurgery" gorm:"default:0;comment:是否已经手术 0未手术 1已手术"`
|
||||
IsInfo int `json:"isInfo" gorm:"default:0;comment:是否已经填写信息 0未填写 1已填写"`
|
||||
HospitalId int `json:"hospital_id" gorm:"comment:手术医院"`
|
||||
SurgeryTime time.Time `json:"surgery_time" gorm:"comment:手术时间"`
|
||||
SurgeryTime string `json:"surgery_time" gorm:"comment:手术时间"`
|
||||
Todos []common.UserTodo `json:"todos" gorm:"comment:用户待办事项"`
|
||||
Notes []common.Notes `json:"notes" gorm:"comment:用户须知"`
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ type User struct {
|
||||
IsSurgery int `json:"isSurgery" gorm:"default:0;comment:是否已经手术 0未手术 1已手术"`
|
||||
IsInfo int `json:"isInfo" gorm:"default:0;comment:是否已经填写信息 0未填写 1已填写"`
|
||||
HospitalId int `json:"hospital_id" gorm:"comment:手术医院"`
|
||||
SurgeryTime time.Time `json:"surgery_time" gorm:"comment:手术时间"`
|
||||
SurgeryTime string `json:"surgery_time" gorm:"comment:手术时间"`
|
||||
LastLoginAt *time.Time `json:"last_login_at" gorm:"comment:'最后登录时间'"`
|
||||
}
|
||||
|
||||
|
@ -4,3 +4,10 @@ type GetUserNotes struct {
|
||||
UserId string `json:"userId" form:"userId" binding:"required"`
|
||||
IsFinish string `json:"isFinish" form:"isFinish" binding:"required"`
|
||||
}
|
||||
|
||||
type TodoTask struct {
|
||||
OpenId string `json:"openId" form:"openId"`
|
||||
Context string `json:"context" form:"context"`
|
||||
Frequency string `json:"frequency" form:"frequency"`
|
||||
RemindTime string `json:"remindTime" form:"remindTime"`
|
||||
}
|
||||
|
@ -6,6 +6,10 @@ type Todos struct {
|
||||
// 任务列表
|
||||
global.GVA_MODEL
|
||||
Content string `json:"content" form:"content" gorm:"comment:任务内容;"`
|
||||
RemindTime string `json:"remindTime" form:"remindTime" gorm:"comment:提醒时间;"`
|
||||
RemindPeriod int `json:"remindPeriod" form:"remindPeriod" gorm:"comment:0术前,1术后;"`
|
||||
Frequency string `json:"frequency" form:"frequency" gorm:"comment:用药频率;"`
|
||||
RemindDay string `json:"remindDay" form:"remindDay" gorm:"comment:提醒日期;"`
|
||||
}
|
||||
|
||||
func (t Todos) TableName() string {
|
||||
|
@ -7,6 +7,10 @@ type UserTodo struct {
|
||||
UserId int `json:"userId" form:"userId" gorm:"comment:用户id;"`
|
||||
Content string `json:"content" form:"content" gorm:"comment:任务内容;"`
|
||||
IsFinish int `json:"isFinish" form:"isFinish" gorm:"comment:是否完成;"`
|
||||
RemindTime string `json:"remindTime" form:"remindTime" gorm:"comment:提醒时间;"`
|
||||
RemindPeriod int `json:"remindPeriod" form:"remindPeriod" gorm:"comment:术前,术后;"`
|
||||
Frequency string `json:"frequency" form:"frequency" gorm:"comment:用药频率;"`
|
||||
RemindDay string `json:"remindDay" form:"remindDay" gorm:"comment:提醒日期;"`
|
||||
}
|
||||
|
||||
func (u UserTodo) TableName() string {
|
||||
|
@ -15,7 +15,7 @@ type SysOperationRecord struct {
|
||||
Path string `json:"path" form:"path" gorm:"column:path;comment:请求路径"` // 请求路径
|
||||
Status int `json:"status" form:"status" gorm:"column:status;comment:请求状态"` // 请求状态
|
||||
Latency time.Duration `json:"latency" form:"latency" gorm:"column:latency;comment:延迟" swaggertype:"string"` // 延迟
|
||||
Agent string `json:"agent" form:"agent" gorm:"column:agent;comment:代理"` // 代理
|
||||
Agent string `json:"agent" form:"agent" gorm:"column:agent; type:longtext; comment:代理"` // 代理
|
||||
ErrorMessage string `json:"error_message" form:"error_message" gorm:"column:error_message;comment:错误信息"` // 错误信息
|
||||
Body string `json:"body" form:"body" gorm:"type:text;column:body;comment:请求Body"` // 请求Body
|
||||
Resp string `json:"resp" form:"resp" gorm:"type:text;column:resp;comment:响应Body"` // 响应Body
|
||||
|
@ -116,6 +116,9 @@ func ExtensionFields(ti oauth2.TokenInfo) (fieldsValue map[string]any) {
|
||||
fieldsValue["IsSurgery"] = userInfo.IsSurgery
|
||||
fieldsValue["HospitalId"] = userInfo.HospitalId
|
||||
fieldsValue["IsInfo"] = userInfo.IsInfo
|
||||
fieldsValue["SurgeryTime"] = userInfo.SurgeryTime
|
||||
fieldsValue["HospitalId"] = userInfo.HospitalId
|
||||
fieldsValue["IsSurgery"] = userInfo.IsSurgery
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ func (s *LoginRouter) InitUserRouter(Router *gin.RouterGroup) {
|
||||
userRouter.GET("todo", todoApi.GetUserTodos)
|
||||
userRouter.PUT("todo", todoApi.UpdateTodo)
|
||||
|
||||
userRouter.POST("msg", baseApi.SendMedicineRemind)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"miniapp/model/app/request"
|
||||
"miniapp/model/app/response"
|
||||
"miniapp/model/common"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -49,7 +50,53 @@ func (UserService) CheckUnionIdIsExist(unionId, openId string) bool {
|
||||
|
||||
// UpdateUserInfo 更新普通用户信息
|
||||
func (UserService) UpdateUserInfo(e *app.User) (err error) {
|
||||
return global.GVA_DB.Updates(&e).Error
|
||||
tUser := app.User{}
|
||||
err = global.GVA_DB.Where("id = ?", e.ID).First(&tUser).Error
|
||||
|
||||
err = global.GVA_DB.Updates(&e).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新用户信息失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
if e.SurgeryTime != "" {
|
||||
if tUser.HospitalId != e.HospitalId {
|
||||
|
||||
err = global.GVA_DB.Delete(&common.UserTodo{}, "user_id = ?", e.ID).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("清除用户Todo列表失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
var hospital common.Hospital
|
||||
err = global.GVA_DB.Where("id = ?", e.HospitalId).Preload("Todos").First(&hospital).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取医院信息失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
if len(hospital.Todos) != 0 {
|
||||
var userTodos []common.UserTodo
|
||||
for _, todo := range hospital.Todos {
|
||||
for _, s := range strings.Split(todo.RemindTime, ",") {
|
||||
userTodos = append(userTodos, common.UserTodo{
|
||||
Content: todo.Content,
|
||||
UserId: int(e.ID),
|
||||
IsFinish: 0,
|
||||
RemindTime: s,
|
||||
RemindPeriod: todo.RemindPeriod,
|
||||
})
|
||||
}
|
||||
}
|
||||
err = global.GVA_DB.Create(&userTodos).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建用户Todo列表失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetAverageUserList 查询普通用户列表
|
||||
@ -126,12 +173,16 @@ func (UserService) UpdateUserHospital(r *request.ChangeUserHospital) (err error)
|
||||
if len(hospital.Todos) != 0 {
|
||||
var userTodos []common.UserTodo
|
||||
for _, todo := range hospital.Todos {
|
||||
for _, s := range strings.Split(todo.RemindTime, ",") {
|
||||
userTodos = append(userTodos, common.UserTodo{
|
||||
Content: todo.Content,
|
||||
UserId: r.UserId,
|
||||
IsFinish: 0,
|
||||
RemindTime: s,
|
||||
RemindPeriod: todo.RemindPeriod,
|
||||
})
|
||||
}
|
||||
}
|
||||
err = global.GVA_DB.Create(&userTodos).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建用户Todo列表失败", zap.Error(err))
|
||||
@ -139,9 +190,9 @@ func (UserService) UpdateUserHospital(r *request.ChangeUserHospital) (err error)
|
||||
}
|
||||
}
|
||||
|
||||
t, _ := time.Parse("2006-01-02", r.SurgeryTime)
|
||||
//t, _ := time.Parse("2006-01-02", r.SurgeryTime)
|
||||
|
||||
err = global.GVA_DB.Table("t_user").Where("id = ?", r.UserId).Updates(app.User{IsInfo: 1, HospitalId: r.HospitalId, SurgeryTime: t}).Error
|
||||
err = global.GVA_DB.Table("t_user").Where("id = ?", r.UserId).Updates(app.User{IsInfo: 1, HospitalId: r.HospitalId, SurgeryTime: r.SurgeryTime}).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新用户信息失败", zap.Error(err))
|
||||
return
|
||||
|
@ -23,12 +23,48 @@ func (h HospitalService) CreateHospital(hospital *common.Hospital) (err error) {
|
||||
|
||||
// UpdateHospital 更新医院
|
||||
func (h HospitalService) UpdateHospital(hospital *common.Hospital) (err error) {
|
||||
return global.GVA_DB.Updates(&hospital).Error
|
||||
for i := range hospital.Notes {
|
||||
if hospital.Notes[i].NotesTime == "手术前" {
|
||||
hospital.Notes[i].NotestimeNum = 1
|
||||
} else if hospital.Notes[i].NotesTime == "手术中" {
|
||||
hospital.Notes[i].NotestimeNum = 2
|
||||
} else {
|
||||
hospital.Notes[i].NotestimeNum = 3
|
||||
}
|
||||
}
|
||||
err = global.GVA_DB.Model(&common.Notes{}).Save(&hospital.Notes).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新医院注意事项失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
err = global.GVA_DB.Model(&hospital).Association("Notes").Replace(&hospital.Notes)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新医院注意事项失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
err = global.GVA_DB.Model(&common.Todos{}).Save(&hospital.Todos).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新医院Todo失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
err = global.GVA_DB.Model(&hospital).Association("Todos").Replace(&hospital.Todos)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新医院Todo关联失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
return global.GVA_DB.Save(&hospital).Error
|
||||
}
|
||||
|
||||
// DeleteHospital 删除医院
|
||||
func (h HospitalService) DeleteHospital(hospital *common.Hospital) (err error) {
|
||||
return global.GVA_DB.Select("Notes").Delete(&hospital).Error
|
||||
err = global.GVA_DB.Model(&hospital).Association("Notes").Clear()
|
||||
err = global.GVA_DB.Model(&hospital).Association("Todos").Clear()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return global.GVA_DB.Delete(&hospital).Error
|
||||
}
|
||||
|
||||
// GetHospitalById 根据id获取医院
|
||||
|
18
task/task.go
Normal file
18
task/task.go
Normal file
@ -0,0 +1,18 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"github.com/go-co-op/gocron"
|
||||
"time"
|
||||
)
|
||||
|
||||
var WxTask *gocron.Scheduler
|
||||
|
||||
func InitTask() {
|
||||
WxTask = gocron.NewScheduler(time.Local)
|
||||
|
||||
// 每天凌晨1点执行
|
||||
_, _ = WxTask.Every(1).Day().At("01:00").Do(CheckUserSurgeryDate) // 检查用户是否已到手术日期
|
||||
|
||||
// 开启定时任务
|
||||
WxTask.StartAsync()
|
||||
}
|
19
task/user.go
Normal file
19
task/user.go
Normal file
@ -0,0 +1,19 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"miniapp/global"
|
||||
"miniapp/model/app"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CheckUserSurgeryDate 检查用户是否已到手术日期
|
||||
func CheckUserSurgeryDate() {
|
||||
var users []app.User
|
||||
global.GVA_DB.Model(&app.User{}).Find(&users)
|
||||
for _, user := range users {
|
||||
parse, _ := time.Parse("2006-01-02", user.SurgeryTime)
|
||||
if time.Now().Sub(parse).Hours()/24 == 0 {
|
||||
global.GVA_DB.Model(&app.User{}).Where("id = ?", user.ID).Updates(app.User{IsSurgery: 1})
|
||||
}
|
||||
}
|
||||
}
|
83
task/wxMsg.go
Normal file
83
task/wxMsg.go
Normal file
@ -0,0 +1,83 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/medivhzhan/weapp/v3"
|
||||
msg "github.com/medivhzhan/weapp/v3/subscribemessage"
|
||||
"go.uber.org/zap"
|
||||
"miniapp/global"
|
||||
"miniapp/model/app"
|
||||
"miniapp/model/common"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func SendMsg(userId int) {
|
||||
var user app.User
|
||||
err := global.GVA_DB.Model(&user).Where("id = ?", userId).Find(&user).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取用户信息失败:%s", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户待办列表
|
||||
var userTodo []common.UserTodo
|
||||
if user.IsSurgery == 0 {
|
||||
err = global.GVA_DB.Model(&userTodo).Where("user_id = ? and is_finish = ? and remind_period = 0", userId, 0).Find(&userTodo).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取用户待办列表:%s", zap.Error(err))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
err = global.GVA_DB.Model(&userTodo).Where("user_id = ? and is_finish = ? and remind_period = 1", userId, 0).Find(&userTodo).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取用户待办列表:%s", zap.Error(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 根据用户手术信息 发送提醒消息
|
||||
parse, _ := time.Parse("2006-01-02", user.SurgeryTime)
|
||||
if time.Now().Sub(parse).Hours()/24 <= -3 {
|
||||
for _, todo := range userTodo {
|
||||
jbo, _ := WxTask.Every(1).Day().At(todo.RemindTime).Do(MiniappSendMsg, *user.WechatOpenId, todo.Content, todo.RemindPeriod, todo.RemindTime) // 检查用户待办事项
|
||||
s := strings.Split("一天3次", "")[2]
|
||||
// 将s转为int类型
|
||||
atoi, _ := strconv.Atoi(s)
|
||||
if jbo.RunCount() == atoi {
|
||||
WxTask.Remove(jbo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func MiniappSendMsg(openId string, context string, frequency string, remindTime string) {
|
||||
sdk := weapp.NewClient(global.GVA_CONFIG.MiniApp.AppId, global.GVA_CONFIG.MiniApp.AppSecret)
|
||||
|
||||
msgData := msg.SendRequest{
|
||||
ToUser: openId,
|
||||
TemplateID: "PgxoZOOSDgBcmIGd_EVLDnYUmL3eu6NQTAZCsHQeuWY",
|
||||
Page: "/page/index/todo",
|
||||
MiniprogramState: msg.MiniprogramStateTrial,
|
||||
Data: msg.SendData{
|
||||
"thing1": msg.SendValue{Value: context},
|
||||
"time2": msg.SendValue{Value: remindTime},
|
||||
"short_thing17": msg.SendValue{Value: frequency},
|
||||
"time15": msg.SendValue{Value: time.DateTime},
|
||||
},
|
||||
}
|
||||
|
||||
send, err := sdk.NewSubscribeMessage().Send(&msgData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = send.GetResponseError()
|
||||
if err != nil {
|
||||
fmt.Printf("微信返回错误: %#v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("返回结果: %#v", send)
|
||||
}
|
190
utils/wx_msg.go
Normal file
190
utils/wx_msg.go
Normal file
@ -0,0 +1,190 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"miniapp/global"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
//type wxMsg struct{}
|
||||
//
|
||||
//func WxMsgUtils() *wxMsg {
|
||||
// return &wxMsg{}
|
||||
//}
|
||||
|
||||
type Wechat struct {
|
||||
appID string
|
||||
secret string
|
||||
templateID string
|
||||
accessToken *AccessToken
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
type OpenIDResponse struct {
|
||||
Openid string `json:"openid"`
|
||||
SessionKey string `json:"session_key"`
|
||||
Unionid string `json:"unionid"`
|
||||
WxErr
|
||||
}
|
||||
|
||||
type CheckTokenRequest struct {
|
||||
Signature string `json:"signature"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Nonce string `json:"nonce"`
|
||||
Echostr string `json:"echostr"`
|
||||
}
|
||||
|
||||
type WxErr struct {
|
||||
Errcode int `json:"errcode"`
|
||||
Errmsg string `json:"errmsg"`
|
||||
}
|
||||
|
||||
type AccessToken struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
ExpiresIn int64 `json:"expires_in"`
|
||||
WxErr
|
||||
}
|
||||
|
||||
type SendRequest struct {
|
||||
Touser string `json:"touser"`
|
||||
Page string `json:"page"`
|
||||
Data Message `json:"data"`
|
||||
EmphasisKeyword string `json:"emphasis_keyword"`
|
||||
}
|
||||
|
||||
type Message map[string]interface{}
|
||||
|
||||
func (w *Wechat) SendMsg(req SendRequest) (err error) {
|
||||
token, err := w.GetAccessToken()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
api, err := TokenAPI("https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send", token)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for key := range req.Data {
|
||||
req.Data[key] = Message{"value": req.Data[key]}
|
||||
}
|
||||
body := map[string]interface{}{
|
||||
"touser": "o9Fq_6_cYKvOWnyUM3McC11hWsTI",
|
||||
"template_id": global.GVA_CONFIG.MiniApp.TemplateID,
|
||||
"page": "/pages/index/todo",
|
||||
"data": req.Data,
|
||||
"emphasis_keyword": req.EmphasisKeyword,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res, err := http.Post(api, "application/json", strings.NewReader(string(b)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != 200 {
|
||||
err = errors.New("WECHAT_SERVER_ERROR")
|
||||
return err
|
||||
}
|
||||
|
||||
var resp WxErr
|
||||
if err = json.NewDecoder(res.Body).Decode(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.Errcode != 0 {
|
||||
return errors.New(resp.Errmsg)
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (w *Wechat) GetAccessToken() (token string, err error) {
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
if w.accessToken == nil || w.accessToken.ExpiresIn < time.Now().Unix() {
|
||||
for i := 0; i < 3; i++ {
|
||||
err = w.getAccessToken()
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
token = w.accessToken.AccessToken
|
||||
return
|
||||
}
|
||||
|
||||
func (w *Wechat) CheckSignature(req CheckTokenRequest) (err error) {
|
||||
if sig := w.sortSha1(req.Timestamp, req.Nonce, req.Echostr); sig != req.Signature {
|
||||
err = errors.New("check signature failed.")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TokenAPI(api, token string) (string, error) {
|
||||
u, err := url.Parse(api)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
query := u.Query()
|
||||
query.Set("access_token", token)
|
||||
u.RawQuery = query.Encode()
|
||||
|
||||
return u.String(), nil
|
||||
}
|
||||
|
||||
func (w *Wechat) getAccessToken() (err error) {
|
||||
urls, err := url.Parse("https://api.weixin.qq.com/cgi-bin/token")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
query := urls.Query()
|
||||
query.Set("appid", w.appID)
|
||||
query.Set("secret", w.secret)
|
||||
query.Set("grant_type", "client_credential")
|
||||
|
||||
urls.RawQuery = query.Encode()
|
||||
|
||||
res, err := http.Get(urls.String())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != 200 {
|
||||
return errors.New("wechat internal server error.")
|
||||
}
|
||||
|
||||
var token AccessToken
|
||||
if err = json.NewDecoder(res.Body).Decode(&token); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if token.Errcode != 0 {
|
||||
return errors.New(token.Errmsg)
|
||||
}
|
||||
w.accessToken.AccessToken = token.AccessToken
|
||||
w.accessToken.ExpiresIn = token.ExpiresIn
|
||||
return
|
||||
}
|
||||
|
||||
func (w *Wechat) sortSha1(s ...string) string {
|
||||
sort.Strings(s)
|
||||
h := sha1.New()
|
||||
h.Write([]byte(strings.Join(s, "")))
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
Loading…
Reference in New Issue
Block a user