优化签名规则
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
*.log
|
||||||
@@ -1,37 +1,49 @@
|
|||||||
package bopx
|
package bopx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.yun.ink/pkg/convx"
|
"code.yun.ink/pkg/convx"
|
||||||
|
"github.com/yuninks/loggerx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 缺点
|
|
||||||
// 1.值必须是字符串,数组/对象这些不允许,或者需要通过一定规则转成字符串
|
|
||||||
|
|
||||||
type apix struct {
|
|
||||||
ingoreKey []string
|
|
||||||
signKey string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewApi(ignoreKey []string, signKey string) *apix {
|
|
||||||
return &apix{
|
|
||||||
ingoreKey: ignoreKey,
|
|
||||||
signKey: signKey,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 签名规则
|
// 签名规则
|
||||||
// 1.除掉不参与签名的用户参数
|
// 1.除掉不参与签名的用户参数
|
||||||
// 1.所有参数的key根据字典排序
|
// 1.所有参数的key根据字典排序
|
||||||
// 2.根据key=val&key2=val2的格式组装字符串
|
// 2.根据key=val&key2=val2的格式组装字符串
|
||||||
// 3.后面拼接用户签名key `&key=xxxx`得道新字符串
|
// 3.后面拼接用户签名key `&key=xxxx`得道新字符串
|
||||||
// 4.把新字符串用md5加密并转大写的道签名的值
|
// 4.把新字符串用md5加密并转大写的道签名的值
|
||||||
func (l *apix) GetSign(params map[string]interface{}) (sign string, err error) {
|
|
||||||
for _, val := range l.ingoreKey {
|
// 缺点
|
||||||
|
// 1.值必须是字符串,数组/对象这些不允许,或者需要通过一定规则转成字符串
|
||||||
|
|
||||||
|
type apix struct {
|
||||||
|
logger loggerx.LoggerInterface
|
||||||
|
ignoreKeys []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApi(opts ...Option) *apix {
|
||||||
|
options := newOptions(opts...)
|
||||||
|
return &apix{
|
||||||
|
logger: options.logger,
|
||||||
|
ignoreKeys: options.ignoreKeys,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算签名值
|
||||||
|
func (l *apix) GetSign(ctx context.Context, signKey string, params map[string]any) (sign string, err error) {
|
||||||
|
if signKey == "" {
|
||||||
|
return "", ErrorSignKeyIsEmpty
|
||||||
|
}
|
||||||
|
if len(params) == 0 {
|
||||||
|
return "", ErrorSignParamIsEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, val := range l.ignoreKeys {
|
||||||
delete(params, val)
|
delete(params, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,21 +60,19 @@ func (l *apix) GetSign(params map[string]interface{}) (sign string, err error) {
|
|||||||
if k > 0 {
|
if k > 0 {
|
||||||
str = str + "&"
|
str = str + "&"
|
||||||
}
|
}
|
||||||
val, err := convx.ToString(params[v])
|
val := convx.ToString(params[v])
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
str = str + v + "=" + val
|
str = str + v + "=" + val
|
||||||
}
|
}
|
||||||
str = str + "&key=" + l.signKey
|
str = str + "&key=" + signKey
|
||||||
data := []byte(str)
|
data := []byte(str)
|
||||||
has := md5.Sum(data)
|
has := md5.Sum(data)
|
||||||
md5str1 := fmt.Sprintf("%x", has) // []byte转16进制
|
md5str1 := fmt.Sprintf("%x", has) // []byte转16进制
|
||||||
sign = strings.ToUpper(md5str1)
|
sign = strings.ToUpper(md5str1)
|
||||||
|
l.logger.Infof(ctx, "bopx sign Str:%s sign:%s", str, sign)
|
||||||
return sign, nil
|
return sign, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *apix) Verify(params map[string]interface{}) error {
|
func (l *apix) Verify(ctx context.Context, signKey string, params map[string]interface{}) error {
|
||||||
|
|
||||||
sign, ok := params["sign"]
|
sign, ok := params["sign"]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -72,7 +82,7 @@ func (l *apix) Verify(params map[string]interface{}) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return ErrorSignMustBeString
|
return ErrorSignMustBeString
|
||||||
}
|
}
|
||||||
g_sign, err := l.GetSign(params)
|
g_sign, err := l.GetSign(ctx, signKey, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+192
@@ -0,0 +1,192 @@
|
|||||||
|
package bopx_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.yun.ink/pkg/bopx"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestApiGetSign 测试API签名生成
|
||||||
|
func TestApiGetSign(t *testing.T) {
|
||||||
|
// 测试用例1: 基本参数签名
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"name": "huang",
|
||||||
|
"age": 18,
|
||||||
|
}
|
||||||
|
|
||||||
|
api := bopx.NewApi()
|
||||||
|
sign, err := api.GetSign(context.Background(), "huangxinyun", params)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSign returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedSign := "F84C5DF671D8279B57AC6EED2C140407" // 根据算法计算得出的预期值
|
||||||
|
if sign != expectedSign {
|
||||||
|
t.Errorf("GetSign() = %v, want %v", sign, expectedSign)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录生成的签名值
|
||||||
|
t.Logf("Generated sign: %s", sign)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestApiVerify 测试API签名验证
|
||||||
|
func TestApiVerify(t *testing.T) {
|
||||||
|
// 测试用例1: 正确签名验证
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"name": "huang",
|
||||||
|
"age": 18,
|
||||||
|
}
|
||||||
|
|
||||||
|
api := bopx.NewApi()
|
||||||
|
sign, err := api.GetSign(context.Background(), "huangxinyun", params)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSign returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
params["sign"] = sign
|
||||||
|
err = api.Verify(context.Background(), "huangxinyun", params)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Verify returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试用例2: 签名参数不存在
|
||||||
|
paramsWithoutSign := map[string]interface{}{
|
||||||
|
"name": "huang",
|
||||||
|
"age": 18,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = api.Verify(context.Background(), "huangxinyun", paramsWithoutSign)
|
||||||
|
if err != bopx.ErrorSignParamNotExist {
|
||||||
|
t.Errorf("Verify should return ErrorSignParamNotExist, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试用例3: 签名参数不是字符串
|
||||||
|
paramsWithInvalidSign := map[string]interface{}{
|
||||||
|
"name": "huang",
|
||||||
|
"age": 18,
|
||||||
|
"sign": 12345, // 非字符串类型
|
||||||
|
}
|
||||||
|
|
||||||
|
err = api.Verify(context.Background(), "huangxinyun", paramsWithInvalidSign)
|
||||||
|
if err != bopx.ErrorSignMustBeString {
|
||||||
|
t.Errorf("Verify should return ErrorSignMustBeString, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试用例4: 签名不匹配
|
||||||
|
paramsWithWrongSign := map[string]interface{}{
|
||||||
|
"name": "huang",
|
||||||
|
"age": 18,
|
||||||
|
"sign": "WRONGSIGN",
|
||||||
|
}
|
||||||
|
|
||||||
|
err = api.Verify(context.Background(), "huangxinyun", paramsWithWrongSign)
|
||||||
|
if err != bopx.ErrorSignFail {
|
||||||
|
t.Errorf("Verify should return ErrorSignFail, got: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestApiIgnoreKeys 测试忽略键功能
|
||||||
|
func TestApiIgnoreKeys(t *testing.T) {
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"name": "huang",
|
||||||
|
"age": 18,
|
||||||
|
"platform_key": "ignored",
|
||||||
|
"sign": "ignored",
|
||||||
|
"key": "ignored",
|
||||||
|
}
|
||||||
|
|
||||||
|
api := bopx.NewApi(bopx.WithIgnoreKeys("platform_key", "sign", "key"))
|
||||||
|
sign, err := api.GetSign(context.Background(), "huangxinyun", params)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSign returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证忽略的键不影响签名结果
|
||||||
|
paramsWithoutIgnored := map[string]interface{}{
|
||||||
|
"name": "huang",
|
||||||
|
"age": 18,
|
||||||
|
}
|
||||||
|
|
||||||
|
signWithoutIgnored, err := api.GetSign(context.Background(), "huangxinyun", paramsWithoutIgnored)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSign returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if sign != signWithoutIgnored {
|
||||||
|
t.Errorf("Signatures with/without ignored keys should be equal. With ignored: %s, without: %s", sign, signWithoutIgnored)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestApiEmptyParams 测试空参数
|
||||||
|
func TestApiEmptyParams(t *testing.T) {
|
||||||
|
params := map[string]interface{}{}
|
||||||
|
|
||||||
|
api := bopx.NewApi(bopx.WithIgnoreKeys("platform_key", "sign", "key"))
|
||||||
|
sign, err := api.GetSign(context.Background(), "huangxinyun", params)
|
||||||
|
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, bopx.ErrorSignParamIsEmpty, err)
|
||||||
|
assert.Equal(t, "", sign)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestApiSpecialValues 测试特殊值
|
||||||
|
func TestApiSpecialValues(t *testing.T) {
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"empty_string": "",
|
||||||
|
"nil_value": nil,
|
||||||
|
"zero": 0,
|
||||||
|
"special_chars": "!@#$%^&*()_+-=[]{}|;':\",./<>?",
|
||||||
|
}
|
||||||
|
|
||||||
|
api := bopx.NewApi(bopx.WithIgnoreKeys("platform_key", "sign", "key"))
|
||||||
|
sign, err := api.GetSign(context.Background(), "testkey", params)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSign returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if sign == "" {
|
||||||
|
t.Error("Sign should not be empty for special values")
|
||||||
|
}
|
||||||
|
|
||||||
|
params["sign"] = sign
|
||||||
|
err = api.Verify(context.Background(), "testkey", params)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Verify returned error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestApiConsistentResults 测试签名一致性
|
||||||
|
func TestApiConsistentResults(t *testing.T) {
|
||||||
|
params1 := map[string]interface{}{
|
||||||
|
"c": "third",
|
||||||
|
"a": "first",
|
||||||
|
"b": "second",
|
||||||
|
}
|
||||||
|
|
||||||
|
params2 := map[string]interface{}{
|
||||||
|
"b": "second",
|
||||||
|
"c": "third",
|
||||||
|
"a": "first",
|
||||||
|
}
|
||||||
|
|
||||||
|
api := bopx.NewApi()
|
||||||
|
|
||||||
|
sign1, err := api.GetSign(context.Background(), "consistentkey", params1)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSign for params1 returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sign2, err := api.GetSign(context.Background(), "consistentkey", params2)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSign for params2 returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 由于参数排序,两种不同顺序的map应该产生相同的签名
|
||||||
|
if sign1 != sign2 {
|
||||||
|
t.Errorf("Signatures should be consistent regardless of parameter order. sign1: %s, sign2: %s", sign1, sign2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,4 +6,7 @@ var (
|
|||||||
ErrorSignParamNotExist = errors.New("签名参数不存在")
|
ErrorSignParamNotExist = errors.New("签名参数不存在")
|
||||||
ErrorSignMustBeString = errors.New("sign必须是字符串")
|
ErrorSignMustBeString = errors.New("sign必须是字符串")
|
||||||
ErrorSignFail = errors.New("验签失败")
|
ErrorSignFail = errors.New("验签失败")
|
||||||
|
ErrorSignParamEmpty = errors.New("签名参数为空")
|
||||||
|
ErrorSignParamIsEmpty = errors.New("签名参数不能为空")
|
||||||
|
ErrorSignKeyIsEmpty = errors.New("签名key不能为空")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,4 +2,38 @@ module code.yun.ink/pkg/bopx
|
|||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require code.yun.ink/pkg/convx v1.0.1
|
require (
|
||||||
|
code.yun.ink/pkg/convx v1.0.3
|
||||||
|
github.com/stretchr/testify v1.8.3
|
||||||
|
github.com/yuninks/loggerx v1.0.13
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/bytedance/sonic v1.9.1 // indirect
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||||
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
github.com/gin-gonic/gin v1.9.1 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||||
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||||
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
|
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||||
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
|
golang.org/x/crypto v0.9.0 // indirect
|
||||||
|
golang.org/x/net v0.10.0 // indirect
|
||||||
|
golang.org/x/sys v0.8.0 // indirect
|
||||||
|
golang.org/x/text v0.9.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,2 +1,89 @@
|
|||||||
code.yun.ink/pkg/convx v1.0.1 h1:T6yIVqyC1nQc9CO0C7iHn5rs7GxbaulmrJtxwg95q9Y=
|
code.yun.ink/pkg/convx v1.0.3 h1:pH8dUOgsoaBYVQ3+4C2+uVua561nDxq6/GpaQ9wnCew=
|
||||||
code.yun.ink/pkg/convx v1.0.1/go.mod h1:6xqmUend1kwarRvJ0TQlfzzS4QCWdRrXQiUY/ggzYqo=
|
code.yun.ink/pkg/convx v1.0.3/go.mod h1:6xqmUend1kwarRvJ0TQlfzzS4QCWdRrXQiUY/ggzYqo=
|
||||||
|
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||||
|
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||||
|
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
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/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||||
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
|
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||||
|
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
|
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.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||||
|
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||||
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
|
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||||
|
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||||
|
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||||
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
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 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||||
|
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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
||||||
|
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
|
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||||
|
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
|
github.com/yuninks/loggerx v1.0.13 h1:NVb0oHoZeJ59ZAaU5HqcpY7TfZlLaXQEzkRhdOTthiA=
|
||||||
|
github.com/yuninks/loggerx v1.0.13/go.mod h1:+QFoywQ1ICh4v40zj6OHM8GBZHEqV0yvRbkZjZUe2o4=
|
||||||
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
|
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||||
|
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
|
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||||
|
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||||
|
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||||
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||||
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||||
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
|
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||||
|
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
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.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package bopx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/yuninks/loggerx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Options struct {
|
||||||
|
logger loggerx.LoggerInterface // 日志接口
|
||||||
|
ignoreKeys []string // 忽略签名的key
|
||||||
|
}
|
||||||
|
|
||||||
|
type Option func(*Options)
|
||||||
|
|
||||||
|
func newOptions(opts ...Option) *Options {
|
||||||
|
options := defaultOptions()
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(options)
|
||||||
|
}
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultOptions() *Options {
|
||||||
|
return &Options{
|
||||||
|
logger: loggerx.NewLogger(
|
||||||
|
context.Background(),
|
||||||
|
loggerx.SetEscapeHTML(false),
|
||||||
|
),
|
||||||
|
ignoreKeys: []string{
|
||||||
|
"sign",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithLogger(logger loggerx.LoggerInterface) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.logger = logger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithIgnoreKeys(keys ...string) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.ignoreKeys = keys
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
-14
@@ -2,28 +2,39 @@
|
|||||||
package bopx
|
package bopx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.yun.ink/pkg/convx"
|
"code.yun.ink/pkg/convx"
|
||||||
|
"github.com/yuninks/loggerx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type platform struct {
|
type platform struct {
|
||||||
ingoreKey []string
|
ingoreKeys []string
|
||||||
signKey string
|
logger loggerx.LoggerInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPlatform(ignoreKey []string, signKey string) *platform {
|
func NewPlatform(opts ...Option) *platform {
|
||||||
|
options := newOptions(opts...)
|
||||||
return &platform{
|
return &platform{
|
||||||
ingoreKey: ignoreKey,
|
ingoreKeys: options.ignoreKeys,
|
||||||
signKey: signKey,
|
logger: options.logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *platform) GetSign(params map[string]interface{}) (sign string, err error) {
|
func (l *platform) GetSign(ctx context.Context, signKey string, params map[string]any) (sign string, err error) {
|
||||||
for _, val := range l.ingoreKey {
|
|
||||||
|
if signKey == "" {
|
||||||
|
return "", ErrorSignKeyIsEmpty
|
||||||
|
}
|
||||||
|
if len(params) == 0 {
|
||||||
|
return "", ErrorSignParamIsEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, val := range l.ingoreKeys {
|
||||||
delete(params, val)
|
delete(params, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,13 +51,10 @@ func (l *platform) GetSign(params map[string]interface{}) (sign string, err erro
|
|||||||
if k > 0 {
|
if k > 0 {
|
||||||
str = str + "&"
|
str = str + "&"
|
||||||
}
|
}
|
||||||
val, err := convx.ToString(params[v])
|
val := convx.ToString(params[v])
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
str = str + v + "=" + val
|
str = str + v + "=" + val
|
||||||
}
|
}
|
||||||
str = str + "&key=" + l.signKey
|
str = str + "&key=" + signKey
|
||||||
data := []byte(str)
|
data := []byte(str)
|
||||||
has := md5.Sum(data)
|
has := md5.Sum(data)
|
||||||
md5str1 := fmt.Sprintf("%x", has) // []byte转16进制
|
md5str1 := fmt.Sprintf("%x", has) // []byte转16进制
|
||||||
@@ -54,7 +62,7 @@ func (l *platform) GetSign(params map[string]interface{}) (sign string, err erro
|
|||||||
return sign, nil
|
return sign, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *platform) VerifySign(params map[string]interface{}) error {
|
func (l *platform) VerifySign(ctx context.Context, signKey string, params map[string]interface{}) error {
|
||||||
sign, ok := params["sign"]
|
sign, ok := params["sign"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrorSignParamNotExist
|
return ErrorSignParamNotExist
|
||||||
@@ -63,7 +71,7 @@ func (l *platform) VerifySign(params map[string]interface{}) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return ErrorSignMustBeString
|
return ErrorSignMustBeString
|
||||||
}
|
}
|
||||||
g_sign, err := l.GetSign(params)
|
g_sign, err := l.GetSign(ctx, signKey, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -1,6 +1,7 @@
|
|||||||
package bopx_test
|
package bopx_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.yun.ink/pkg/bopx"
|
"code.yun.ink/pkg/bopx"
|
||||||
@@ -16,14 +17,14 @@ func TestGetSign(t *testing.T) {
|
|||||||
// delete(params, "sign")
|
// delete(params, "sign")
|
||||||
// delete(params, "key")
|
// delete(params, "key")
|
||||||
|
|
||||||
s := bopx.NewPlatform([]string{"platform_key", "sign", "key"}, "huangxinyun")
|
s := bopx.NewPlatform()
|
||||||
sign, err := s.GetSign(params)
|
sign, err := s.GetSign(context.Background(), "huangxinyun", params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
t.Log(sign)
|
t.Log(sign)
|
||||||
params["sign"] = sign
|
params["sign"] = sign
|
||||||
err = s.VerifySign(params)
|
err = s.VerifySign(context.Background(), "huangxinyun", params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user