mir: add alipay api implement for new web service

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

@ -8,29 +8,32 @@ import (
"github.com/alimy/mir/v3" "github.com/alimy/mir/v3"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web" "github.com/rocboss/paopao-ce/internal/model/web"
"github.com/rocboss/paopao-ce/internal/servants/base"
) )
type AlipayPriv interface { type AlipayPriv interface {
// Chain provide handlers chain for gin // Chain provide handlers chain for gin
Chain() gin.HandlersChain Chain() gin.HandlersChain
UserWalletBills(*web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) UserWalletBills(*web.UserWalletBillsReq) (*base.PageResp, mir.Error)
UserRechargeResult() mir.Error UserRechargeResult(*web.UserRechargeResultReq) (*web.UserRechargeResultResp, mir.Error)
UserRechargeLink() mir.Error UserRechargeLink(*web.UserRechargeLinkReq) (*web.UserRechargeLinkResp, mir.Error)
mustEmbedUnimplementedAlipayPrivServant() mustEmbedUnimplementedAlipayPrivServant()
} }
type AlipayPrivBinding interface { type AlipayPrivBinding interface {
BindUserWalletBills(*gin.Context) (*web.UserWalletBillsReq, mir.Error) BindUserWalletBills(*gin.Context) (*web.UserWalletBillsReq, mir.Error)
BindUserRechargeResult(*gin.Context) (*web.UserRechargeResultReq, mir.Error)
BindUserRechargeLink(*gin.Context) (*web.UserRechargeLinkReq, mir.Error)
mustEmbedUnimplementedAlipayPrivBinding() mustEmbedUnimplementedAlipayPrivBinding()
} }
type AlipayPrivRender interface { type AlipayPrivRender interface {
RenderUserWalletBills(*gin.Context, *web.UserWalletBillsResp, mir.Error) RenderUserWalletBills(*gin.Context, *base.PageResp, mir.Error)
RenderUserRechargeResult(*gin.Context, mir.Error) RenderUserRechargeResult(*gin.Context, *web.UserRechargeResultResp, mir.Error)
RenderUserRechargeLink(*gin.Context, mir.Error) RenderUserRechargeLink(*gin.Context, *web.UserRechargeLinkResp, mir.Error)
mustEmbedUnimplementedAlipayPrivRender() mustEmbedUnimplementedAlipayPrivRender()
} }
@ -66,7 +69,13 @@ func RegisterAlipayPrivServant(e *gin.Engine, s AlipayPriv, b AlipayPrivBinding,
default: default:
} }
r.RenderUserRechargeResult(c, s.UserRechargeResult()) req, err := b.BindUserRechargeResult(c)
if err != nil {
r.RenderUserRechargeResult(c, nil, err)
return
}
resp, err := s.UserRechargeResult(req)
r.RenderUserRechargeResult(c, resp, err)
}) })
router.Handle("POST", "/user/recharge", func(c *gin.Context) { router.Handle("POST", "/user/recharge", func(c *gin.Context) {
@ -76,7 +85,13 @@ func RegisterAlipayPrivServant(e *gin.Engine, s AlipayPriv, b AlipayPrivBinding,
default: default:
} }
r.RenderUserRechargeLink(c, s.UserRechargeLink()) req, err := b.BindUserRechargeLink(c)
if err != nil {
r.RenderUserRechargeLink(c, nil, err)
return
}
resp, err := s.UserRechargeLink(req)
r.RenderUserRechargeLink(c, resp, err)
}) })
} }
@ -89,16 +104,16 @@ func (UnimplementedAlipayPrivServant) Chain() gin.HandlersChain {
return nil return nil
} }
func (UnimplementedAlipayPrivServant) UserWalletBills(req *web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) { func (UnimplementedAlipayPrivServant) UserWalletBills(req *web.UserWalletBillsReq) (*base.PageResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
func (UnimplementedAlipayPrivServant) UserRechargeResult() mir.Error { func (UnimplementedAlipayPrivServant) UserRechargeResult(req *web.UserRechargeResultReq) (*web.UserRechargeResultResp, mir.Error) {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
func (UnimplementedAlipayPrivServant) UserRechargeLink() mir.Error { func (UnimplementedAlipayPrivServant) UserRechargeLink(req *web.UserRechargeLinkReq) (*web.UserRechargeLinkResp, mir.Error) {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
func (UnimplementedAlipayPrivServant) mustEmbedUnimplementedAlipayPrivServant() {} func (UnimplementedAlipayPrivServant) mustEmbedUnimplementedAlipayPrivServant() {}
@ -108,16 +123,16 @@ type UnimplementedAlipayPrivRender struct {
RenderAny func(*gin.Context, any, mir.Error) RenderAny func(*gin.Context, any, mir.Error)
} }
func (r *UnimplementedAlipayPrivRender) RenderUserWalletBills(c *gin.Context, data *web.UserWalletBillsResp, err mir.Error) { func (r *UnimplementedAlipayPrivRender) RenderUserWalletBills(c *gin.Context, data *base.PageResp, err mir.Error) {
r.RenderAny(c, data, err) r.RenderAny(c, data, err)
} }
func (r *UnimplementedAlipayPrivRender) RenderUserRechargeResult(c *gin.Context, err mir.Error) { func (r *UnimplementedAlipayPrivRender) RenderUserRechargeResult(c *gin.Context, data *web.UserRechargeResultResp, err mir.Error) {
r.RenderAny(c, nil, err) r.RenderAny(c, data, err)
} }
func (r *UnimplementedAlipayPrivRender) RenderUserRechargeLink(c *gin.Context, err mir.Error) { func (r *UnimplementedAlipayPrivRender) RenderUserRechargeLink(c *gin.Context, data *web.UserRechargeLinkResp, err mir.Error) {
r.RenderAny(c, nil, err) r.RenderAny(c, data, err)
} }
func (r *UnimplementedAlipayPrivRender) mustEmbedUnimplementedAlipayPrivRender() {} func (r *UnimplementedAlipayPrivRender) mustEmbedUnimplementedAlipayPrivRender() {}
@ -133,4 +148,16 @@ func (b *UnimplementedAlipayPrivBinding) BindUserWalletBills(c *gin.Context) (*w
return obj, err return obj, err
} }
func (b *UnimplementedAlipayPrivBinding) BindUserRechargeResult(c *gin.Context) (*web.UserRechargeResultReq, mir.Error) {
obj := new(web.UserRechargeResultReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAlipayPrivBinding) BindUserRechargeLink(c *gin.Context) (*web.UserRechargeLinkReq, mir.Error) {
obj := new(web.UserRechargeLinkReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAlipayPrivBinding) mustEmbedUnimplementedAlipayPrivBinding() {} func (b *UnimplementedAlipayPrivBinding) mustEmbedUnimplementedAlipayPrivBinding() {}

@ -36,7 +36,6 @@ type Core interface {
type CoreBinding interface { type CoreBinding interface {
BindChangeAvatar(*gin.Context) (*web.ChangeAvatarReq, mir.Error) BindChangeAvatar(*gin.Context) (*web.ChangeAvatarReq, mir.Error)
BindGetUserInfo(*gin.Context) (*web.UserInfoReq, mir.Error) BindGetUserInfo(*gin.Context) (*web.UserInfoReq, mir.Error)
mustEmbedUnimplementedCoreBinding() mustEmbedUnimplementedCoreBinding()

@ -6,7 +6,7 @@ require (
github.com/Masterminds/semver/v3 v3.1.1 github.com/Masterminds/semver/v3 v3.1.1
github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868
github.com/alimy/cfg v0.3.0 github.com/alimy/cfg v0.3.0
github.com/alimy/mir/v3 v3.0.0-beta.2 github.com/alimy/mir/v3 v3.0.0-beta.3
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible
github.com/allegro/bigcache/v3 v3.0.2 github.com/allegro/bigcache/v3 v3.0.2
github.com/bytedance/sonic v1.5.0 github.com/bytedance/sonic v1.5.0

@ -147,8 +147,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C
github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk=
github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY= github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY=
github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c=
github.com/alimy/mir/v3 v3.0.0-beta.2 h1:qpg0l4FEUafkpzGXlBIJtJbFjQfzbK9lDP5FJjjgOrA= github.com/alimy/mir/v3 v3.0.0-beta.3 h1:b+2C9rvZg2ssZ0+gMUf9aYwhuJFKExO611ybXRP+/30=
github.com/alimy/mir/v3 v3.0.0-beta.2/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/alimy/mir/v3 v3.0.0-beta.3/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU=
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM=
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=

@ -7,15 +7,37 @@ package web
import ( import (
"context" "context"
"github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/smartwalle/alipay/v3" "github.com/smartwalle/alipay/v3"
) )
type UserWalletBillsReq struct { type UserWalletBillsReq struct {
*BaseInfo `json:"-" binding:"-"` UserId int64
Page int
PageSize int
} }
type UserWalletBillsResp struct { type UserWalletBillsResp = base.PageResp
// TODO
type UserRechargeLinkReq struct {
*BaseInfo `json:"-" form:"-" binding:"-"`
Host string `json:"-" form:"-" binding:"-"`
Amount int64 `json:"amount" form:"amount" binding:"required"`
}
type UserRechargeLinkResp struct {
Id int64 `json:"id"`
Pay string `json:"pay"`
}
type UserRechargeResultReq struct {
UserId int64
Id int64
}
type UserRechargeResultResp struct {
Id int64 `json:"id"`
Status string `json:"status"`
} }
type AlipayNotifyReq struct { type AlipayNotifyReq struct {

@ -49,6 +49,14 @@ func UserFrom(c *gin.Context) (*core.User, bool) {
return nil, false return nil, false
} }
func UserIdFrom(c *gin.Context) (int64, bool) {
if u, exists := c.Get("UID"); exists {
uid, ok := u.(int64)
return uid, ok
}
return -1, false
}
func BindAny(c *gin.Context, obj any) mir.Error { func BindAny(c *gin.Context, obj any) mir.Error {
var errs xerror.ValidErrors var errs xerror.ValidErrors
err := c.ShouldBind(obj) err := c.ShouldBind(obj)
@ -57,7 +65,10 @@ func BindAny(c *gin.Context, obj any) mir.Error {
} }
// setup *core.User if needed // setup *core.User if needed
if setter, ok := obj.(UserSetter); ok { if setter, ok := obj.(UserSetter); ok {
user, _ := UserFrom(c) user, exist := UserFrom(c)
if !exist {
return xerror.UnauthorizedTokenError
}
setter.SetUser(user) setter.SetUser(user)
} }
return nil return nil

@ -0,0 +1,27 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package base
type Pager struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
TotalRows int64 `json:"total_rows"`
}
type PageResp struct {
List any `json:"list"`
Pager Pager `json:"pager"`
}
func PageRespFrom(list any, page int, pageSize int, totalRows int64) *PageResp {
return &PageResp{
List: list,
Pager: Pager{
Page: page,
PageSize: pageSize,
TotalRows: totalRows,
},
}
}

@ -5,6 +5,7 @@
package web package web
import ( import (
"fmt"
"time" "time"
"github.com/alimy/mir/v3" "github.com/alimy/mir/v3"
@ -13,7 +14,9 @@ import (
"github.com/rocboss/paopao-ce/internal/model/web" "github.com/rocboss/paopao-ce/internal/model/web"
"github.com/rocboss/paopao-ce/internal/servants/base" "github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/rocboss/paopao-ce/internal/servants/chain" "github.com/rocboss/paopao-ce/internal/servants/chain"
"github.com/rocboss/paopao-ce/pkg/app"
"github.com/rocboss/paopao-ce/pkg/convert" "github.com/rocboss/paopao-ce/pkg/convert"
"github.com/rocboss/paopao-ce/pkg/xerror"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/smartwalle/alipay/v3" "github.com/smartwalle/alipay/v3"
) )
@ -44,6 +47,9 @@ type alipayPubRender struct {
type alipayPrivSrv struct { type alipayPrivSrv struct {
api.UnimplementedAlipayPrivServant api.UnimplementedAlipayPrivServant
*base.DaoServant
alipayClient *alipay.Client
} }
type alipayPrivBinding struct { type alipayPrivBinding struct {
@ -94,10 +100,97 @@ func (s *alipayPubSrv) AlipayNotify(req *web.AlipayNotifyReq) mir.Error {
return nil return nil
} }
func (b *alipayPrivBinding) BindUserWalletBills(c *gin.Context) (*web.UserWalletBillsReq, mir.Error) {
uid, ok := base.UserIdFrom(c)
if !ok {
return nil, xerror.UnauthorizedTokenError
}
page, pageSize := app.GetPageOffset(c)
return &web.UserWalletBillsReq{
UserId: uid,
Page: page,
PageSize: pageSize,
}, nil
}
func (b *alipayPrivBinding) BindUserRechargeLink(c *gin.Context) (*web.UserRechargeLinkReq, mir.Error) {
v := &web.UserRechargeLinkReq{
Host: c.Request.Host,
}
err := b.BindAny(c, v)
return v, err
}
func (b *alipayPrivBinding) BindUserRechargeResult(c *gin.Context) (*web.UserRechargeResultReq, mir.Error) {
uid, exist := base.UserIdFrom(c)
if !exist {
return nil, xerror.UnauthorizedTokenError
}
return &web.UserRechargeResultReq{
UserId: uid,
Id: convert.StrTo(c.Query("id")).MustInt64(),
}, nil
}
func (s *alipayPrivSrv) Chain() gin.HandlersChain { func (s *alipayPrivSrv) Chain() gin.HandlersChain {
return gin.HandlersChain{chain.JWT()} return gin.HandlersChain{chain.JWT()}
} }
func (s *alipayPrivSrv) UserWalletBills(req *web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) {
bills, err := s.Ds.GetUserWalletBills(req.UserId, (req.Page-1)*req.PageSize, req.PageSize)
if err != nil {
logrus.Errorf("GetUserWalletBills err: %s", err)
return nil, _errUserWalletBillsFailed
}
totalRows, err := s.Ds.GetUserWalletBillCount(req.UserId)
if err != nil {
logrus.Errorf("GetUserWalletBillCount err: %s", err)
return nil, _errUserWalletBillsFailed
}
return base.PageRespFrom(bills, req.Page, req.PageSize, totalRows), nil
}
func (s *alipayPrivSrv) UserRechargeLink(req *web.UserRechargeLinkReq) (*web.UserRechargeLinkResp, mir.Error) {
recharge, err := s.Ds.CreateRecharge(req.User.ID, req.Amount)
if err != nil {
logrus.Errorf("Ds.CreateRecharge err: %v", err)
return nil, _errRechargeReqFail
}
p := alipay.TradePreCreate{}
p.OutTradeNo = fmt.Sprintf("%d", recharge.ID)
p.Subject = "PaoPao用户钱包充值"
p.TotalAmount = fmt.Sprintf("%.2f", float64(recharge.Amount)/100.0)
p.NotifyURL = "https://" + req.Host + "/v1/alipay/notify"
rsp, err := s.alipayClient.TradePreCreate(p)
if err != nil {
logrus.Errorf("client.TradePreCreate err: %v\n", err)
return nil, _errRechargeReqFail
}
if rsp.Content.Code != alipay.CodeSuccess {
return nil, _errRechargeReqFail
}
return &web.UserRechargeLinkResp{
Id: recharge.ID,
Pay: rsp.Content.QRCode,
}, nil
}
func (s *alipayPrivSrv) UserRechargeResult(req *web.UserRechargeResultReq) (*web.UserRechargeResultResp, mir.Error) {
recharge, err := s.Ds.GetRechargeByID(req.Id)
if err != nil {
logrus.Errorf("Ds.GetRechargeByID err: %v", err)
return nil, _errGetRechargeFailed
}
if recharge.UserID != req.UserId {
logrus.Errorf("Ds.GetRechargeByID userId not equel recharge.UserID: %d req.UserId %d", recharge.UserID, req.UserId)
return nil, _errGetRechargeFailed
}
return &web.UserRechargeResultResp{
Id: recharge.ID,
Status: recharge.TradeStatus,
}, nil
}
func newAlipayPubSrv(s *base.DaoServant) api.AlipayPub { func newAlipayPubSrv(s *base.DaoServant) api.AlipayPub {
return &alipayPubSrv{ return &alipayPubSrv{
DaoServant: s, DaoServant: s,
@ -121,8 +214,11 @@ func newAlipayPubRender() api.AlipayPubRender {
} }
} }
func newAlipayPrivSrv() api.AlipayPriv { func newAlipayPrivSrv(s *base.DaoServant, client *alipay.Client) api.AlipayPriv {
return &alipayPrivSrv{} return &alipayPrivSrv{
DaoServant: s,
alipayClient: client,
}
} }
func newAlipayPrivBinding() api.AlipayPrivBinding { func newAlipayPrivBinding() api.AlipayPrivBinding {

@ -34,7 +34,7 @@ func RouteWeb(e *gin.Engine) {
"Alipay": func() { "Alipay": func() {
client := mustAlipayClient() client := mustAlipayClient()
api.RegisterAlipayPubServant(e, newAlipayPubSrv(ds), newAlipayPubBinding(client), newAlipayPubRender()) api.RegisterAlipayPubServant(e, newAlipayPubSrv(ds), newAlipayPubBinding(client), newAlipayPubRender())
api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(), newAlipayPrivBinding(), newAlipayPrivRender()) api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(ds, client), newAlipayPrivBinding(), newAlipayPrivRender())
}, },
"Followship": func() { "Followship": func() {
api.RegisterFollowshipServant(e, newFollowshipSrv(), newFollowshipBinding(), newFollowshipRender()) api.RegisterFollowshipServant(e, newFollowshipSrv(), newFollowshipBinding(), newFollowshipRender())

@ -66,6 +66,7 @@ var (
_errRechargeReqFail = xerror.NewError(70001, "充值请求失败") _errRechargeReqFail = xerror.NewError(70001, "充值请求失败")
_errRechargeNotifyError = xerror.NewError(70002, "充值回调失败") _errRechargeNotifyError = xerror.NewError(70002, "充值回调失败")
_errGetRechargeFailed = xerror.NewError(70003, "充值详情获取失败") _errGetRechargeFailed = xerror.NewError(70003, "充值详情获取失败")
_errUserWalletBillsFailed = xerror.NewError(70004, "用户钱包账单获取失败")
_errNoRequestingFriendToSelf = xerror.NewError(80001, "不允许添加自己为好友") _errNoRequestingFriendToSelf = xerror.NewError(80001, "不允许添加自己为好友")
_errNotExistFriendId = xerror.NewError(80002, "好友id不存在") _errNotExistFriendId = xerror.NewError(80002, "好友id不存在")

@ -24,10 +24,10 @@ type AlipayPriv struct {
Group Group `mir:"v1"` Group Group `mir:"v1"`
// UserRechargeLink 用户充值 // UserRechargeLink 用户充值
UserRechargeLink func(Post) `mir:"/user/recharge"` UserRechargeLink func(Post, web.UserRechargeLinkReq) web.UserRechargeLinkResp `mir:"/user/recharge"`
// UserRechargeResult 获取钱包余额 // UserRechargeResult 获取充值结果
UserRechargeResult func(Get) `mir:"/user/recharge"` UserRechargeResult func(Get, web.UserRechargeResultReq) web.UserRechargeResultResp `mir:"/user/recharge"`
// UserWalletBills 获取用户账单 // UserWalletBills 获取用户账单
UserWalletBills func(Get, web.UserWalletBillsReq) web.UserWalletBillsResp `mir:"/user/wallet/bills"` UserWalletBills func(Get, web.UserWalletBillsReq) web.UserWalletBillsResp `mir:"/user/wallet/bills"`

Loading…
Cancel
Save