1
0

4 Sitoutukset 20cf9bddd2 ... 6c70c092bb

Tekijä SHA1 Viesti Päivämäärä
  lt 6c70c092bb 11 4 päivää sitten
  lt 0428c276ee 11 5 päivää sitten
  lt 2aa5a25deb 11 5 päivää sitten
  lt f1696d4725 11 5 päivää sitten

+ 187 - 4
RO_Server_Trunk-branch_0.1.39/roserver/game/model/role.go

@@ -1,6 +1,9 @@
 package model
 
 import (
+	"crypto/md5"
+	"encoding/hex"
+	"encoding/json"
 	"errors"
 	"fmt"
 	"math"
@@ -11,6 +14,8 @@ import (
 	"rocommon/util"
 	"roserver/baseserver/model"
 	"roserver/serverproto"
+	"sort"
+	"strconv"
 	"strings"
 	"time"
 	"unicode/utf8"
@@ -59,6 +64,7 @@ type RoleOuter interface {
 	SetHardFight(b int)
 	SetYuanRankScore()
 	SetSdkJson(a string)
+	SetSdkJson2(a string)
 	GetSdkJson() string
 }
 
@@ -507,6 +513,7 @@ type Role struct {
 	activeCode   string                              //激活码
 	isHardFight  int                                 //是否是困难模式 //0普通.1困难,2噩梦
 	Guid         string                              //小七uid
+	Guid2        string                              //小七uid
 
 	base            *RoleBase    //角色基础信息
 	roleHero        *RoleHero    //伙伴信息
@@ -692,6 +699,9 @@ func (this *Role) GetSdkJson() string {
 func (this *Role) SetSdkJson(a string) {
 	this.Guid = a
 }
+func (this *Role) SetSdkJson2(a string) {
+	this.Guid2 = a
+}
 func (this *Role) SetSelectZone(selectZone int32) {
 	if selectZone <= 0 {
 		this.selectZone = int32(service.GetServiceConfig().Node.Zone)
@@ -3695,12 +3705,52 @@ func (this *Role) PayInfoGet(goodsType, goodsId, count int32, rushStage, rushRou
 			util.InfoF("uid=%v pc mode: shop:%v id:%v, count:%v, price:%v", this.GetUUid(), payOrderInfo.GoodsType, payOrderInfo.GoodsId, payOrderInfo.Count, payOrderInfo.Amount)
 			return
 		}
+		server := int(payOrderInfo.SId / 2)
+		corderid := strconv.FormatUint(payOrderInfo.CpOrderId, 10)
+		price := fmt.Sprintf("%.2f", payOrderInfo.Amount)
+		guid, _ := strconv.Atoi(this.Guid2)
+		name := this.GetNickName()
+		if name == "" {
+			name = "Player"
+		}
+		ordeinfo := OrderRequest{
+			GameArea:          strconv.Itoa(server),
+			GameLevel:         strconv.Itoa(int(this.GetRoleLevel())),
+			GameOrderId:       corderid,
+			GameCurrency:      "USD",
+			GamePrice:         price,
+			GameRoleId:        strconv.Itoa(int(this.GetUUid())),
+			GameRoleName:      name,
+			GameGuid:          guid,
+			NotifyId:          service.GetServiceConfig().Node.PayCallBack,
+			Subject:           price + " Pack",
+			GameAccessVersion: "2507",
+		}
+		extra := &Extras{
+			ServerId:  server,
+			Platform:  this.platform,
+			CpOrderId: corderid,
+		}
+		v, _ := json.Marshal(extra)
+		ordeinfo.ExtendsInfoData = string(v)
+
 		payOrderInfo.SdkOrderId = sdkOrderId
 		//保存订单信息到数据库
 		ackMsg.Amount = payOrderInfo.Amount
 		ackMsg.CpOrderId = payOrderInfo.CpOrderId
-		ackMsg.GoodsName = payOrderInfo.GoodsName
-		//ackMsg.GoodsName = service.GetServiceConfig().Node.PayCallBack
+		//ackMsg.GoodsName = payOrderInfo.GoodsName
+		info, err := GenerateGameSign(ordeinfo, "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCfYd3FqSaWqCpWLSktBSSgAelt0F6T+tO4C25YKR/6X/sPacDBbX662/0fW+H+YbXigHWFB/yangkhiZTpD/VmiOo5lISX6L0/m+13ti9b8jzTZcfVngfLsP+Ztbk81N1Jk0gWF4bndZxREJ3IxcEDHnIrwXgLGA2GJ89kdgudwIDAQAB")
+		if err != nil {
+			ackMsg.Error = int32(serverproto.ErrorCode_ERROR_PAY_NOT_OPEN)
+			this.ReplayGate(ackMsg, true)
+			util.ErrorF("uid=%v GenerateGameSign err:%v", this.GetUUid(), err)
+			return
+		}
+		ordeinfo.GameSign = info
+		b, _ := json.Marshal(ordeinfo)
+		payOrderInfo.GoodsName = string(b)
+
+		util.ErrorF("uid:%v pay info platform:%v order:%v", this.GetUUid(), this.platform, payOrderInfo)
 		ssSaveReqMsg := &serverproto.SSPayInfoSaveReq{
 			PayOrderInfo: payOrderInfo,
 			SaveNotify:   true,
@@ -3711,6 +3761,139 @@ func (this *Role) PayInfoGet(goodsType, goodsId, count int32, rushStage, rushRou
 	}
 }
 
+func GenerateGameSign(params interface{}, rsaPublicKey string) (string, error) {
+	// 1. 将结构体转换为 map
+	paramsMap, err := structToMap(params)
+	if err != nil {
+		return "", err
+	}
+
+	// 2. 过滤掉 game_sign 字段
+	delete(paramsMap, "game_sign")
+
+	// 3. 获取所有 key 并排序(字典序)
+	keys := make([]string, 0, len(paramsMap))
+	for k := range paramsMap {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+
+	// 4. 按顺序构建 QueryString
+	var queryParts []string
+	for _, k := range keys {
+		v := paramsMap[k]
+		// 跳过空值或零值(根据实际需求调整)
+		if v == "" || v == nil {
+			continue
+		}
+		// 将值转换为字符串
+		strValue := fmt.Sprintf("%v", v)
+		queryParts = append(queryParts, fmt.Sprintf("%s=%s", k, strValue))
+	}
+	queryString := strings.Join(queryParts, "&")
+
+	// 5. 在 QueryString 后面拼接 RSA 公钥
+	stringToSign := queryString + rsaPublicKey
+
+	// 6. 计算 MD5
+	hash := md5.Sum([]byte(stringToSign))
+	sign := hex.EncodeToString(hash[:])
+
+	return sign, nil
+}
+
+// structToMap 将结构体转换为 map[string]interface{}
+// 使用 json tag 作为 key
+func structToMap(obj interface{}) (map[string]interface{}, error) {
+	result := make(map[string]interface{})
+
+	v := reflect.ValueOf(obj)
+	t := reflect.TypeOf(obj)
+
+	// 如果是指针,获取其指向的值
+	if v.Kind() == reflect.Ptr {
+		v = v.Elem()
+		t = t.Elem()
+	}
+
+	// 确保是结构体类型
+	if v.Kind() != reflect.Struct {
+		return nil, fmt.Errorf("expected struct, got %v", v.Kind())
+	}
+
+	for i := 0; i < v.NumField(); i++ {
+		field := t.Field(i)
+		value := v.Field(i)
+
+		// 获取 json tag
+		jsonTag := field.Tag.Get("json")
+		if jsonTag == "" || jsonTag == "-" {
+			continue
+		}
+
+		// 处理 omitempty(去除后面的,omitempty)
+		jsonTag = strings.Split(jsonTag, ",")[0]
+
+		// 获取字段值
+		if value.Kind() == reflect.Ptr && value.IsNil() {
+			result[jsonTag] = nil
+		} else {
+			result[jsonTag] = value.Interface()
+		}
+	}
+
+	return result, nil
+}
+
+type OrderRequest struct {
+	// 訂單擴展數據,支持JSON或QueryString格式
+	ExtendsInfoData string `json:"extends_info_data"` // 最大128字符
+
+	// 角色所在的遊戲區,須與X7game平台上傳的開服表信息中的支付顯示區服欄位一致
+	GameArea string `json:"game_area"` // 最大20字符,必填
+
+	// 用戶遊戲中角色等級
+	GameLevel string `json:"game_level"` // 最大30字符,必填
+
+	// 遊戲訂單號
+	GameOrderId string `json:"game_orderid"` // 最大100字符,必填
+
+	// 貨幣單位,可用值:CNY,USD,HKD,VND,KRW (game_access_version=7.98時新增)
+	GameCurrency string `json:"game_currency"` // 最大10字符,必填
+
+	// 商品價格,保留小數點後兩位
+	GamePrice string `json:"game_price"` // 格式:10,2,必填
+
+	// 用戶遊戲中角色id信息
+	GameRoleId string `json:"game_role_id"` // 最大30字符,必填
+
+	// 用戶遊戲中角色名稱
+	GameRoleName string `json:"game_role_name"` // 最大30字符,必填
+
+	// 用戶遊戲小號的唯一標識
+	GameGuid int `json:"game_guid"` // 最大12位整數,必填
+
+	// 支付回調通知id,可設置為-1,但不允許為0
+	NotifyId string `json:"notify_id"` // 最大11字符,必填
+
+	// 道具簡介
+	Subject string `json:"subject"` // 最大100字符,必填
+
+	// 簽名,將其他所有字段按字典序生成QueryString後拼接小7RSA公鑰,再MD5
+	GameSign string `json:"game_sign"` // 最大32字符,必填
+
+	// 接入簽名方式版本,新遊戲接入選擇 '2507'
+	GameAccessVersion string `json:"game_access_version"` // 最大10字符,必填
+}
+
+type Extras struct {
+	ServerId    int    `json:"serverId"`
+	Platform    string `json:"platform"`
+	SubPlatform string `json:"subPlatform"`
+	Bima        string `json:"bima"`
+	CpOrderId   string `json:"cpOrderId"`
+}
+
 func (this *Role) payInfoGet(goodsType, goodsId, count int32, rushStage, rushRound int32, cpOrderId uint64) (serverproto.ErrorCode, *serverproto.PayOrderSaveInfo) {
 	if count <= 0 {
 		return serverproto.ErrorCode_ERROR_PAY_ITEM_NO, nil
@@ -3820,8 +4003,8 @@ func (this *Role) payInfoGet(goodsType, goodsId, count int32, rushStage, rushRou
 		return serverproto.ErrorCode_ERROR_FAIL, nil
 	}
 
-	payRewardInfo.GoodsName = service.GetServiceConfig().Node.PayCallBack
-	util.ErrorF("uid:%v pay info platform:%v order:%v", this.GetUUid(), this.platform, payRewardInfo)
+	//payRewardInfo.GoodsName = service.GetServiceConfig().Node.PayCallBack
+	//util.ErrorF("uid:%v pay info platform:%v order:%v", this.GetUUid(), this.platform, payRewardInfo)
 	//if this.platform == SDKPlatform_YouYi_IOS || this.platform == "PC" {
 	//	payRewardInfo.GoodsName += ",1"
 	//}

+ 32 - 28
RO_Server_Trunk-branch_0.1.39/roserver/game/msg/login_msg.go

@@ -53,36 +53,39 @@ func init() {
 	serverproto.Handle_GAME_CSLoginReq = model.HandleBackendMessage(func(ev rocommon.ProcEvent, cliId model.ClientID) {
 		msg := ev.Msg().(*serverproto.CSLoginReq)
 		util.InfoF("receive CSLoginReq msg=%v cliId=%v", msg, cliId)
-		token := msg.PlatformToken
-		sign := getmd5("a8faf2c0acaaa5ef5d23860f219d7538" + token)
-		//tmpRequest := &XiaoQILoginResp{}
-		urlPath := "https://api.x7sy.com/user/check_v4_login?tokenkey=" + token + "&sign=" + sign
-		util.InfoF("urlPath=%v", urlPath)
-
-		resp, err := http.Get(urlPath)
-		if err != nil {
-			util.ErrorF("login sdk check error:%v", err)
-		}
-		defer resp.Body.Close() // 确保关闭响应体
-
-		// 读取响应体
-		body, _ := io.ReadAll(resp.Body)
-		res := string(body)
-		//err := httpNode.(rocommon.HTTPConnector).Request("GET", urlPath, tmpRequest)
-		util.InfoF("tmpRequest.ResMsg:%v", res)
+		var gguid []byte
 		var resRu XiaoQILoginResp
-		err = json.Unmarshal(body, &resRu)
-		if err != nil {
-			util.ErrorF("auth login json Unmarshal err:%v", err)
-		}
-		msg.OpenId = resRu.Data.Guid
-		gguid, _ := json.Marshal(resRu.Data)
-		if msg.OpenId == "" {
-			ack := &serverproto.SCLoginAck{
-				Error: int32(serverproto.ErrorCode_ERROR_FAIL),
+		if msg.Platform != "PC" {
+			token := msg.PlatformToken
+			sign := getmd5("a8faf2c0acaaa5ef5d23860f219d7538" + token)
+			//tmpRequest := &XiaoQILoginResp{}
+			urlPath := "https://api.x7sy.com/user/check_v4_login?tokenkey=" + token + "&sign=" + sign
+			util.InfoF("urlPath=%v", urlPath)
+
+			resp, err := http.Get(urlPath)
+			if err != nil {
+				util.ErrorF("login sdk check error:%v", err)
+			}
+			defer resp.Body.Close() // 确保关闭响应体
+
+			// 读取响应体
+			body, _ := io.ReadAll(resp.Body)
+			res := string(body)
+			//err := httpNode.(rocommon.HTTPConnector).Request("GET", urlPath, tmpRequest)
+			util.InfoF("tmpRequest.ResMsg:%v", res)
+			err = json.Unmarshal(body, &resRu)
+			if err != nil {
+				util.ErrorF("auth login json Unmarshal err:%v", err)
+			}
+			msg.OpenId = resRu.Data.Guid
+			gguid, _ = json.Marshal(resRu.Data)
+			if msg.OpenId == "" {
+				ack := &serverproto.SCLoginAck{
+					Error: int32(serverproto.ErrorCode_ERROR_FAIL),
+				}
+				model.ServiceReplay(ev, ack)
+				return
 			}
-			model.ServiceReplay(ev, ack)
-			return
 		}
 
 		if msg.GameVersion > 0 && msg.GameVersion != int32(serverproto.GameVersion_GameVersion_Main) {
@@ -130,6 +133,7 @@ func init() {
 		role.SetSelectZone(msg.SelectZone) //客户端登陆时选择的服务器zone
 		role.SetHardFight(0)
 		role.SetSdkJson(string(gguid))
+		role.SetSdkJson2(resRu.Data.Guid)
 
 		//利用缓存数据
 		if bHas {

+ 3 - 3
RO_Server_Trunk-branch_0.1.39/roserver/gmweb/main.go

@@ -167,9 +167,9 @@ func main() {
 		router.POST("/pay/hwQucikFromS1GmWeb", msg.WebPayHwQuickNotifyFromS1GmWeb) // 海外quick 1服转发到其他服,这里接收
 		//router.POST("/pay/nb", msg.WebPayNBSDKNotify)	// 畅梦牛逼SDK
 		router.POST("/pay/uni", msg.WebPayUniSDKNotify)
-		router.POST("/pay/nbh5", msg.WebPayNBH5Notify)       // 畅梦h5
-		router.POST("/pay/mycard", msg.WebPayNBH5Notify)     // mycard回调
-		router.POST("/pay/xiaoqi", msg.WebPayHwXiaoQiNotify) // 海外小七回调
+		router.POST("/pay/nbh5", msg.WebPayNBH5Notify)   // 畅梦h5
+		router.POST("/pay/mycard", msg.WebPayNBH5Notify) // mycard回调
+		r2.POST("/pay/xiaoqi", msg.WebPayHwXiaoQiNotify) // 海外小七回调
 
 		//
 		r1.GET("/guildbattle", msg.WebGmProcessGuildBattle)

+ 1 - 0
RO_Server_Trunk-branch_0.1.39/roserver/gmweb/msg/web_paymsg.go

@@ -1266,6 +1266,7 @@ func webPayNotify(webNtf *WebNotifyData, payAmount float32, c *gin.Context) stri
 		} else {
 			payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayFailed)
 			util.ErrorF("uid=%v WebPayQuickNotify failed payAmount:%v order=%v", payInfo.Uid, payAmount, payInfo)
+			return "FAILED"
 		}
 		payInfo.OrderProcessTime = util.GetTimeMilliseconds()
 		payInfo.SdkOrderId = webNtf.SdkOrderId //sdk订单id\

BIN
RO_Server_Trunk-branch_0.1.39/transfor/transfor