第一版

This commit is contained in:
zyj
2026-02-09 16:05:56 +08:00
parent fcdc5b8f2d
commit 514d7f9b0e
11 changed files with 1137 additions and 365 deletions

164
services/order.go Normal file
View File

@@ -0,0 +1,164 @@
package services
import (
"fmt"
"log"
"strings"
"time"
"github.com/go-rod/rod"
)
// OrderResult 下单结果
type OrderResult struct {
Success bool
Message string
}
// Order 订单提交服务
type Order struct {
page *rod.Page
}
// NewOrder 创建订单服务
func NewOrder(page *rod.Page) *Order {
return &Order{page: page}
}
// 提交订单按钮选择器列表
var submitSelectors = []string{
"#submitOrder > div > div.btnBox--p9CumEtE > div.btn--QDjHtErD", // 淘宝新版提交按钮
}
// WaitForConfirmPage 等待订单确认页加载
func (o *Order) WaitForConfirmPage(timeout time.Duration) error {
log.Println("[订单] 等待订单确认页加载...")
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
url := o.page.MustEval("() => window.location.href").String()
if o.isConfirmPage(url) {
log.Printf("[订单] 已进入订单确认页: %s", url)
o.page.MustWaitLoad()
time.Sleep(500 * time.Millisecond)
return nil
}
time.Sleep(100 * time.Millisecond)
}
return fmt.Errorf("等待订单确认页超时")
}
// Refresh 刷新当前订单确认页
func (o *Order) Refresh() {
log.Println("[订单] 刷新订单确认页...")
o.page.MustReload().MustWaitLoad()
o.page.MustWaitIdle()
log.Println("[订单] 刷新完成")
}
// CanSubmit 检测当前订单页是否可以提交(按钮存在且未被禁用)
func (o *Order) CanSubmit() bool {
for _, sel := range submitSelectors {
el, err := o.page.Timeout(1 * time.Second).Element(sel)
if err != nil || el == nil {
continue
}
// 检查按钮是否被禁用class 含 disabled / 属性 disabled 等)
className, _ := el.Attribute("class")
if className != nil && strings.Contains(*className, "disabled") {
log.Printf("[订单] 按钮存在但被禁用: %s", sel)
return false
}
disabledAttr, _ := el.Attribute("disabled")
if disabledAttr != nil {
log.Printf("[订单] 按钮存在但 disabled 属性: %s", sel)
return false
}
log.Printf("[订单] ✅ 按钮可点击: %s", sel)
return true
}
// 还可以检查页面上是否有"该商品暂时无法购买"之类的提示
pageText := o.page.MustEval(`() => document.body.innerText`).String()
if strings.Contains(pageText, "无法购买") ||
strings.Contains(pageText, "暂不可售") ||
strings.Contains(pageText, "已下架") ||
strings.Contains(pageText, "未开始") {
log.Println("[订单] 页面提示商品暂时无法购买")
return false
}
log.Println("[订单] 未找到提交按钮")
return false
}
// RefreshUntilCanSubmit 循环刷新订单页,直到可以提交,返回时表示可以立即点击提交
func (o *Order) RefreshUntilCanSubmit(interval time.Duration, maxAttempts int) bool {
for i := 1; i <= maxAttempts; i++ {
log.Printf("[订单] 第 %d/%d 次检测是否可购买...", i, maxAttempts)
if o.CanSubmit() {
log.Println("[订单] ✅ 商品可购买!")
return true
}
if i < maxAttempts {
time.Sleep(interval)
o.Refresh()
}
}
log.Println("[订单] 已达最大检测次数,商品仍不可购买")
return false
}
// Submit 点击"提交订单"按钮
func (o *Order) Submit() *OrderResult {
log.Println("[订单] 点击提交订单...")
for _, sel := range submitSelectors {
el, err := o.page.Timeout(2 * time.Second).Element(sel)
if err == nil && el != nil {
el.MustClick()
log.Printf("[订单] 已点击提交按钮: %s", sel)
time.Sleep(1 * time.Second)
return o.checkResult()
}
}
return &OrderResult{
Success: false,
Message: "未找到提交订单按钮",
}
}
// checkResult 检查下单结果
func (o *Order) checkResult() *OrderResult {
time.Sleep(2 * time.Second)
url := o.page.MustEval("() => window.location.href").String()
log.Printf("[订单] 提交后 URL: %s", url)
if strings.Contains(url, "cashier") ||
strings.Contains(url, "pay") ||
strings.Contains(url, "alipay") {
return &OrderResult{
Success: true,
Message: "抢购成功!请尽快完成付款",
}
}
return &OrderResult{
Success: false,
Message: fmt.Sprintf("提交后仍在: %s", url),
}
}
// isConfirmPage 判断 URL 是否为订单确认页
func (o *Order) isConfirmPage(url string) bool {
return strings.Contains(url, "buy.taobao.com") ||
strings.Contains(url, "buyertrade")
}