(原) 个人微信收费功能应用

原创文章,请后转载,并注明出处。

之前的方案类似,这次使用了Umi-OCR,当前的最新版本支持HTTP服务,占用资源也不多。可惜一点的是它是一个GUI应用。

直接附上代码,原理就是:1.adb手机截图 2.OCR识别 3.判断付费(这段代码没有)

package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"time"
)

// OCR请求结构体
type OCRRequest struct {
	Base64  string            `json:"base64"`
	Options map[string]string `json:"options,omitempty"`
}

func main() {
	// 1. 通过ADB截取屏幕
	imagePath, err := captureScreen()
	if err != nil {
		panic(fmt.Sprintf("截图失败: %v", err))
	}
	defer os.Remove(imagePath) // 清理临时文件

	// 2. 读取图片并编码为Base64
	base64Str, err := imageToBase64(imagePath)
	if err != nil {
		panic(fmt.Sprintf("Base64编码失败: %v", err))
	}

	// 3. 构造请求体
	reqData := OCRRequest{
		Base64: base64Str,
		Options: map[string]string{
			"data.format": "text",
		},
	}

	// 4. 发送HTTP请求
	url := "http://127.0.0.1:1224/api/ocr"
	resp, err := sendOCRRequest(url, reqData)
	if err != nil {
		panic(fmt.Sprintf("API请求失败: %v", err))
	}

	fmt.Printf("识别结果: %+v\n", resp)
}

// ADB截图实现(需确保adb在PATH中)
func captureScreen() (string, error) {
	timestamp := time.Now().Format("20060102_150405")
	remotePath := fmt.Sprintf("/sdcard/screenshot_%s.png", timestamp)
	localPath := fmt.Sprintf("screenshot_%s.png", timestamp)

	// 执行截图命令
	cmd := exec.Command("adb", "shell", "screencap", "-p", remotePath)
	if err := cmd.Run(); err != nil {
		return "", fmt.Errorf("执行ADB截图命令失败: %v", err)
	}

	// 拉取截图到本地
	cmd = exec.Command("adb", "pull", remotePath, localPath)
	if err := cmd.Run(); err != nil {
		return "", fmt.Errorf("拉取截图文件失败: %v", err)
	}

	// 清理设备端文件
	exec.Command("adb", "shell", "rm", remotePath).Run()

	return localPath, nil
}

// 图片转Base64(不包含Data URI前缀)
func imageToBase64(path string) (string, error) {
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer file.Close()

	bytes, err := io.ReadAll(file)
	if err != nil {
		return "", err
	}

	return base64.StdEncoding.EncodeToString(bytes), nil
}

// 定义API响应结构体(仅保留data字段)
type OCRResponse struct {
	Data interface{} `json:"data"` // 根据实际API返回结构定义具体类型
}

// 发送OCR请求(支持自定义选项)
func sendOCRRequest(url string, reqData OCRRequest) (interface{}, error) {
	jsonData, err := json.Marshal(reqData)
	if err != nil {
		return nil, fmt.Errorf("JSON序列化失败: %v", err)
	}

	resp, err := http.Post(url, "application/json", bytes.NewReader(jsonData))
	if err != nil {
		return nil, fmt.Errorf("HTTP请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 仅解析data字段
	var response struct {
		Data interface{} `json:"data"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
		return nil, fmt.Errorf("JSON解析失败: %v", err)
	}

	return response.Data, nil
}
[ 关闭聊天 ]