├── .gitattributes ├── .env ├── LICENSE ├── README.md └── main.go /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | # fragment.com 接口配置 2 | ResHash= "" # fragment.com 生成的hash值 3 | ResCookie= "" # fragment.com 生成的cookie值 4 | 5 | 6 | # 开通会员 参数配置 7 | OpenDuration= 3 # 开通日期 3 6 12 单位月 8 | OpenUserName= "" # 开通会员的用户名 9 | 10 | 11 | # 钱包配置 付款助记词 12 | WalletMnemonic= "" # 钱包助记词 用空格分隔 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 MCG LAB 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 关于本项目 2 | 3 | Telegram自动开会员源代码 基于 `Golang` ,这是一个完整的24小时全自动开通TG会员的代码,如果你会一点技术,可无缝对接至你的机器人实现24小时自动代开。 4 | 5 | ## 开始 6 | ~~这只是一个demo版本,没有写配置文件,使用之前,你应该详细阅读源代码里的备注,修改应该代码里备注需要修改的地方。~~ 7 | 请仔细查看`.env`配置文件的说明,如配置错误导致付款以后会员未开通,自行负责。 8 | 9 | **如不会获取配置文件的 `COOKIE` 与 `Hash` 请进交流群自行询问,或动手能力强的自行研究。** 10 | 11 | ### 安装环境 12 | 项目运行基于`Golang`,你需要先安装`Golang` 13 | 14 | + Windows 15 | > https://go.dev/ 前往Golang官方网站进行下载安装,如不会建议Google。 16 | + Linux 17 | - Centos 18 | > yum install golang 19 | - Ubuntu 20 | > sudo apt-get install golang 21 | 22 | ### 安装依赖 23 | 24 | + golang 25 | > go mod init 26 | go mod tidy 27 | 或者 28 | go install 29 | 30 | ### 运行OR编译 31 | + Windows 32 | > 直接运行 33 | go run main.go 34 | 编译运行 35 | go build . 36 | + Linux 37 | > 同上,如需在windows下交叉编译Linux 请自行 `golang 交叉编译` 38 | 39 | 40 | ## 实现逻辑 41 | 42 | 1. 通过解析https://fragment.com的数据 43 | 2. 指定开通会员的用户名 44 | 3. 解析出相关Payload 45 | 4. 携带Payload进行Ton支付 46 | 5. 支付完成,开通完成。 47 | 48 | ## 技术交流/意见反馈 49 | 50 | + MCG技术交流群 https://t.me/MCG_Club 51 | 52 | ## AD -- 免费领取国际信用卡 53 | >免费领取VISA卡,万事达卡,充值USDT即可随便刷 54 | 可绑微信、支付宝、美区AppStore消费 55 | 24小时自助开卡充值 无需KYC 56 | 无需人工协助,用户可自行免费注册,后台自助实现入金、开卡、绑卡、销卡、查询等操作,支持无限开卡、在线接码。 57 | ✅支持 OpenAi 人工智能 chatGPT PLUS 开通 58 | ✅支持 开通Telegram飞机会员 59 | ➡️➡️➡️ [点击领取你的国际信用卡](https://t.me/pikabaobot?start=0480f979-3) 60 | 61 | ## AD -- 机器人推广 62 | 63 | 查币机器人 - 链上信息查询:[查币机](https://t.me/QueryTokenBot) 64 | > 可查地址信息 代币实时价格等等 65 | 66 | 兑币机 - TRX自动兑换:[兑币机](https://t.me/ConvertTrxBot) 67 | > 自用兑币机,并不是开源版机器人!!! 68 | 69 | 波场能量机器人:[波场能量机器人](https://t.me/BuyEnergysBot) 70 | > 波场能量租用,有能量时转账USDT不扣TRX,为你节省50-70%的TRX 71 | 72 | TG会员秒开机器人:[TG会员秒开-全自动发货](https://t.me/BuySvipBot) 73 | > 24小时自动开通Telegram Premium会员,只需一个用户名即可开通。 74 | 75 | ## 许可证 76 | 77 | 根据 MIT 许可证分发。打开 [LICENSE.txt](LICENSE.txt) 查看更多内容。 78 | 79 | 80 |

(返回顶部)

81 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "encoding/base64" 7 | "encoding/json" 8 | "errors" 9 | "fmt" 10 | "io/ioutil" 11 | "log" 12 | "net/http" 13 | "net/url" 14 | "os" 15 | "strconv" 16 | "strings" 17 | "time" 18 | "unicode" 19 | 20 | "github.com/joho/godotenv" 21 | "github.com/xssnick/tonutils-go/address" 22 | "github.com/xssnick/tonutils-go/liteclient" 23 | "github.com/xssnick/tonutils-go/tlb" 24 | "github.com/xssnick/tonutils-go/ton" 25 | "github.com/xssnick/tonutils-go/ton/wallet" 26 | ) 27 | 28 | type PaymentService struct { 29 | } 30 | 31 | type RequestPayload struct { 32 | Query string 33 | Months int 34 | Recipient string 35 | ID string 36 | ShowSender int 37 | Method string 38 | } 39 | 40 | var ( 41 | UserName string = os.Getenv("OpenUserName") // 需要开通的用户名 42 | Duration string = os.Getenv("OpenDuration") // 需要开通的月份 43 | Hash string = os.Getenv("ResHash") // 接口的hash 44 | Cookie string = os.Getenv("ResCookie") // 接口的 cookie 45 | apiURL string = fmt.Sprintf("https://fragment.com/api/v1/%s", Hash) 46 | Mnemonic string = os.Getenv("WalletMnemonic") // 钱包助记词 47 | ) 48 | 49 | func main() { 50 | // 初始化配置文件 51 | err := godotenv.Load() 52 | if err != nil { 53 | log.Fatal("配置文件加载失败,请检查!", err) 54 | } 55 | // 创建 PaymentService 实例 56 | ps := &PaymentService{} 57 | duration, err := strconv.ParseInt(Duration, 10, 64) 58 | if err != nil { 59 | log.Println("Error:", err) 60 | return 61 | } 62 | // 获取对方信息 63 | payload1 := RequestPayload{ 64 | Query: UserName, //需要开通的用户名 65 | Months: int(duration), //需要开通的月份 66 | Method: "searchPremiumGiftRecipient", 67 | } 68 | result1, err := ps.SendRequest(payload1) 69 | if err != nil { 70 | log.Println("Error:", err) 71 | return 72 | } 73 | recipient := result1["recipient"].(string) 74 | log.Println("Result recipient:", recipient) 75 | // 获取 reqid 76 | payload2 := RequestPayload{ 77 | Recipient: recipient, 78 | Months: int(duration), //需要开通的月份 79 | Method: "initGiftPremiumRequest", 80 | } 81 | result2, err := ps.SendRequest(payload2) 82 | if err != nil { 83 | log.Println("Error:", err) 84 | return 85 | } 86 | reqId := result2["req_id"].(string) 87 | log.Println("Result reqId:", reqId) 88 | // 确认订单 89 | ConfirmOrder := RequestPayload{ 90 | ID: reqId, 91 | ShowSender: 1, 92 | Method: "getGiftPremiumLink", 93 | } 94 | ConfirmOrderResult, err := ps.SendRequest(ConfirmOrder) 95 | if err != nil { 96 | log.Println("Error:", err) 97 | return 98 | } 99 | currentTime := time.Now() 100 | expireTime := ConfirmOrderResult["expire_after"].(float64) 101 | fiveMinutesLater := currentTime.Add(time.Duration(expireTime) * time.Second) 102 | log.Println("订单过期时间:", fiveMinutesLater.Format("2006-01-02 15:04:05")) 103 | // 获取payload 104 | payload, amount, err := ps.GetRawRequest(reqId) 105 | if err != nil { 106 | log.Println("Error:", err) 107 | } 108 | log.Println("Result payload:", payload) 109 | transferTon(amount, payload) 110 | 111 | } 112 | 113 | func (ps *PaymentService) SendRequest(payload RequestPayload) (map[string]interface{}, error) { 114 | client := &http.Client{} 115 | 116 | data := url.Values{} 117 | if payload.Query != "" { 118 | data.Set("query", payload.Query) 119 | } 120 | if payload.Months != 0 { 121 | data.Set("months", strconv.Itoa(payload.Months)) 122 | } 123 | if payload.Recipient != "" { 124 | data.Set("recipient", payload.Recipient) 125 | } 126 | if payload.ID != "" { 127 | data.Set("id", payload.ID) 128 | } 129 | if payload.ShowSender != 0 { 130 | data.Set("show_sender", strconv.Itoa(payload.ShowSender)) 131 | } 132 | data.Set("method", payload.Method) 133 | req, err := http.NewRequest("POST", apiURL, bytes.NewBufferString(data.Encode())) 134 | if err != nil { 135 | return nil, err 136 | } 137 | req.Header.Set("Content-Type", "application/x-www-form-urlencoded") 138 | req.Header.Set("Cookie", Cookie) 139 | 140 | resp, err := client.Do(req) 141 | if err != nil { 142 | return nil, err 143 | } 144 | defer resp.Body.Close() 145 | 146 | body, err := ioutil.ReadAll(resp.Body) 147 | if err != nil { 148 | return nil, err 149 | } 150 | var result map[string]interface{} 151 | err = json.Unmarshal(body, &result) 152 | if err != nil { 153 | return nil, err 154 | } 155 | method := data.Get("method") 156 | switch method { 157 | case "searchPremiumGiftRecipient": 158 | if ok, exists := result["ok"]; !exists || !ok.(bool) { 159 | return nil, errors.New("请求失败") 160 | } 161 | found, ok := result["found"].(map[string]interface{}) 162 | if !ok { 163 | return nil, errors.New("invalid 'found' field in the response") 164 | } 165 | recipient, ok := found["recipient"].(string) 166 | if !ok { 167 | return nil, errors.New("invalid 'recipient' field in the 'found' object") 168 | } 169 | log.Printf("recipient: %v\n", recipient) 170 | return found, nil 171 | case "initGiftPremiumRequest": 172 | req_id, ok := result["req_id"].(string) 173 | if !ok { 174 | return nil, errors.New("invalid 'req_id' field in the 'found' object") 175 | } 176 | log.Printf("req_id: %v\n", req_id) 177 | return result, nil 178 | case "getGiftPremiumLink": 179 | if ok, exists := result["ok"]; !exists || !ok.(bool) { 180 | return nil, errors.New("请求失败") 181 | } 182 | //fmt.Printf("result: %v\n", result) 183 | _, ok := result["expire_after"].(float64) 184 | if !ok { 185 | return nil, errors.New("invalid 'expire_after' field in the 'found' object") 186 | } 187 | return result, nil 188 | default: 189 | return nil, errors.New("invalid method") 190 | } 191 | 192 | } 193 | 194 | func (p *PaymentService) GetRawRequest(id string) (string, string, error) { 195 | url := fmt.Sprintf("https://fragment.com/tonkeeper/rawRequest?id=%s", id) 196 | client := &http.Client{} 197 | req, err := http.NewRequest("GET", url, nil) 198 | if err != nil { 199 | return "", "", err 200 | } 201 | req.Header.Set("Content-Type", "application/x-www-form-urlencoded") 202 | req.Header.Set("Cookie", Cookie) 203 | resp, err := client.Do(req) 204 | if err != nil { 205 | return "", "", err 206 | } 207 | defer resp.Body.Close() 208 | 209 | body, err := ioutil.ReadAll(resp.Body) 210 | if err != nil { 211 | return "", "", err 212 | } 213 | 214 | var result map[string]interface{} 215 | json.Unmarshal(body, &result) 216 | 217 | bodyObj, ok := result["body"].(map[string]interface{}) 218 | if !ok { 219 | return "", "", errors.New("invalid 'body' field in the response") 220 | } 221 | 222 | params, ok := bodyObj["params"].(map[string]interface{}) 223 | if !ok { 224 | return "", "", errors.New("invalid 'params' field in the 'body' object") 225 | } 226 | 227 | messages, ok := params["messages"].([]interface{}) 228 | if !ok || len(messages) == 0 { 229 | return "", "", errors.New("invalid 'messages' field in the 'params' object") 230 | } 231 | 232 | firstMessage, ok := messages[0].(map[string]interface{}) 233 | if !ok { 234 | return "", "", errors.New("invalid 'messages' field in the 'params' object") 235 | } 236 | amount, ok := firstMessage["amount"].(float64) 237 | payamount := fmt.Sprintf("%g", amount/1e9) 238 | if !ok { 239 | 240 | return "", "", errors.New("invalid 'amount' field in the first message object") 241 | } 242 | payload, ok := firstMessage["payload"].(string) 243 | if !ok { 244 | return "", "", errors.New("invalid 'payload' field in the first message object") 245 | } 246 | 247 | log.Printf("支付金额: %v\n", payamount) 248 | // base64 decode payload 249 | padding := len(payload) % 4 250 | if padding > 0 { 251 | payload += strings.Repeat("=", 4-padding) 252 | } 253 | log.Printf("payload: %v\n", payload) 254 | decodedPayload, err := base64.StdEncoding.DecodeString(payload) 255 | if err != nil { 256 | fmt.Println("Error:", err) 257 | } 258 | decodedPayloadStr := string(decodedPayload) 259 | // 使用正则表达式匹配目标字符串 260 | match := extractRefFromPayload(decodedPayloadStr) 261 | if len(match) == 8 { 262 | log.Println("提取到的字符:", match) 263 | } else { 264 | log.Println("未找到匹配的字符") 265 | } 266 | return match, payamount, nil 267 | } 268 | 269 | func extractRefFromPayload(payload string) string { 270 | decodedPayloadStr := payload 271 | 272 | refStr := "" 273 | i := strings.Index(decodedPayloadStr, "#") 274 | 275 | //fmt.Println("Input:", decodedPayloadStr) 276 | 277 | if i != -1 { 278 | // 开始从 "Ref#" 之后的位置提取字符 279 | for i = i + 1; i < len(decodedPayloadStr) && len(refStr) < 8; i++ { 280 | if unicode.IsLetter(rune(decodedPayloadStr[i])) || unicode.IsNumber(rune(decodedPayloadStr[i])) { 281 | refStr += string(decodedPayloadStr[i]) 282 | } 283 | } 284 | } else { 285 | fmt.Println("Ref# not found") 286 | } 287 | 288 | return refStr 289 | } 290 | 291 | func transferTon(amount string, payload string) { 292 | client := liteclient.NewConnectionPool() 293 | 294 | // 这里使用官方的节点配置文件 比较慢 你可以自创节点 295 | configUrl := "https://ton-blockchain.github.io/global.config.json" 296 | err := client.AddConnectionsFromConfigUrl(context.Background(), configUrl) 297 | if err != nil { 298 | panic(err) 299 | } 300 | 301 | // 初始化 ton api lite 连接包装器 302 | api := ton.NewAPIClient(client) 303 | 304 | // 如果我们想将所有请求路由到同一个节点,我们可以使用它 305 | ctx := client.StickyContext(context.Background()) 306 | 307 | // 我们需要新的区块信息来运行 get 方法 308 | b, err := api.CurrentMasterchainInfo(ctx) 309 | if err != nil { 310 | log.Fatalln("get block err:", err.Error()) 311 | return 312 | } 313 | 314 | addr := address.MustParseAddr("EQBAjaOyi2wGWlk-EDkSabqqnF-MrrwMadnwqrurKpkla9nE") //这里是官方的钱包地址 请勿更改 否则开通会员将不会到账 315 | 316 | // 我们使用 WaitForBlock 来确保块准备好, 317 | // 它是可选的,但可以让我们避免 liteserver 块未准备好错误 318 | res, err := api.WaitForBlock(b.SeqNo).GetAccount(ctx, b, addr) 319 | if err != nil { 320 | log.Fatalln("get account err:", err.Error()) 321 | return 322 | } 323 | 324 | log.Printf("Is active: %v\n", res.IsActive) 325 | if res.IsActive { 326 | log.Printf("Status: %s\n", res.State.Status) 327 | log.Printf("Balance: %s TON\n", res.State.Balance.TON()) 328 | if res.Data != nil { 329 | log.Printf("Data: %s\n", res.Data.Dump()) 330 | } 331 | } 332 | 333 | fmt.Printf("\nTransactions:\n") 334 | 335 | words := strings.Split(Mnemonic, " ") 336 | 337 | w, err := wallet.FromSeed(api, words, wallet.V4R2) 338 | 339 | if err != nil { 340 | log.Fatalln("FromSeed err:", err.Error()) 341 | return 342 | } 343 | 344 | log.Println("wallet address:", w.Address()) 345 | 346 | block, err := api.CurrentMasterchainInfo(ctx) 347 | if err != nil { 348 | log.Fatalln("CurrentMasterchainInfo err:", err.Error()) 349 | return 350 | } 351 | 352 | balance, err := w.GetBalance(ctx, block) 353 | if err != nil { 354 | log.Fatalln("GetBalance err:", err.Error()) 355 | return 356 | } 357 | 358 | if balance.NanoTON().Uint64() >= 3000000 { 359 | addr := address.MustParseAddr("EQBAjaOyi2wGWlk-EDkSabqqnF-MrrwMadnwqrurKpkla9nE") //这里是官方的钱包地址 请勿更改 否则开通会员将不会到账 360 | // 创建消息 361 | comment, err := wallet.CreateCommentCell(fmt.Sprintf("Telegram Premium for %s months Ref#%s", Duration, payload)) //这里的3是开通3个月需要和上方的月份对应 362 | if err != nil { 363 | log.Fatalln("CreateComment err:", err.Error()) 364 | return 365 | } 366 | amount := tlb.MustFromTON(amount) 367 | 368 | log.Printf("付款地址: %s , 金额: %v\n", addr, amount) 369 | 370 | var messages []*wallet.Message 371 | messages = append(messages, &wallet.Message{ 372 | Mode: 1, 373 | InternalMessage: &tlb.InternalMessage{ 374 | Bounce: false, // 不允许回退 一般情况下不需要回退 375 | DstAddr: addr, 376 | Amount: amount, 377 | Body: comment, 378 | }, 379 | }) 380 | 381 | log.Println("发送付款请求并等待区块确认中...") 382 | 383 | // 发送交易 并等待区块确认 384 | tx, block, err := w.SendManyWaitTransaction(context.Background(), messages) 385 | if err != nil { 386 | log.Fatalln("Transfer err:", err.Error()) 387 | return 388 | } 389 | balance, err = w.GetBalance(context.Background(), block) 390 | if err != nil { 391 | log.Fatalln("GetBalance err:", err.Error()) 392 | return 393 | } 394 | 395 | log.Println("区块已确认,交易成功! 交易hash:", base64.StdEncoding.EncodeToString(tx.Hash)) 396 | log.Println("查看交易: https://tonscan.org/tx/" + base64.URLEncoding.EncodeToString(tx.Hash)) 397 | log.Println("钱包还剩余余额: ", balance.TON()) 398 | return 399 | } 400 | 401 | log.Println("not enough balance:", balance.TON()) 402 | } 403 | --------------------------------------------------------------------------------