From fa659d87ae73735243a6537883277de93d312514 Mon Sep 17 00:00:00 2001 From: ayflying Date: Tue, 29 Jul 2025 11:19:43 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4oppo=E6=94=AF=E4=BB=98?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E5=BC=95=E7=94=A8=E5=A4=96=E9=83=A8=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 3 -- go.sum | 7 --- package/pay/{ => common}/func.go | 2 +- package/pay/honor/honor.go | 4 +- package/pay/oppo/const.go | 9 ++++ package/pay/oppo/notify.go | 32 +++++++++++++ package/pay/oppo/oppo.go | 5 +- package/pay/oppo/sign.go | 80 ++++++++++++++++++++++++++++++++ 8 files changed, 126 insertions(+), 16 deletions(-) rename package/pay/{ => common}/func.go (97%) create mode 100644 package/pay/oppo/const.go create mode 100644 package/pay/oppo/notify.go create mode 100644 package/pay/oppo/sign.go diff --git a/go.mod b/go.mod index f4b040f..512fe4e 100644 --- a/go.mod +++ b/go.mod @@ -47,8 +47,6 @@ require ( github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/haxqer/gofunc v0.0.0-20210609183449-586b0cce5fe4 // indirect - github.com/haxqer/xthird v0.0.0-20210703071732-ff4f4dbb6e5d // indirect github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/magiconair/properties v1.8.9 // indirect @@ -62,7 +60,6 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.3 // indirect - github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/go.sum b/go.sum index 66540c1..a6a3f74 100644 --- a/go.sum +++ b/go.sum @@ -225,10 +225,6 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/haxqer/gofunc v0.0.0-20210609183449-586b0cce5fe4 h1:QQOImHnvEkzqEbozZup+76WLv+W0QhO84GTLHppMY1M= -github.com/haxqer/gofunc v0.0.0-20210609183449-586b0cce5fe4/go.mod h1:XQaEUze5QCq3D9oenfHItzPQUD+NGg+0TDt1kJhJAAc= -github.com/haxqer/xthird v0.0.0-20210703071732-ff4f4dbb6e5d h1:e2qgvCNjMrp9fNtUQr3gQnK15B0C2CIUjPWMc7jZnbo= -github.com/haxqer/xthird v0.0.0-20210703071732-ff4f4dbb6e5d/go.mod h1:9avb74vS4djGUwtueA6V01grbpskLGisSy0jxFZIBY8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -300,8 +296,6 @@ github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZ 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20= -github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= 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_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -463,7 +457,6 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= diff --git a/package/pay/func.go b/package/pay/common/func.go similarity index 97% rename from package/pay/func.go rename to package/pay/common/func.go index 719de75..192b22e 100644 --- a/package/pay/func.go +++ b/package/pay/common/func.go @@ -1,4 +1,4 @@ -package pay +package common import "strings" diff --git a/package/pay/honor/honor.go b/package/pay/honor/honor.go index 36dff37..2738a5e 100644 --- a/package/pay/honor/honor.go +++ b/package/pay/honor/honor.go @@ -8,7 +8,7 @@ import ( "encoding/base64" "encoding/pem" "errors" - "github.com/ayflying/utility_go/package/pay" + "github.com/ayflying/utility_go/package/pay/common" ) type Pay struct { @@ -35,7 +35,7 @@ func (p *Pay) VerifyRSASignature(data []byte, sign string) (bool, error) { return false, errors.New("签名解码失败: " + err.Error()) } - pubkey := pay.FormatPublicKey(p.PubKey) + pubkey := common.FormatPublicKey(p.PubKey) // 解析PEM格式的公钥 block, _ := pem.Decode([]byte(pubkey)) if block == nil { diff --git a/package/pay/oppo/const.go b/package/pay/oppo/const.go new file mode 100644 index 0000000..ed1b61d --- /dev/null +++ b/package/pay/oppo/const.go @@ -0,0 +1,9 @@ +package oppo + +const ( + LoginUrl = "https://iopen.game.oppomobile.com/sdkopen/user/fileIdInfo?fileId=%s&token=%s" + LocationShanghai = "Asia/Shanghai" + + RSA = "RSA" + RSA2 = "RSA2" +) diff --git a/package/pay/oppo/notify.go b/package/pay/oppo/notify.go new file mode 100644 index 0000000..914e711 --- /dev/null +++ b/package/pay/oppo/notify.go @@ -0,0 +1,32 @@ +package oppo + +import ( + "net/http" + "net/url" +) + +func (p *OppoType) ParseNotifyToBodyMap(req *http.Request) (bm map[string]interface{}, err error) { + if err = req.ParseForm(); err != nil { + return nil, err + } + var form map[string][]string = req.Form + bm = make(map[string]interface{}, len(form)+1) + for k, v := range form { + if len(v) == 1 { + bm[k] = v[0] + //bm.Set(k, v[0]) + } + } + return +} + +func (p *OppoType) ParseNotifyByURLValues(value url.Values) (bm map[string]interface{}, err error) { + bm = make(map[string]interface{}, len(value)+1) + for k, v := range value { + if len(v) == 1 { + bm[k] = v[0] + //bm.Set(k, v[0]) + } + } + return +} diff --git a/package/pay/oppo/oppo.go b/package/pay/oppo/oppo.go index 7c41bec..5afc6bd 100644 --- a/package/pay/oppo/oppo.go +++ b/package/pay/oppo/oppo.go @@ -3,7 +3,6 @@ package oppo import ( "context" "github.com/gogf/gf/v2/frame/g" - "github.com/haxqer/xthird/oppo" ) // 跟充值平台通信的加密key @@ -30,12 +29,12 @@ func (p *OppoType) Verify(ctx context.Context) (err error) { oppoPublicKey := "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmreYIkPwVovKR8rLHWlFVw7YDfm9uQOJKL89Smt6ypXGVdrAKKl0wNYc3/jecAoPi2ylChfa2iRu5gunJyNmpWZzlCNRIau55fxGW0XEu553IiprOZcaw5OuYGlf60ga8QT6qToP0/dpiL/ZbmNUO9kUhosIjEu22uFgR+5cYyQIDAQAB" //oppoPublicKey := p.PublicKey // 解析请求参数 - bodyMap, err := oppo.ParseNotifyToBodyMap(g.RequestFromCtx(ctx).Request) + bodyMap, err := p.ParseNotifyToBodyMap(g.RequestFromCtx(ctx).Request) if err != nil { // 解析失败, 处理错误逻辑 return } - err = oppo.VerifySign(oppoPublicKey, bodyMap) + err = p.VerifySign(oppoPublicKey, bodyMap) return } diff --git a/package/pay/oppo/sign.go b/package/pay/oppo/sign.go new file mode 100644 index 0000000..48c7c6c --- /dev/null +++ b/package/pay/oppo/sign.go @@ -0,0 +1,80 @@ +package oppo + +import ( + "crypto" + "crypto/hmac" + "crypto/rsa" + "crypto/sha1" + "crypto/x509" + "encoding/base64" + "encoding/pem" + "errors" + "fmt" + "github.com/ayflying/utility_go/package/pay/common" + "github.com/gogf/gf/v2/util/gconv" + "hash" + "math/rand" + "net/url" + "time" +) + +func (p *OppoType) GenLoginBaseStr(bm map[string]interface{}, appKey, appSecret string) (string, string) { + baseStr := fmt.Sprintf("oauthConsumerKey=%s&oauthToken=%s&oauthSignatureMethod=HMAC-SHA1&oauthTimestamp=%d&oauthNonce=%d&oauthVersion=1.0&", + appKey, url.QueryEscape(gconv.String(bm["token"])), time.Now().Unix(), rand.Int31n(100000000)) + + var h hash.Hash + h = hmac.New(sha1.New, []byte(appSecret+"&")) + h.Write([]byte(baseStr)) + + sign := url.QueryEscape(base64.StdEncoding.EncodeToString(h.Sum(nil))) + return baseStr, sign +} + +func (p *OppoType) VerifySign(oppoPayPublicKey string, bm map[string]interface{}) (err error) { + if oppoPayPublicKey == "" || bm == nil { + return errors.New("oppoPayPublicKey or bm is nil") + } + + bodySign := bm["sign"].(string) + bodySignType := RSA + signData := fmt.Sprintf("notifyId=%s&partnerOrder=%s&productName=%s&productDesc=%s&price=%s&count=%s&attach=%s", + bm["notifyId"], bm["partnerOrder"], bm["productName"], + bm["productDesc"], bm["price"], bm["count"], bm["attach"]) + pKey := common.FormatPublicKey(oppoPayPublicKey) + if err = p.verifySign(signData, bodySign, bodySignType, pKey); err != nil { + return err + } + return nil +} + +func (p *OppoType) verifySign(signData, sign, signType, oppoPayPublicKey string) (err error) { + var ( + h hash.Hash + hashs crypto.Hash + block *pem.Block + pubKey interface{} + publicKey *rsa.PublicKey + ok bool + ) + signBytes, _ := base64.StdEncoding.DecodeString(sign) + if block, _ = pem.Decode([]byte(oppoPayPublicKey)); block == nil { + return errors.New("OPPO公钥Decode错误") + } + if pubKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { + return fmt.Errorf("x509.ParsePKIXPublicKey:%w", err) + } + if publicKey, ok = pubKey.(*rsa.PublicKey); !ok { + return errors.New("OPPO公钥转换错误") + } + switch signType { + case RSA: + hashs = crypto.SHA1 + case RSA2: + hashs = crypto.SHA256 + default: + hashs = crypto.SHA256 + } + h = hashs.New() + h.Write([]byte(signData)) + return rsa.VerifyPKCS1v15(publicKey, hashs, h.Sum(nil), signBytes) +}