feat: 会员接口(套餐/状态/下单/回调)+ 支付配置
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
commonHttp "slogan-agent/common"
|
||||
"slogan-agent/styleagent/dao"
|
||||
"slogan-agent/styleagent/model/dto"
|
||||
"slogan-agent/styleagent/model/entity"
|
||||
"slogan-agent/styleagent/payment"
|
||||
"slogan-agent/styleagent/service"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
type member struct{}
|
||||
|
||||
var Member = new(member)
|
||||
|
||||
// PlanList 会员套餐列表
|
||||
func (c *member) PlanList(ctx context.Context, req *dto.MemberPlanListReq) (res *dto.MemberPlanListRes, err error) {
|
||||
list, err := service.MemberService.PlanList(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.MemberPlanListRes{List: list}, nil
|
||||
}
|
||||
|
||||
// Status 我的会员状态
|
||||
func (c *member) Status(ctx context.Context, req *dto.MemberStatusReq) (res *dto.MemberStatusRes, err error) {
|
||||
st, err := service.MemberService.Status(ctx, commonHttp.GetUserId(g.RequestFromCtx(ctx)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.MemberStatusRes{
|
||||
IsVip: st.IsVip, ExpireAt: st.ExpireAt, PlanName: st.PlanName, Benefits: st.Benefits,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// OrderCreate 下单 → 返回支付 URL
|
||||
func (c *member) OrderCreate(ctx context.Context, req *dto.MemberOrderCreateReq) (res *dto.MemberOrderCreateRes, err error) {
|
||||
order, payURL, err := service.MemberService.CreateOrder(ctx, commonHttp.GetUserId(g.RequestFromCtx(ctx)), req.PlanId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.MemberOrderCreateRes{OrderNo: order.OrderNo, PayUrl: payURL}, nil
|
||||
}
|
||||
|
||||
// OrderStatus 订单状态(App 轮询)
|
||||
func (c *member) OrderStatus(ctx context.Context, req *dto.MemberOrderStatusReq) (res *dto.MemberOrderStatusRes, err error) {
|
||||
order, err := service.MemberService.OrderStatus(ctx, req.OrderNo)
|
||||
if err != nil || order == nil {
|
||||
return nil, errors.New("订单不存在")
|
||||
}
|
||||
paidAt := ""
|
||||
if order.PaidAt != nil {
|
||||
paidAt = order.PaidAt.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
return &dto.MemberOrderStatusRes{Status: order.Status, TradeNo: order.TradeNo, PaidAt: paidAt}, nil
|
||||
}
|
||||
|
||||
// MemberNotify 虎皮棋支付回调:验签 → 幂等开通 → 返回裸文本 "success"
|
||||
// 虎皮棋要求回调响应体为字面 "success",故不走统一 JSON 包装
|
||||
func MemberNotify(r *ghttp.Request) {
|
||||
ctx := r.Context()
|
||||
body := r.GetBodyString()
|
||||
hash := r.Get("hash").String()
|
||||
orderNo := r.Get("trade_order_id").String()
|
||||
remoteIP := r.GetClientIp()
|
||||
|
||||
params := make(map[string]string)
|
||||
for k, v := range r.GetRequestMap() {
|
||||
params[k] = fmt.Sprint(v)
|
||||
}
|
||||
ok := payment.VerifyNotify(params, hash, g.Cfg().MustGet(ctx, "payment.xunhu_appsecret", "").String())
|
||||
|
||||
if !ok {
|
||||
_ = dao.PayNotifyLog.Insert(ctx, &entity.PayNotifyLog{
|
||||
OrderNo: orderNo, Body: body, Sign: hash, RemoteIp: remoteIP, Status: "bad_sign",
|
||||
})
|
||||
r.Response.Write("fail")
|
||||
r.ExitAll()
|
||||
return
|
||||
}
|
||||
|
||||
state, err := service.MemberService.HandlePaidNotify(ctx, orderNo, r.Get("transaction_id").String(), body)
|
||||
_ = dao.PayNotifyLog.Insert(ctx, &entity.PayNotifyLog{
|
||||
OrderNo: orderNo, Body: body, Sign: hash, RemoteIp: remoteIP, Status: state,
|
||||
})
|
||||
if err != nil || state != "ok" {
|
||||
r.Response.Write("fail")
|
||||
r.ExitAll()
|
||||
return
|
||||
}
|
||||
r.Response.Write("success")
|
||||
r.ExitAll()
|
||||
}
|
||||
Reference in New Issue
Block a user