diff --git a/src/server/conf/server.json b/src/server/conf/server.json index 21d7fca4..f756a1c7 100644 --- a/src/server/conf/server.json +++ b/src/server/conf/server.json @@ -28,6 +28,7 @@ "RedisAddr":"127.0.0.1", "RedisPort" :"6379", "RedisPwd" :"", + "GoogleVerify":true, "RemoteAddr":"host.docker.internal:9001" diff --git a/src/server/game/PlayerFunc.go b/src/server/game/PlayerFunc.go index 53c67d19..4f40ce74 100644 --- a/src/server/game/PlayerFunc.go +++ b/src/server/game/PlayerFunc.go @@ -1,10 +1,7 @@ package game import ( - "encoding/json" "fmt" - "io" - "net/http" "server/GoUtil" "server/MergeConst" mergeCluster "server/cluster" @@ -22,6 +19,7 @@ import ( "server/game/mod/order" "server/game/mod/playroom" proto "server/msg" + "server/pay" "server/pkg/github.com/name5566/leaf/log" "sort" ) @@ -414,33 +412,23 @@ func GoogleVerify(p *Player, OrderSn, ProduceId, Token string) (*db.SqlChargeOrd if Order.PayStatus != MergeConst.ORDER_STATUS_IDLE { return nil, fmt.Errorf("订单已经支付") } - PackageName := "com.DefaultCompany.PetHomeMergeStory" - accessToken := "ya29.a0ARW5m75hnUnTbdLYAMW_0GTZSC1JY0GkPZ2fVqXGexVnPoDLoTviRTMtGVUmkG18F9tf2mmLeaRh7gPYYRAm145rtifW_J8_WUn0rhdOEpqU23vAsdCo1v2aArMsjw2dPHBf5ZCYBPirW_3ckL3MC1VzI4akvY3gt3EMz7U0aCgYKAR0SARISFQHGX2MipUmvPZgSya_iDJWbczKpnA0175" - url := fmt.Sprintf("https://www.googleapis.com/androidpublisher/v3/applications/%s/purchases/products/%s/tokens/%s?access_token=%s", - PackageName, ProduceId, Token, accessToken) - resp, err := http.Get(url) + AccessToken, err := pay.PostRefreshToken() if err != nil { return nil, err } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("failed to get data: %s", resp.Status) - } - - body, err := io.ReadAll(resp.Body) + OrderInfo, err := pay.GetOrder(ProduceId, Token, AccessToken.AccessToken) if err != nil { return nil, err } - res := make(map[string]interface{}) - log.Debug(string(body)) - err = json.Unmarshal(body, &res) - if err != nil { - return nil, err + if OrderInfo.ConsumptionState == pay.PAY_STATUS_FAIL { + return nil, fmt.Errorf("订单支付失败") + } + if OrderInfo.DeveloperPayload != OrderSn { + return nil, fmt.Errorf("订单号不一致") } Order.PayTime = GoUtil.Now() - Order.PayChannelOrderId = res["orderId"].(string) - Order.PayStatus = res["consumptionState"].(int) + Order.PayChannelOrderId = OrderInfo.OrderId + Order.PayStatus = OrderInfo.ConsumptionState Order.ProductName = ProduceId err = db.UpdatePlayerChargeData(Order) if err != nil { diff --git a/src/server/pay/google.go b/src/server/pay/google.go new file mode 100644 index 00000000..87a96bf5 --- /dev/null +++ b/src/server/pay/google.go @@ -0,0 +1,103 @@ +package pay + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "time" +) + +var ( + PackageName = "com.DefaultCompany.PetHomeMergeStory" //包名 + GrantType = "refresh_token" + ClientId = "757279522891-nrfqc345ng13d92br5cd579e1k7f2jsj.apps.googleusercontent.com" //客户端id + ClientSecret = "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" //客户端秘钥 + RefreshToken = "1//0ewdqw7P83uNRCgYIARAAGA4SNwF-L9IreCVIYzd-6T5Cz0J-UoAqdbGL7AmB849q_YKy7CbvJIjmvwQelezgs1utmU4nDI4_kWU" //RefreshToken,上面第二步获取的 +) + +const ( + PAY_STATUS_SUCCESS = 1 + PAY_STATUS_FAIL = 0 +) + +type TokenInfo struct { + AccessToken string `json:"access_token"` + ExpiresIn int `json:"expires_in"` + Scope string `json:"scope"` + TokenType string `json:"token_type"` +} + +type OrderInfo struct { + Kind string `json:"kind"` + PurchaseTimeMillis string `json:"purchaseTimeMillis"` // 支付时间, 毫秒 + PurchaseState int `json:"purchaseState"` // 是否付费: 0 已支付, 1 取消 + ConsumptionState int `json:"consumptionState"` // 是否被消费: 0 未消费, 1 已消费 + DeveloperPayload string `json:"developerPayload"` // 开发者透传参数 + OrderId string `json:"orderId"` // 谷歌订单号 + AcknowledgementState int `json:"acknowledgementState"` // 支付类型: 0 测试, 1 真实 +} + +// 获取token凭证 +func PostRefreshToken() (*TokenInfo, error) { + client := &http.Client{ + Timeout: 10 * time.Second, + } + + var resp *http.Response + var err error + for i := 0; i < 3; i++ { // 重试3次 + resp, err = client.PostForm("https://accounts.google.com/o/oauth2/token", url.Values{ + "grant_type": {GrantType}, + "client_id": {ClientId}, + "client_secret": {ClientSecret}, + "refresh_token": {RefreshToken}, + }) + if err == nil { + break + } + fmt.Printf("PostToken attempt %d failed: %v\n", i+1, err) + time.Sleep(2 * time.Second) // 等待2秒后重试 + } + if err != nil { + return nil, fmt.Errorf("PostToken err:%v", err) + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Println("PostToken body err:", err) + } + fmt.Println("token:", string(body)) + info := new(TokenInfo) + err = json.Unmarshal(body, &info) + if err != nil { + return nil, fmt.Errorf("PostToken Unmarshal err:%v", err) + } + fmt.Println("token info:", info) + return info, nil +} + +// 获取订单信息 +func GetOrder(productId, token, accessToken string) (*OrderInfo, error) { + client := &http.Client{} + resp, err := client.Get("https://www.googleapis.com/androidpublisher/v3/applications/" + + PackageName + "/purchases/products/" + productId + "/tokens/" + token + "?access_token=" + accessToken + "") + if err != nil { + return nil, fmt.Errorf("GetOrder err:%v", err) + } + + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Println("GetOrder body err:", err) + } + fmt.Println("GetOrder:", string(body)) + info := new(OrderInfo) + err = json.Unmarshal(body, &info) + if err != nil { + return nil, fmt.Errorf("GetOrder Unmarshal err:%v", err) + } + fmt.Println("GetOrder info:", info) + return info, nil +}