feat(supplier): 添加 FatSix 支付功能及相关逻辑

- 新增 FatSix 支付任务类型及其处理逻辑
- 实现 OCR 识别验证码功能,优化支付请求流程
- 更新相关依赖库版本,确保兼容性和性能
- 增强日志记录,便于追踪支付请求和响应
- 重构部分代码以提高可读性和维护性
This commit is contained in:
danial
2025-08-07 20:18:21 +08:00
parent 5a2b8078f0
commit 14ad15fe08
10 changed files with 640 additions and 109 deletions

71
go.mod
View File

@@ -9,10 +9,10 @@ require github.com/beego/beego/v2 v2.3.8
require (
github.com/PuerkitoBio/goquery v1.10.3
github.com/bytedance/gopkg v0.1.2
github.com/bytedance/sonic v1.13.3
github.com/bytedance/sonic v1.14.0
github.com/carlmjohnson/requests v0.24.3
github.com/duke-git/lancet/v2 v2.3.6
github.com/forgoer/openssl v1.6.0
github.com/duke-git/lancet/v2 v2.3.7
github.com/forgoer/openssl v1.7.0
github.com/go-resty/resty/v2 v2.16.5
github.com/go-sql-driver/mysql v1.9.3
github.com/go-stomp/stomp/v3 v3.1.3
@@ -20,26 +20,26 @@ require (
github.com/iunary/fakeuseragent v1.0.0
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/prometheus/client_golang v1.22.0
github.com/redis/go-redis/v9 v9.9.0
github.com/prometheus/client_golang v1.23.0
github.com/redis/go-redis/v9 v9.12.0
github.com/rs/xid v1.6.0
github.com/shopspring/decimal v1.4.0
github.com/stretchr/testify v1.10.0
github.com/widuu/gojson v0.0.0-20170212122013-7da9d2cd949b
go.opentelemetry.io/contrib/bridges/otelzap v0.11.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0
go.opentelemetry.io/otel v1.36.0
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0
go.opentelemetry.io/otel/log v0.12.2
go.opentelemetry.io/otel/sdk v1.36.0
go.opentelemetry.io/otel/sdk/log v0.12.2
go.opentelemetry.io/otel/sdk/metric v1.36.0
go.opentelemetry.io/otel/trace v1.36.0
go.opentelemetry.io/contrib/bridges/otelzap v0.12.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0
go.opentelemetry.io/otel v1.37.0
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.13.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.37.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0
go.opentelemetry.io/otel/log v0.13.0
go.opentelemetry.io/otel/sdk v1.37.0
go.opentelemetry.io/otel/sdk/log v0.13.0
go.opentelemetry.io/otel/sdk/metric v1.37.0
go.opentelemetry.io/otel/trace v1.37.0
go.uber.org/zap v1.27.0
golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792
)
require (
@@ -47,41 +47,42 @@ require (
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/cenkalti/backoff/v5 v5.0.2 // indirect
github.com/bytedance/sonic/loader v0.3.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
github.com/cloudwego/base64x v0.1.6 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dubonzi/otelresty v1.5.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.64.0 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/prometheus/common v0.65.0 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/metric v1.36.0 // indirect
go.opentelemetry.io/proto/otlp v1.7.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.17.0 // indirect
golang.org/x/crypto v0.38.0 // indirect
golang.org/x/net v0.40.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/grpc v1.72.2 // indirect
golang.org/x/arch v0.19.0 // indirect
golang.org/x/crypto v0.40.0 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b // indirect
google.golang.org/grpc v1.74.2 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

74
go.sum
View File

@@ -18,17 +18,25 @@ github.com/bytedance/gopkg v0.1.2 h1:8o2feYuxknDpN+O7kPwvSXfMEKfYvJYiA2K7aonoMEQ
github.com/bytedance/gopkg v0.1.2/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0=
github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/carlmjohnson/requests v0.24.3 h1:LYcM/jVIVPkioigMjEAnBACXl2vb42TVqiC8EYNoaXQ=
github.com/carlmjohnson/requests v0.24.3/go.mod h1:duYA/jDnyZ6f3xbcF5PpZ9N8clgopubP2nK5i6MVMhU=
github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8=
github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -36,14 +44,20 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dubonzi/otelresty v1.5.0 h1:s0vBIxRSLBVDD1DenVpFa3Tb3fhptt5Ez6Sa756kJIQ=
github.com/dubonzi/otelresty v1.5.0/go.mod h1:N7leMFX3VT8Ncg10W7O1jgExSArAODW+RbYFH1rZFyo=
github.com/duke-git/lancet/v2 v2.3.6 h1:NKxSSh+dlgp37funvxLCf3xLBeUYa7VW1thYQP6j3Y8=
github.com/duke-git/lancet/v2 v2.3.6/go.mod h1:zGa2R4xswg6EG9I6WnyubDbFO/+A/RROxIbXcwryTsc=
github.com/duke-git/lancet/v2 v2.3.7 h1:nnNBA9KyoqwbPm4nFmEFVIbXeAmpqf6IDCH45+HHHNs=
github.com/duke-git/lancet/v2 v2.3.7/go.mod h1:zGa2R4xswg6EG9I6WnyubDbFO/+A/RROxIbXcwryTsc=
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/forgoer/openssl v1.6.0 h1:IueL+UfH0hKo99xFPojHLlO3QzRBQqFY+Cht0WwtOC0=
github.com/forgoer/openssl v1.6.0/go.mod h1:9DZ4yOsQmveP0aXC/BpQ++Y5TKaz5yR9+emcxmIZNZs=
github.com/forgoer/openssl v1.7.0 h1:yXbHlyR9IFdfo3Vs3cfLMsPzNxjM35rt6wr6czysheM=
github.com/forgoer/openssl v1.7.0/go.mod h1:nklnf8K63XPA3quw2vN7sfIeHNGovuOLvAhpFIF8sS8=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -66,6 +80,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/iunary/fakeuseragent v1.0.0 h1:QlxZqFFzb9oDd6p7478/AYeljJJwI74IRfxi/vs/Egs=
@@ -75,6 +91,8 @@ github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYW
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@@ -102,14 +120,22 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4=
github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
github.com/redis/go-redis/v9 v9.9.0 h1:URbPQ4xVQSQhZ27WMQVmZSo3uT3pL+4IdHVcYq2nVfM=
github.com/redis/go-redis/v9 v9.9.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/redis/go-redis/v9 v9.12.0 h1:XlVPGlflh4nxfhsNXPA8Qp6EmEfTo0rp8oaBzPipXnU=
github.com/redis/go-redis/v9 v9.12.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
@@ -140,36 +166,66 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/bridges/otelzap v0.11.0 h1:u2E32P7j1a/gRgZDWhIXC+Shd4rLg70mnE7QLI/Ssnw=
go.opentelemetry.io/contrib/bridges/otelzap v0.11.0/go.mod h1:pJPCLM8gzX4ASqLlyAXjHBEYxgbOQJ/9bidWxD6PEPQ=
go.opentelemetry.io/contrib/bridges/otelzap v0.12.0 h1:FGre0nZh5BSw7G73VpT3xs38HchsfPsa2aZtMp0NPOs=
go.opentelemetry.io/contrib/bridges/otelzap v0.12.0/go.mod h1:X2PYPViI2wTPIMIOBjG17KNybTzsrATnvPJ02kkz7LM=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY=
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 h1:tPLwQlXbJ8NSOfZc4OkgU5h2A38M4c9kfHSVc4PFQGs=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2/go.mod h1:QTnxBwT/1rBIgAG1goq6xMydfYOBKU6KTiYF4fp5zL8=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.13.0 h1:zUfYw8cscHHLwaY8Xz3fiJu+R59xBnkgq2Zr1lwmK/0=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.13.0/go.mod h1:514JLMCcFLQFS8cnTepOk6I09cKWJ5nGHBxHrMJ8Yfg=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0 h1:gAU726w9J8fwr4qRDqu1GYMNNs4gXrU+Pv20/N1UpB4=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0/go.mod h1:RboSDkp7N292rgu+T0MgVt2qgFGu6qa1RpZDOtpL76w=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.37.0 h1:9PgnL3QNlj10uGxExowIDIZu66aVBwWhXmbOp1pa6RA=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.37.0/go.mod h1:0ineDcLELf6JmKfuo0wvvhAVMuxWFYvkTin2iV4ydPQ=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA=
go.opentelemetry.io/otel/log v0.12.2 h1:yob9JVHn2ZY24byZeaXpTVoPS6l+UrrxmxmPKohXTwc=
go.opentelemetry.io/otel/log v0.12.2/go.mod h1:ShIItIxSYxufUMt+1H5a2wbckGli3/iCfuEbVZi/98E=
go.opentelemetry.io/otel/log v0.13.0 h1:yoxRoIZcohB6Xf0lNv9QIyCzQvrtGZklVbdCoyb7dls=
go.opentelemetry.io/otel/log v0.13.0/go.mod h1:INKfG4k1O9CL25BaM1qLe0zIedOpvlS5Z7XgSbmN83E=
go.opentelemetry.io/otel/log/logtest v0.0.0-20250521073539-a85ae98dcedc h1:TU7eU/nib68C+4ZMQ5t4em5Jhf50kRorSCV4w+v65vo=
go.opentelemetry.io/otel/log/logtest v0.0.0-20250521073539-a85ae98dcedc/go.mod h1:4AsFc5k1BDLWm5jt0yagrodTEA9xS9McwcnYm+Jf73A=
go.opentelemetry.io/otel/log/logtest v0.13.0 h1:xxaIcgoEEtnwdgj6D6Uo9K/Dynz9jqIxSDu2YObJ69Q=
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
go.opentelemetry.io/otel/sdk/log v0.12.2 h1:yNoETvTByVKi7wHvYS6HMcZrN5hFLD7I++1xIZ/k6W0=
go.opentelemetry.io/otel/sdk/log v0.12.2/go.mod h1:DcpdmUXHJgSqN/dh+XMWa7Vf89u9ap0/AAk/XGLnEzY=
go.opentelemetry.io/otel/sdk/log v0.13.0 h1:I3CGUszjM926OphK8ZdzF+kLqFvfRY/IIoFq/TjwfaQ=
go.opentelemetry.io/otel/sdk/log v0.13.0/go.mod h1:lOrQyCCXmpZdN7NchXb6DOZZa1N5G1R2tm5GMMTpDBw=
go.opentelemetry.io/otel/sdk/log/logtest v0.0.0-20250521073539-a85ae98dcedc h1:uqxdywfHqqCl6LmZzI3pUnXT1RGFYyUgxj0AkWPFxi0=
go.opentelemetry.io/otel/sdk/log/logtest v0.0.0-20250521073539-a85ae98dcedc/go.mod h1:TY/N/FT7dmFrP/r5ym3g0yysP1DefqGpAZr4f82P0dE=
go.opentelemetry.io/otel/sdk/log/logtest v0.13.0 h1:9yio6AFZ3QD9j9oqshV1Ibm9gPLlHNxurno5BreMtIA=
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os=
go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo=
go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@@ -178,6 +234,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU=
golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
golang.org/x/arch v0.19.0 h1:LmbDQUodHThXE+htjrnmVD73M//D9GTH6wFZjyDkjyU=
golang.org/x/arch v0.19.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@@ -187,8 +245,12 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b h1:QoALfVG9rhQ/M7vYDScfPdWjGL9dlsVVM5VGh7aKoAA=
golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 h1:R9PFI6EUdfVKgwKjZef7QIwGcBKu86OEFpJ9nUEP2l4=
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
@@ -208,6 +270,8 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -232,6 +296,8 @@ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -252,6 +318,8 @@ golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -266,10 +334,16 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b h1:ULiyYQ0FdsJhwwZUwbaXpZF5yUE3h+RA+gxvBu37ucc=
google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:oDOGiMSXHL4sDTJvFvIB9nRQCGdLP1o/iVaqQK8zB+M=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b h1:zPKJod4w6F1+nRGDI9ubnXYhU9NSWoFAijkHkUXeTK8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8=
google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -5,11 +5,12 @@ import (
"encoding/json"
"fmt"
"gateway/internal/otelTrace"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"strings"
"time"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"github.com/beego/beego/v2/client/httplib"
"go.uber.org/zap"
)
@@ -55,11 +56,12 @@ const (
)
func (c *HeePayClient) QueryCard(ctx context.Context, input *QueryCardInput) (*QueryCardOutput, error) {
otelTrace.Span(ctx, "HeePayClient", "QueryCard", trace.WithAttributes(
ctx, span := otelTrace.Span(ctx, "HeePayClient", "QueryCard", trace.WithAttributes(
attribute.String("bankOrderId", input.OrderNo),
attribute.String("cardNo", input.CardNo),
attribute.String("cardPassword", input.CardPassword),
))
defer span.End()
var lastErr error
for i := range maxRetries {
client := httplib.NewBeegoRequestWithCtx(ctx,

View File

@@ -0,0 +1,57 @@
package client
import (
"bytes"
"context"
"encoding/json"
"fmt"
"gateway/internal/otelTrace"
"github.com/go-resty/resty/v2"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap"
)
type OCRClient struct {
}
func NewOCRClient() *OCRClient {
return &OCRClient{}
}
type CalcInput struct {
File []byte
FileName string
Category string
}
func (c *OCRClient) Calc(ctx context.Context, input *CalcInput) (string, error) {
ctx, span := otelTrace.Span(ctx, "OCRClient", "Calc", trace.WithAttributes(
attribute.String("fileName", input.FileName),
))
defer span.End()
if input.Category == "" {
input.Category = "calc"
}
resp, err := resty.New().R().SetFormData(map[string]string{
"category": input.Category,
}).SetFileReader("file", input.FileName, bytes.NewReader(input.File)).Post("http://kami_spider:8000/ocr/recognize")
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("识别验证码失败", zap.Error(err))
return "", err
}
respStr := struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data struct {
Text string `json:"text"`
} `json:"data"`
}{}
json.Unmarshal(resp.Body(), &respStr)
otelTrace.Logger.WithContext(ctx).Info("识别验证码返回", zap.Any("response", respStr))
if respStr.Code != 1 {
return "", fmt.Errorf("识别验证码失败: %s", respStr.Msg)
}
return respStr.Data.Text, nil
}

View File

@@ -9,13 +9,20 @@ import (
"gateway/internal/service/client"
"gateway/internal/service/supplier/third_party/pool/card_sender"
"gateway/internal/utils"
"math/rand/v2"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/beego/beego/v2/client/httplib"
"github.com/dubonzi/otelresty"
"github.com/duke-git/lancet/v2/convertor"
"github.com/go-resty/resty/v2"
"github.com/iunary/fakeuseragent"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap"
)
@@ -30,6 +37,15 @@ type cardTypeQuery struct {
}
func (c *cardTypeQuery) GetBalance(ctx context.Context) (balance float64, err error) {
ctx, span := otelTrace.Span(ctx, "cardTypeQuery", "GetBalance", trace.WithAttributes(
attribute.String("cardNo", c.CardNo),
attribute.String("channelCode", c.ChannelCode),
attribute.String("orderNo", c.OrderNo),
attribute.String("queryType", c.QueryType),
attribute.Float64("balance", c.Balance),
))
defer span.End()
switch c.QueryType {
case "xintian":
return c.xinTianQuery(ctx)
@@ -37,6 +53,8 @@ func (c *cardTypeQuery) GetBalance(ctx context.Context) (balance float64, err er
return c.kailiantongQuery(ctx)
case "jvnka":
return c.jvnkaQuery(ctx)
case "outletcard":
return c.outletCardQuery(ctx)
}
return c.Balance, nil
}
@@ -128,6 +146,86 @@ func (c *cardTypeQuery) xinTianQuery(ctx context.Context) (balance float64, err
return queryResp.Data.Balance / 100, nil
}
func (c *cardTypeQuery) outletCardQuery(ctx context.Context) (balance float64, err error) {
ua := fakeuseragent.RandomUserAgent()
webClient := resty.New().SetTimeout(5 * time.Second).SetRetryCount(3).SetHeaders(map[string]string{
"user-agent": ua,
}).SetHeaders(map[string]string{
"Origin": "https://card.outletcard.cn",
"Referer": "https://card.outletcard.cn/outlet/query",
})
otelresty.TraceClient(webClient, otelresty.WithTracerName("outlet_card_client"))
for range 10 {
resp, err := webClient.R().Get("https://card.outletcard.cn/web/captcha?rand=" + strconv.FormatFloat(rand.Float64(), 'f', -1, 64))
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("获取验证码失败", zap.Error(err))
return 0, errors.New("获取验证码失败")
}
ocrClient := client.NewOCRClient()
ocrResp, err := ocrClient.Calc(ctx, &client.CalcInput{
File: resp.Body(),
FileName: "captcha.jpg",
Category: "normal",
})
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("识别验证码失败", zap.Error(err))
continue
}
if len(ocrResp) != 5 {
continue
}
resp, err = webClient.R().SetFormData(map[string]string{
"card": c.CardNo,
"pass": c.CardPwd,
"code": ocrResp,
}).Post("https://card.outletcard.cn/outlet/query")
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("查询卡片状态失败", zap.Error(err))
continue
}
respStr := struct {
Code int `json:"code"`
Msg string `json:"msg"`
}{}
err = json.Unmarshal(resp.Body(), &respStr)
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("转换返回值失败", zap.Error(err), zap.String("response", string(resp.Body())))
continue
}
otelTrace.Logger.WithContext(ctx).Info("查询卡片状态返回", zap.Any("response", respStr), zap.Any("params", map[string]string{
"card": c.CardNo,
"pass": c.CardPwd,
"code": ocrResp,
}))
if respStr.Code != 0 && respStr.Msg == "验证码错误" {
continue
}
if respStr.Code != 0 {
return c.Balance, nil
}
succeedRespStr := struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data struct {
Card struct {
Total string `json:"total"`
} `json:"card"`
} `json:"data,omitempty"`
}{}
err = json.Unmarshal(resp.Body(), &succeedRespStr)
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("转换返回值失败", zap.Error(err), zap.String("response", string(resp.Body())))
return c.Balance, nil
}
balance, err = convertor.ToFloat(succeedRespStr.Data.Card.Total)
if err != nil || balance <= 0 {
return c.Balance, nil
}
return balance, nil
}
return c.Balance, nil
}
func (c *cardTypeQuery) kailiantongQuery(ctx context.Context) (balance float64, err error) {
if len(c.CardNo) != 19 {
return 0, errors.New("卡号无效")

View File

@@ -2,20 +2,17 @@ package third_party
import (
"context"
"encoding/json"
"gateway/internal/config"
"gateway/internal/otelTrace"
"gateway/internal/service/supplier"
"time"
"gateway/internal/models/merchant"
"gateway/internal/models/merchant_deploy"
"gateway/internal/models/order"
"gateway/internal/models/payfor"
"gateway/internal/models/road"
"gateway/internal/models/supply_model"
"gateway/internal/service"
"net/http"
"gateway/internal/service/supplier"
"gateway/internal/service/supplier/third_party/pool/card_sender"
"net/url"
"sort"
"strconv"
@@ -24,13 +21,11 @@ import (
"github.com/beego/beego/v2/server/web"
"github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/cryptor"
"github.com/duke-git/lancet/v2/formatter"
"github.com/duke-git/lancet/v2/maputil"
"github.com/duke-git/lancet/v2/netutil"
"github.com/duke-git/lancet/v2/pointer"
"github.com/duke-git/lancet/v2/structs"
"github.com/widuu/gojson"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap"
@@ -40,20 +35,10 @@ type FatSixImpl struct {
*web.Controller
}
type sendCardReq struct {
Mid string `json:"mid"` // 商户号
MerOrderTid string `json:"merOrderTid"` // 商户单号
Money string `json:"money"` // 金额
ChannelCode string `json:"channelCode"` // 通道编码
//ClientUserPayRemark string `json:"clientUserPayRemark"` // 付款人备注
//ClientUserId string `json:"clientUserId"` // 商户端用户Id
NotifyUrl string `json:"notifyUrl"`
}
func sign(params map[string]any, keys []string, paySecret string) string {
sort.Strings(keys)
str := ""
for i := 0; i < len(keys); i++ {
for i := range keys {
k := keys[i]
if len(convertor.ToString(params[k])) == 0 || k == "sign" {
continue
@@ -75,56 +60,48 @@ type sendCardResp struct {
} `json:"result"`
}
func (f *FatSixImpl) sendCard(ctx context.Context, jsonStr string, cardInfo supplier.RedeemCardInfo, attach string) (bool, *sendCardResp) {
response := &sendCardResp{}
req := sendCardReq{
Mid: gojson.Json(jsonStr).Get("mid").Tostring(),
MerOrderTid: attach,
Money: cardInfo.FaceType,
ChannelCode: gojson.Json(jsonStr).Get("channelCode").Tostring(),
NotifyUrl: config.GetConfig().GetSixFatNotifyUrl(),
}
params, _ := structs.ToMap(req)
params["sign"] = sign(params, maputil.Keys(params), gojson.Json(jsonStr).Get("paySecret").Tostring())
pretty, _ := formatter.Pretty(params)
otelTrace.Logger.WithContext(ctx).Info("请求参数:" + pretty)
body, err := json.Marshal(params)
func (f *FatSixImpl) sendCard(ctx context.Context, cardInfo supplier.RedeemCardInfo, orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) (bool, string) {
orderAmount, err := (&cardTypeQuery{
OrderNo: orderInfo.BankOrderId,
QueryType: gojson.Json(roadInfo.Params).Get("queryType").Tostring(),
CardNo: cardInfo.CardNo,
ChannelCode: gojson.Json(roadInfo.Params).Get("channelCode").Tostring(),
CardPwd: cardInfo.Data,
Balance: cardInfo.GetFaceTypeFloat(ctx),
}).GetBalance(ctx)
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("解析参数失败", zap.Error(err))
return false, response
return false, err.Error()
}
header := http.Header{}
header.Add("Content-Type", "application/x-www-form-urlencoded")
request := &netutil.HttpRequest{
Headers: header,
RawURL: "http://ti8lj4yj3am3mr4id0tl.itxitongsf.xyz/api/services/app/Api_PayOrder/CreateOrderPay",
Method: "POST",
Body: body,
}
httpClient := netutil.NewHttpClient()
httpClient.Timeout = 30 * time.Second
httpClient.Transport = otelhttp.NewTransport(http.DefaultTransport)
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
otelTrace.Logger.WithContext(ctx).Error("发送数据失败", zap.Error(err))
return false, response
}
err = httpClient.DecodeResponse(resp, &response)
if err != nil || pointer.IsNil(response) {
otelTrace.Logger.WithContext(ctx).Error("解析分解会结构失败", zap.Error(err), zap.Any("response", response))
return false, response
cardInfo.FaceType = strconv.FormatFloat(orderAmount, 'f', 2, 64)
merchantDeploy := merchant_deploy.GetMerchantDeployByUidAndRoadUid(ctx, merchantInfo.MerchantUid, roadInfo.RoadUid)
if merchantDeploy.MerchantUid == "" {
return false, "商户不存在"
}
pretty, _ = formatter.Pretty(response)
otelTrace.Logger.WithContext(ctx).Info("返回参数:" + pretty)
if response.Status == 0 {
return true, response
if merchantDeploy.SubmitStrategy == merchant_deploy.SUBMIT_STRATEGY_POOL {
if err := orderPoolService.PushOrder(ctx, card_sender.SendCardTask{
CardInfo: cardInfo,
RoadUid: roadInfo.RoadUid,
LocalOrderID: orderInfo.BankOrderId,
SendCardTaskType: card_sender.SendCardTaskTypeEnumFavorableClouds,
NeedQuery: gojson.Json(roadInfo.Params).Get("needQuery").Tostring() == "1",
}); err != nil {
otelTrace.Logger.WithContext(ctx).Error("推送订单失败", zap.Error(err))
return false, err.Error()
}
return true, "订单已提交"
}
return false, response
if err := orderPoolService.SubmitOrder(ctx, card_sender.SendCardTask{
CardInfo: cardInfo,
RoadUid: roadInfo.RoadUid,
LocalOrderID: orderInfo.BankOrderId,
SendCardTaskType: card_sender.SendCardTaskTypeEnumFavorableClouds,
NeedQuery: gojson.Json(roadInfo.Params).Get("needQuery").Tostring() == "1",
}); err != nil {
return false, err.Error()
}
return true, "订单已提交"
}
func (f *FatSixImpl) Scan(ctx context.Context, orderInfo order.OrderInfo, roadInfo road.RoadInfo, info3 merchant.MerchantInfo) supplier.ScanData {
@@ -137,14 +114,14 @@ func (f *FatSixImpl) Scan(ctx context.Context, orderInfo order.OrderInfo, roadIn
cdata := supplier.RedeemCardInfo{
FaceType: convertor.ToString(orderInfo.OrderAmount),
}
ok, response := f.sendCard(ctx, roadInfo.Params, cdata, orderInfo.BankOrderId)
ok, response := f.sendCard(ctx, cdata, orderInfo, roadInfo, info3)
if !ok {
return supplier.ScanData{
Status: "-1",
Msg: "订单有误,请稍后再试:" + convertor.ToString(response.ErrMsg),
Msg: "订单有误,请稍后再试:" + response,
BankNo: orderInfo.MerchantOrderId,
OrderNo: orderInfo.BankOrderId,
ReturnData: convertor.ToString(response.ErrMsg),
ReturnData: response,
}
}
scanData := supplier.ScanData{
@@ -152,16 +129,18 @@ func (f *FatSixImpl) Scan(ctx context.Context, orderInfo order.OrderInfo, roadIn
BankNo: orderInfo.MerchantOrderId,
OrderPrice: strconv.FormatFloat(orderInfo.OrderAmount, 'f', 2, 64),
Status: "00",
PayUrl: response.Result.PayUrl,
PayUrl: "",
Msg: "",
ReturnData: convertor.ToString(response.ErrMsg),
UpStreamOrderNo: response.Result.Tid,
ReturnData: response,
UpStreamOrderNo: "",
}
return scanData
}
func (f *FatSixImpl) PayNotify() {
ctx := f.Ctx.Request.Context()
ctx, span := otelTrace.Span(ctx, "FatSixImpl", "PayNotify")
defer span.End()
resp := struct {
MerOrderTid string `json:"merOrderTid"`

View File

@@ -0,0 +1,106 @@
package third_party
import (
"bytes"
"encoding/json"
"gateway/internal/config"
"gateway/internal/otelTrace"
"gateway/internal/utils"
"net/url"
"testing"
"github.com/beego/beego/v2/client/httplib"
"github.com/dubonzi/otelresty"
"github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/maputil"
"github.com/duke-git/lancet/v2/pointer"
"github.com/duke-git/lancet/v2/random"
"github.com/duke-git/lancet/v2/structs"
"github.com/go-resty/resty/v2"
"github.com/iunary/fakeuseragent"
"github.com/widuu/gojson"
"go.uber.org/zap"
)
func TestFatSixImpl_Scan(t *testing.T) {
jsonStr := `{"mid":"M200082","channelCode":"888","paySecret":"1bfc66113a6636005f32ad1ee0be04bc"}`
type sendCardReq struct {
Mid string `json:"mid"` // 商户号
MerOrderTid string `json:"merOrderTid"` // 商户单号
Money string `json:"money"` // 金额
ChannelCode string `json:"channelCode"` // 通道编码
NotifyUrl string `json:"notifyUrl"`
}
response := &sendCardResp{}
reqData := sendCardReq{
Mid: gojson.Json(jsonStr).Get("mid").Tostring(),
MerOrderTid: utils.GenerateId(),
Money: "10",
ChannelCode: gojson.Json(jsonStr).Get("channelCode").Tostring(),
NotifyUrl: config.GetConfig().GetSixFatNotifyUrl(),
}
req := httplib.NewBeegoRequestWithCtx(t.Context(),
"http://ti8lj4yj3am3mr4id0tl.itxitongsf.xyz/api/services/app/Api_PayOrder/CreateOrderPay",
"POST",
)
params, _ := structs.ToMap(reqData)
params["sign"] = sign(params, maputil.Keys(params), gojson.Json(jsonStr).Get("paySecret").Tostring())
for s, a := range params {
req.Param(s, convertor.ToString(a))
}
req.Header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
resp, err := req.String()
if err != nil || pointer.IsNil(response) {
otelTrace.Logger.WithContext(t.Context()).Error("解析分解结构失败", zap.Error(err))
}
otelTrace.Logger.WithContext(t.Context()).Info("返回参:", zap.Any("response", resp), zap.Any("params", params))
}
func TestFatSixImpl_SendCard(t *testing.T) {
ua := fakeuseragent.RandomUserAgent()
randStrList := random.RandStringSlice(random.Numeral+random.LowwerLetters, 1, 6)
client := resty.New().SetHeaders(map[string]string{
"user-agent": ua,
}).SetHeaders(map[string]string{
"Origin": "http://api.zbgj79.com",
})
// 配置 otelresty 追踪
otelresty.TraceClient(client, otelresty.WithTracerName("fat_six_client"))
// 请求会自动携带 Cookie
resp, err := client.R().SetQueryParamsFromValues(url.Values{
"rand": []string{
randStrList[0],
},
}).Get("http://api.zbgj79.com/captcha")
if err != nil {
t.Fatal(err)
}
resp2, err := client.R().SetFormData(map[string]string{
"category": "calc",
}).SetFileReader("file", "captcha.png", bytes.NewReader(resp.Body())).Post("http://127.0.0.1:8000/ocr/recognize")
if err != nil {
t.Fatal(err)
}
respStr := struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data struct {
Text string `json:"text"`
} `json:"data"`
}{}
json.Unmarshal(resp2.Body(), &respStr)
if respStr.Code != 1 {
t.Fatal(respStr.Msg)
}
resp, err = client.R().SetFormData(map[string]string{
"order_no": "202508071638303009631185",
"card_no": "123456",
"pass": "123456",
"captcha": respStr.Data.Text,
}).SetHeaders(map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
"Referer": "http://api.zbgj79.com/pay?order_no=202508071638303009631185",
}).Post("http://api.zbgj79.com/pay")
otelTrace.Logger.WithContext(t.Context()).Info("返回参:", zap.Any("response", resp))
}

View File

@@ -33,6 +33,7 @@ const (
SendCardTaskTypeEnumFavorableClouds SendCardTaskEnum = "FAVORABLE_CLOUDS"
SendCardTaskTypeEnumWowsPay SendCardTaskEnum = "WOWSPAY"
SendCardTaskTypeEnumFlyFish SendCardTaskEnum = "FLYFISH"
SendCardTaskTypeEnumFatSix SendCardTaskEnum = "FATSIX"
)
func (sendCardTaskTypeEnum SendCardTaskEnum) String() string {
@@ -57,6 +58,8 @@ func (sendCardTaskTypeEnum SendCardTaskEnum) GetSendCardTaskType() sendCardTaskT
return &SendCardTaskTypeWowsPay{}
case SendCardTaskTypeEnumFlyFish:
return &SendCardTaskTypeFlyFish{}
case SendCardTaskTypeEnumFatSix:
return &SendCardTaskTypeFatSix{}
}
return nil
}

View File

@@ -0,0 +1,207 @@
package card_sender
import (
"context"
"encoding/json"
"errors"
"fmt"
"gateway/internal/config"
"gateway/internal/models/road"
"gateway/internal/otelTrace"
"gateway/internal/service/client"
"gateway/internal/utils"
"net/url"
"slices"
"sort"
"strings"
"time"
"github.com/beego/beego/v2/client/httplib"
"github.com/dubonzi/otelresty"
"github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/cryptor"
"github.com/duke-git/lancet/v2/maputil"
"github.com/duke-git/lancet/v2/random"
"github.com/duke-git/lancet/v2/structs"
"github.com/go-resty/resty/v2"
"github.com/iunary/fakeuseragent"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"github.com/widuu/gojson"
"go.uber.org/zap"
)
type SendCardTaskTypeFatSix struct {
sendCardTaskTypeSendCardTaskBase
}
func (s *SendCardTaskTypeFatSix) sign(params map[string]any, keys []string, paySecret string) string {
sort.Strings(keys)
str := ""
for i := 0; i < len(keys); i++ {
k := keys[i]
if len(convertor.ToString(params[k])) == 0 || k == "sign" {
continue
}
str += k + "=" + convertor.ToString(params[k]) + "&"
}
str += paySecret
return strings.ToUpper(cryptor.Md5String(str))
}
func (s *SendCardTaskTypeFatSix) CreateOrder(ctx context.Context, roadUid string, faceValue float64) (OrderPoolItem, error) {
orderPoolItem := OrderPoolItem{}
roadInfo := road.GetRoadInfoByRoadUid(ctx, roadUid)
orderNo := utils.GenerateId()
reqData := struct {
Mid string `json:"mid"` // 商户号
MerOrderTid string `json:"merOrderTid"` // 商户单号
Money string `json:"money"` // 金额
ChannelCode string `json:"channelCode"` // 通道编码
NotifyUrl string `json:"notifyUrl"`
}{
Mid: gojson.Json(roadInfo.Params).Get("mid").Tostring(),
MerOrderTid: orderNo,
Money: fmt.Sprintf("%.2f", faceValue),
ChannelCode: gojson.Json(roadInfo.Params).Get("channelCode").Tostring(),
NotifyUrl: config.GetConfig().GetSixFatNotifyUrl(),
}
req := httplib.NewBeegoRequestWithCtx(ctx,
"http://ti8lj4yj3am3mr4id0tl.itxitongsf.xyz/api/services/app/Api_PayOrder/CreateOrderPay",
"POST",
)
params, _ := structs.ToMap(reqData)
params["sign"] = s.sign(params, maputil.Keys(params), gojson.Json(roadInfo.Params).Get("paySecret").Tostring())
for t, a := range params {
req.Param(t, convertor.ToString(a))
}
req.Header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
resp, err := req.String()
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("解析分解会结构失败", zap.Error(err))
return orderPoolItem, err
}
otelTrace.Logger.WithContext(ctx).Info("查询参数", zap.Any("response", resp), zap.Any("params", params))
responseData := &struct {
Status int `json:"status"`
ErrMsg string `json:"errMsg"`
Result struct {
Tid string `json:"tid"`
MerOrderTid string `json:"merOrderTid"`
PayUrl string `json:"payUrl"`
PayOrderStatus int `json:"payOrderStatus"`
} `json:"result"`
}{}
err = json.Unmarshal([]byte(resp), responseData)
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("json解析失败", zap.Error(err), zap.Any("response", resp))
return orderPoolItem, err
}
if responseData.Status != 0 {
err = fmt.Errorf("创建订单失败:%s状态吗不正确", responseData.ErrMsg)
return orderPoolItem, err
}
return OrderPoolItem{
OrderID: orderNo,
CreateTime: time.Now(),
PayURL: responseData.Result.PayUrl,
RoadUid: roadUid,
ProductCode: "",
FaceValue: faceValue,
DispatchCount: 0,
SendCardTaskType: SendCardTaskTypeEnumMyself,
}, nil
}
func (s *SendCardTaskTypeFatSix) HandleSendCardTask(ctx context.Context, orderItem OrderPoolItem, task SendCardTask) error {
ctx, span := otelTrace.Span(ctx, "HandleSendCardTask", "fat_six", trace.WithAttributes(
attribute.String("order_id", orderItem.OrderID),
attribute.String("bankOrderId", task.LocalOrderID),
attribute.String("cardNo", task.CardInfo.CardNo),
attribute.String("cardPassword", task.CardInfo.Data),
))
defer span.End()
queryUrl, err := url.Parse(orderItem.PayURL)
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("解析支付URL失败", zap.Error(err))
return err
}
orderNo := queryUrl.Query().Get("order_no")
for range 3 {
ua := fakeuseragent.RandomUserAgent()
randStrList := random.RandStringSlice(random.Numeral+random.LowwerLetters, 1, 6)
webClient := resty.New().SetTimeout(5 * time.Second).SetRetryCount(3).SetHeaders(map[string]string{
"user-agent": ua,
}).SetHeaders(map[string]string{
"Origin": "http://api.zbgj79.com",
})
// 配置 otelresty 追踪
otelresty.TraceClient(webClient, otelresty.WithTracerName("fat_six_client"))
// 请求会自动携带 Cookie
resp, err := webClient.R().SetQueryParamsFromValues(url.Values{
"rand": []string{
randStrList[0],
},
}).Get("http://api.zbgj79.com/captcha")
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("获取验证码失败", zap.Error(err))
continue
}
ocrClient := client.NewOCRClient()
ocrResp, err := ocrClient.Calc(ctx, &client.CalcInput{
File: resp.Body(),
FileName: "captcha.jpg",
Category: "calc",
})
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("识别验证码失败", zap.Error(err))
continue
}
if ocrResp == "" {
continue
}
resp, err = webClient.R().SetFormData(map[string]string{
"order_no": orderNo,
"card_no": task.CardInfo.CardNo,
"pass": task.CardInfo.Data,
"captcha": ocrResp,
}).SetHeaders(map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
"Referer": "http://api.zbgj79.com/pay?order_no=" + orderNo,
}).Post("http://api.zbgj79.com/pay")
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("提交支付失败", zap.Error(err))
continue
}
submitRespStr := struct {
Code int `json:"code"`
Msg string `json:"msg"`
}{}
otelTrace.Logger.WithContext(ctx).Info("提交支付返回", zap.Any("response", resp))
json.Unmarshal(resp.Body(), &submitRespStr)
msgList := []string{
"必须是数字",
"计算结果错误",
}
if slices.Contains(msgList, submitRespStr.Msg) {
continue
}
if submitRespStr.Code != 0 {
otelTrace.Logger.WithContext(ctx).Error("支付失败", zap.Any("response", resp))
return fmt.Errorf("支付失败:%s", submitRespStr.Msg)
}
return nil
}
return errors.New("提交失败")
}
func (s *SendCardTaskTypeFatSix) QueryOrder(ctx context.Context, orderItem OrderPoolItem, task SendCardTask) error {
return nil
}

View File

@@ -353,13 +353,17 @@ func HandleCardQueryTask(ctx context.Context, task Task) error {
}
if queryTask.RetryCount > 0 && time.Since(queryTask.RetryTime) <= time.Second*10 {
pauseTime := queryTask.RetryCount
if pauseTime >= 60 {
pauseTime = 60
}
time.Sleep(time.Duration(pauseTime) * time.Second)
otelTrace.Logger.WithContext(ctx).Info("卡密查询任务重试,间隔时间太短", zap.String("channel", queryTask.Channel()), zap.String("cardNo", queryTask.CardNo), zap.String("bankOrderId", queryTask.BankOrderId), zap.Int("retryCount", queryTask.RetryCount))
time.Sleep(time.Second)
return GetQueueManager().EnqueueTask(ctx, TaskTypeCardQuery, queryTask)
}
// 如果查询次数超过最大次数,不再重试
if queryTask.RetryCount >= 20 {
if queryTask.RetryCount >= 60 {
otelTrace.Logger.WithContext(ctx).Warn("查询卡密已达到最大重试次数",
zap.String("channel", queryTask.Channel()),
zap.String("cardNo", queryTask.CardNo),