281 lines
7.7 KiB
Go
281 lines
7.7 KiB
Go
package paymentconfig
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"hfb_sys/backend/internal/middleware"
|
|
"hfb_sys/backend/pkg/response"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type Handler struct {
|
|
service *Service
|
|
}
|
|
|
|
func NewHandler(service *Service) *Handler {
|
|
return &Handler{service: service}
|
|
}
|
|
|
|
// List 获取支付配置列表
|
|
// @Summary 获取支付配置列表
|
|
// @Tags 管理后台-支付配置
|
|
// @Param provider query string false "支付服务商"
|
|
// @Param status query string false "状态"
|
|
// @Param environment query string false "环境"
|
|
// @Param page query int false "页码"
|
|
// @Param page_size query int false "每页数量"
|
|
// @Success 200 {object} response.Response{data=ListResponse}
|
|
// @Router /admin/payment-configs [get]
|
|
func (h *Handler) List(c *gin.Context) {
|
|
var query ListQuery
|
|
if err := c.ShouldBindQuery(&query); err != nil {
|
|
response.BadRequest(c, "参数错误")
|
|
return
|
|
}
|
|
|
|
resp, err := h.service.List(query)
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "internal_error", "查询失败")
|
|
return
|
|
}
|
|
|
|
response.OK(c, resp)
|
|
}
|
|
|
|
// Get 获取单个支付配置
|
|
// @Summary 获取单个支付配置
|
|
// @Tags 管理后台-支付配置
|
|
// @Param id path int true "配置ID"
|
|
// @Param include_secret query bool false "是否包含密钥"
|
|
// @Success 200 {object} response.Response{data=ConfigDTO}
|
|
// @Router /admin/payment-configs/{id} [get]
|
|
func (h *Handler) Get(c *gin.Context) {
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
response.BadRequest(c, "无效的ID")
|
|
return
|
|
}
|
|
|
|
includeSecret := c.Query("include_secret") == "true"
|
|
|
|
config, err := h.service.Get(id, includeSecret)
|
|
if err == ErrConfigNotFound {
|
|
response.NotFound(c, "配置不存在")
|
|
return
|
|
}
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "internal_error", "查询失败")
|
|
return
|
|
}
|
|
|
|
response.OK(c, config)
|
|
}
|
|
|
|
// ExportBackup 导出支付配置备份
|
|
// @Summary 导出支付配置备份
|
|
// @Tags 管理后台-支付配置
|
|
// @Success 200 {file} file "支付配置备份 JSON"
|
|
// @Router /admin/payment-configs/export [get]
|
|
func (h *Handler) ExportBackup(c *gin.Context) {
|
|
adminID, ok := currentAdminID(c)
|
|
if !ok {
|
|
response.Unauthorized(c, "未授权")
|
|
return
|
|
}
|
|
|
|
backup, err := h.service.ExportBackup(adminID, auditMeta(c))
|
|
if err == ErrDecryptionFailed {
|
|
response.Error(c, http.StatusInternalServerError, "decrypt_failed", "密钥解密失败")
|
|
return
|
|
}
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "internal_error", "导出失败")
|
|
return
|
|
}
|
|
|
|
data, err := json.MarshalIndent(backup, "", " ")
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "internal_error", "导出失败")
|
|
return
|
|
}
|
|
|
|
filename := "payment-config-backup-" + time.Now().Format("20060102-150405") + ".json"
|
|
contentType := "application/json; charset=utf-8"
|
|
c.Header("Content-Disposition", `attachment; filename="`+filename+`"`)
|
|
c.Data(http.StatusOK, contentType, data)
|
|
}
|
|
|
|
// ImportBackup 导入支付配置备份
|
|
// @Summary 导入支付配置备份
|
|
// @Tags 管理后台-支付配置
|
|
// @Param body body ExportBackup true "支付配置备份 JSON"
|
|
// @Success 200 {object} response.Response{data=ImportBackupResult}
|
|
// @Router /admin/payment-configs/import [post]
|
|
func (h *Handler) ImportBackup(c *gin.Context) {
|
|
adminID, ok := currentAdminID(c)
|
|
if !ok {
|
|
response.Unauthorized(c, "未授权")
|
|
return
|
|
}
|
|
|
|
var backup ExportBackup
|
|
if err := c.ShouldBindJSON(&backup); err != nil {
|
|
response.BadRequest(c, "备份文件格式错误")
|
|
return
|
|
}
|
|
|
|
result, err := h.service.ImportBackup(backup, adminID, auditMeta(c))
|
|
if err == ErrInvalidBackup || err == ErrEmptyBackup || err == ErrInvalidProvider ||
|
|
err == ErrNameRequired || err == ErrMerchantIDRequired || err == ErrGatewayURLRequired ||
|
|
err == ErrSignKeyRequired || err == ErrNotifyKeyRequired || err == ErrNotifyURLRequired ||
|
|
err == ErrInvalidSignType || err == ErrInvalidStatus || err == ErrAppIDRequired ||
|
|
err == ErrSerialNoRequired || err == ErrTermNoRequired {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
if err == ErrEncryptionFailed {
|
|
response.Error(c, http.StatusInternalServerError, "encrypt_failed", "密钥加密失败")
|
|
return
|
|
}
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "internal_error", "导入失败")
|
|
return
|
|
}
|
|
|
|
response.OK(c, result)
|
|
}
|
|
|
|
// Create 创建支付配置
|
|
// @Summary 创建支付配置
|
|
// @Tags 管理后台-支付配置
|
|
// @Param body body CreateRequest true "创建请求"
|
|
// @Success 200 {object} response.Response{data=ConfigDTO}
|
|
// @Router /admin/payment-configs [post]
|
|
func (h *Handler) Create(c *gin.Context) {
|
|
adminID, ok := currentAdminID(c)
|
|
if !ok {
|
|
response.Unauthorized(c, "未授权")
|
|
return
|
|
}
|
|
|
|
var req CreateRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "参数错误: "+err.Error())
|
|
return
|
|
}
|
|
|
|
config, err := h.service.Create(req, adminID, auditMeta(c))
|
|
if err == ErrNameRequired || err == ErrMerchantIDRequired || err == ErrGatewayURLRequired ||
|
|
err == ErrSignKeyRequired || err == ErrNotifyKeyRequired || err == ErrInvalidProvider ||
|
|
err == ErrNotifyURLRequired || err == ErrInvalidSignType || err == ErrAppIDRequired ||
|
|
err == ErrInvalidStatus || err == ErrSerialNoRequired || err == ErrTermNoRequired {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "internal_error", "创建失败")
|
|
return
|
|
}
|
|
|
|
response.OK(c, config)
|
|
}
|
|
|
|
// Update 更新支付配置
|
|
// @Summary 更新支付配置
|
|
// @Tags 管理后台-支付配置
|
|
// @Param id path int true "配置ID"
|
|
// @Param body body UpdateRequest true "更新请求"
|
|
// @Success 200 {object} response.Response{data=ConfigDTO}
|
|
// @Router /admin/payment-configs/{id} [put]
|
|
func (h *Handler) Update(c *gin.Context) {
|
|
adminID, ok := currentAdminID(c)
|
|
if !ok {
|
|
response.Unauthorized(c, "未授权")
|
|
return
|
|
}
|
|
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
response.BadRequest(c, "无效的ID")
|
|
return
|
|
}
|
|
|
|
var req UpdateRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "参数错误: "+err.Error())
|
|
return
|
|
}
|
|
|
|
config, err := h.service.Update(id, req, adminID, auditMeta(c))
|
|
if err == ErrConfigNotFound {
|
|
response.NotFound(c, "配置不存在")
|
|
return
|
|
}
|
|
if err == ErrInvalidSignType || err == ErrInvalidStatus || err == ErrNotifyURLRequired {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "internal_error", "更新失败")
|
|
return
|
|
}
|
|
|
|
response.OK(c, config)
|
|
}
|
|
|
|
// Delete 删除支付配置
|
|
// @Summary 删除支付配置
|
|
// @Tags 管理后台-支付配置
|
|
// @Param id path int true "配置ID"
|
|
// @Success 200 {object} response.Response
|
|
// @Router /admin/payment-configs/{id} [delete]
|
|
func (h *Handler) Delete(c *gin.Context) {
|
|
adminID, ok := currentAdminID(c)
|
|
if !ok {
|
|
response.Unauthorized(c, "未授权")
|
|
return
|
|
}
|
|
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
response.BadRequest(c, "无效的ID")
|
|
return
|
|
}
|
|
|
|
err = h.service.Delete(id, adminID, auditMeta(c))
|
|
if err == ErrConfigNotFound {
|
|
response.NotFound(c, "配置不存在")
|
|
return
|
|
}
|
|
if err == ErrCannotDeleteInUse {
|
|
response.BadRequest(c, "配置正在使用中,无法删除")
|
|
return
|
|
}
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "internal_error", "删除失败")
|
|
return
|
|
}
|
|
|
|
response.OK(c, gin.H{"message": "删除成功"})
|
|
}
|
|
|
|
func currentAdminID(c *gin.Context) (uint64, bool) {
|
|
val, exists := c.Get(middleware.ContextAdminID)
|
|
if !exists {
|
|
return 0, false
|
|
}
|
|
id, ok := val.(uint64)
|
|
return id, ok
|
|
}
|
|
|
|
func auditMeta(c *gin.Context) AuditMeta {
|
|
return AuditMeta{
|
|
IP: c.ClientIP(),
|
|
UserAgent: c.Request.UserAgent(),
|
|
}
|
|
}
|