package main /* #cgo linux LDFLAGS: -ldl #cgo windows LDFLAGS: -lkernel32 #include #ifdef _WIN32 #include static void* dlopen(const char* filename, int flags) { return (void*)LoadLibraryA(filename); } static void dlclose(void* handle) { FreeLibrary((HMODULE)handle); } static void* dlsym(void* handle, const char* name) { return (void*)GetProcAddress((HMODULE)handle, name); } static const char* dlerror() { static char buf[256]; FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, buf, sizeof(buf), NULL); return buf; } #define RTLD_LAZY 0 #else #include #endif */ import "C" import ( "encoding/json" "fmt" "log" "net/http" "os" "path/filepath" "runtime" "unsafe" ) // 配置结构 type Configs struct { App struct { MaxRetryTimes int `json:"max_retry_times"` RateLimitDelay int `json:"rate_limit_delay"` Size int `json:"size"` DefaultUserAgent string `json:"default_user_agent"` } `json:"app"` API struct { LoginURL string `json:"login_url"` BookSearchURL string `json:"book_search_url"` ProductSearchURL string `json:"product_search_url"` } `json:"api"` Proxy struct { Servers string `json:"servers"` Username string `json:"username"` Password string `json:"password"` TailMachineCode string `json:"tail_machine_code"` TailCardKey string `json:"tail_card_key"` ProxyFilePath string `json:"proxy_file_path"` } `json:"proxy"` } // API响应结构 type APIResponseSO struct { Success bool `json:"success"` Message string `json:"message,omitempty"` GoodsNum string `json:"goods_num,omitempty"` PNum string `json:"pnum,omitempty"` Data interface{} `json:"data,omitempty"` Error string `json:"error,omitempty"` } // APIResp 简化的响应结构体 type APIRespSO struct { Success bool `json:"success"` Message string `json:"message"` Data interface{} `json:"data,omitempty"` } type SOManager struct { handle unsafe.Pointer } func NewSOManager(soPath string) (*SOManager, error) { // 根据平台调整库文件扩展名 if runtime.GOOS == "windows" { soPath = changeExtensionToDLL(soPath) } // 使用 dlopen 加载 .so 文件 cSoPath := C.CString(soPath) defer C.free(unsafe.Pointer(cSoPath)) handle := C.dlopen(cSoPath, C.RTLD_LAZY) if handle == nil { return nil, fmt.Errorf("加载SO文件失败: %s", C.GoString(C.dlerror())) } return &SOManager{handle: handle}, nil } func (m *SOManager) Close() { if m.handle != nil { C.dlclose(m.handle) } } func changeExtensionToDLL(path string) string { ext := filepath.Ext(path) if ext == ".so" { return path[:len(path)-len(ext)] + ".dll" } return path } // 获取函数指针 func (m *SOManager) getFunction(funcName string) (unsafe.Pointer, error) { cFuncName := C.CString(funcName) defer C.free(unsafe.Pointer(cFuncName)) symbol := C.dlsym(m.handle, cFuncName) if symbol == nil { return nil, fmt.Errorf("找不到函数 %s: %s", funcName, C.GoString(C.dlerror())) } return symbol, nil } // 初始化 func (m *SOManager) Initialize(configJSON string) (string, error) { function, err := m.getFunction("Initialize") if err != nil { return "", err } funcPtr := (*func(*C.char) *C.char)(unsafe.Pointer(&function)) configJSONC := C.CString(configJSON) defer C.free(unsafe.Pointer(configJSONC)) result := (*funcPtr)(configJSONC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 登录 func (m *SOManager) OutLogin(username, password string) (string, error) { function, err := m.getFunction("OutLogin") if err != nil { return "", err } funcPtr := (*func(*C.char, *C.char) *C.char)(unsafe.Pointer(&function)) usernameC := C.CString(username) passwordC := C.CString(password) defer C.free(unsafe.Pointer(usernameC)) defer C.free(unsafe.Pointer(passwordC)) result := (*funcPtr)(usernameC, passwordC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 获取用户信息 func (m *SOManager) OutGetUserMsg(token string) (string, error) { function, err := m.getFunction("OutGetUserMsg") if err != nil { return "", err } funcPtr := (*func(*C.char) *C.char)(unsafe.Pointer(&function)) tokenC := C.CString(token) defer C.free(unsafe.Pointer(tokenC)) result := (*funcPtr)(tokenC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 获取商品模版 func (m *SOManager) OutGetGoodsTplMsg(token, itemId, proxy string) (string, error) { function, err := m.getFunction("OutGetGoodsTplMsg") if err != nil { return "", err } funcPtr := (*func(*C.char, *C.char, *C.char) *C.char)(unsafe.Pointer(&function)) tokenC := C.CString(token) itemIdC := C.CString(itemId) proxyC := C.CString(proxy) defer C.free(unsafe.Pointer(tokenC)) defer C.free(unsafe.Pointer(itemIdC)) defer C.free(unsafe.Pointer(proxyC)) result := (*funcPtr)(tokenC, itemIdC, proxyC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 获取商品列表-已登的店铺 func (m *SOManager) OutGetGoodsListMsgFromSelfShop(token string, proxy string, itemSn string, priceMin string, priceMax string, startCreateTime int, endCreateTime int, requestType string, isItemSnEqual int, page int, size int) (string, error) { function, err := m.getFunction("OutGetGoodsListMsgFromSelfShop") if err != nil { return "", err } funcPtr := (*func(*C.char, *C.char, *C.char, *C.char, *C.char, C.int, C.int, *C.char, C.int, C.int, C.int) *C.char)(unsafe.Pointer(&function)) tokenC := C.CString(token) proxyC := C.CString(proxy) itemSnC := C.CString(itemSn) priceMinC := C.CString(priceMin) priceMaxC := C.CString(priceMax) startCreateTimeC := C.int(startCreateTime) endCreateTimeC := C.int(endCreateTime) requestTypeC := C.CString(requestType) isItemSnEqualC := C.int(isItemSnEqual) pageC := C.int(page) sizeC := C.int(size) defer C.free(unsafe.Pointer(tokenC)) defer C.free(unsafe.Pointer(proxyC)) defer C.free(unsafe.Pointer(itemSnC)) defer C.free(unsafe.Pointer(priceMinC)) defer C.free(unsafe.Pointer(priceMaxC)) defer C.free(unsafe.Pointer(requestTypeC)) result := (*funcPtr)(tokenC, proxyC, itemSnC, priceMinC, priceMaxC, startCreateTimeC, endCreateTimeC, requestTypeC, isItemSnEqualC, pageC, sizeC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 删除商品-已登的店铺 func (m *SOManager) OutDelGoodsFromSelfShop(token, itemId, proxy string) (string, error) { function, err := m.getFunction("OutDelGoodsFromSelfShop") if err != nil { return "", err } funcPtr := (*func(*C.char, *C.char, *C.char) *C.char)(unsafe.Pointer(&function)) tokenC := C.CString(token) itemIdC := C.CString(itemId) proxyC := C.CString(proxy) defer C.free(unsafe.Pointer(tokenC)) defer C.free(unsafe.Pointer(itemIdC)) defer C.free(unsafe.Pointer(proxyC)) result := (*funcPtr)(tokenC, itemIdC, proxyC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 新增商品 func (m *SOManager) OutAddGoods(token, proxy, formData string) (string, error) { function, err := m.getFunction("OutAddGoods") if err != nil { return "", err } funcPtr := (*func(*C.char, *C.char, *C.char) *C.char)(unsafe.Pointer(&function)) tokenC := C.CString(token) proxyC := C.CString(proxy) formDataC := C.CString(formData) defer C.free(unsafe.Pointer(tokenC)) defer C.free(unsafe.Pointer(proxyC)) defer C.free(unsafe.Pointer(formDataC)) result := (*funcPtr)(tokenC, proxyC, formDataC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 获取图片URL(官图和拍图)带有店铺过滤 func (m *SOManager) OutGetImageFilterShopId(token string, isbn string, shopId int, proxy string, isLiveImage int, isReturnMsg int) (string, error) { function, err := m.getFunction("OutGetImageFilterShopId") if err != nil { return "", err } funcPtr := (*func(*C.char, *C.char, C.int, *C.char, C.int, C.int) *C.char)(unsafe.Pointer(&function)) tokenC := C.CString(token) isbnC := C.CString(isbn) shopIdC := C.int(shopId) proxyC := C.CString(proxy) isLiveImageC := C.int(isLiveImage) isReturnMsgC := C.int(isReturnMsg) defer C.free(unsafe.Pointer(tokenC)) defer C.free(unsafe.Pointer(isbnC)) defer C.free(unsafe.Pointer(proxyC)) result := (*funcPtr)(tokenC, isbnC, shopIdC, proxyC, isLiveImageC, isReturnMsgC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 获取商品图片 func (m *SOManager) OutGetImageByIsbn(token string, isbn string, proxy string, isLiveImage int, isReturnMsg int) (string, error) { function, err := m.getFunction("OutGetImageByIsbn") if err != nil { return "", err } funcPtr := (*func(*C.char, *C.char, *C.char, C.int, C.int) *C.char)(unsafe.Pointer(&function)) tokenC := C.CString(token) isbnC := C.CString(isbn) proxyC := C.CString(proxy) isLiveImageC := C.int(isLiveImage) isReturnMsgC := C.int(isReturnMsg) defer C.free(unsafe.Pointer(tokenC)) defer C.free(unsafe.Pointer(isbnC)) defer C.free(unsafe.Pointer(proxyC)) result := (*funcPtr)(tokenC, isbnC, proxyC, isLiveImageC, isReturnMsgC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 获取商品列表通过店铺ID func (m *SOManager) OutGetGoodsListMsgByShopId(shopId int, proxy string, retPrice int, isImage int, sortType string, sort string, priceMin float32, priceMax float32, pageNum, returnNum int) (string, error) { function, err := m.getFunction("OutGetGoodsListMsgByShopId") if err != nil { return "", err } funcPtr := (*func(C.int, *C.char, C.int, C.int, *C.char, *C.char, C.double, C.double, C.int, C.int) *C.char)(unsafe.Pointer(&function)) shopIdC := C.int(shopId) proxyC := C.CString(proxy) retPriceC := C.int(retPrice) isImageC := C.int(isImage) sortTypeC := C.CString(sortType) sortC := C.CString(sort) priceMinC := C.double(priceMin) priceMaxC := C.double(priceMax) pageNumC := C.int(pageNum) returnNumC := C.int(returnNum) defer C.free(unsafe.Pointer(proxyC)) defer C.free(unsafe.Pointer(sortTypeC)) defer C.free(unsafe.Pointer(sortC)) result := (*funcPtr)(shopIdC, proxyC, retPriceC, isImageC, sortTypeC, sortC, priceMinC, priceMaxC, pageNumC, returnNumC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 获取商品信息通过商品详情链接 func (m *SOManager) OutGetGoodsMsgByDetailUrl(detailUrl, proxy string) (string, error) { function, err := m.getFunction("OutGetGoodsMsgByDetailUrl") if err != nil { return "", err } funcPtr := (*func(*C.char, *C.char) *C.char)(unsafe.Pointer(&function)) detailUrlC := C.CString(detailUrl) proxyC := C.CString(proxy) defer C.free(unsafe.Pointer(detailUrlC)) defer C.free(unsafe.Pointer(proxyC)) result := (*funcPtr)(detailUrlC, proxyC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 获取销量榜商品列表 func (m *SOManager) OutGetTopGoodsListMsg(catId int, proxy string) (string, error) { function, err := m.getFunction("OutGetTopGoodsListMsg") if err != nil { return "", err } funcPtr := (*func(C.int, *C.char) *C.char)(unsafe.Pointer(&function)) catIdC := C.int(catId) proxyC := C.CString(proxy) defer C.free(unsafe.Pointer(proxyC)) result := (*funcPtr)(catIdC, proxyC) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil } // 创建默认配置 func createDefaultConfig() Configs { var configs Configs // App配置 configs.App.MaxRetryTimes = 3 configs.App.RateLimitDelay = 1000 configs.App.Size = 10 configs.App.DefaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" // API配置 configs.API.LoginURL = "https://login.kongfz.com/Pc/Login/account" configs.API.BookSearchURL = "https://search.kongfz.com/pc-gw/search-web/client/pc/bookLib/keyword/list" configs.API.ProductSearchURL = "https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/list" // 代理配置 configs.Proxy.Servers = "http-dynamic.xiaoxiangdaili.com,http-dynamic-S02.xiaoxiangdaili.com,http-dynamic-S03.xiaoxiangdaili.com,http-dynamic-S04.xiaoxiangdaili.com" configs.Proxy.Username = "1297757178467602432" configs.Proxy.Password = "QgQBvP7f" configs.Proxy.TailMachineCode = "b7bf22a237ec692f13fcc2c43ee63252" configs.Proxy.TailCardKey = "DL_20_YK_1920acb2129844c2aabade3896560a9b" configs.Proxy.ProxyFilePath = "so/proxyConfig.so" return configs } // 获取当前可执行文件所在目录 func getExecutableDir() string { exePath, err := os.Executable() if err != nil { return "." } return filepath.Dir(exePath) } func main() { http.HandleFunc("/api/kfzShopBookInfo", handleGetKFZShopBookInfo) port := "8080" log.Printf("🚀 服务器启动在端口 %s", port) if err := http.ListenAndServe(":"+port, nil); err != nil { log.Fatalf("服务器启动失败: %v", err) } } func handleGetKFZShopBookInfo(w http.ResponseWriter, r *http.Request) { // 设置响应头 w.Header().Set("Content-Type", "application/json; charset=utf-8") // 只支持GET请求 if r.Method != http.MethodGet { sendErrorResponse(w, http.StatusMethodNotAllowed, "只支持GET方法") return } // 加载SO manager, err := NewSOManager("so/kongfz.so") if err != nil { log.Printf("初始化SO管理器失败: %v", err) sendErrorResponse(w, http.StatusInternalServerError, "初始化SO管理器失败") return } defer manager.Close() log.Println("✅ SO加载成功") // 使用默认配置初始化 config := createDefaultConfig() configJSON, err := json.Marshal(config) if err != nil { log.Printf("序列化配置失败: %v", err) sendErrorResponse(w, http.StatusInternalServerError, "序列化配置失败") return } result, err := manager.Initialize(string(configJSON)) if err != nil { log.Printf("初始化失败: %v", err) sendErrorResponse(w, http.StatusInternalServerError, "初始化失败") return } var initResp APIResponseSO if err := json.Unmarshal([]byte(result), &initResp); err != nil { log.Printf("解析初始化响应失败: %v", err) sendErrorResponse(w, http.StatusInternalServerError, "解析初始化响应失败") return } if !initResp.Success { log.Printf("初始化失败: %s", initResp.Message) sendErrorResponse(w, http.StatusInternalServerError, "初始化失败: "+initResp.Message) return } log.Println("✅ SO初始化成功") // 登录示例 user, err := manager.OutLogin("18904056801", "Long6166@@") if err != nil { log.Printf("登录失败: %v", err) } else { log.Printf("登录结果: %s", user) } // 解析token var data APIResponseSO if err := json.Unmarshal([]byte(user), &data); err != nil { log.Printf("解析登录响应失败: %v", err) } else { var token string if dataMap, ok := data.Data.(map[string]interface{}); ok { if tk, exists := dataMap["token"]; exists { token = tk.(string) log.Printf("获取到Token: %s", token) // 使用token获取用户信息 msg, err := manager.OutGetUserMsg(token) if err != nil { log.Printf("获取用户信息失败: %v", err) } else { log.Printf("用户信息: %s", msg) } } else { log.Println("Token 不存在") } } else { log.Println("Data 格式不正确") } } // 返回成功响应 response := APIRespSO{ Success: true, Message: "SO调用成功", } json.NewEncoder(w).Encode(response) } // 发送错误响应 func sendErrorResponse(w http.ResponseWriter, statusCode int, message string) { response := APIRespSO{ Success: false, Message: message, } w.WriteHeader(statusCode) json.NewEncoder(w).Encode(response) }