git-subtree-dir: server git-subtree-mainline:c4e617ada7git-subtree-split:e64421295f
95 lines
3.5 KiB
Go
95 lines
3.5 KiB
Go
package dao
|
|
|
|
import (
|
|
"context"
|
|
|
|
"slogan-agent/styleagent/consts"
|
|
"slogan-agent/styleagent/model/entity"
|
|
|
|
"github.com/gogf/gf/v2/database/gdb"
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
)
|
|
|
|
var PaymentOrder = &paymentOrderDao{}
|
|
|
|
type paymentOrderDao struct{}
|
|
|
|
func init() {
|
|
ctx := context.Background()
|
|
_, err := dbPay().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)
|
|
}
|
|
if _, err := dbPay().Exec(ctx, `CREATE INDEX IF NOT EXISTS idx_payment_order_user ON `+consts.TableNamePaymentOrder+`(user_id, created_at)`); err != nil {
|
|
g.Log().Warningf(ctx, "create index idx_payment_order_user failed: %v", err)
|
|
}
|
|
}
|
|
|
|
func (d *paymentOrderDao) Insert(ctx context.Context, order *entity.PaymentOrder) (int64, error) {
|
|
r, err := dbPay().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 := dbPay().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 := dbPay().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
|
|
}
|
|
|
|
// ===== 事务版本(HandlePaidNotify 回调流程使用,保证订单状态与会员开通原子) =====
|
|
|
|
func (d *paymentOrderDao) GetByOrderNoTx(ctx context.Context, tx gdb.TX, orderNo string) (*entity.PaymentOrder, error) {
|
|
var o *entity.PaymentOrder
|
|
err := tx.Model(consts.TableNamePaymentOrder).Ctx(ctx).Where("order_no", orderNo).Scan(&o)
|
|
return o, err
|
|
}
|
|
|
|
func (d *paymentOrderDao) MarkPaidTx(ctx context.Context, tx gdb.TX, orderNo, tradeNo, notifyRaw string) (bool, error) {
|
|
r, err := tx.Ctx(ctx).Exec(
|
|
"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 := dbPay().Model(consts.TableNamePaymentOrder).Ctx(ctx).
|
|
Where("user_id", userId).OrderDesc("id").Limit(20).Scan(&list)
|
|
return list, err
|
|
}
|