feat: integrate customer service chat

This commit is contained in:
richjohnrambo
2026-10-14 16:37:12 +08:00
parent f3f59fe7c3
commit 48b3564ac9
22 changed files with 1788 additions and 64 deletions
+5 -2
View File
@@ -9,6 +9,7 @@ import (
"git.118im.com/im_team/olons_server/internal/finance"
"git.118im.com/im_team/olons_server/internal/mall"
"git.118im.com/im_team/olons_server/internal/portal"
"git.118im.com/im_team/olons_server/internal/support"
"git.118im.com/im_team/olons_server/internal/tasks"
)
@@ -20,10 +21,11 @@ type API struct {
mall *mall.Service
finance *finance.Service
attachments *attachments.Service
support *support.Service
}
func New(authenticator *auth.Authenticator, accountService *accounts.Service, portalService *portal.Service, taskService *tasks.Service, mallService *mall.Service, financeService *finance.Service, attachmentService *attachments.Service) *API {
return &API{auth: authenticator, accounts: accountService, portal: portalService, tasks: taskService, mall: mallService, finance: financeService, attachments: attachmentService}
func New(authenticator *auth.Authenticator, accountService *accounts.Service, portalService *portal.Service, taskService *tasks.Service, mallService *mall.Service, financeService *finance.Service, attachmentService *attachments.Service, supportService *support.Service) *API {
return &API{auth: authenticator, accounts: accountService, portal: portalService, tasks: taskService, mall: mallService, finance: financeService, attachments: attachmentService, support: supportService}
}
func (a *API) Register(mux *http.ServeMux) {
@@ -40,6 +42,7 @@ func (a *API) Register(mux *http.ServeMux) {
mux.HandleFunc("/v1/member-levels", a.memberLevels)
mux.HandleFunc("/v1/leaderboard", a.leaderboard)
mux.HandleFunc("/v1/customer-services", a.customerServices)
mux.HandleFunc("/v1/customer-services/", a.customerServiceResource)
mux.HandleFunc("/v1/notices", a.notices)
mux.HandleFunc("/v1/notices/popup", a.popupNotice)
mux.HandleFunc("/v1/notices/", a.noticeResource)
+76
View File
@@ -0,0 +1,76 @@
package httpapi
import (
"errors"
"log"
"net/http"
"strconv"
"strings"
"git.118im.com/im_team/olons_server/internal/support"
)
type customerServiceSessionRequest struct {
DeviceID string `json:"device_id"`
Platform string `json:"platform"`
AppVersion string `json:"app_version"`
}
func (a *API) customerServiceResource(w http.ResponseWriter, r *http.Request) {
path := strings.Trim(strings.TrimPrefix(r.URL.Path, "/v1/customer-services/"), "/")
parts := strings.Split(path, "/")
if len(parts) != 2 || parts[1] != "session" {
writeError(w, r, http.StatusNotFound, 30004, "RESOURCE_NOT_FOUND", "resource not found", nil)
return
}
serviceID, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil || serviceID <= 0 {
writeError(w, r, http.StatusNotFound, 30004, "RESOURCE_NOT_FOUND", "resource not found", nil)
return
}
if r.Method != http.MethodPost {
methodNotAllowed(w, r, http.MethodPost)
return
}
principal, ok := a.authenticateMember(w, r)
if !ok {
return
}
if a.support == nil {
writeSupportError(w, r, support.ErrIMUnavailable)
return
}
var body customerServiceSessionRequest
if !decodeBody(w, r, &body) {
return
}
deviceID := strings.TrimSpace(body.DeviceID)
if deviceID == "" {
deviceID = principal.DeviceID
}
result, err := a.support.OpenSession(r.Context(), principal.TenantID, principal.MemberID, serviceID,
support.SessionRequest{DeviceID: deviceID, Platform: body.Platform})
if err != nil {
writeSupportError(w, r, err)
return
}
writeSuccess(w, r, result)
}
func writeSupportError(w http.ResponseWriter, r *http.Request, err error) {
log.Printf("customer service session failed request_id=%s err=%v", r.Header.Get("X-Request-ID"), err)
switch {
case errors.Is(err, support.ErrServiceNotFound):
writeError(w, r, http.StatusNotFound, 41001, "CUSTOMER_SERVICE_NOT_FOUND", "customer service not found", nil)
case errors.Is(err, support.ErrServiceNotBound):
writeError(w, r, http.StatusConflict, 41002, "CUSTOMER_SERVICE_NOT_BOUND", "customer service account is not configured", nil)
case errors.Is(err, support.ErrRelationPending):
writeError(w, r, http.StatusConflict, 41003, "IM_RELATION_PENDING", "customer service relationship is pending", nil)
case errors.Is(err, support.ErrRelationDenied):
writeError(w, r, http.StatusForbidden, 41004, "IM_RELATION_NOT_ALLOWED", "customer service relationship is not allowed", nil)
case errors.Is(err, support.ErrIMUnavailable):
writeError(w, r, http.StatusServiceUnavailable, 41005, "IM_SERVICE_UNAVAILABLE", "IM service unavailable", nil)
default:
writeError(w, r, http.StatusBadGateway, 41006, "IM_SERVICE_UNAVAILABLE", "IM service unavailable", nil)
}
}