mir: add partital interface implement for new web service

pull/196/head
Michael Li 2 years ago
parent 9feb1a5a0b
commit da939f7c73
No known key found for this signature in database

@ -5,5 +5,7 @@
package web
type ChangeUserStatusReq struct {
*BaseInfo `json:"-"`
*BaseInfo `json:"-" binding:"-"`
ID int64 `json:"id" form:"id" binding:"required"`
Status int `json:"status" form:"status" binding:"required,oneof=1 2"`
}

@ -4,8 +4,14 @@
package web
import (
"context"
"github.com/smartwalle/alipay/v3"
)
type UserWalletBillsReq struct {
*BaseInfo `json:"-"`
*BaseInfo `json:"-" binding:"-"`
}
type UserWalletBillsResp struct {
@ -13,5 +19,8 @@ type UserWalletBillsResp struct {
}
type AlipayNotifyReq struct {
// TODO
Ctx context.Context
ID int64
TradeNo string
TradeStatus alipay.TradeStatus
}

@ -9,6 +9,7 @@ import (
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
"github.com/go-redis/redis/v8"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/pkg/xerror"
)
@ -17,6 +18,11 @@ type BaseServant struct {
// TODO
}
type DaoServant struct {
Redis *redis.Client
Ds core.DataService
}
type BaseBinding struct {
// TODO
}
@ -47,7 +53,7 @@ func BindAny(c *gin.Context, obj any) mir.Error {
var errs xerror.ValidErrors
err := c.ShouldBind(obj)
if err != nil {
return mir.NewError(xerror.InvalidParams.Code(), xerror.InvalidParams.WithDetails(errs.Error()))
return mir.NewError(xerror.InvalidParams.StatusCode(), xerror.InvalidParams.WithDetails(errs.Error()))
}
// setup *core.User if needed
if setter, ok := obj.(UserSetter); ok {
@ -65,7 +71,7 @@ func RenderAny(c *gin.Context, data any, err mir.Error) {
Data: data,
})
} else {
c.JSON(http.StatusInternalServerError, &JsonResp{
c.JSON(xerror.HttpStatusCode(err), &JsonResp{
Code: err.StatusCode(),
Msg: err.Error(),
})

@ -5,10 +5,13 @@
package web
import (
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
api "github.com/rocboss/paopao-ce/auto/api/v1"
"github.com/rocboss/paopao-ce/internal/model/web"
"github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/rocboss/paopao-ce/internal/servants/chain"
"github.com/rocboss/paopao-ce/pkg/xerror"
)
var (
@ -18,17 +21,15 @@ var (
)
type adminSrv struct {
base.BaseServant
api.UnimplementedAdminServant
*base.DaoServant
}
type adminBinding struct {
base.BaseBinding
*api.UnimplementedAdminBinding
}
type adminRender struct {
base.BaseRender
*api.UnimplementedAdminRender
}
@ -36,8 +37,23 @@ func (s *adminSrv) Chain() gin.HandlersChain {
return gin.HandlersChain{chain.JWT(), chain.Admin()}
}
func newAdminSrv() api.Admin {
return &adminSrv{}
func (s *adminSrv) ChangeUserStatus(req *web.ChangeUserStatusReq) mir.Error {
user, err := s.Ds.GetUserByID(req.ID)
if err != nil || user.Model == nil || user.ID <= 0 {
return _errNoExistUsername
}
// 执行更新
user.Status = req.Status
if err := s.Ds.UpdateUser(user); err != nil {
return xerror.ServerError
}
return nil
}
func newAdminSrv(s *base.DaoServant) api.Admin {
return &adminSrv{
DaoServant: s,
}
}
func newAdminBinding() api.AdminBinding {

@ -5,10 +5,17 @@
package web
import (
"time"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
api "github.com/rocboss/paopao-ce/auto/api/v1"
"github.com/rocboss/paopao-ce/internal/model/web"
"github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/rocboss/paopao-ce/internal/servants/chain"
"github.com/rocboss/paopao-ce/pkg/convert"
"github.com/sirupsen/logrus"
"github.com/smartwalle/alipay/v3"
)
var (
@ -21,48 +28,88 @@ var (
)
type alipayPubSrv struct {
base.BaseServant
api.UnimplementedAlipayPubServant
*base.DaoServant
}
type alipayPubBinding struct {
base.BaseBinding
*api.UnimplementedAlipayPubBinding
alipayClient *alipay.Client
}
type alipayPubRender struct {
base.BaseRender
*api.UnimplementedAlipayPubRender
}
type alipayPrivSrv struct {
base.BaseServant
api.UnimplementedAlipayPrivServant
}
type alipayPrivBinding struct {
base.BaseBinding
*api.UnimplementedAlipayPrivBinding
}
type alipayPrivRender struct {
base.BaseRender
*api.UnimplementedAlipayPrivRender
}
func (b *alipayPubBinding) BindAlipayNotify(c *gin.Context) (*web.AlipayNotifyReq, mir.Error) {
if err := c.Request.ParseForm(); err != nil {
logrus.Errorf("parse form err: %s", err)
return nil, _errRechargeNotifyError
}
noti, err := b.alipayClient.GetTradeNotification(c.Request)
if err != nil {
logrus.Errorf("alipayClient.GetTradeNotification err: %s form: %v", err, c.Request.Form)
return nil, _errRechargeNotifyError
}
return &web.AlipayNotifyReq{
Ctx: c.Request.Context(),
ID: convert.StrTo(noti.OutTradeNo).MustInt64(),
TradeNo: noti.TradeNo,
TradeStatus: noti.TradeStatus,
}, nil
}
func (s *alipayPubSrv) AlipayNotify(req *web.AlipayNotifyReq) mir.Error {
if req.TradeStatus == alipay.TradeStatusSuccess {
if ok, _ := s.Redis.SetNX(req.Ctx, "PaoPaoRecharge:"+req.TradeNo, 1, time.Second*5).Result(); ok {
recharge, err := s.Ds.GetRechargeByID(req.ID)
if err != nil {
logrus.Errorf("GetRechargeByID id:%d err: %s", req.ID, err)
return _errRechargeNotifyError
}
if recharge.TradeStatus != "TRADE_SUCCESS" {
// 标记为已付款
err := s.Ds.HandleRechargeSuccess(recharge, req.TradeNo)
defer s.Redis.Del(req.Ctx, "PaoPaoRecharge:"+req.TradeNo)
if err != nil {
logrus.Errorf("HandleRechargeSuccess id:%d err: %s", req.ID, err)
return _errRechargeNotifyError
}
}
}
}
return nil
}
func (s *alipayPrivSrv) Chain() gin.HandlersChain {
return gin.HandlersChain{chain.JWT()}
}
func newAlipayPubSrv() api.AlipayPub {
return &alipayPubSrv{}
func newAlipayPubSrv(s *base.DaoServant) api.AlipayPub {
return &alipayPubSrv{
DaoServant: s,
}
}
func newAlipayPubBinding() api.AlipayPubBinding {
func newAlipayPubBinding(alipayClient *alipay.Client) api.AlipayPubBinding {
return &alipayPubBinding{
UnimplementedAlipayPubBinding: &api.UnimplementedAlipayPubBinding{
BindAny: base.BindAny,
},
alipayClient: alipayClient,
}
}

@ -7,6 +7,7 @@ package web
import (
"github.com/gin-gonic/gin"
api "github.com/rocboss/paopao-ce/auto/api/v1"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/rocboss/paopao-ce/internal/servants/chain"
)
@ -18,17 +19,18 @@ var (
)
type coreSrv struct {
base.BaseServant
api.UnimplementedCoreServant
*base.DaoServant
ts core.TweetSearchService
oss core.ObjectStorageService
}
type coreBinding struct {
base.BaseBinding
*api.UnimplementedCoreBinding
}
type coreRender struct {
base.BaseRender
*api.UnimplementedCoreRender
}
@ -36,8 +38,12 @@ func (s *coreSrv) Chain() gin.HandlersChain {
return gin.HandlersChain{chain.JWT()}
}
func newCoreSrv() api.Core {
return &coreSrv{}
func newCoreSrv(s *base.DaoServant, ts core.TweetSearchService, oss core.ObjectStorageService) api.Core {
return &coreSrv{
DaoServant: s,
ts: ts,
oss: oss,
}
}
func newCoreBinding() api.CoreBinding {

@ -8,19 +8,32 @@ import (
"github.com/alimy/cfg"
"github.com/gin-gonic/gin"
api "github.com/rocboss/paopao-ce/auto/api/v1"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/dao"
"github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/sirupsen/logrus"
"github.com/smartwalle/alipay/v3"
)
// RouteWeb register web route
func RouteWeb(e *gin.Engine) {
api.RegisterAdminServant(e, newAdminSrv(), newAdminBinding(), newAdminRender())
api.RegisterCoreServant(e, newCoreSrv(), newCoreBinding(), newCoreRender())
ts := dao.TweetSearchService()
oss := dao.ObjectStorageService()
ds := &base.DaoServant{
Redis: conf.Redis,
Ds: dao.DataService(),
}
// aways register servants
api.RegisterAdminServant(e, newAdminSrv(ds), newAdminBinding(), newAdminRender())
api.RegisterCoreServant(e, newCoreSrv(ds, ts, oss), newCoreBinding(), newCoreRender())
api.RegisterLooseServant(e, newLooseSrv(), newLooseBinding(), newLooseRender())
api.RegisterPrivServant(e, newPrivSrv(), newPrivBinding(), newPrivRender())
api.RegisterPubServant(e, newPubSrv(), newPubBinding(), newPubRender())
// regster servants if needed by configure
cfg.In(cfg.Actions{
"Alipay": func() {
api.RegisterAlipayPubServant(e, newAlipayPubSrv(), newAlipayPubBinding(), newAlipayPubRender())
client := mustAlipayClient()
api.RegisterAlipayPubServant(e, newAlipayPubSrv(ds), newAlipayPubBinding(client), newAlipayPubRender())
api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(), newAlipayPrivBinding(), newAlipayPrivRender())
},
"Followship": func() {
@ -31,3 +44,25 @@ func RouteWeb(e *gin.Engine) {
},
})
}
func mustAlipayClient() *alipay.Client {
s := conf.AlipaySetting
// 将 key 的验证调整到初始化阶段
client, err := alipay.New(s.AppID, s.PrivateKey, s.InProduction)
if err != nil {
logrus.Fatalf("alipay.New err: %s", err)
}
// 加载应用公钥证书
if err = client.LoadAppPublicCertFromFile(s.AppPublicCertFile); err != nil {
logrus.Fatalf("client.LoadAppPublicCertFromFile err: %s\n", err)
}
// 加载支付宝根证书
if err = client.LoadAliPayRootCertFromFile(s.RootCertFile); err != nil {
logrus.Fatalf("client.LoadAliPayRootCertFromFile err: %s\n", err)
}
// 加载支付宝公钥证书
if err = client.LoadAliPayPublicCertFromFile(s.PublicCertFile); err != nil {
logrus.Fatalf("client.LoadAliPayPublicCertFromFile err: %s\n", err)
}
return client
}

@ -8,9 +8,13 @@ import (
"fmt"
"net/http"
"strings"
"github.com/alimy/mir/v3"
)
var (
_ mir.Error = (*Error)(nil)
codes = map[int]string{}
)
@ -51,10 +55,10 @@ func NewError(code int, msg string) *Error {
}
func (e *Error) Error() string {
return fmt.Sprintf("错误码: %d, 错误信息: %s", e.Code(), e.Msg())
return fmt.Sprintf("错误码: %d, 错误信息: %s", e.StatusCode(), e.Msg())
}
func (e *Error) Code() int {
func (e *Error) StatusCode() int {
return e.code
}
@ -78,27 +82,26 @@ func (e *Error) WithDetails(details ...string) *Error {
return &newError
}
func (e *Error) StatusCode() int {
switch e.Code() {
case Success.Code():
func HttpStatusCode(e mir.Error) int {
switch e.StatusCode() {
case Success.StatusCode():
return http.StatusOK
case ServerError.Code():
case ServerError.StatusCode():
return http.StatusInternalServerError
case InvalidParams.Code():
case InvalidParams.StatusCode():
return http.StatusBadRequest
case UnauthorizedAuthNotExist.Code():
case UnauthorizedAuthNotExist.StatusCode():
fallthrough
case UnauthorizedAuthFailed.Code():
case UnauthorizedAuthFailed.StatusCode():
fallthrough
case UnauthorizedTokenError.Code():
case UnauthorizedTokenError.StatusCode():
fallthrough
case UnauthorizedTokenGenerate.Code():
case UnauthorizedTokenGenerate.StatusCode():
fallthrough
case UnauthorizedTokenTimeout.Code():
case UnauthorizedTokenTimeout.StatusCode():
return http.StatusUnauthorized
case TooManyRequests.Code():
case TooManyRequests.StatusCode():
return http.StatusTooManyRequests
}
return http.StatusInternalServerError
}

Loading…
Cancel
Save