Răsfoiți Sursa

wechat sdk orm database

kobe6258 8 luni în urmă
părinte
comite
b22ad2d7b3

+ 24 - 34
common/client/http_client.go

@@ -3,73 +3,63 @@ package client
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"time"
 )
 
 type HttpClient struct {
-	client     *http.Client
-	maxRetries int
-	retryDelay time.Duration
+	*http.Client
+	maxRetries     int
+	retryDelayFunc RetryDelayFunc
 }
 
 func GetInstance(timeout time.Duration, maxRetries int) *HttpClient {
 	return &HttpClient{
-		client:     &http.Client{Timeout: timeout},
-		maxRetries: maxRetries,
+		Client:         &http.Client{Timeout: timeout},
+		maxRetries:     maxRetries,
+		retryDelayFunc: defaultRetryDelayFunc,
 	}
 }
 
+func defaultRetryDelayFunc(attempt int) time.Duration {
+	delay := time.Duration(attempt) * time.Second
+	if attempt > 0 {
+		delay *= 2
+	}
+	return delay
+}
+
 type RetryDelayFunc func(attempt int) time.Duration
 
 // DoWithRetry 发送带有重试机制的HTTP请求,允许用户自定义重试延迟逻辑
-func (hc *HttpClient) DoWithRetry(ctx context.Context, req *http.Request, retryDelayFunc RetryDelayFunc) (*http.Response, error) {
+func (hc *HttpClient) DoWithRetry(ctx context.Context, req *http.Request) (*http.Response, error) {
 	attempt := 0
 	for {
-		resp, err := hc.client.Do(req.WithContext(ctx))
+		resp, err := hc.Do(req.WithContext(ctx))
 		if err != nil {
 			if attempt >= hc.maxRetries {
 				return nil, fmt.Errorf("请求失败: %w", err)
 			}
 			attempt++
-			delay := retryDelayFunc(attempt)
+			delay := hc.retryDelayFunc(attempt)
 			time.Sleep(delay)
 			continue
 		}
 		return resp, nil
 	}
 }
-func main() {
-	client := GetInstance(10*time.Second, 3) // 超时10秒,最多重试3次
 
-	// 自定义重试延迟逻辑
-	customRetryDelay := func(attempt int) time.Duration {
-		// 示例:首次重试立即进行,之后每次重试等待时间加倍
-		delay := time.Duration(attempt) * time.Second
-		if attempt > 0 {
-			delay *= 2
-		}
-		return delay
-	}
+func (hc *HttpClient) Post(url string, contentType string, buf io.Reader) (resp *http.Response, err error) {
+	return
+}
 
-	url := "http://example.com/api/data"
+func (hc *HttpClient) Get(url string) (resp *http.Response, err error) {
 	req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, nil)
 	if err != nil {
 		log.Fatalf("创建请求失败: %v", err)
 	}
-
-	resp, err := client.DoWithRetry(req.Context(), req, customRetryDelay)
-	if err != nil {
-		log.Fatalf("%v,请求失败", err)
-	}
-	defer resp.Body.Close()
-
-	body, readErr := ioutil.ReadAll(resp.Body)
-	if readErr != nil {
-		log.Fatalf("解析应答失败: %v", readErr)
-	}
-
-	fmt.Printf("应答结果为: %s\n", body)
+	resp, err = hc.DoWithRetry(req.Context(), req)
+	return
 }

+ 47 - 0
common/exception/exc_enums.go

@@ -0,0 +1,47 @@
+package exception
+
+import "errors"
+
+type ErrorCode int
+
+const (
+	SysErrCode ErrorCode = iota + 10000 // iota 自动递增,从 1 开始
+	ErrCodeNotFound
+	ErrCodeUnauthorized
+	ErrCodeBadRequest
+	ErrCodeInternalServer
+)
+
+const (
+	BIZErrCode ErrorCode = iota + 20000 // iota 自动递增,从 1 开始
+	BIZErrCodeErrCodeNotFound
+	BIZErrCodeErrCodeUnauthorized
+	BIZErrCodeErrCodeBadRequest
+	BIZErrCodeErrCodeInternalServer
+)
+
+// 为枚举类型定义一个字符串表示
+func (e ErrorCode) String() string {
+	switch e {
+	case ErrCodeNotFound:
+		return "Not Found"
+	case ErrCodeUnauthorized:
+		return "Unauthorized"
+	case ErrCodeBadRequest:
+		return "Bad Request"
+	case ErrCodeInternalServer:
+		return "Internal Server Error"
+	default:
+		return "Unknown Error"
+	}
+}
+
+// 为每个错误代码定义一个错误实例
+var (
+	ErrNotFound       = errors.New(ErrCodeNotFound.String())
+	ErrUnauthorized   = errors.New(ErrCodeUnauthorized.String())
+	ErrBadRequest     = errors.New(ErrCodeBadRequest.String())
+	ErrInternalServer = errors.New(ErrCodeInternalServer.String())
+)
+
+//sys_error 系统错误

+ 5 - 4
common/exception/panic_recover/panic_advice.go

@@ -13,7 +13,9 @@ func PanicAdvice(ctx *context.Context, conf *web.Config) {
 		if err == web.ErrAbort {
 			return
 		}
-
+		if !web.BConfig.RecoverPanic {
+			panic(err)
+		}
 		stack := ""
 		msg := fmt.Sprintf("The request url is  %v", ctx.Input.URL())
 		stack += msg + "</br>"
@@ -32,9 +34,8 @@ func PanicAdvice(ctx *context.Context, conf *web.Config) {
 			logs.Critical(fmt.Sprintf("%s:%d", file, line))
 			stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d</br>", file, line))
 		}
-		//go utils.SendEmail(utils.APP_NAME_CN+"崩了"+time.Now().Format("2006-01-02 15:04:05"), stack, utils.EmailSendToUsers)
-		//go alarm_msg.SendAlarmMsg(utils.APP_NAME_CN+"崩了"+time.Now().Format("2006-01-02 15:04:05")+"<br/>"+stack, 3)
+		//go utils.SendEmail(utils.APPNAME+"崩了"+time.Now().Format("2006-01-02 15:04:05"), stack, utils.EmailSendToUsers)
+		//go alarm_msg.SendAlarmMsg(utils.APPNAME+"崩了"+time.Now().Format("2006-01-02 15:04:05")+"<br/>"+stack, 3)
 	}
-
 	return
 }

+ 7 - 9
component/cache/redis.go

@@ -2,8 +2,8 @@ package cache
 
 import (
 	"context"
+	config2 "eta_mini_ht_api/component/config"
 	logger "eta_mini_ht_api/component/log"
-	redisConfig "eta_mini_ht_api/config"
 	"github.com/go-redis/redis/v8"
 	"log"
 	"strings"
@@ -18,28 +18,26 @@ var (
 
 func GetInstance() *RedisCache {
 	once.Do(func() {
-		config := redisConfig.GetConfig("redis")
+		redisConf, ok := config2.GetConfig("redis").(*config2.RedisConfig)
 		// 检查是否成功获取到RedisConfig实例
-		redisInstance, ok := config.(*redisConfig.RedisConfig)
 		if !ok {
-			// 处理错误情况,比如记录日志或返回错误信息
 			logger.Info("加载redis配置失败")
-			return // 或者采取其他适当的错误处理措施
+			return
 		}
-		// 获取Redis配置选项,这里假设GetConfig方法返回(*RedisOpts, error),需要检查错误
-		opts := redisInstance.GetConfig().(redisConfig.RedisOpts)
+		opts, ok := redisConf.GetConfig().(config2.RedisOpts)
 		// 检查Host是否已设置,然后初始化或执行相应操作
-		if opts.Host != "" {
+		if ok && opts.Host != "" {
 			logger.Info("初始化redis")
 			// 这里可以添加初始化Redis的逻辑
 			redisCache = newRedis(opts)
 		} else {
 			logger.Info("Redis configuration is incomplete: Host is missing")
+			return
 		}
 	})
 	return redisCache
 }
-func newRedis(opts redisConfig.RedisOpts) *RedisCache {
+func newRedis(opts config2.RedisOpts) *RedisCache {
 	if &opts == nil || opts.Host == "" {
 		log.Fatalf("redis 连接失败")
 	}

+ 0 - 0
config/config.go → component/config/config.go


+ 0 - 0
config/redis_config.go → component/config/redis_config.go


+ 32 - 0
component/config/wechat_config.go

@@ -0,0 +1,32 @@
+package config
+
+// RedisOpts redis 连接属性
+type WechatOpts struct {
+	Appid  string
+	Secret string
+}
+type WechatConfig struct {
+	BaseConfig
+	opts WechatOpts
+}
+
+func (w *WechatConfig) GetConfig() interface{} {
+	return w.opts
+}
+func (w *WechatConfig) InitConfig() {
+	opts := WechatOpts{
+		Appid:  w.GetString("appid"),
+		Secret: w.GetString("secret"),
+	}
+	w.opts = opts
+}
+func NewWechat() Config {
+	return &WechatConfig{
+		BaseConfig: BaseConfig{prefix: "wechat"},
+		opts:       WechatOpts{},
+	}
+}
+
+func init() {
+	Register("wechat", NewWechat)
+}

+ 29 - 0
component/database/data_base.go

@@ -0,0 +1,29 @@
+package database
+
+import "github.com/beego/beego/v2/core/logs"
+
+type DataBase interface {
+}
+
+var dbs = make(map[string]DBInstance)
+
+type DBInstance func() DataBase
+
+func GetDBInstance(name string) (db DataBase) {
+	instanceFunc, ok := dbs[name]
+	if !ok {
+		logs.Error("db: 未知数据源类型 %q ", name)
+		return nil
+	}
+	db = instanceFunc()
+	return
+}
+func Register(name string, adapter DBInstance) {
+	if adapter == nil {
+		panic("不支持的数据源格式")
+	}
+	if _, ok := dbs[name]; ok {
+		panic("数据源已注册" + name)
+	}
+	dbs[name] = adapter
+}

+ 1 - 57
component/wechat/http/request.go

@@ -5,12 +5,10 @@ import (
 	"context"
 	"encoding/json"
 	"encoding/xml"
+	"errors"
 	"eta_mini_ht_api/common/client"
 	"github.com/medivhzhan/weapp/v3/logger"
-	"io"
-	"mime/multipart"
 	"net/http"
-	"os"
 )
 
 // ContentType 请求内容类型
@@ -57,7 +55,6 @@ func (cli *Request) Get(url string, response interface{}) error {
 		return err
 	}
 	defer resp.Body.Close()
-
 	switch cli.contentType {
 	case ContentTypeXML:
 		return xml.NewDecoder(resp.Body).Decode(response)
@@ -128,56 +125,3 @@ func (cli *Request) PostWithBody(url string, params interface{}) (*http.Response
 
 	return rsp, nil
 }
-
-func (cli *Request) FormPostWithFile(url, field, filename string, response interface{}) error {
-	file, err := os.Open(filename)
-	if err != nil {
-		return err
-	}
-	defer file.Close()
-
-	return cli.FormPost(url, field, filename, file, response)
-}
-
-func (cli *Request) FormPost(url, field, filename string, reader io.Reader, response interface{}) error {
-	cli.logger().Info(context.Background(), "request url: %s", url)
-	// Prepare a form that you will submit to that URL.
-	buf := new(bytes.Buffer)
-	w := multipart.NewWriter(buf)
-	fw, err := w.CreateFormFile(field, filename)
-	if err != nil {
-		return err
-	}
-
-	if _, err = io.Copy(fw, reader); err != nil {
-		return err
-	}
-
-	// Don't forget to close the multipart writer.
-	// If you don't close it, your request will be missing the terminating boundary.
-	w.Close()
-
-	// Now that you have a form, you can submit it to your handler.
-	req, err := http.NewRequest("POST", url, buf)
-	if err != nil {
-		return err
-	}
-	// Don't forget to set the content type, this will contain the boundary.
-	req.Header.Set("Content-Type", w.FormDataContentType())
-
-	resp, err := cli.http.Do(req)
-	if err != nil {
-		cli.logger().Error(context.Background(), "form post error: %s", err)
-		return err
-	}
-	defer resp.Body.Close()
-
-	switch cli.contentType {
-	case ContentTypeXML:
-		return xml.NewDecoder(resp.Body).Decode(response)
-	case ContentTypeJSON:
-		return json.NewDecoder(resp.Body).Decode(response)
-	default:
-		return errors.New("invalid content type")
-	}
-}

+ 36 - 0
component/wechat/http/response.go

@@ -0,0 +1,36 @@
+package http
+
+import (
+	"fmt"
+)
+
+// CommonError 微信返回错误信息
+type CommonError struct {
+	ErrCode int    `json:"errcode"` // 	错误码
+	ErrMSG  string `json:"errmsg"`  // 	错误描述
+}
+
+// GetResponseError 获取微信服务器错返回误信息
+func (err CommonError) GetResponseError() error {
+	if err.ErrCode != 0 {
+		return fmt.Errorf("wechat server error: code[%d] msg[%s]", err.ErrCode, err.ErrMSG)
+	}
+
+	return nil
+}
+
+// CommonResult 微信返回错误信息
+type CommonResult struct {
+	ResultCode int    `json:"resultcode"` // 	错误码
+	ResultMsg  string `json:"resultmsg"`  // 	错误描述
+}
+
+// GetResponseError 获取微信服务器错返回误信息
+func (err CommonResult) GetResponseError() error {
+
+	if err.ResultCode != 0 {
+		return fmt.Errorf("wechat server error: code[%d] msg[%s]", err.ResultCode, err.ResultMsg)
+	}
+
+	return nil
+}

+ 16 - 3
component/wechat/wechat_client.go

@@ -2,6 +2,7 @@ package wechat
 
 import (
 	"eta_mini_ht_api/component/cache"
+	config2 "eta_mini_ht_api/component/config"
 	"eta_mini_ht_api/component/log"
 	"github.com/medivhzhan/weapp/v3/auth"
 	"github.com/medivhzhan/weapp/v3/request"
@@ -36,8 +37,20 @@ type Client struct {
 
 func GetInstance() *Client {
 	once.Do(func() {
+		wechatConf, ok := config2.GetConfig("wechat").(*config2.WechatConfig)
+		if !ok {
+			// 处理错误情况,比如记录日志或返回错误信息
+			logger.Info("加载wechat配置失败")
+			return // 或者采取其他适当的错误处理措施
+		}
+		opts, ok := wechatConf.GetConfig().(config2.WechatOpts)
+		if !ok {
+			// 处理错误情况,比如记录日志或返回错误信息
+			logger.Info("加载wechat配置失败")
+			return // 或者采取其他适当的错误处理措施
+		}
 		// 默认配置
-		wechatClient = NewClient("", "",
+		wechatClient = NewClient(opts.Appid, opts.Secret,
 			WithHttpClient(http.DefaultClient),
 			WithCache(cache.GetInstance()),
 			WithLogger(logger.GetInstance()),
@@ -46,10 +59,10 @@ func GetInstance() *Client {
 	return wechatClient
 }
 
-// 用户自定义获取access_token的方法
+// AccessTokenGetter 用户自定义获取access_token的方法
 type AccessTokenGetter func(appid, secret string) (token string, expireIn uint)
 
-// 初始化客户端并用自定义配置替换默认配置
+// NewClient 初始化客户端并用自定义配置替换默认配置
 func NewClient(appid, secret string, opts ...func(*Client)) *Client {
 	cli := &Client{
 		appid:  appid,

+ 2 - 0
main.go

@@ -14,9 +14,11 @@ func main() {
 		web.BConfig.WebConfig.DirectoryIndex = true
 		web.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
 	}
+
 	logger.Info("初始化成功")
 	//增加授权拦截
 	web.InsertFilter("*", web.BeforeRouter, middleware.AuthMiddleware())
+	//web.ErrorHandler("*", panic_recover.PanicAdvice)
 	web.BConfig.RecoverFunc = panic_recover.PanicAdvice
 	web.Run()
 }