daShangDao_kfzgw-info/dyso.go

497 lines
15 KiB
Go

package main
/*
#cgo linux LDFLAGS: -ldl
#cgo windows LDFLAGS: -lkernel32
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
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 <dlfcn.h>
#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)
}