feat: 初始化 Wails + React + Go 桌面应用模板

- Wails v2.16.0 + React 19 + TypeScript + Vite 7
- 插件系统(build tag 控制编译,plugin.json 运行时配置)
- 支付插件(授权、账号、订单、退款、账单)
- 高并发基础设施(任务池、批量处理器、限流器、环形缓冲、管道)
- Windows 系统托盘(Win32 API)
- CodeGraph 索引 + .memory 记忆包
- 默认图标 assets/icon.png
This commit is contained in:
2026-09-17 19:31:17 +08:00
commit 1ea8c9da9c
57 changed files with 6305 additions and 0 deletions

149
internal/payment/service.go Normal file
View File

@@ -0,0 +1,149 @@
package payment
import (
"context"
"encoding/json"
"fmt"
)
// Service 支付业务层,内部封装 Client,对外暴露方法
type Service struct {
client *Client
cfg Config
}
// NewService 创建支付服务
func NewService(cfg Config) *Service {
return &Service{
client: NewClient(cfg),
cfg: cfg,
}
}
// GetClient 获取底层 HTTP 客户端(供高级用法)
func (s *Service) GetClient() *Client {
return s.client
}
// Login 登录授权,获取 access_token
func (s *Service) Login(ctx context.Context) (map[string]any, error) {
token, err := s.client.GetToken(ctx)
if err != nil {
return nil, err
}
return map[string]any{
"success": true,
"access_token": token.AccessToken,
"expires_in": token.ExpiresIn,
"message": "授权成功",
}, nil
}
// CheckAuth 查询授权状态
func (s *Service) CheckAuth(ctx context.Context) (map[string]any, error) {
token, err := s.client.GetToken(ctx)
if err != nil {
return map[string]any{"success": false, "message": "授权失效,请重新登录"}, err
}
return map[string]any{
"success": true,
"access_token": token.AccessToken,
"expires_in": token.ExpiresIn,
"message": "授权有效",
}, nil
}
// Refresh 主动刷新令牌
func (s *Service) Refresh(ctx context.Context) (map[string]any, error) {
token, err := s.client.RefreshToken(ctx)
if err != nil {
return nil, err
}
return map[string]any{
"success": true,
"access_token": token.AccessToken,
"expires_in": token.ExpiresIn,
"message": "续期成功",
}, nil
}
// GetAccountInfo 获取授权账号信息
func (s *Service) GetAccountInfo(ctx context.Context) (map[string]any, error) {
raw, err := s.client.Get(ctx, "/v1/account/info", nil)
if err != nil {
return nil, fmt.Errorf("get account info: %w", err)
}
return parseAPIResponse(raw)
}
// QueryOrder 通过 order_id 查询订单
func (s *Service) QueryOrder(ctx context.Context, orderID string) (map[string]any, error) {
raw, err := s.client.Get(ctx, "/v1/orders/"+orderID, nil)
if err != nil {
return nil, fmt.Errorf("query order: %w", err)
}
return parseAPIResponse(raw)
}
// QueryOrderByOutNo 通过商户订单号查询
func (s *Service) QueryOrderByOutNo(ctx context.Context, outTradeNo string) (map[string]any, error) {
raw, err := s.client.Get(ctx, "/v1/orders", map[string]string{"out_trade_no": outTradeNo})
if err != nil {
return nil, fmt.Errorf("query order by out_no: %w", err)
}
return parseAPIResponse(raw)
}
// RequestRefund 申请退款
func (s *Service) RequestRefund(ctx context.Context, req map[string]any) (map[string]any, error) {
raw, err := s.client.Post(ctx, "/v1/refunds", nil, req)
if err != nil {
return nil, fmt.Errorf("request refund: %w", err)
}
return parseAPIResponse(raw)
}
// GetBill 分页获取账单
func (s *Service) GetBill(ctx context.Context, page, pageSize int) (map[string]any, error) {
params := map[string]string{
"page": fmt.Sprintf("%d", page),
"page_size": fmt.Sprintf("%d", pageSize),
}
raw, err := s.client.Get(ctx, "/v1/bills", params)
if err != nil {
return nil, fmt.Errorf("get bill: %w", err)
}
return parseAPIResponse(raw)
}
// GetBillByDate 按日期范围查账单
func (s *Service) GetBillByDate(ctx context.Context, startDate, endDate string) (map[string]any, error) {
params := map[string]string{
"start_date": startDate,
"end_date": endDate,
}
raw, err := s.client.Get(ctx, "/v1/bills/range", params)
if err != nil {
return nil, fmt.Errorf("get bill by date: %w", err)
}
return parseAPIResponse(raw)
}
// ─────────────────────────────────────────────
// 内部辅助
// ─────────────────────────────────────────────
func parseAPIResponse(raw []byte) (map[string]any, error) {
var result struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
if err := json.Unmarshal(raw, &result); err != nil {
return nil, err
}
if result.Code != 0 {
return nil, fmt.Errorf("api error code=%d msg=%s", result.Code, result.Message)
}
return map[string]any{"success": true, "data": result.Data, "message": result.Message}, nil
}