mirror of
https://git.oceanpay.cc/danial/kami_scripts.git
synced 2025-12-18 21:12:33 +00:00
- 新增配置项 QueryURL,支持自定义查询地址 - 修改QueryCardInput结构体,调整字段名更准确 - 使用resty替代beego httplib,提升请求稳定性和重试能力 - 调整请求URL为kami-spider-monorepo服务地址 - 优化错误重试逻辑,针对验证码识别失败进行重试 - 调整响应解析和错误处理逻辑 - 更新order_service调用,传递新配置和请求参数 - 升级多个依赖包版本,提升模块稳定性和安全性 - 修正配置文件config.yaml中字段及格式,使配置更合理
165 lines
4.5 KiB
Go
165 lines
4.5 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/csv"
|
|
"encoding/json"
|
|
"order/internal/client"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/duke-git/lancet/v2/convertor"
|
|
"github.com/pkg/errors"
|
|
|
|
"order/internal/config"
|
|
"order/internal/interfaces"
|
|
|
|
"github.com/duke-git/lancet/v2/slice"
|
|
)
|
|
|
|
// OrderServiceImpl 订单服务实现
|
|
type OrderServiceImpl struct {
|
|
repo interfaces.OrderRepository
|
|
sender interfaces.OrderSender
|
|
logger interfaces.Logger
|
|
config *config.Config
|
|
}
|
|
|
|
// NewOrderService 创建订单服务实例
|
|
func NewOrderService(
|
|
repo interfaces.OrderRepository,
|
|
sender interfaces.OrderSender,
|
|
logger interfaces.Logger,
|
|
config *config.Config,
|
|
) interfaces.OrderService {
|
|
return &OrderServiceImpl{
|
|
repo: repo,
|
|
sender: sender,
|
|
logger: logger,
|
|
config: config,
|
|
}
|
|
}
|
|
|
|
// ProcessOrders 处理订单
|
|
func (s *OrderServiceImpl) ProcessOrders(ctx context.Context) error {
|
|
// 判断这个文件有没有,如果有,打开,没有就创建一个
|
|
filePath := "order.csv"
|
|
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
|
_, _ = os.Create(filePath)
|
|
}
|
|
// 从 csv 中读取最后一个匹配的 road_uid 和 bank_order_id
|
|
csvFile, err := os.OpenFile("order.csv", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
|
|
if err != nil {
|
|
s.logger.Error("打开文件失败", "error", err)
|
|
return err
|
|
}
|
|
defer func(csvFile *os.File) {
|
|
_ = csvFile.Close()
|
|
}(csvFile)
|
|
|
|
orders, err := s.repo.FindOrdersByReason(ctx, "不支持的骏卡", time.Now().Add(-2*time.Minute), time.Now().Add(1*time.Minute))
|
|
if err != nil {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
s.logger.Error("获取订单失败", "error", err)
|
|
}
|
|
return err
|
|
}
|
|
if len(orders) == 0 {
|
|
return nil
|
|
}
|
|
csvReader := csv.NewReader(csvFile)
|
|
// 读取所有数据
|
|
records, err2 := csvReader.ReadAll()
|
|
if err2 != nil {
|
|
s.logger.Error("读取文件失败", "error", err)
|
|
}
|
|
|
|
// 筛选符合条件的数据
|
|
existBankOrders := slice.Filter(slice.Map(records, func(index int, record []string) string {
|
|
if len(record) >= 1 {
|
|
return record[0]
|
|
}
|
|
return ""
|
|
}), func(index int, record string) bool {
|
|
return record != ""
|
|
})
|
|
existBankOrders = slice.Unique(existBankOrders)
|
|
for _, order := range orders {
|
|
if slice.Contain(existBankOrders, order.BankOrderID) {
|
|
continue
|
|
}
|
|
s.logger.Info("开始处理订单", "order", order, "已有订单数量", len(existBankOrders))
|
|
heePayClient := client.NewHeePayClient()
|
|
exRedeemValue := RedeemCardInfo{}
|
|
if err = json.Unmarshal([]byte(convertor.ToString(order.ExValue)), &exRedeemValue); err != nil {
|
|
s.logger.Error("解析exValue失败", "error", err)
|
|
continue
|
|
}
|
|
heePayResp, err3 := heePayClient.QueryCard(ctx, &client.QueryCardInput{
|
|
QueryURL: s.config.QueryURL,
|
|
OrderId: order.BankOrderID,
|
|
CardNumber: exRedeemValue.CardNo,
|
|
CardPassword: exRedeemValue.Data,
|
|
})
|
|
if err3 != nil {
|
|
s.logger.Error("查询卡密失败", "error", err)
|
|
continue
|
|
}
|
|
merchants := s.config.Merchants
|
|
merchant, ok := slice.FindBy(merchants, func(index int, item *struct {
|
|
Name string `mapstructure:"name"`
|
|
SubmitURL string `mapstructure:"submit_url"`
|
|
ProductCode string `mapstructure:"product_code"`
|
|
PayKey string `mapstructure:"pay_key"`
|
|
PaySecret string `mapstructure:"pay_secret"`
|
|
CardType string `mapstructure:"card_type"`
|
|
}) bool {
|
|
return strings.Contains(heePayResp.Data.CardType, item.CardType)
|
|
})
|
|
if !ok {
|
|
s.logger.Error("未找到匹配的商户", "error", heePayResp)
|
|
continue
|
|
}
|
|
if err = s.sender.Send(ctx, order, merchant.ProductCode, merchant.PayKey, merchant.PaySecret, merchant.SubmitURL); err != nil {
|
|
s.logger.Error("提交订单失败", "error", err)
|
|
continue
|
|
}
|
|
csvWriter := csv.NewWriter(csvFile)
|
|
if err = csvWriter.Write([]string{order.BankOrderID}); err != nil {
|
|
s.logger.Error("写入文件失败", "error", err)
|
|
}
|
|
csvWriter.Flush()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type RedeemCardInfo struct {
|
|
FaceType string `json:"faceType"` // 面额
|
|
RecoveryType string `json:"RecoveryType,omitempty"` // 类型 2 仅卡密 8 卡号卡密
|
|
Data string `json:"data"` // 卡密
|
|
CardNo string `json:"cardNo,omitempty"` // 卡号
|
|
}
|
|
|
|
func (d *RedeemCardInfo) GetFaceType() string {
|
|
return d.FaceType
|
|
}
|
|
|
|
func (d *RedeemCardInfo) GetFaceTypeFloat(ctx context.Context) float64 {
|
|
result, err := convertor.ToFloat(d.FaceType)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (d *RedeemCardInfo) GetRecoveryType() string {
|
|
return d.RecoveryType
|
|
}
|
|
|
|
func (d *RedeemCardInfo) ToJson() string {
|
|
jsonStr, _ := json.Marshal(d)
|
|
return string(jsonStr)
|
|
}
|