Commit d51a2a30 by zhengqiuyun86

微信相关

parent fcc5ecad
[database] [database]
#张捷的PG库
dbDSN = "host=60.205.190.129 user=postgres password=buzhidao123. dbname=dcpgdb1 port=5432 sslmode=disable TimeZone=Asia/Shanghai"
#阿里云9.9 外网 #阿里云9.9 外网
dbDSN = "user=higher password=hj^&bhjb789j$^* dbname=dctest1 host=pgm-2ze3yp0bss39cxvh1o.pg.rds.aliyuncs.com port=1921 sslmode=disable" #dbDSN = "user=higher password=hj^&bhjb789j$^* dbname=dctest1 host=pgm-2ze3yp0bss39cxvh1o.pg.rds.aliyuncs.com port=1921 sslmode=disable"
#阿里云9.9 内网 pgm-2ze3yp0bss39cxvh129210.pg.rds.aliyuncs.com #阿里云9.9 内网 pgm-2ze3yp0bss39cxvh129210.pg.rds.aliyuncs.com
#dbDSN = "user=higher password=hj^&bhjb789j$^* dbname=jeff_study host=pgm-2ze3yp0bss39cxvh129210.pg.rds.aliyuncs.com port=1921 sslmode=disable" #dbDSN = "user=higher password=hj^&bhjb789j$^* dbname=jeff_study host=pgm-2ze3yp0bss39cxvh129210.pg.rds.aliyuncs.com port=1921 sslmode=disable"
...@@ -16,7 +19,7 @@ dbDSN = "user=higher password=hj^&bhjb789j$^* dbname=dctest1 host=pgm-2ze3yp0bss ...@@ -16,7 +19,7 @@ dbDSN = "user=higher password=hj^&bhjb789j$^* dbname=dctest1 host=pgm-2ze3yp0bss
[http_server] [http_server]
#debug release #debug release
ServerMode = release ServerMode = debug
ServerPort = :50000 ServerPort = :50000
Swagger = true Swagger = true
...@@ -37,7 +40,7 @@ OldConnReadDeadline = 180 ...@@ -37,7 +40,7 @@ OldConnReadDeadline = 180
#debug info: 记录流水数据(都存在info.log里) #debug info: 记录流水数据(都存在info.log里)
#warn: 应检查原因,主要来自外部 #warn: 应检查原因,主要来自外部
#error DPanic Panci Fatal: 应立即检查原因来内部或硬件设备或业务服务器 #error DPanic Panci Fatal: 应立即检查原因来内部或硬件设备或业务服务器
Level = warn Level = debug
#log文件的存储路径 #log文件的存储路径
Path = ./log/ Path = ./log/
#单个日志文件大小限制,单位MB #单个日志文件大小限制,单位MB
......
...@@ -116,6 +116,58 @@ var doc = `{ ...@@ -116,6 +116,58 @@ var doc = `{
} }
} }
}, },
"/v1/login/{code}": {
"post": {
"description": "微信code传至后台,后台返回token,token有效时长:24小时",
"tags": [
"微信"
],
"summary": "登录",
"parameters": [
{
"type": "string",
"description": "用户微信的code",
"name": "code",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "{\"code\": 200, \"token\": string}",
"schema": {
"type": "string"
}
}
}
}
},
"/v1/test": {
"get": {
"description": "测试使用",
"tags": [
"微信"
],
"summary": "测试",
"parameters": [
{
"type": "string",
"description": "用户微信的unionid",
"name": "unionid",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/web.TestResponse"
}
}
}
}
},
"/we/login/{code}": { "/we/login/{code}": {
"post": { "post": {
"description": "微信code传至后台,后台返回token,token有效时长:24小时", "description": "微信code传至后台,后台返回token,token有效时长:24小时",
...@@ -186,6 +238,65 @@ var doc = `{ ...@@ -186,6 +238,65 @@ var doc = `{
"example": "四川省" "example": "四川省"
} }
} }
},
"model.UWeCustomer": {
"type": "object",
"properties": {
"avatarurl": {
"description": "微信头像",
"type": "string"
},
"country": {
"type": "string"
},
"createAt": {
"type": "string"
},
"id": {
"type": "integer"
},
"language": {
"type": "string"
},
"loginAt": {
"type": "string"
},
"nickname": {
"description": "微信昵称",
"type": "string"
},
"openid": {
"description": "微信小程序对应的openid",
"type": "string"
},
"province": {
"type": "string"
},
"testRole": {
"description": "是否是有测试权限",
"type": "boolean"
},
"unionid": {
"description": "微信小程序对应的unionid",
"type": "string"
}
}
},
"web.TestResponse": {
"type": "object",
"properties": {
"code": {
"description": "1000为成功,其他都是失败",
"type": "integer"
},
"data": {
"$ref": "#/definitions/model.UWeCustomer"
},
"msg": {
"description": "code非1000时的错误描述",
"type": "string"
}
}
} }
}, },
"securityDefinitions": { "securityDefinitions": {
......
...@@ -101,6 +101,58 @@ ...@@ -101,6 +101,58 @@
} }
} }
}, },
"/v1/login/{code}": {
"post": {
"description": "微信code传至后台,后台返回token,token有效时长:24小时",
"tags": [
"微信"
],
"summary": "登录",
"parameters": [
{
"type": "string",
"description": "用户微信的code",
"name": "code",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "{\"code\": 200, \"token\": string}",
"schema": {
"type": "string"
}
}
}
}
},
"/v1/test": {
"get": {
"description": "测试使用",
"tags": [
"微信"
],
"summary": "测试",
"parameters": [
{
"type": "string",
"description": "用户微信的unionid",
"name": "unionid",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/web.TestResponse"
}
}
}
}
},
"/we/login/{code}": { "/we/login/{code}": {
"post": { "post": {
"description": "微信code传至后台,后台返回token,token有效时长:24小时", "description": "微信code传至后台,后台返回token,token有效时长:24小时",
...@@ -171,6 +223,65 @@ ...@@ -171,6 +223,65 @@
"example": "四川省" "example": "四川省"
} }
} }
},
"model.UWeCustomer": {
"type": "object",
"properties": {
"avatarurl": {
"description": "微信头像",
"type": "string"
},
"country": {
"type": "string"
},
"createAt": {
"type": "string"
},
"id": {
"type": "integer"
},
"language": {
"type": "string"
},
"loginAt": {
"type": "string"
},
"nickname": {
"description": "微信昵称",
"type": "string"
},
"openid": {
"description": "微信小程序对应的openid",
"type": "string"
},
"province": {
"type": "string"
},
"testRole": {
"description": "是否是有测试权限",
"type": "boolean"
},
"unionid": {
"description": "微信小程序对应的unionid",
"type": "string"
}
}
},
"web.TestResponse": {
"type": "object",
"properties": {
"code": {
"description": "1000为成功,其他都是失败",
"type": "integer"
},
"data": {
"$ref": "#/definitions/model.UWeCustomer"
},
"msg": {
"description": "code非1000时的错误描述",
"type": "string"
}
}
} }
}, },
"securityDefinitions": { "securityDefinitions": {
......
...@@ -12,6 +12,47 @@ definitions: ...@@ -12,6 +12,47 @@ definitions:
example: 四川省 example: 四川省
type: string type: string
type: object type: object
model.UWeCustomer:
properties:
avatarurl:
description: 微信头像
type: string
country:
type: string
createAt:
type: string
id:
type: integer
language:
type: string
loginAt:
type: string
nickname:
description: 微信昵称
type: string
openid:
description: 微信小程序对应的openid
type: string
province:
type: string
testRole:
description: 是否是有测试权限
type: boolean
unionid:
description: 微信小程序对应的unionid
type: string
type: object
web.TestResponse:
properties:
code:
description: 1000为成功,其他都是失败
type: integer
data:
$ref: '#/definitions/model.UWeCustomer'
msg:
description: code非1000时的错误描述
type: string
type: object
info: info:
contact: {} contact: {}
description: 用于家长端微信小程序及web端管理后台 description: 用于家长端微信小程序及web端管理后台
...@@ -75,6 +116,40 @@ paths: ...@@ -75,6 +116,40 @@ paths:
summary: 获取全国省份列表 summary: 获取全国省份列表
tags: tags:
- 公用接口 - 公用接口
/v1/login/{code}:
post:
description: 微信code传至后台,后台返回token,token有效时长:24小时
parameters:
- description: 用户微信的code
in: path
name: code
required: true
type: string
responses:
"200":
description: '{"code": 200, "token": string}'
schema:
type: string
summary: 登录
tags:
- 微信
/v1/test:
get:
description: 测试使用
parameters:
- description: 用户微信的unionid
in: query
name: unionid
required: true
type: string
responses:
"200":
description: OK
schema:
$ref: '#/definitions/web.TestResponse'
summary: 测试
tags:
- 微信
/we/login/{code}: /we/login/{code}:
post: post:
description: 微信code传至后台,后台返回token,token有效时长:24小时 description: 微信code传至后台,后台返回token,token有效时长:24小时
......
...@@ -5,10 +5,15 @@ go 1.17 ...@@ -5,10 +5,15 @@ go 1.17
require ( require (
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394
github.com/gin-gonic/gin v1.7.4 github.com/gin-gonic/gin v1.7.4
github.com/goinggo/mapstructure v0.0.0-20140717182941-194205d9b4a9
github.com/lib/pq v1.10.3 github.com/lib/pq v1.10.3
github.com/natefinch/lumberjack v2.0.0+incompatible github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/swaggo/gin-swagger v1.3.2
github.com/swaggo/swag v1.7.3
go.uber.org/zap v1.19.1 go.uber.org/zap v1.19.1
gopkg.in/ini.v1 v1.63.2 gopkg.in/ini.v1 v1.63.2
gorm.io/driver/postgres v1.1.2
gorm.io/gorm v1.21.16
) )
require ( require (
...@@ -25,6 +30,16 @@ require ( ...@@ -25,6 +30,16 @@ require (
github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.9.0 // indirect github.com/go-playground/validator/v10 v10.9.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.10.0 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.1.1 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.8.1 // indirect
github.com/jackc/pgx/v4 v4.13.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.2 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/leodido/go-urn v1.2.1 // indirect github.com/leodido/go-urn v1.2.1 // indirect
...@@ -33,16 +48,14 @@ require ( ...@@ -33,16 +48,14 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/swaggo/gin-swagger v1.3.2 // indirect
github.com/swaggo/swag v1.7.3 // indirect
github.com/ugorji/go/codec v1.2.6 // indirect github.com/ugorji/go/codec v1.2.6 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.7.0 // indirect go.uber.org/multierr v1.7.0 // indirect
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/net v0.0.0-20210421230115-4e50805a0758 // indirect golang.org/x/net v0.0.0-20211007125505-59d4e928ea9d // indirect
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect
golang.org/x/text v0.3.6 // indirect golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.5 // indirect golang.org/x/tools v0.1.7 // indirect
google.golang.org/protobuf v1.27.1 // indirect google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"dc_golang_server_1/devproduct/dcphone20" "dc_golang_server_1/devproduct/dcphone20"
"dc_golang_server_1/logger" "dc_golang_server_1/logger"
"dc_golang_server_1/web" "dc_golang_server_1/web"
"dc_golang_server_1/wechat/dao"
"fmt" "fmt"
"runtime" "runtime"
"time" "time"
...@@ -17,7 +18,7 @@ import ( ...@@ -17,7 +18,7 @@ import (
func initConfigAndLogger() { func initConfigAndLogger() {
config.ConfigInit() config.ConfigInit()
logger.InitLogger() logger.InitLogger()
dao.InitPgDb()
//突然发现这种方式瓜眉日眼的,以后不用了,直接在shell脚本里面重定向输出文件 //突然发现这种方式瓜眉日眼的,以后不用了,直接在shell脚本里面重定向输出文件
//f, err := os.OpenFile(config.LogPath+"panic.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755) //f, err := os.OpenFile(config.LogPath+"panic.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
//if err != nil { //if err != nil {
......
package cache
import (
"dc_golang_server_1/logger"
"dc_golang_server_1/wechat/model"
"github.com/goinggo/mapstructure"
"sync"
)
var UWeCustomerMap sync.Map //
func FindUWeCustomerByUnionid(unionid string) (customer model.UWeCustomer, err error) {
customerCache, ok := UWeCustomerMap.Load(unionid)
if ok {
logger.Log.Debug("UWeCustomerMap缓存命中:" + unionid)
} else {
logger.Log.Debug("UWeCustomerMap缓存未命中:" + unionid)
}
if err = mapstructure.Decode(customerCache, &customer); err != nil {
logger.Log.Error(err.Error())
}
return customer, err
}
func SetUWeCustomerByUnionid(customer model.UWeCustomer) {
UWeCustomerMap.Store(customer.Unionid, customer)
}
package dao
import (
"dc_golang_server_1/wechat/model"
)
func FindUWeCustomerByUnionid(unionid string) model.UWeCustomer {
var customer model.UWeCustomer
PgDb.First(&customer, "unionid = ?", unionid) //
return customer
}
package dao
import (
"dc_golang_server_1/config"
dc_logger "dc_golang_server_1/logger"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"os"
"time"
)
var PgDb *gorm.DB
func InitPgDb() {
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer(日志输出的目标,前缀和日志包含的内容——译者注)
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // 日志级别
IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound(记录未找到)错误
Colorful: false, // 禁用彩色打印
},
)
var err error
dc_logger.Log.Info("初始化连接")
PgDb, err = gorm.Open(postgres.Open(config.DbDSN), &gorm.Config{
Logger: newLogger,
})
if err != nil {
dc_logger.Log.Error(err.Error())
}
}
package model
import "time"
type UWeCustomer struct {
Id uint32 `json:"id"`
Openid string `json:"openid"` //微信小程序对应的openid
Unionid string `json:"unionid"` //微信小程序对应的unionid
Nickname string `json:"nickname"` //微信昵称
Avatarurl string `json:"avatarurl"` //微信头像
Country string `json:"country"`
Province string `json:"province"`
Language string `json:"language"`
CreateAt time.Time `json:"createAt"`
LoginAt time.Time `json:"loginAt"`
TestRole bool `json:"testRole"` //是否是有测试权限
}
package service
import (
"dc_golang_server_1/wechat/cache"
"dc_golang_server_1/wechat/dao"
"dc_golang_server_1/wechat/model"
"dc_golang_server_1/wechat/web/response"
responseState "dc_golang_server_1/wechat/web/response/state"
)
func FindUWeCustomerByUnionid(unionid string) model.UWeCustomer {
customer, _ := cache.FindUWeCustomerByUnionid(unionid)
if customer == (model.UWeCustomer{}) {
customer = dao.FindUWeCustomerByUnionid(unionid)
cache.SetUWeCustomerByUnionid(customer)
}
return customer
}
func initUWeCustomer(unionid string, openid string) {
}
type LoginFromWechatAppletData struct {
token string
tokenCreatTime uint32
testRole uint8 // 测试用户(可看到测试校区)
nickname string //微信昵称
masterCardUserID []uint32 //自己创建的学生用户
slaveCardUserID []uint32 //被邀请查看的学生用户
}
//微信小程序登陆
func LoginFromWechatApplet(code string) (LoginFromWechatAppletData, response.ServerErrorResponse) {
var loginFromWechatAppletData LoginFromWechatAppletData
wxOAuth2ResponseData, err := JsCode2session(code)
if err != nil {
return loginFromWechatAppletData, response.ServerErrorResponse{Code: responseState.StateBusinessError, Msg: err.Error()}
} else {
var customer model.UWeCustomer
customer = FindUWeCustomerByUnionid(wxOAuth2ResponseData.Unionid)
if customer == (model.UWeCustomer{}) {
initUWeCustomer(wxOAuth2ResponseData.Unionid, wxOAuth2ResponseData.Openid)
}
}
return loginFromWechatAppletData, response.ServerErrorResponse{}
}
package response
import (
responseState "dc_golang_server_1/wechat/web/response/state"
)
type ServerErrorResponse struct {
Code responseState.State `json:"code"` //1000为成功,其他都是失败
Msg string `json:"msg"`
}
type ServerDataResponse struct {
Code responseState.State `json:"code"` //1000为成功,其他都是失败
Data interface{} `json:"data"`
}
package responseState
type State int16
const (
StateOK State = 1000
StateContentTypeMismatch State = 1000 + iota
StateParamsError
StateSignatureMismatch
StateBusinessError
)
type StateMap map[State]string
var StateMapping = StateMap{
StateOK: "Success",
StateContentTypeMismatch: "Content-type mismatch",
StateParamsError: "params error",
StateSignatureMismatch: "Signature mismatch",
StateBusinessError: "business error, please checking",
}
package web
import "github.com/gin-gonic/gin"
// InitWechatRout 在InitRouter中添加InitWechatRout(r),进行路由初始化
func InitWechatRout(engine *gin.Engine) {
engine.GET("/v1/test", test)
engine.POST("/v1/login", weLogin)
}
package web
import (
"dc_golang_server_1/wechat/model"
"dc_golang_server_1/wechat/service"
"dc_golang_server_1/wechat/web/response"
responseState "dc_golang_server_1/wechat/web/response/state"
"github.com/gin-gonic/gin"
"net/http"
)
type TestResponse struct {
Code responseState.State `json:"code"` //1000为成功,其他都是失败
Msg string `json:"msg"` //code非1000时的错误描述
Data model.UWeCustomer `json:"data"`
}
// @Tags 微信
// @Summary 测试
// @Description 测试使用
// @Param unionid query string true "用户微信的unionid"
// @Product json
// @Success 200 {object} TestResponse"
// @Router /v1/test [GET]
func test(c *gin.Context) {
unionid := c.Query("unionid")
var customer model.UWeCustomer
customer = service.FindUWeCustomerByUnionid(unionid)
if customer.Id == 0 {
c.JSON(http.StatusOK, response.ServerErrorResponse{Code: responseState.StateBusinessError, Msg: "用户不存在"})
} else {
c.JSON(http.StatusOK, response.ServerDataResponse{Code: responseState.StateOK, Data: customer})
}
}
// @Tags 微信
// @Summary 登录
// @Description 微信code传至后台,后台返回token,token有效时长:24小时
// @Param code path string true "用户微信的code"
// @Product json
// @Success 200 {object} service.LoginFromWechatAppletResponse"
// @Router /v1/login/{code} [POST]
func weLogin(c *gin.Context) {
code := c.Param("code")
responseData, err := service.LoginFromWechatApplet(code)
if err != (response.ServerErrorResponse{}) {
c.JSON(http.StatusOK, err)
} else {
c.JSON(http.StatusOK, responseData)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment