商城c端前端
This commit is contained in:
@@ -36,6 +36,8 @@ func (a *API) Register(mux *http.ServeMux) {
|
||||
mux.HandleFunc("/v1/banners", a.banners)
|
||||
mux.HandleFunc("/v1/contents/", a.content)
|
||||
mux.HandleFunc("/v1/member-levels", a.memberLevels)
|
||||
mux.HandleFunc("/v1/leaderboard", a.leaderboard)
|
||||
mux.HandleFunc("/v1/customer-services", a.customerServices)
|
||||
mux.HandleFunc("/v1/task-halls", a.taskHalls)
|
||||
mux.HandleFunc("/v1/tasks/eligibility", a.taskEligibility)
|
||||
mux.HandleFunc("/v1/tasks/stats", a.taskStats)
|
||||
@@ -45,6 +47,9 @@ func (a *API) Register(mux *http.ServeMux) {
|
||||
mux.HandleFunc("/v1/manual-products", a.manualProducts)
|
||||
mux.HandleFunc("/v1/manual-products/", a.manualProduct)
|
||||
mux.HandleFunc("/v1/payment-accounts", a.paymentAccounts)
|
||||
mux.HandleFunc("/v1/recharge/channels", a.rechargeChannels)
|
||||
mux.HandleFunc("/v1/recharge-orders", a.rechargeOrders)
|
||||
mux.HandleFunc("/v1/recharge-orders/", a.rechargeOrder)
|
||||
mux.HandleFunc("/v1/withdrawal-orders/quote", a.withdrawalQuote)
|
||||
mux.HandleFunc("/v1/withdrawal-orders", a.withdrawalOrders)
|
||||
mux.HandleFunc("/v1/withdrawal-orders/", a.withdrawalOrder)
|
||||
|
||||
@@ -62,6 +62,91 @@ func (a *API) withdrawalQuote(w http.ResponseWriter, r *http.Request) {
|
||||
writeSuccess(w, r, result)
|
||||
}
|
||||
|
||||
func (a *API) rechargeChannels(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r, http.MethodGet)
|
||||
return
|
||||
}
|
||||
principal, ok := a.authenticateFinanceMember(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
result, err := a.finance.RechargeChannels(r.Context(), principal.TenantID)
|
||||
if err != nil {
|
||||
writeFinanceError(w, r, err)
|
||||
return
|
||||
}
|
||||
writeSuccess(w, r, result)
|
||||
}
|
||||
|
||||
func (a *API) rechargeOrders(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet && r.Method != http.MethodPost {
|
||||
methodNotAllowed(w, r, http.MethodGet, http.MethodPost)
|
||||
return
|
||||
}
|
||||
principal, ok := a.authenticateFinanceMember(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if r.Method == http.MethodGet {
|
||||
page, ok := optionalPositiveInt(w, r, "page")
|
||||
if !ok {
|
||||
writeFinanceError(w, r, finance.ErrPageInvalid)
|
||||
return
|
||||
}
|
||||
pageSize, ok := optionalPositiveInt(w, r, "page_size")
|
||||
if !ok {
|
||||
writeFinanceError(w, r, finance.ErrPageSizeInvalid)
|
||||
return
|
||||
}
|
||||
result, err := a.finance.RechargeOrders(r.Context(), principal.TenantID, principal.MemberID,
|
||||
page, pageSize, r.URL.Query().Get("status"))
|
||||
if err != nil {
|
||||
writeFinanceError(w, r, err)
|
||||
return
|
||||
}
|
||||
writeSuccess(w, r, result)
|
||||
return
|
||||
}
|
||||
var body finance.CreateRechargeInput
|
||||
if !decodeBody(w, r, &body) {
|
||||
return
|
||||
}
|
||||
result, err := a.finance.CreateRecharge(r.Context(), principal.TenantID, principal.MemberID, body)
|
||||
if err != nil {
|
||||
writeFinanceError(w, r, err)
|
||||
return
|
||||
}
|
||||
writeSuccess(w, r, result)
|
||||
}
|
||||
|
||||
func (a *API) rechargeOrder(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r, http.MethodGet)
|
||||
return
|
||||
}
|
||||
orderIDText := strings.Trim(strings.TrimPrefix(r.URL.Path, "/v1/recharge-orders/"), "/")
|
||||
if orderIDText == "" || strings.Contains(orderIDText, "/") {
|
||||
writeFinanceError(w, r, finance.ErrRechargeOrderIDInvalid)
|
||||
return
|
||||
}
|
||||
orderID, err := strconv.ParseInt(orderIDText, 10, 64)
|
||||
if err != nil || orderID <= 0 {
|
||||
writeFinanceError(w, r, finance.ErrRechargeOrderIDInvalid)
|
||||
return
|
||||
}
|
||||
principal, ok := a.authenticateFinanceMember(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
result, err := a.finance.RechargeOrder(r.Context(), principal.TenantID, principal.MemberID, orderID)
|
||||
if err != nil {
|
||||
writeFinanceError(w, r, err)
|
||||
return
|
||||
}
|
||||
writeSuccess(w, r, result)
|
||||
}
|
||||
|
||||
func (a *API) withdrawalOrders(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet && r.Method != http.MethodPost {
|
||||
methodNotAllowed(w, r, http.MethodGet, http.MethodPost)
|
||||
@@ -159,6 +244,12 @@ func writeFinanceError(w http.ResponseWriter, r *http.Request, err error) {
|
||||
writeError(w, r, http.StatusBadRequest, 30000, "CURRENCY_INVALID", "validation failed", map[string]any{"field": "currency"})
|
||||
case errors.Is(err, finance.ErrAmountInvalid), errors.Is(err, store.ErrWithdrawalAmount):
|
||||
writeError(w, r, http.StatusUnprocessableEntity, 30022, "WITHDRAWAL_AMOUNT_INVALID", "withdrawal amount is outside the allowed range", nil)
|
||||
case errors.Is(err, store.ErrRechargeAmount):
|
||||
writeError(w, r, http.StatusUnprocessableEntity, 30022, "RECHARGE_AMOUNT_INVALID", "recharge amount is outside the allowed range", nil)
|
||||
case errors.Is(err, finance.ErrRemarkInvalid):
|
||||
writeError(w, r, http.StatusBadRequest, 30000, "RECHARGE_REMARK_INVALID", "validation failed", map[string]any{"field": "remark"})
|
||||
case errors.Is(err, finance.ErrVoucherInvalid):
|
||||
writeError(w, r, http.StatusBadRequest, 30000, "RECHARGE_VOUCHER_INVALID", "validation failed", map[string]any{"field": "voucher_attachment_ids"})
|
||||
case errors.Is(err, finance.ErrIdempotencyKey):
|
||||
writeError(w, r, http.StatusBadRequest, 30000, "IDEMPOTENCY_KEY_INVALID", "valid Idempotency-Key header is required", map[string]any{"field": "Idempotency-Key"})
|
||||
case errors.Is(err, finance.ErrPageInvalid):
|
||||
@@ -167,6 +258,10 @@ func writeFinanceError(w http.ResponseWriter, r *http.Request, err error) {
|
||||
writeError(w, r, http.StatusBadRequest, 30000, "PAGE_SIZE_INVALID", "validation failed", map[string]any{"field": "page_size"})
|
||||
case errors.Is(err, finance.ErrStatusInvalid):
|
||||
writeError(w, r, http.StatusBadRequest, 30000, "WITHDRAWAL_STATUS_INVALID", "validation failed", map[string]any{"field": "status"})
|
||||
case errors.Is(err, finance.ErrRechargeStatusInvalid):
|
||||
writeError(w, r, http.StatusBadRequest, 30000, "RECHARGE_STATUS_INVALID", "validation failed", map[string]any{"field": "status"})
|
||||
case errors.Is(err, finance.ErrRechargeOrderIDInvalid):
|
||||
writeError(w, r, http.StatusBadRequest, 30000, "RECHARGE_ORDER_ID_INVALID", "validation failed", map[string]any{"field": "order_id"})
|
||||
case errors.Is(err, finance.ErrOrderIDInvalid):
|
||||
writeError(w, r, http.StatusBadRequest, 30000, "WITHDRAWAL_ORDER_ID_INVALID", "validation failed", map[string]any{"field": "order_id"})
|
||||
case errors.Is(err, store.ErrPaymentAccountExists):
|
||||
@@ -177,6 +272,8 @@ func writeFinanceError(w http.ResponseWriter, r *http.Request, err error) {
|
||||
writeError(w, r, http.StatusUnprocessableEntity, 30022, "WITHDRAWAL_DISABLED", "withdrawal feature is disabled", nil)
|
||||
case errors.Is(err, store.ErrWithdrawalChannel):
|
||||
writeError(w, r, http.StatusServiceUnavailable, 30053, "WITHDRAWAL_CHANNEL_UNAVAILABLE", "withdrawal channel is unavailable", nil)
|
||||
case errors.Is(err, store.ErrRechargeChannel):
|
||||
writeError(w, r, http.StatusServiceUnavailable, 30053, "RECHARGE_CHANNEL_UNAVAILABLE", "recharge channel is unavailable", nil)
|
||||
case errors.Is(err, store.ErrWithdrawalLimit):
|
||||
writeError(w, r, http.StatusUnprocessableEntity, 30022, "WITHDRAWAL_DAILY_LIMIT_REACHED", "daily withdrawal limit reached", nil)
|
||||
case errors.Is(err, store.ErrInsufficientBalance):
|
||||
@@ -187,6 +284,10 @@ func writeFinanceError(w http.ResponseWriter, r *http.Request, err error) {
|
||||
writeError(w, r, http.StatusUnprocessableEntity, 30022, "ACCOUNT_RESTRICTED", "account is restricted", nil)
|
||||
case errors.Is(err, store.ErrWithdrawalNotFound):
|
||||
writeError(w, r, http.StatusNotFound, 30044, "WITHDRAWAL_ORDER_NOT_FOUND", "withdrawal order not found", nil)
|
||||
case errors.Is(err, store.ErrRechargeNotFound):
|
||||
writeError(w, r, http.StatusNotFound, 30044, "RECHARGE_ORDER_NOT_FOUND", "recharge order not found", nil)
|
||||
case errors.Is(err, store.ErrRechargeVoucher):
|
||||
writeError(w, r, http.StatusBadRequest, 30000, "RECHARGE_VOUCHER_INVALID", "validation failed", map[string]any{"field": "voucher_attachment_ids"})
|
||||
case errors.Is(err, store.ErrIdempotencyConflict):
|
||||
writeError(w, r, http.StatusConflict, 30040, "IDEMPOTENCY_CONFLICT", "Idempotency-Key was reused with different request data", nil)
|
||||
case errors.Is(err, store.ErrAttachmentInvalid):
|
||||
|
||||
@@ -117,6 +117,46 @@ func (a *API) memberLevels(w http.ResponseWriter, r *http.Request) {
|
||||
writeSuccess(w, r, items)
|
||||
}
|
||||
|
||||
func (a *API) leaderboard(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r, http.MethodGet)
|
||||
return
|
||||
}
|
||||
if !a.ensurePortal(w, r) {
|
||||
return
|
||||
}
|
||||
principal, ok := a.authenticateMember(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
items, err := a.portal.Leaderboard(r.Context(), principal.TenantID)
|
||||
if err != nil {
|
||||
writePortalError(w, r, err)
|
||||
return
|
||||
}
|
||||
writeSuccess(w, r, items)
|
||||
}
|
||||
|
||||
func (a *API) customerServices(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
methodNotAllowed(w, r, http.MethodGet)
|
||||
return
|
||||
}
|
||||
if !a.ensurePortal(w, r) {
|
||||
return
|
||||
}
|
||||
principal, ok := a.authenticateMember(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
items, err := a.portal.CustomerServices(r.Context(), principal.TenantID)
|
||||
if err != nil {
|
||||
writePortalError(w, r, err)
|
||||
return
|
||||
}
|
||||
writeSuccess(w, r, items)
|
||||
}
|
||||
|
||||
func (a *API) ensurePortal(w http.ResponseWriter, r *http.Request) bool {
|
||||
if a.portal != nil {
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user