直连天下,v2插件
This commit is contained in:
parent
41071798b9
commit
bf0678f587
6
Makefile
6
Makefile
|
@ -35,6 +35,12 @@ zltx_card:
|
|||
make build-linux name=zltx_card && \
|
||||
make build-win name=zltx_card
|
||||
|
||||
.PHONY: zltx_v2
|
||||
zltx_v2:
|
||||
make build-mac name=zltx_v2 && \
|
||||
make build-linux name=zltx_v2 && \
|
||||
make build-win name=zltx_v2
|
||||
|
||||
.PHONY: union_pay_cpn
|
||||
union_pay_cpn:
|
||||
make build-mac name=union_pay_cpn && \
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
module plugins/zltxv2
|
||||
|
||||
go 1.22.2
|
||||
|
||||
replace plugins/utils => ../../utils
|
||||
|
||||
require (
|
||||
gitea.cdlsxd.cn/sdk/plugin v0.0.0-20240911021858-7f3ba37bbbca
|
||||
gitee.com/chengdu_blue_brothers/openapi-go-sdk-v2 v0.0.0-20240919023950-493c464e0ed7
|
||||
github.com/carlmjohnson/requests v0.24.2
|
||||
github.com/go-playground/validator/v10 v10.22.0
|
||||
github.com/hashicorp/go-plugin v1.6.1
|
||||
github.com/stretchr/testify v1.9.0
|
||||
plugins/utils v0.0.0-00010101000000-000000000000
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fatih/color v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/hashicorp/go-hclog v0.14.1 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
|
||||
github.com/json-iterator/go v1.1.5 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.10 // indirect
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
|
||||
github.com/oklog/run v1.0.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/crypto v0.25.0 // indirect
|
||||
golang.org/x/net v0.27.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
|
||||
google.golang.org/grpc v1.64.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
|
@ -0,0 +1,78 @@
|
|||
gitea.cdlsxd.cn/sdk/plugin v0.0.0-20240911021858-7f3ba37bbbca h1:snL161P7OynMA8hRVMLDjwnzZA2Q4mePg/iT/dyIfzA=
|
||||
gitea.cdlsxd.cn/sdk/plugin v0.0.0-20240911021858-7f3ba37bbbca/go.mod h1:cd+ZFTmd/ZxrrVc1OZCkrh2wAMPDaAa8ce13FAAkBg0=
|
||||
gitee.com/chengdu_blue_brothers/openapi-go-sdk-v2 v0.0.0-20240919023950-493c464e0ed7 h1:2wOzkUfS17P6U/i6CWFjLyXrdLMnW3osk897ZfOUCxY=
|
||||
gitee.com/chengdu_blue_brothers/openapi-go-sdk-v2 v0.0.0-20240919023950-493c464e0ed7/go.mod h1:aS6ecVHvGLGzYYFIhxBrRWmq69ifo6pt1G92QblSdQQ=
|
||||
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
|
||||
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
|
||||
github.com/carlmjohnson/requests v0.24.2 h1:JDakhAmTIKL/qL/1P7Kkc2INGBJIkIFP6xUeUmPzLso=
|
||||
github.com/carlmjohnson/requests v0.24.2/go.mod h1:duYA/jDnyZ6f3xbcF5PpZ9N8clgopubP2nK5i6MVMhU=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
|
||||
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU=
|
||||
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI=
|
||||
github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
|
||||
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE=
|
||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 h1:7GoSOOW2jpsfkntVKaS2rAr1TJqfcxotyaUcuxoZSzg=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||
google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
|
||||
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -0,0 +1,194 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"gitea.cdlsxd.cn/sdk/plugin/proto"
|
||||
"gitee.com/chengdu_blue_brothers/openapi-go-sdk-v2/api"
|
||||
"gitee.com/chengdu_blue_brothers/openapi-go-sdk-v2/notify"
|
||||
"gitee.com/chengdu_blue_brothers/openapi-go-sdk-v2/sdk"
|
||||
"plugins/utils/helper"
|
||||
"plugins/zltxv2/internal/vo"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
AppId string `json:"app_id"`
|
||||
AppKey string `json:"app_key"`
|
||||
BaseUri string `json:"base_uri"`
|
||||
NotifyUrl string `json:"notify_url"`
|
||||
}
|
||||
|
||||
type Card struct {
|
||||
Number string `json:"number"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
func (c *Card) ToJson() []byte {
|
||||
bytes, _ := json.Marshal(c)
|
||||
return bytes
|
||||
}
|
||||
|
||||
func transConfig(config []byte) (*Config, error) {
|
||||
var c Config
|
||||
err := json.Unmarshal(config, &c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
func (c *Config) client() (*sdk.Client, error) {
|
||||
scheme := getScheme(c.BaseUri)
|
||||
domain, err := getDomain(c.BaseUri, scheme)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sdk.NewClientWithAccessKey(c.AppKey, scheme, domain)
|
||||
}
|
||||
|
||||
func (c *Config) orderReq(in *proto.OrderRequest) *api.OrderCreateReq {
|
||||
accountType := int64(0)
|
||||
if in.Order.Account == "" {
|
||||
accountType = 0
|
||||
} else if helper.IsPhoneNumber(in.Order.Account) {
|
||||
accountType = 1
|
||||
} else if helper.IsEmail(in.Order.Account) {
|
||||
accountType = 2
|
||||
}
|
||||
return &api.OrderCreateReq{
|
||||
OutTradeNo: in.Order.OrderNo, // 商户侧订单号长度只能是1-64位
|
||||
ProductId: in.Product.ProductNo, // 产品编码不能为空
|
||||
Number: int(in.Order.Quantity), // 部分商品存在限购数量,具体可联系商务
|
||||
NotifyUrl: c.NotifyUrl, // 订单回调通知地址长度不能为空,且长度不能超过255
|
||||
Extends: string(in.Order.Extra), // 部分特殊商品需要,具体可联系商务
|
||||
RechargeAccount: in.Order.Account, // 账号类型:直充类型商品必传,商品为卡密类型时,则表示接收卡密的手机号
|
||||
AccountType: accountType, // 直充类型商品必传 - 1:手机号 - 2: QQ 号
|
||||
Attach: "", // 透传参数,当传了此参数时,查询和回调接口中将原样携带此参数
|
||||
UnitPrice: 0, // 交易商品单价,单位:元(最多保留4位小数) - 0或不传表示不限制 - 当此价格小于采购价时,下单失败
|
||||
}
|
||||
}
|
||||
|
||||
func orderResp(request *proto.OrderRequest, resp *api.OrderCreateResp) *proto.OrderResponse {
|
||||
data, _ := json.Marshal(resp)
|
||||
return &proto.OrderResponse{
|
||||
Result: &proto.Result{
|
||||
Status: proto.Status_ING,
|
||||
OrderNo: request.Order.OrderNo,
|
||||
TradeNo: resp.OrderNo, // 平台订单号
|
||||
Message: "成功",
|
||||
Data: data,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) queryReq(in *proto.QueryRequest) *api.OrderQueryReq {
|
||||
return &api.OrderQueryReq{
|
||||
OutTradeNo: in.Order.OrderNo,
|
||||
}
|
||||
}
|
||||
|
||||
func queryResp(appKey string, request *proto.QueryRequest, resp *api.OrderQueryResp) (*proto.QueryResponse, error) {
|
||||
data, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
status := vo.OrderStatus(resp.TradeStatus)
|
||||
pb := &proto.QueryResponse{
|
||||
Result: &proto.Result{
|
||||
Status: status.GetOrderStatus(),
|
||||
OrderNo: request.Order.OrderNo,
|
||||
TradeNo: resp.OrderNo,
|
||||
Message: resp.TradeStateDesc,
|
||||
Data: data,
|
||||
Extra: nil,
|
||||
},
|
||||
}
|
||||
if len(resp.Cards) > 0 {
|
||||
c, err := getQueryCard(appKey, &resp.Cards[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pb.Result.Extra = c.ToJson()
|
||||
}
|
||||
return pb, nil
|
||||
}
|
||||
|
||||
func getQueryCard(appKey string, card *api.Cards) (*Card, error) {
|
||||
// - 1:卡密+卡密:no和pwd都不为空
|
||||
// - 2:卡密,pwd不为空
|
||||
// - 3:链接,url不为空
|
||||
car := &Card{}
|
||||
if card.CardType == 1 {
|
||||
pwd, err := decryptAES(card.Pwd, appKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
no, err := decryptAES(card.No, appKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
car.Password = pwd
|
||||
car.Number = no
|
||||
} else if card.CardType == 2 {
|
||||
pwd, err := decryptAES(card.Pwd, appKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
car.Password = pwd
|
||||
} else if card.CardType == 3 {
|
||||
// 无
|
||||
}
|
||||
return car, nil
|
||||
}
|
||||
|
||||
func notifyResp(appKey string, resp *notify.OrderReq) (*proto.NotifyResponse, error) {
|
||||
data, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
status := vo.OrderStatus(resp.TradeStatus)
|
||||
pb := &proto.NotifyResponse{
|
||||
Result: &proto.Result{
|
||||
Status: status.GetOrderStatus(),
|
||||
OrderNo: resp.OutTradeNo,
|
||||
TradeNo: resp.OrderNo,
|
||||
Message: resp.TradeStateDesc,
|
||||
Data: data,
|
||||
Extra: nil,
|
||||
},
|
||||
}
|
||||
b, err := getNotifyCard(appKey, resp.Cards)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pb.Result.Extra = b
|
||||
return pb, nil
|
||||
}
|
||||
|
||||
func getNotifyCard(appKey string, cards []notify.Cards) ([]byte, error) {
|
||||
if len(cards) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
card := cards[0]
|
||||
car := &Card{}
|
||||
if card.CardType == 1 {
|
||||
pwd, err := decryptAES(card.Pwd, appKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
no, err := decryptAES(card.No, appKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
car.Password = pwd
|
||||
car.Number = no
|
||||
} else if card.CardType == 2 {
|
||||
pwd, err := decryptAES(card.Pwd, appKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
car.Password = pwd
|
||||
} else if card.CardType == 3 {
|
||||
// 无
|
||||
}
|
||||
return car.ToJson(), nil
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"gitee.com/chengdu_blue_brothers/openapi-go-sdk-v2/sdk/requests"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getScheme(url string) string {
|
||||
if strings.HasPrefix(url, "https://") {
|
||||
return requests.HTTPS
|
||||
}
|
||||
return requests.HTTP
|
||||
}
|
||||
|
||||
func getDomain(url, scheme string) (string, error) {
|
||||
if strings.HasPrefix(url, fmt.Sprintf("%s://", strings.ToLower(scheme))) {
|
||||
parts := strings.Split(url, "//")
|
||||
if len(parts) >= 2 {
|
||||
return parts[1], nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("invalid url")
|
||||
}
|
||||
|
||||
func decryptAES(encryptedData string, secretKey string) (string, error) {
|
||||
// 第一步:对加密的卡密做base64 decode
|
||||
encryptedBytes, err := base64.StdEncoding.DecodeString(encryptedData)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 第二步:使用aes-256-ecb解密
|
||||
cipher, _ := aes.NewCipher([]byte(secretKey))
|
||||
decrypted := make([]byte, len(encryptedBytes))
|
||||
size := 16
|
||||
for bs, be := 0, size; bs < len(encryptedBytes); bs, be = bs+size, be+size {
|
||||
cipher.Decrypt(decrypted[bs:be], encryptedBytes[bs:be])
|
||||
}
|
||||
paddingSize := int(decrypted[len(decrypted)-1])
|
||||
return string(decrypted[0 : len(decrypted)-paddingSize]), nil
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package vo
|
||||
|
||||
import (
|
||||
"gitea.cdlsxd.cn/sdk/plugin/proto"
|
||||
)
|
||||
|
||||
type OrderStatus string
|
||||
|
||||
const (
|
||||
OrderSuccess OrderStatus = "SUCCESS" // 充值成功
|
||||
OrderIng OrderStatus = "RECHARGING" // 充值处理中
|
||||
OrderFail OrderStatus = "FAIL" // 充值失败
|
||||
)
|
||||
|
||||
var orderStatusMap = map[OrderStatus]proto.Status{
|
||||
OrderSuccess: proto.Status_SUCCESS,
|
||||
OrderIng: proto.Status_ING,
|
||||
OrderFail: proto.Status_FAIL,
|
||||
}
|
||||
|
||||
var orderStatusTextMap = map[OrderStatus]string{
|
||||
OrderSuccess: "充值成功",
|
||||
OrderIng: "充值处理中",
|
||||
OrderFail: "充值失败",
|
||||
}
|
||||
|
||||
func (o OrderStatus) IsSuccess() bool {
|
||||
return o == OrderSuccess
|
||||
}
|
||||
|
||||
func (o OrderStatus) IsIng() bool {
|
||||
return o == OrderIng
|
||||
}
|
||||
|
||||
func (o OrderStatus) IsFail() bool {
|
||||
return o == OrderFail
|
||||
}
|
||||
|
||||
func (o OrderStatus) GetOrderStatus() proto.Status {
|
||||
if resultStatus, ok := orderStatusMap[o]; ok {
|
||||
return resultStatus
|
||||
}
|
||||
return proto.Status_ING
|
||||
}
|
||||
|
||||
func (o OrderStatus) GetOrderStatusText() string {
|
||||
if text, ok := orderStatusTextMap[o]; ok {
|
||||
return text
|
||||
}
|
||||
return ""
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gitea.cdlsxd.cn/sdk/plugin/proto"
|
||||
"gitee.com/chengdu_blue_brothers/openapi-go-sdk-v2/api"
|
||||
"gitee.com/chengdu_blue_brothers/openapi-go-sdk-v2/notify"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// 插件通信信息,若不对应则会报错panic
|
||||
const (
|
||||
Tag = "zltx_v2"
|
||||
Version = 1
|
||||
CookieKey = "zltx_v2"
|
||||
CookieValue = "zltx_v2"
|
||||
)
|
||||
|
||||
type ZLTXV2Service struct{}
|
||||
|
||||
func (p *ZLTXV2Service) Order(ctx context.Context, request *proto.OrderRequest) (*proto.OrderResponse, error) {
|
||||
c, err := transConfig(request.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := c.client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
response, errResp, err := api.OrderCreate(ctx, client, c.AppId, c.orderReq(request))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("请求异常[%v]", err)
|
||||
}
|
||||
if errResp != nil {
|
||||
return nil, fmt.Errorf("请求错误[code:%d]-[reason:%s]-[msg:%s]", errResp.Code, errResp.Reason, errResp.Message)
|
||||
}
|
||||
|
||||
return orderResp(request, response), nil
|
||||
}
|
||||
|
||||
func (p *ZLTXV2Service) Query(ctx context.Context, request *proto.QueryRequest) (*proto.QueryResponse, error) {
|
||||
c, err := transConfig(request.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := c.client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, errResp, err := api.OrderQuery(ctx, client, c.AppId, c.queryReq(request))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("请求异常[%v]", err)
|
||||
}
|
||||
if errResp != nil {
|
||||
return nil, fmt.Errorf("请求错误[code:%d]-[reason:%s]-[msg:%s]", errResp.Code, errResp.Reason, errResp.Message)
|
||||
}
|
||||
|
||||
return queryResp(c.AppKey, request, response)
|
||||
}
|
||||
|
||||
func (p *ZLTXV2Service) Notify(_ context.Context, request *proto.NotifyRequest) (*proto.NotifyResponse, error) {
|
||||
req := &http.Request{
|
||||
Method: "",
|
||||
URL: nil,
|
||||
Proto: "",
|
||||
ProtoMajor: 0,
|
||||
ProtoMinor: 0,
|
||||
Header: nil,
|
||||
Body: nil,
|
||||
GetBody: nil,
|
||||
ContentLength: 0,
|
||||
TransferEncoding: nil,
|
||||
Close: false,
|
||||
Host: "",
|
||||
Form: nil,
|
||||
PostForm: nil,
|
||||
MultipartForm: nil,
|
||||
Trailer: nil,
|
||||
RemoteAddr: "",
|
||||
RequestURI: "",
|
||||
TLS: nil,
|
||||
Cancel: nil,
|
||||
Response: nil,
|
||||
}
|
||||
headers := make(map[string]string)
|
||||
if err := json.Unmarshal(request.Headers, &headers); err != nil {
|
||||
return nil, fmt.Errorf("headers Unmarshal err [%v]", err)
|
||||
}
|
||||
httpHeaders := make(http.Header, len(headers))
|
||||
for k, value := range headers {
|
||||
httpHeaders.Add(k, value)
|
||||
}
|
||||
req.Header = httpHeaders
|
||||
req.Body = ioutil.NopCloser(bytes.NewBuffer(request.Body))
|
||||
|
||||
c, err := transConfig(request.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
n, err := notify.NewNotify(c.AppId, c.AppKey).ParseAndVerify(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return notifyResp(c.AppKey, n)
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gitea.cdlsxd.cn/sdk/plugin/proto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var zltx = &ZLTXV2Service{}
|
||||
|
||||
func config() []byte {
|
||||
c := &Config{
|
||||
AppId: "23329",
|
||||
AppKey: "8db16e8cc8363ed4eb4c14f9520bcc32",
|
||||
BaseUri: "http://211.137.105.198:17100",
|
||||
NotifyUrl: "http://192.168.6.184:8090/ping",
|
||||
}
|
||||
marshal, _ := json.Marshal(c)
|
||||
return marshal
|
||||
}
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
t.Run("TestConfig", func(t *testing.T) {
|
||||
c := config()
|
||||
fmt.Printf("%+s\n", string(c))
|
||||
assert.NotEmpty(t, c)
|
||||
})
|
||||
}
|
||||
|
||||
func TestOrder(t *testing.T) {
|
||||
request := &proto.OrderRequest{
|
||||
Config: config(),
|
||||
Order: &proto.OrderRequest_Order{
|
||||
OrderNo: "test_zltx_v2_3",
|
||||
Account: "",
|
||||
Quantity: 1,
|
||||
Extra: nil,
|
||||
},
|
||||
Product: &proto.OrderRequest_Product{
|
||||
ProductNo: "CEMLKRLK9640",
|
||||
Extra: []byte(`{}`),
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("TestOrder", func(t *testing.T) {
|
||||
got, err := zltx.Order(context.Background(), request)
|
||||
if err != nil {
|
||||
t.Errorf("Order() error = %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%+v\n", got)
|
||||
assert.Equal(t, int(proto.Status_ING), int(got.Result.Status))
|
||||
})
|
||||
}
|
||||
|
||||
func TestQuery(t *testing.T) {
|
||||
request := &proto.QueryRequest{
|
||||
Config: config(),
|
||||
Order: &proto.QueryRequest_Order{
|
||||
OrderNo: "test_zltx_v2_3",
|
||||
TradeNo: "",
|
||||
Account: "",
|
||||
Extra: nil,
|
||||
},
|
||||
}
|
||||
t.Run("TestQuery", func(t *testing.T) {
|
||||
got, err := zltx.Query(context.Background(), request)
|
||||
if err != nil {
|
||||
t.Errorf("Query() error = %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%+v\n", got)
|
||||
assert.Equal(t, int(proto.Status_SUCCESS), int(got.Result.Status))
|
||||
})
|
||||
}
|
||||
|
||||
func TestNotify(t *testing.T) {
|
||||
jsonData := `{
|
||||
"tradeStatus": "SUCCESS",
|
||||
"orderNo": "C2081410801687044096",
|
||||
"tradeStateDesc": "成功",
|
||||
"cards": [
|
||||
{"no":"*","pwd":"*","deadline":"2024-07-03 23:59:59","cardType":1}
|
||||
],
|
||||
"mchId": 23329,
|
||||
"outTradeNo": "20240802212326527830",
|
||||
"rechargeAccount": "17384082748",
|
||||
"unitPrice":102.5
|
||||
}`
|
||||
headers := `{"Authorization":"292e21f3683219369cf68dede0d45730","Content-Type":"application/json"}`
|
||||
in := &proto.NotifyRequest{
|
||||
Config: config(),
|
||||
Queries: nil,
|
||||
Headers: []byte(headers),
|
||||
Body: []byte(jsonData),
|
||||
}
|
||||
t.Run("TestNotify", func(t *testing.T) {
|
||||
got, err := zltx.Notify(context.Background(), in)
|
||||
if !assert.Nil(t, err) {
|
||||
t.Errorf("Notify() error = %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%s \n", got.String())
|
||||
assert.Equal(t, int(proto.Status_SUCCESS), int(got.Result.Status))
|
||||
})
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"gitea.cdlsxd.cn/sdk/plugin/shared"
|
||||
"github.com/hashicorp/go-plugin"
|
||||
"plugins/zltxv2/internal"
|
||||
)
|
||||
|
||||
func main() {
|
||||
plugin.Serve(&plugin.ServeConfig{
|
||||
HandshakeConfig: shared.HandshakeConfig(internal.Version, internal.CookieKey, internal.CookieValue),
|
||||
Plugins: shared.PluginSet(shared.NewPlugin(&internal.ZLTXV2Service{}, internal.Tag)),
|
||||
GRPCServer: plugin.DefaultGRPCServer,
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue