mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	feat: remove wechat bot, replace with api callback for receive wechat payment transactions
This commit is contained in:
		@@ -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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user