mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-19 09:46:39 +08:00
feat: remove wechat bot, replace with api callback for receive wechat payment transactions
This commit is contained in:
parent
5db247e632
commit
0b27890484
@ -186,6 +186,7 @@ func authorizeMiddleware(s *AppServer) gin.HandlerFunc {
|
|||||||
if c.Request.URL.Path == "/api/user/login" ||
|
if c.Request.URL.Path == "/api/user/login" ||
|
||||||
c.Request.URL.Path == "/api/admin/login" ||
|
c.Request.URL.Path == "/api/admin/login" ||
|
||||||
c.Request.URL.Path == "/api/user/register" ||
|
c.Request.URL.Path == "/api/user/register" ||
|
||||||
|
c.Request.URL.Path == "/api/reward/push" ||
|
||||||
strings.HasPrefix(c.Request.URL.Path, "/api/sms/") ||
|
strings.HasPrefix(c.Request.URL.Path, "/api/sms/") ||
|
||||||
strings.HasPrefix(c.Request.URL.Path, "/api/captcha/") ||
|
strings.HasPrefix(c.Request.URL.Path, "/api/captcha/") ||
|
||||||
strings.HasPrefix(c.Request.URL.Path, "/static/") ||
|
strings.HasPrefix(c.Request.URL.Path, "/static/") ||
|
||||||
|
@ -33,8 +33,8 @@ func NewDefaultConfig() *types.AppConfig {
|
|||||||
HttpOnly: false,
|
HttpOnly: false,
|
||||||
SameSite: http.SameSiteLaxMode,
|
SameSite: http.SameSiteLaxMode,
|
||||||
},
|
},
|
||||||
ApiConfig: types.ChatPlusApiConfig{},
|
ApiConfig: types.ChatPlusApiConfig{},
|
||||||
StartWechatBot: false,
|
ChatPlusExtApiToken: utils.RandString(32),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,19 +6,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type AppConfig struct {
|
type AppConfig struct {
|
||||||
Path string `toml:"-"`
|
Path string `toml:"-"`
|
||||||
Listen string
|
Listen string
|
||||||
Session Session
|
Session Session
|
||||||
ProxyURL string
|
ProxyURL string
|
||||||
MysqlDns string // mysql 连接地址
|
MysqlDns string // mysql 连接地址
|
||||||
Manager Manager // 后台管理员账户信息
|
Manager Manager // 后台管理员账户信息
|
||||||
StaticDir string // 静态资源目录
|
StaticDir string // 静态资源目录
|
||||||
StaticUrl string // 静态资源 URL
|
StaticUrl string // 静态资源 URL
|
||||||
Redis RedisConfig // redis 连接信息
|
Redis RedisConfig // redis 连接信息
|
||||||
ApiConfig ChatPlusApiConfig // ChatPlus API authorization configs
|
ApiConfig ChatPlusApiConfig // ChatPlus API authorization configs
|
||||||
AesEncryptKey string
|
AesEncryptKey string
|
||||||
SmsConfig AliYunSmsConfig // AliYun send message service config
|
SmsConfig AliYunSmsConfig // AliYun send message service config
|
||||||
StartWechatBot bool // 是否启动微信机器人
|
ChatPlusExtApiToken string // chatgpt-plus-exts callback api token
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChatPlusApiConfig struct {
|
type ChatPlusApiConfig struct {
|
||||||
|
@ -5,14 +5,12 @@ go 1.19
|
|||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v1.1.0
|
github.com/BurntSushi/toml v1.1.0
|
||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.62.405
|
github.com/aliyun/alibaba-cloud-sdk-go v1.62.405
|
||||||
github.com/eatmoreapple/openwechat v1.2.1
|
|
||||||
github.com/gin-contrib/sessions v0.0.5
|
github.com/gin-contrib/sessions v0.0.5
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.9.1
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/imroc/req/v3 v3.37.2
|
github.com/imroc/req/v3 v3.37.2
|
||||||
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230415042440-a5e3d8259ae0
|
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230415042440-a5e3d8259ae0
|
||||||
github.com/pkoukk/tiktoken-go v0.1.1-0.20230418101013-cae809389480
|
github.com/pkoukk/tiktoken-go v0.1.1-0.20230418101013-cae809389480
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
go.uber.org/zap v1.23.0
|
go.uber.org/zap v1.23.0
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
|
@ -18,8 +18,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dlclark/regexp2 v1.8.1 h1:6Lcdwya6GjPUNsBct8Lg/yRPwMhABj269AAzdGSiR+0=
|
github.com/dlclark/regexp2 v1.8.1 h1:6Lcdwya6GjPUNsBct8Lg/yRPwMhABj269AAzdGSiR+0=
|
||||||
github.com/dlclark/regexp2 v1.8.1/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.8.1/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
github.com/eatmoreapple/openwechat v1.2.1 h1:ez4oqF/Y2NSEX/DbPV8lvj7JlfkYqvieeo4awx5lzfU=
|
|
||||||
github.com/eatmoreapple/openwechat v1.2.1/go.mod h1:61HOzTyvLobGdgWhL68jfGNwTJEv0mhQ1miCXQrvWU8=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||||
@ -140,8 +138,6 @@ github.com/quic-go/quic-go v0.35.1 h1:b0kzj6b/cQAf05cT0CkQubHM31wiA+xH3IBkxP62po
|
|||||||
github.com/quic-go/quic-go v0.35.1/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g=
|
github.com/quic-go/quic-go v0.35.1/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g=
|
||||||
github.com/refraction-networking/utls v1.3.2 h1:o+AkWB57mkcoW36ET7uJ002CpBWHu0KPxi6vzxvPnv8=
|
github.com/refraction-networking/utls v1.3.2 h1:o+AkWB57mkcoW36ET7uJ002CpBWHu0KPxi6vzxvPnv8=
|
||||||
github.com/refraction-networking/utls v1.3.2/go.mod h1:fmoaOww2bxzzEpIKOebIsnBvjQpqP7L2vcm/9KUfm/E=
|
github.com/refraction-networking/utls v1.3.2/go.mod h1:fmoaOww2bxzzEpIKOebIsnBvjQpqP7L2vcm/9KUfm/E=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
@ -21,6 +21,50 @@ func NewRewardHandler(server *core.AppServer, db *gorm.DB) *RewardHandler {
|
|||||||
return &h
|
return &h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *RewardHandler) Push(c *gin.Context) {
|
||||||
|
token := c.GetHeader("X-TOKEN")
|
||||||
|
if token != h.App.Config.ChatPlusExtApiToken {
|
||||||
|
resp.NotAuth(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var data struct {
|
||||||
|
TransId string `json:"trans_id"` // 微信转账交易 ID
|
||||||
|
Amount float64 `json:"amount"` // 微信转账交易金额
|
||||||
|
Remark string `json:"remark"` // 转账备注
|
||||||
|
}
|
||||||
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.Amount <= 0 {
|
||||||
|
resp.ERROR(c, "Amount should not be 0")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Infof("收到众筹收款信息: %+v", data)
|
||||||
|
var item model.Reward
|
||||||
|
res := h.db.Where("tx_id = ?", data.TransId).First(&item)
|
||||||
|
if res.Error == nil {
|
||||||
|
resp.ERROR(c, "当前交易 ID 己经存在!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res = h.db.Create(&model.Reward{
|
||||||
|
TxId: data.TransId,
|
||||||
|
Amount: data.Amount,
|
||||||
|
Remark: data.Remark,
|
||||||
|
Status: false,
|
||||||
|
})
|
||||||
|
if res.Error != nil {
|
||||||
|
logger.Errorf("交易保存失败: %v", res.Error)
|
||||||
|
resp.ERROR(c, "交易保存失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.SUCCESS(c)
|
||||||
|
}
|
||||||
|
|
||||||
// Verify 打赏码核销
|
// Verify 打赏码核销
|
||||||
func (h *RewardHandler) Verify(c *gin.Context) {
|
func (h *RewardHandler) Verify(c *gin.Context) {
|
||||||
var data struct {
|
var data struct {
|
||||||
|
13
api/main.go
13
api/main.go
@ -6,7 +6,6 @@ import (
|
|||||||
"chatplus/handler"
|
"chatplus/handler"
|
||||||
"chatplus/handler/admin"
|
"chatplus/handler/admin"
|
||||||
logger2 "chatplus/logger"
|
logger2 "chatplus/logger"
|
||||||
"chatplus/modules/wexin"
|
|
||||||
"chatplus/service"
|
"chatplus/service"
|
||||||
"chatplus/service/function"
|
"chatplus/service/function"
|
||||||
"chatplus/store"
|
"chatplus/store"
|
||||||
@ -104,17 +103,6 @@ func main() {
|
|||||||
return xdb.NewWithBuffer(cBuff)
|
return xdb.NewWithBuffer(cBuff)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 创建微信机器人
|
|
||||||
fx.Provide(wexin.NewWeChatBot),
|
|
||||||
fx.Invoke(func(bot *wexin.WeChatBot) {
|
|
||||||
go func() {
|
|
||||||
err := bot.Login()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}),
|
|
||||||
|
|
||||||
// 创建函数
|
// 创建函数
|
||||||
fx.Provide(func(config *types.AppConfig) (function.FuncZaoBao, error) {
|
fx.Provide(func(config *types.AppConfig) (function.FuncZaoBao, error) {
|
||||||
return function.NewZaoBao(config.ApiConfig), nil
|
return function.NewZaoBao(config.ApiConfig), nil
|
||||||
@ -192,6 +180,7 @@ func main() {
|
|||||||
}),
|
}),
|
||||||
fx.Invoke(func(s *core.AppServer, h *handler.RewardHandler) {
|
fx.Invoke(func(s *core.AppServer, h *handler.RewardHandler) {
|
||||||
group := s.Engine.Group("/api/reward/")
|
group := s.Engine.Group("/api/reward/")
|
||||||
|
group.POST("push", h.Push)
|
||||||
group.POST("verify", h.Verify)
|
group.POST("verify", h.Verify)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
package wexin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"chatplus/store/model"
|
|
||||||
"github.com/eatmoreapple/openwechat"
|
|
||||||
"github.com/skip2/go-qrcode"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MessageHandler 消息处理
|
|
||||||
func MessageHandler(msg *openwechat.Message, db *gorm.DB) {
|
|
||||||
sender, err := msg.Sender()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 只处理微信支付的推送消息
|
|
||||||
if sender.NickName == "微信支付" ||
|
|
||||||
msg.MsgType == openwechat.MsgTypeApp ||
|
|
||||||
msg.AppMsgType == openwechat.AppMsgTypeUrl {
|
|
||||||
// 解析支付金额
|
|
||||||
message, err := parseTransactionMessage(msg.Content)
|
|
||||||
if err == nil {
|
|
||||||
transaction := extractTransaction(message)
|
|
||||||
logger.Infof("解析到收款信息:%+v", transaction)
|
|
||||||
if transaction.Amount <= 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var item model.Reward
|
|
||||||
res := db.Where("tx_id = ?", transaction.TransId).First(&item)
|
|
||||||
if res.Error == nil {
|
|
||||||
logger.Infof("当前交易 ID %s 己经存在!", transaction.TransId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
res = db.Create(&model.Reward{
|
|
||||||
TxId: transaction.TransId,
|
|
||||||
Amount: transaction.Amount,
|
|
||||||
Remark: transaction.Remark,
|
|
||||||
Status: false,
|
|
||||||
})
|
|
||||||
if res.Error != nil {
|
|
||||||
logger.Errorf("交易保存失败,ID: %s", transaction.TransId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// QrCodeCallBack 登录扫码回调,
|
|
||||||
func QrCodeCallBack(uuid string) {
|
|
||||||
logger.Info("请使用微信扫描下面二维码登录")
|
|
||||||
q, _ := qrcode.New("https://login.weixin.qq.com/l/"+uuid, qrcode.Medium)
|
|
||||||
logger.Info(q.ToString(true))
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
package wexin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/xml"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Message 转账消息
|
|
||||||
type Message struct {
|
|
||||||
XMLName xml.Name `xml:"msg"`
|
|
||||||
AppMsg struct {
|
|
||||||
Des string `xml:"des"`
|
|
||||||
Url string `xml:"url"`
|
|
||||||
} `xml:"appmsg"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transaction 解析后的交易信息
|
|
||||||
type Transaction struct {
|
|
||||||
TransId string `json:"trans_id"` // 微信转账交易 ID
|
|
||||||
Amount float64 `json:"amount"` // 微信转账交易金额
|
|
||||||
Remark string `json:"remark"` // 转账备注
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析微信转账消息
|
|
||||||
func parseTransactionMessage(xmlData string) (*Message, error) {
|
|
||||||
var msg Message
|
|
||||||
if err := xml.Unmarshal([]byte(xmlData), &msg); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &msg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出交易信息
|
|
||||||
func extractTransaction(message *Message) Transaction {
|
|
||||||
var tx = Transaction{}
|
|
||||||
// 导出交易金额和备注
|
|
||||||
lines := strings.Split(message.AppMsg.Des, "\n")
|
|
||||||
for _, line := range lines {
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
if len(line) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 解析收款金额
|
|
||||||
prefix := "收款金额¥"
|
|
||||||
if strings.HasPrefix(line, prefix) {
|
|
||||||
if value, err := strconv.ParseFloat(line[len(prefix):], 64); err == nil {
|
|
||||||
tx.Amount = value
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 解析收款备注
|
|
||||||
prefix = "付款方备注"
|
|
||||||
if strings.HasPrefix(line, prefix) {
|
|
||||||
tx.Remark = line[len(prefix):]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析交易 ID
|
|
||||||
index := strings.Index(message.AppMsg.Url, "trans_id=")
|
|
||||||
if index != -1 {
|
|
||||||
end := strings.LastIndex(message.AppMsg.Url, "&")
|
|
||||||
tx.TransId = strings.TrimSpace(message.AppMsg.Url[index+9 : end])
|
|
||||||
}
|
|
||||||
return tx
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
package wexin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"chatplus/core/types"
|
|
||||||
logger2 "chatplus/logger"
|
|
||||||
"github.com/eatmoreapple/openwechat"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 微信收款机器人服务
|
|
||||||
var logger = logger2.GetLogger()
|
|
||||||
|
|
||||||
type WeChatBot struct {
|
|
||||||
bot *openwechat.Bot
|
|
||||||
db *gorm.DB
|
|
||||||
appConfig *types.AppConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewWeChatBot(db *gorm.DB, config *types.AppConfig) *WeChatBot {
|
|
||||||
bot := openwechat.DefaultBot(openwechat.Desktop)
|
|
||||||
// 注册消息处理函数
|
|
||||||
bot.MessageHandler = func(msg *openwechat.Message) {
|
|
||||||
MessageHandler(msg, db)
|
|
||||||
}
|
|
||||||
// 注册登陆二维码回调
|
|
||||||
bot.UUIDCallback = QrCodeCallBack
|
|
||||||
return &WeChatBot{
|
|
||||||
bot: bot,
|
|
||||||
db: db,
|
|
||||||
appConfig: config,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *WeChatBot) Login() error {
|
|
||||||
if !b.appConfig.StartWechatBot {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建热存储容器对象
|
|
||||||
reloadStorage := openwechat.NewJsonFileHotReloadStorage("storage.json")
|
|
||||||
// 执行热登录
|
|
||||||
err := b.bot.HotLogin(reloadStorage)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("login error: %v", err)
|
|
||||||
return b.bot.Login()
|
|
||||||
}
|
|
||||||
logger.Info("微信登录成功!")
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -20,6 +20,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
fmt.Println(utils.RandString(32))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Http client 取消操作
|
// Http client 取消操作
|
||||||
|
@ -4,8 +4,11 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AesEncrypt 加密
|
// AesEncrypt 加密
|
||||||
@ -68,3 +71,14 @@ func pkcs7UnPadding(data []byte) ([]byte, error) {
|
|||||||
unPadding := int(data[length-1])
|
unPadding := int(data[length-1])
|
||||||
return data[:(length - unPadding)], nil
|
return data[:(length - unPadding)], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Sha256(data string) string {
|
||||||
|
hash := sha256.New()
|
||||||
|
_, err := io.WriteString(hash, data)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
hashValue := hash.Sum(nil)
|
||||||
|
return fmt.Sprintf("%x", hashValue)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user