138 lines
3.8 KiB
Go
138 lines
3.8 KiB
Go
package handler
|
|
|
|
import (
|
|
"io"
|
|
"kra/internal/biz"
|
|
"kra/internal/server/httpx"
|
|
"kra/internal/service"
|
|
"kra/internal/service/dto"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type Payment struct{ service *service.PaymentService }
|
|
|
|
func NewPayment(service *service.PaymentService) *Payment { return &Payment{service: service} }
|
|
func (h *Payment) Configs(c *gin.Context) {
|
|
v, err := h.service.Configs(c.Request.Context())
|
|
if err != nil {
|
|
httpx.Fail(c, err.Error())
|
|
return
|
|
}
|
|
httpx.OKWithData(c, v)
|
|
}
|
|
func (h *Payment) SaveConfig(c *gin.Context) {
|
|
var req dto.PaymentConfigRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
httpx.Fail(c, err.Error())
|
|
return
|
|
}
|
|
if err := h.service.SaveConfig(c.Request.Context(), &biz.PaymentConfig{Provider: req.Provider, Enabled: req.Enabled, Values: req.Config}); err != nil {
|
|
httpx.Fail(c, err.Error())
|
|
return
|
|
}
|
|
httpx.OK(c)
|
|
}
|
|
func (h *Payment) Order(c *gin.Context) {
|
|
var req dto.PaymentQueryRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
httpx.Fail(c, err.Error())
|
|
return
|
|
}
|
|
order, err := h.service.Order(c.Request.Context(), req.Provider, req.TradeNo)
|
|
if err != nil {
|
|
httpx.Fail(c, err.Error())
|
|
return
|
|
}
|
|
httpx.OKWithData(c, order)
|
|
}
|
|
func (h *Payment) Create(c *gin.Context) {
|
|
var req dto.PaymentRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
httpx.Fail(c, err.Error())
|
|
return
|
|
}
|
|
req.ClientIP = c.ClientIP()
|
|
result, err := h.service.Create(c.Request.Context(), &biz.PaymentRequest{
|
|
Provider: req.Provider, TradeNo: req.TradeNo, Subject: req.Subject,
|
|
Amount: req.Amount, OriginalAmount: req.OriginalAmount, Currency: req.Currency, NotifyURL: req.NotifyURL,
|
|
ReturnURL: req.ReturnURL, ClientIP: req.ClientIP, Extra: req.Extra,
|
|
BusinessType: req.BusinessType, BusinessID: req.BusinessID, PaymentMode: req.PaymentMode,
|
|
})
|
|
if err != nil {
|
|
httpx.Fail(c, err.Error())
|
|
return
|
|
}
|
|
httpx.OKWithData(c, result)
|
|
}
|
|
func (h *Payment) Query(c *gin.Context) {
|
|
var req dto.PaymentQueryRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
httpx.Fail(c, err.Error())
|
|
return
|
|
}
|
|
result, err := h.service.Query(c.Request.Context(), req.Provider, req.TradeNo)
|
|
if err != nil {
|
|
httpx.Fail(c, err.Error())
|
|
return
|
|
}
|
|
httpx.OKWithData(c, result)
|
|
}
|
|
func (h *Payment) Refund(c *gin.Context) {
|
|
var req dto.PaymentRefundRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
httpx.Fail(c, err.Error())
|
|
return
|
|
}
|
|
result, err := h.service.Refund(c.Request.Context(), req.Provider, req.TradeNo, req.Amount)
|
|
if err != nil {
|
|
httpx.Fail(c, err.Error())
|
|
return
|
|
}
|
|
httpx.OKWithData(c, result)
|
|
}
|
|
func (h *Payment) Callback(c *gin.Context) {
|
|
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 8<<20)
|
|
raw, err := io.ReadAll(c.Request.Body)
|
|
if err != nil {
|
|
writePaymentCallbackAck(c, biz.DefaultPaymentCallbackAck(c.Param("provider"), false))
|
|
return
|
|
}
|
|
headers := map[string]string{}
|
|
for k, v := range c.Request.Header {
|
|
if len(v) > 0 {
|
|
headers[k] = v[0]
|
|
}
|
|
}
|
|
query := map[string]string{}
|
|
for k, v := range c.Request.URL.Query() {
|
|
if len(v) > 0 {
|
|
query[k] = v[0]
|
|
}
|
|
}
|
|
result, err := h.service.Callback(c.Request.Context(), &biz.PaymentCallback{Provider: c.Param("provider"), Headers: headers, Body: raw, Query: query})
|
|
if err != nil {
|
|
writePaymentCallbackAck(c, biz.CallbackFailure(err, biz.DefaultPaymentCallbackAck(c.Param("provider"), false)))
|
|
return
|
|
}
|
|
ack := biz.DefaultPaymentCallbackAck(c.Param("provider"), true)
|
|
if result != nil && result.SuccessAck.StatusCode != 0 {
|
|
ack = result.SuccessAck
|
|
}
|
|
writePaymentCallbackAck(c, ack)
|
|
}
|
|
|
|
func writePaymentCallbackAck(c *gin.Context, ack biz.PaymentCallbackAck) {
|
|
if ack.StatusCode == 0 {
|
|
ack.StatusCode = http.StatusInternalServerError
|
|
}
|
|
if ack.ContentType != "" {
|
|
c.Header("Content-Type", ack.ContentType)
|
|
}
|
|
c.Status(ack.StatusCode)
|
|
if len(ack.Body) > 0 {
|
|
_, _ = c.Writer.Write(ack.Body)
|
|
}
|
|
}
|