You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
5.4 KiB
145 lines
5.4 KiB
package console
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"yunyan/comm"
|
|
"yunyan/lego/sys/postgres"
|
|
"yunyan/pb"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// ============================ 渠道分发 (channelapp) ============================
|
|
//
|
|
// 「SaaS 管理 → 渠道分发」的后端:管理各应用在各分发渠道(华为/小米/OPPO/VIVO/荣耀/官方/苹果/谷歌)
|
|
// 上**因渠道而异**的东西——本渠道下载地址、上架状态、支付渠道、是否允许跳过设备绑定。
|
|
// 模型见 comm/channelapp.go,存 console 主库(postgres.GetSys()),按 app_name 作用域,
|
|
// 业务服务(home 的 user 模块)运行时按 (app_name=? OR app_name='') 直读下发。
|
|
//
|
|
// ⚠️ 版本号/最低支持版本/强制更新/更新日志/送审版本/游客登录开关**不在这里**:它们是
|
|
// 「整个应用一套」的,已搬到「服务配置 → 版本控制 / 游客显隐控制」(api_apprelease.go)。
|
|
// 别再往本页加这些字段——按渠道各存一份的直接后果是同一个开关有 8 处能改、客户端只读一处。
|
|
//
|
|
// 旧实现(deep_server modules/api/api_*channelapp.go + 各应用业务库 mysql 的 channelapp 表)已下线:
|
|
// 数据统一收到 console 主库,后台一个库即可总览全部应用的渠道版本。
|
|
//
|
|
// 支付:本页只管「这个渠道开放哪几种支付」(PayChannels);各支付方式的商户凭据仍在
|
|
// 「应用中心 → 业务功能配置」的支付分组(app_module_config)里配,不在此重复。
|
|
// getChannelPayStatus 负责把两边对上——告诉前端哪些已开的支付渠道其实还没配凭据。
|
|
|
|
// getChannelApps 列出某作用域下的渠道配置(app_name=”为全局默认)。
|
|
func (this *serverComp) getChannelApps(c *gin.Context) {
|
|
var req struct {
|
|
AppName string `json:"app_name"`
|
|
}
|
|
_ = c.ShouldBindJSON(&req)
|
|
items := make([]*comm.ChannelApp, 0)
|
|
if err := postgres.Find(comm.TableChannelAppCfg, &items, "app_name=?", req.AppName); err != nil {
|
|
writeErr(c, pb.ErrorCode_DBError, err.Error())
|
|
return
|
|
}
|
|
writeOK(c, gin.H{"items": items})
|
|
}
|
|
|
|
// saveChannelApp 新增或更新一个渠道配置(按 app_name+channel upsert)。
|
|
func (this *serverComp) saveChannelApp(c *gin.Context) {
|
|
var m comm.ChannelApp
|
|
if err := c.ShouldBindJSON(&m); err != nil {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, err.Error())
|
|
return
|
|
}
|
|
if m.Channel == 0 {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, "渠道 必选")
|
|
return
|
|
}
|
|
// 版本/强更/游客登录的校验已随字段搬到 api_apprelease.go(按应用配,不分渠道)。
|
|
now := time.Now().UnixMilli()
|
|
m.Updatetime = now
|
|
old := &comm.ChannelApp{}
|
|
err := postgres.FindOne(comm.TableChannelAppCfg, old, "app_name=? AND channel=?", m.AppName, m.Channel)
|
|
if err != nil {
|
|
m.RowId = 0
|
|
m.Createtime = now
|
|
err = postgres.Insert(comm.TableChannelAppCfg, &m)
|
|
} else {
|
|
m.RowId = old.RowId
|
|
m.Createtime = old.Createtime
|
|
err = postgres.Save(comm.TableChannelAppCfg, &m)
|
|
}
|
|
if err != nil {
|
|
writeErr(c, pb.ErrorCode_DBError, err.Error())
|
|
return
|
|
}
|
|
broadcastConfigChanged(comm.ConfigKindChannelApp, "update", 0)
|
|
writeOK(c, &m)
|
|
}
|
|
|
|
// delChannelApp 删除某作用域下某渠道的配置。
|
|
func (this *serverComp) delChannelApp(c *gin.Context) {
|
|
var req struct {
|
|
AppName string `json:"app_name"`
|
|
Channel int32 `json:"channel"`
|
|
}
|
|
_ = c.ShouldBindJSON(&req)
|
|
if req.Channel == 0 {
|
|
writeErr(c, pb.ErrorCode_ReqParameterError, "channel 必填")
|
|
return
|
|
}
|
|
if err := postgres.Delete(comm.TableChannelAppCfg, "app_name=? AND channel=?", req.AppName, req.Channel); err != nil {
|
|
writeErr(c, pb.ErrorCode_DBError, err.Error())
|
|
return
|
|
}
|
|
broadcastConfigChanged(comm.ConfigKindChannelApp, "delete", 0)
|
|
writeOK(c, gin.H{"channel": req.Channel})
|
|
}
|
|
|
|
// getChannelPayStatus 查这个应用的支付凭据配了哪几种。
|
|
//
|
|
// 渠道配置里的 PayChannels 只是「开放哪几种支付入口」,真正的商户凭据在**应用业务库**的
|
|
// app_module_config 里。两者分处不同库,运营很容易开了入口却忘了配凭据,故后台直接把结论算好:
|
|
// 遍历该 app_name 下的部署,连上任意一个业务库,读出已配置的支付模块键。
|
|
// 全局作用域(app_name=”)没有对应业务库,返回空表示「无法判定」,前端据此不告警。
|
|
func (this *serverComp) getChannelPayStatus(c *gin.Context) {
|
|
var req struct {
|
|
AppName string `json:"app_name"`
|
|
}
|
|
_ = c.ShouldBindJSON(&req)
|
|
resp := gin.H{"configured": []string{}, "checked": false}
|
|
if strings.TrimSpace(req.AppName) == "" {
|
|
writeOK(c, resp)
|
|
return
|
|
}
|
|
regs := make([]*AppRegistry, 0)
|
|
if err := postgres.Find(comm.TableAppRegistry, ®s, "app_name=?", req.AppName); err != nil || len(regs) == 0 {
|
|
writeOK(c, resp)
|
|
return
|
|
}
|
|
payModules := map[string]bool{}
|
|
for _, m := range comm.PayChannelModule {
|
|
payModules[m] = true
|
|
}
|
|
for _, r := range regs {
|
|
db, err := this.module.registry.getServiceDB(r.Id)
|
|
if err != nil {
|
|
continue // 这个部署连不上,试下一个
|
|
}
|
|
rows, err := listModuleConfig(db, "")
|
|
if err != nil {
|
|
continue
|
|
}
|
|
configured := make([]string, 0, len(payModules))
|
|
seen := map[string]bool{}
|
|
for _, row := range rows {
|
|
if !payModules[row.Module] || seen[row.Module] || strings.TrimSpace(row.Value) == "" {
|
|
continue
|
|
}
|
|
seen[row.Module] = true
|
|
configured = append(configured, row.Module)
|
|
}
|
|
writeOK(c, gin.H{"configured": configured, "checked": true, "app_id": r.Id})
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
}
|
|
|