hi-server/internal/logic/notify/alipayNotifyLogic.go
shanshanzhong ab38cd4943
Some checks failed
Build docker and publish / build (20.15.1) (push) Failing after 4m44s
x
2026-04-26 21:12:22 -07:00

117 lines
4.1 KiB
Go

package notify
import (
"context"
"encoding/json"
"fmt"
"net/http"
commonLogic "github.com/perfect-panel/server/internal/logic/common"
"github.com/perfect-panel/server/pkg/constant"
"github.com/perfect-panel/server/pkg/xerr"
"github.com/pkg/errors"
"github.com/hibiken/asynq"
"github.com/perfect-panel/server/internal/model/payment"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/payment/alipay"
"github.com/perfect-panel/server/queue/types"
)
type AlipayNotifyLogic struct {
logger.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// Alipay notify
func NewAlipayNotifyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AlipayNotifyLogic {
return &AlipayNotifyLogic{
Logger: logger.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AlipayNotifyLogic) AlipayNotify(r *http.Request) error {
data, ok := l.ctx.Value(constant.CtxKeyPayment).(*payment.Payment)
if !ok {
return fmt.Errorf("payment config not found")
}
var config payment.AlipayF2FConfig
if err := json.Unmarshal([]byte(data.Config), &config); err != nil {
l.Logger.Error("[AlipayNotify] Unmarshal config failed", logger.Field("error", err.Error()))
return err
}
client := alipay.NewClient(alipay.Config{
AppId: config.AppId,
PrivateKey: config.PrivateKey,
PublicKey: config.PublicKey,
InvoiceName: config.InvoiceName,
NotifyURL: data.Domain + "/v1/payment/alipay/notify",
})
notify, err := client.DecodeNotification(r.Form)
if err != nil {
l.Logger.Error("[AlipayNotify] Decode notification failed", logger.Field("error", err.Error()))
return err
}
commonLogic.SubscriptionTraceInfo(l.Logger, commonLogic.SubscriptionTraceFlowOrder, "payment_notify_received",
"[SubscriptionFlow] alipay notify received",
logger.Field("order_no", notify.OrderNo),
logger.Field("payment_platform", data.Platform),
logger.Field("notify_status", string(notify.Status)),
)
if notify.Status == alipay.Success {
orderInfo, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, notify.OrderNo)
if err != nil {
l.Logger.Error("[AlipayNotify] Find order failed", logger.Field("error", err.Error()), logger.Field("orderNo", notify.OrderNo))
return errors.Wrapf(xerr.NewErrCode(xerr.OrderNotExist), "order not exist: %v", notify.OrderNo)
}
if orderInfo.Status == 5 {
return nil
}
// Update order status
err = l.svcCtx.OrderModel.UpdateOrderStatus(l.ctx, notify.OrderNo, 2)
if err != nil {
l.Logger.Error("[AlipayNotify] Update order status failed", logger.Field("error", err.Error()), logger.Field("orderNo", notify.OrderNo))
return err
}
commonLogic.SubscriptionTraceInfo(l.Logger, commonLogic.SubscriptionTraceFlowOrder, "payment_settled",
"[SubscriptionFlow] alipay notify marked order as paid",
append(commonLogic.OrderTraceFields(orderInfo),
logger.Field("payment_platform", data.Platform),
)...,
)
l.Logger.Info("[AlipayNotify] Notify status success", logger.Field("orderNo", notify.OrderNo))
payload := types.ForthwithActivateOrderPayload{
OrderNo: notify.OrderNo,
}
bytes, err := json.Marshal(&payload)
if err != nil {
l.Logger.Error("[AlipayNotify] Marshal payload failed", logger.Field("error", err.Error()))
return err
}
task := asynq.NewTask(types.ForthwithActivateOrder, bytes, asynq.MaxRetry(5))
taskInfo, err := l.svcCtx.Queue.EnqueueContext(l.ctx, task)
if err != nil {
l.Logger.Error("[AlipayNotify] Enqueue task failed", logger.Field("error", err.Error()))
return err
}
commonLogic.SubscriptionTraceInfo(l.Logger, commonLogic.SubscriptionTraceFlowOrder, "activation_task_enqueued",
"[SubscriptionFlow] activation task enqueued from alipay notify",
append(commonLogic.OrderTraceFields(orderInfo),
logger.Field("payment_platform", data.Platform),
logger.Field("queue_task_id", taskInfo.ID),
)...,
)
l.Logger.Info("[AlipayNotify] Enqueue task success", logger.Field("taskInfo", taskInfo))
} else {
l.Logger.Error("[AlipayNotify] Notify status failed", logger.Field("status", string(notify.Status)))
}
return nil
}