Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+163
View File
@@ -0,0 +1,163 @@
package daichong
import "91porn-server/common/stderr"
// 接口地址
const (
takeChat = "/api/chat/playerChat" //发起聊天
getOrder = "/api/chat/getOrder" //获取订单信息
orderCallBack = "/api/call/orderCallBack" //通知代充平台订单处理结果
uploadFile = "/file" //上传图片 路径file 拼接要上传的图片名称 玩家ID加上毫秒时间戳 /file/u123456156332544.jpg
getChatRecordsByOrderId = "/api/chat/getChatRecordsByOrderId" //根据订单ID获取聊天记录
getTraderPayInfo = "/api/chat/getTraderPayInfo" //获取商人支付信息
// 接口地址
newtakeChat = "/api/dc/daichong/takeChat" //发起聊天
newgetOrder = "/api/dc/daichong/orderInfo" //获取订单信息
newgetTraderPayInfo = "/api/dc/daichong/traderPayInfo" //获取商人支付信息
// 通知订单状态
Success int = 4 //成功
Failed int = 5 //失败
)
// ======================================================================================================================
// 聊天返回响应模型
type ChatResp struct {
Code stderr.Code `json:"code"`
Msg string `json:"msg"`
Data Chat `json:"data"`
}
// 发起聊天参数模型
type ChatReq struct {
AppId string `json:"appId"` //代充平台提供的appId
Data string `json:"data"` //加密结果字符串
ProtoType int `json:"protoType"` //协议类型 1: Google Protobuf 2: Pomelo Protobuf 3: JSON
ProductType int `json:"productType"` //0 站群 (默认) 1棋牌
}
type ChatSign struct {
UID string `json:"uid"`
NickName string `json:"nickName"`
Avatar string `json:"avatar"`
Channel string `json:"channel"`
}
// 聊天模型
type Chat struct {
IsReconnect bool `json:"isReconnect"` //当前玩家是否处于断线重连
Traders []Trader `json:"traders"`
URL string `json:"url"` //客户端连接webSocket的地址
WsURL string `json:"wsUrl"` //客户端连接webSocket的地址
PicUrl string `json:"picUrl"` //图片文件服务
OrdUrl string `json:"ordUrl,omitempty"` //获取订单信息地址
TraderUrl string `json:"traderUrl,omitempty"` //获取商人列表地址
UserInfo struct {
UID uint64 `json:"uid,omitempty"` //用户id
Gender string `json:"gender,omitempty"` //性别
Name string `json:"name,omitempty"` //用户名称
Portrait string `json:"portrait,omitempty"` //头像
} `json:"userInfo"` //用户uid
ChargeMoney uint64 `json:"chargeMoney"` //充值金额
Limit uint64 `json:"limit"` //限定金额 超过限定金额 使用大额扫码 ,小于等于限定金额 使用小额扫码
UserAgent string `json:"userAgent,omitempty"` //UserAgent header
}
// 商人模型
type Trader struct {
ImId int64 `json:"imId"` //商人在聊天系统中的ID
UserId string `json:"userId"` //商人在代充系统中的ID
Avatar string `json:"avatar"` //头像
NickName string `json:"nickName"` //昵称
PayInfos []PayInfo `json:"payInfos"` //支付方式
WelcomeMsg string `json:"welcomeMsg"` //商人欢迎语
}
// 支付方式
type PayInfo struct {
PayMethod int64 `json:"payMethod"` //支付方式大类别
PayType []int64 `json:"payType"` //支付方式小类别
}
// ======================================================================================================================
// 获取订单响应模型
type OrderResp struct {
Code stderr.Code `json:"code"`
Msg string `json:"msg"`
Data Order `json:"data"`
}
type OrderSign struct {
TraderId int64 `form:"traderId" json:"traderId"`
PlayerId int64 `form:"playerId" json:"playerId"`
Proof string `form:"proof" json:"proof"` //玩家上传的图片名称
SessionId string `form:"sessionId" json:"sessionId"` //当前会话的sessionId
ProductInfo string `form:"productInfo" json:"productInfo"` //商品信息
ProT int `form:"productType" json:"productType" ` //0 站群 1棋牌
}
// 请求模型
type CommonReq struct {
AppId string `json:"appId"` //代充平台提供的appId
Data string `json:"data"` //加密字符串
}
// 订单模型
type Order struct {
OrderId string `json:"orderId"` //订单号
Proof string `json:"proof"` //当前订单生成的凭证(即玩家上传的图片名称
CreateTime string `json:"createTime"` //订单创建的时间
}
// ======================================================================================================================
// 上分通知
type OrderCallSign struct {
OrderId string `json:"orderId"` //订单号 代充平台订单号
Time int64 `json:"time"` //通知时间 时间戳 毫秒
Status int `json:"status"` //状态
}
// 上传参数
type UploadFileReq struct {
FileName string `json:"fileName"` //文件名
AppId string `json:"appId"` //代充平台提供的appId
UserID string `json:"userId"` //用户ID
SessionId string `json:"sessionId"` //会话ID
File string `json:"file"` //base64 字符串
}
// 聊天记录返回模型
type RecordResp struct {
Code stderr.Code `json:"code"`
Msg string `json:"msg"`
Data recordChat `json:"data"`
}
// 聊天记录列表
type recordChat struct {
List []chat `json:"list"`
Total int64 `json:"total"`
}
// 聊天
type chat struct {
MessageId string `json:"messageId"`
SessionId string `json:"sessionId"`
SenderId int64 `json:"senderId"`
TargetId int64 `json:"targetId"`
SendType int `json:"sendType"`
MessageType int `json:"messageType"`
Text string `json:"text"`
Photo []string `json:"photo"`
Payload string `json:"payload"`
CreateDate int `json:"createDate"`
IsRead int `json:"isRead"`
}
// 商人支付信息
type PayInfoResp struct {
Code stderr.Code `json:"code"`
Msg string `json:"msg"`
Data PayInfo `json:"data"`
}
+149
View File
@@ -0,0 +1,149 @@
package daichong
import (
"context"
"encoding/hex"
"fmt"
"net/url"
"reflect"
"strconv"
"time"
"91porn-server/app/appg"
"91porn-server/common"
"91porn-server/common/crypt"
"91porn-server/common/httputil"
"91porn-server/common/log"
"91porn-server/models/commod"
)
// 发起聊天
func TakeChat(req ChatReq, domian string) (chatResp ChatResp, err error) {
var code int
param, _ := common.ToJsonM(req)
c, cancle := context.WithTimeout(context.Background(), time.Duration(appg.Conf.HttpOptions.DcCtxTimeOut)*time.Second)
defer cancle()
code, err = httputil.DefaultClientPostJsonWithResp(&chatResp, common.BindUrl(domian, takeChat), nil, param)
common.Go(func() {
<-c.Done()
fmt.Print("current http method takeChat", c.Err())
})
log.Info("http method TakeChat response code ==>", log.Any("statusCode", code), log.Any("respCode", chatResp.Code))
if err != nil {
log.Error("TakeChat failed", log.E(err))
}
return
}
// 获取订单信息
func GetOrder(req CommonReq, domian string) (orderResp OrderResp, err error) {
param, _ := common.ToJsonM(req)
code, err := httputil.DefaultClientPostJsonWithResp(&orderResp, common.BindUrl(domian, getOrder), nil, param)
log.Info("http method GetOrder response code ==>", log.Any("statusCode", code), log.Any("respCode", orderResp.Code))
if err != nil {
log.Error("GetOrder failed", log.E(err))
}
return
}
// 上分通知
func OrderCallBack(ctx context.Context, req CommonReq, domian string) (resp commod.Resp, err error) {
param, _ := common.ToJsonM(req)
code, err := httputil.DefaultClientPostJsonWithResp(&resp, common.BindUrl(domian, orderCallBack), nil, param)
log.InfoX(ctx, "http method OrderCallBack response code ==>", log.Any("statusCode", code),
log.Any("respCode", resp.Code))
if err != nil {
log.ErrorX(ctx, "OrderCallBack failed", log.E(err))
}
return
}
// 上传图片
func UploadFile(req UploadFileReq, domian string) (resp commod.Resp, err error) {
header := map[string]string{
"Authorization": req.UserID + "&" + req.SessionId,
}
data := map[string]interface{}{
"file": req.File,
}
code, err := httputil.DefaultClientPostJsonWithResp(&resp, common.BindUrl(domian, uploadFile, req.FileName), header, data)
log.Info("http method UploadFile response code ==>", log.Any("statusCode", code), log.Any("respCode", resp.Code))
if err != nil {
log.Error("UploadFile failed", log.E(err))
}
return
}
// 根据订单ID获取聊天记录
func GetChatRecordsByOrderId(req CommonReq, domian string) (resp RecordResp, err error) {
code, err := httputil.DefaultClientPostJsonWithResp(&resp, common.BindUrl(domian, getChatRecordsByOrderId), nil, req)
log.Info("http method GetChatRecordsByOrderId response code ==>", log.Any("statusCode", code), log.Any("respCode", resp.Code))
if err != nil {
log.Error("GetChatRecordsByOrderId failed", log.E(err))
}
return
}
// 获取商人支付信息
func GetTraderPayInfo(req CommonReq, domian string) (resp PayInfoResp, err error) {
code, err := httputil.DefaultClientPostJsonWithResp(&resp, common.BindUrl(domian, getTraderPayInfo), nil, req)
log.Info("http method GetTraderPayInfo response code ==>", log.Any("statusCode", code), log.Any("respCode", resp.Code))
if err != nil {
log.Error("GetTraderPayInfo failed", log.E(err))
}
return
}
// 结构体转换为加密的16进制字符串
func Convert2Sign(obj interface{}, appSecret string) (string, error) {
urlParam, err := crypt.Strcut2UrlValue(obj)
if err != nil {
log.Warn("chat sign struct convert to url values wrong", log.Any("urlParam", urlParam), log.Any("warn", err))
return "", err
}
log.Info("covert obj to urlParam ==>", log.Any("obj", obj), log.Any("urlParam", urlParam))
sign, err := crypt.AesEncrypt(urlParam, appSecret)
if err != nil {
log.Warn("create sign data wrong", log.Any("warn", err))
return "", err
}
cryptdata := hex.EncodeToString(sign)
return cryptdata, nil
}
// 加密的16进制字符串转为结构体
func Sign2Struct(obj interface{}, sign, appSecret string) error {
cryptdata, err := hex.DecodeString(sign)
if err != nil {
log.Warn("hex decode string occour error", log.Any("warn", err))
return err
}
origin, err := crypt.CoreAesDecrypt(cryptdata, appSecret)
if err != nil {
log.Warn("core aes decrypt sign data wrong", log.Any("warn", err))
return err
}
t := reflect.TypeOf(obj)
m := make(map[string]interface{})
u, err := url.ParseQuery(origin)
if err == nil {
for k, v := range u {
s, _ := t.Elem().FieldByName(common.Ucfirst(k))
typ := s.Type.Kind()
switch typ {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
rv, _ := strconv.ParseInt(v[0], 10, 64)
m[k] = rv
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
rv, _ := strconv.ParseUint(v[0], 10, 64)
m[k] = rv
default:
m[k] = v[0]
}
}
}
if len(m) > 0 {
return common.Map2JSONStruct(obj, m)
}
return nil
}
+53
View File
@@ -0,0 +1,53 @@
package daichong
import (
"context"
"fmt"
"time"
"91porn-server/app/appg"
"91porn-server/common"
"91porn-server/common/httputil"
"91porn-server/common/log"
"91porn-server/models/e/daichongmod"
)
// 发起聊天
func NewTakeChat(ctx context.Context, req NewChatReq, domain string) (chatResp ChatResp, err error) {
var code int
param, _ := common.ToJsonM(req)
c, cancle := context.WithTimeout(ctx, time.Duration(appg.Conf.HttpOptions.DcCtxTimeOut)*time.Second)
defer cancle()
code, err = httputil.DefaultClientPostJsonWithResp(&chatResp, common.BindUrl(domain, newtakeChat), nil, param)
common.Go(func() {
<-c.Done()
fmt.Print("current http method takeChat", c.Err())
})
log.InfoX(c, "http method TakeChat response code ==>", log.Any("statusCode", code),
log.Any("respCode", chatResp.Code))
if err != nil {
log.ErrorX(c, "TakeChat failed", log.Any("req", req), log.Any("domain", domain), log.E(err))
}
return
}
// 获取订单信息
func NewGetOrder(req OrderSign, domain string) (orderResp OrderResp, err error) {
param, _ := common.ToJsonM(req)
code, err := httputil.DefaultClientPostJsonWithResp(&orderResp, common.BindUrl(domain, newgetOrder), nil, param)
log.Info("http method GetOrder response code ==>", log.Any("statusCode", code), log.Any("respCode", orderResp.Code))
if err != nil {
log.Error("GetOrder failed", log.E(err))
}
return
}
// 获取商人支付信息
func NewGetTraderPayInfo(req daichongmod.PayInfoReq, domain string) (resp PayInfoResp, err error) {
code, err := httputil.DefaultClientPostJsonWithResp(&resp, common.BindUrl(domain, newgetTraderPayInfo), nil, req)
log.Info("http method GetTraderPayInfo response code ==>", log.Any("statusCode", code), log.Any("respCode", resp.Code))
if err != nil {
log.Error("GetTraderPayInfo failed", log.E(err))
}
return
}
+9
View File
@@ -0,0 +1,9 @@
package daichong
// 发起聊天参数模型
type NewChatReq struct {
UID string `json:"uid"` //用户id
Name string `json:"name"` //用户名称
Portrait string `json:"portrait"` //用户头像
ProductType int `json:"productType"` //0 站群 (默认) 1棋牌
}