feat: 支付订单/会员/回调日志 DAO
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"slogan-agent/styleagent/consts"
|
||||
"slogan-agent/styleagent/model/entity"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
var PayNotifyLog = &payNotifyLogDao{}
|
||||
|
||||
type payNotifyLogDao struct{}
|
||||
|
||||
func init() {
|
||||
ctx := context.Background()
|
||||
_, err := g.DB().Exec(ctx, `CREATE TABLE IF NOT EXISTS `+consts.TableNamePayNotifyLog+` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
order_no TEXT NOT NULL DEFAULT '',
|
||||
body TEXT NOT NULL DEFAULT '',
|
||||
sign TEXT NOT NULL DEFAULT '',
|
||||
remote_ip TEXT NOT NULL DEFAULT '',
|
||||
status TEXT NOT NULL DEFAULT 'ok',
|
||||
created_at DATETIME DEFAULT (datetime('now','localtime'))
|
||||
)`)
|
||||
if err != nil {
|
||||
g.Log().Warningf(ctx, "create pay_notify_log table failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *payNotifyLogDao) Insert(ctx context.Context, log *entity.PayNotifyLog) error {
|
||||
_, err := g.DB().Model(consts.TableNamePayNotifyLog).Ctx(ctx).Data(g.Map{
|
||||
"order_no": log.OrderNo, "body": log.Body, "sign": log.Sign,
|
||||
"remote_ip": log.RemoteIp, "status": log.Status,
|
||||
}).Insert()
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"slogan-agent/styleagent/consts"
|
||||
"slogan-agent/styleagent/model/entity"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
var PaymentOrder = &paymentOrderDao{}
|
||||
|
||||
type paymentOrderDao struct{}
|
||||
|
||||
func init() {
|
||||
ctx := context.Background()
|
||||
_, err := g.DB().Exec(ctx, `CREATE TABLE IF NOT EXISTS `+consts.TableNamePaymentOrder+` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
order_no TEXT NOT NULL UNIQUE,
|
||||
user_id INTEGER NOT NULL DEFAULT 0,
|
||||
plan_id INTEGER NOT NULL DEFAULT 0,
|
||||
amount_fen INTEGER NOT NULL DEFAULT 0,
|
||||
channel TEXT NOT NULL DEFAULT '',
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
trade_no TEXT NOT NULL DEFAULT '',
|
||||
notify_raw TEXT NOT NULL DEFAULT '',
|
||||
paid_at DATETIME,
|
||||
created_at DATETIME DEFAULT (datetime('now','localtime'))
|
||||
)`)
|
||||
if err != nil {
|
||||
g.Log().Warningf(ctx, "create payment_order table failed: %v", err)
|
||||
}
|
||||
_, _ = g.DB().Exec(ctx, `CREATE INDEX IF NOT EXISTS idx_payment_order_user ON `+consts.TableNamePaymentOrder+`(user_id, created_at)`)
|
||||
}
|
||||
|
||||
func (d *paymentOrderDao) Insert(ctx context.Context, order *entity.PaymentOrder) (int64, error) {
|
||||
r, err := g.DB().Model(consts.TableNamePaymentOrder).Ctx(ctx).Data(g.Map{
|
||||
"order_no": order.OrderNo, "user_id": order.UserId, "plan_id": order.PlanId,
|
||||
"amount_fen": order.AmountFen, "channel": order.Channel, "status": order.Status,
|
||||
}).Insert()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return r.LastInsertId()
|
||||
}
|
||||
|
||||
func (d *paymentOrderDao) GetByOrderNo(ctx context.Context, orderNo string) (*entity.PaymentOrder, error) {
|
||||
var o *entity.PaymentOrder
|
||||
err := g.DB().Model(consts.TableNamePaymentOrder).Ctx(ctx).
|
||||
Where("order_no", orderNo).Scan(&o)
|
||||
return o, err
|
||||
}
|
||||
|
||||
// MarkPaid 状态机 pending→paid(只更新 pending 行,返回是否成功,回调并发安全)
|
||||
func (d *paymentOrderDao) MarkPaid(ctx context.Context, orderNo, tradeNo, notifyRaw string) (bool, error) {
|
||||
r, err := g.DB().Exec(ctx,
|
||||
"UPDATE "+consts.TableNamePaymentOrder+" SET status=?, trade_no=?, notify_raw=?, paid_at=datetime('now','localtime') WHERE order_no=? AND status=?",
|
||||
consts.PayStatusPaid, tradeNo, notifyRaw, orderNo, consts.PayStatusPending)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
n, _ := r.RowsAffected()
|
||||
return n > 0, nil
|
||||
}
|
||||
|
||||
func (d *paymentOrderDao) GetByUser(ctx context.Context, userId int64) ([]*entity.PaymentOrder, error) {
|
||||
var list []*entity.PaymentOrder
|
||||
err := g.DB().Model(consts.TableNamePaymentOrder).Ctx(ctx).
|
||||
Where("user_id", userId).OrderDesc("id").Limit(20).Scan(&list)
|
||||
return list, err
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"slogan-agent/styleagent/consts"
|
||||
"slogan-agent/styleagent/model/entity"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
var UserMember = &userMemberDao{}
|
||||
|
||||
type userMemberDao struct{}
|
||||
|
||||
func init() {
|
||||
ctx := context.Background()
|
||||
_, err := g.DB().Exec(ctx, `CREATE TABLE IF NOT EXISTS `+consts.TableNameUserMember+` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL UNIQUE,
|
||||
plan_id INTEGER NOT NULL DEFAULT 0,
|
||||
expire_at DATETIME,
|
||||
source TEXT NOT NULL DEFAULT 'vip_pay',
|
||||
created_at DATETIME DEFAULT (datetime('now','localtime')),
|
||||
updated_at DATETIME
|
||||
)`)
|
||||
if err != nil {
|
||||
g.Log().Warningf(ctx, "create user_member table failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *userMemberDao) GetByUser(ctx context.Context, userId int64) (*entity.UserMember, error) {
|
||||
var m *entity.UserMember
|
||||
err := g.DB().Model(consts.TableNameUserMember).Ctx(ctx).
|
||||
Where("user_id", userId).Scan(&m)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// Upsert 无则插入有则整体覆盖(expire_at 由 Service 算好传入)
|
||||
func (d *userMemberDao) Upsert(ctx context.Context, userId, planId int64, expireAt, source string) error {
|
||||
_, err := g.DB().Exec(ctx,
|
||||
"INSERT INTO "+consts.TableNameUserMember+" (user_id, plan_id, expire_at, source, created_at, updated_at) VALUES (?, ?, ?, ?, datetime('now','localtime'), datetime('now','localtime')) "+
|
||||
"ON CONFLICT(user_id) DO UPDATE SET plan_id=excluded.plan_id, expire_at=excluded.expire_at, source=excluded.source, updated_at=datetime('now','localtime')",
|
||||
userId, planId, expireAt, source)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsVip 当前是否会员(未过期)
|
||||
func (d *userMemberDao) IsVip(ctx context.Context, userId int64) bool {
|
||||
n, err := g.DB().Model(consts.TableNameUserMember).Ctx(ctx).
|
||||
Where("user_id", userId).Where("expire_at > datetime('now','localtime')").Count()
|
||||
return err == nil && n > 0
|
||||
}
|
||||
Reference in New Issue
Block a user