Created
August 28, 2020 12:58
-
-
Save aimuz/cd930774ca1de00e2dc77315ccd5e3f9 to your computer and use it in GitHub Desktop.
Generate the corresponding pre signature string according to the object
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sign | |
import ( | |
"reflect" | |
"sort" | |
"strconv" | |
"strings" | |
) | |
// GeneratePreSign from objects generates a pre-signed message | |
func GeneratePreSign(value interface{}) string { | |
valueOf := reflect.ValueOf(value) | |
return generatePreSign(valueOf) | |
} | |
func generatePreSign(valueOf reflect.Value) string { | |
valueOf = originalValue(valueOf) | |
kind := valueOf.Kind() | |
var ( | |
kvs []string | |
childOf reflect.Value | |
) | |
switch kind { | |
case reflect.String: | |
str := valueOf.String() | |
str = strings.Replace(str, " ", "", -1) | |
kvs = make([]string, len(str)) | |
for i, s := range str { | |
kvs[i] = strconv.Itoa(i) + "=" + string(s) | |
} | |
case reflect.Map: | |
keys := valueOf.MapKeys() | |
kvs = make([]string, len(keys)) | |
for i, key := range keys { | |
childOf = originalValue(valueOf.MapIndex(key)) | |
kvs[i] = key.String() + "=" + generateObjectString(childOf) | |
} | |
case reflect.Struct: | |
typeOf := valueOf.Type() | |
var ( | |
childField reflect.StructField | |
tag string | |
) | |
num := typeOf.NumField() | |
kvs = make([]string, num) | |
for i := 0; i < num; i++ { | |
childField = typeOf.Field(i) | |
childOf = originalValue(valueOf.Field(i)) | |
tag = strings.Split(childField.Tag.Get("json"), ",")[0] | |
if tag == "-" { | |
continue | |
} | |
if len(tag) > 0 { | |
kvs[i] += tag | |
} else { | |
kvs[i] += childField.Name | |
} | |
kvs[i] += "=" + generateObjectString(childOf) | |
} | |
case reflect.Array, reflect.Slice: | |
kvs = make([]string, 0, valueOf.Len()) | |
for i := 0; i < valueOf.Len(); i++ { | |
childOf = valueOf.Index(i) | |
kvs[i] = strconv.Itoa(i) + "=" + generateObjectString(childOf) | |
} | |
} | |
sort.Strings(kvs) | |
return strings.Join(kvs, "&") | |
} | |
func generateObjectString(valueOf reflect.Value) string { | |
kind := valueOf.Kind() | |
if isObject(kind) { | |
return "{" + generatePreSign(valueOf) + "}" | |
} else if isArray(kind) { | |
var result string | |
var childOf reflect.Value | |
valueOfLen := valueOf.Len() | |
for i := 0; i < valueOfLen; i++ { | |
childOf = originalValue(valueOf.Index(i)) | |
kind = childOf.Kind() | |
if isObject(kind) || isArray(kind) { | |
result += "{" + generatePreSign(childOf) + "}" | |
} else { | |
result += toStrings(childOf) | |
} | |
if i < valueOfLen-1 { | |
result += "," | |
} | |
} | |
return result | |
} | |
return toStrings(valueOf) | |
} | |
func toStrings(valueOf reflect.Value) string { | |
switch valueOf.Kind() { | |
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | |
return strconv.FormatInt(valueOf.Int(), 10) | |
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | |
return strconv.FormatUint(valueOf.Uint(), 10) | |
case reflect.Float32, reflect.Float64: | |
return strconv.FormatFloat(valueOf.Float(), 'f', -1, 64) | |
case reflect.Bool: | |
return strconv.FormatBool(valueOf.Bool()) | |
case reflect.String: | |
return valueOf.String() | |
} | |
return "" | |
} | |
func isObject(kind reflect.Kind) bool { | |
return kind == reflect.Map || kind == reflect.Struct | |
} | |
func isArray(kind reflect.Kind) bool { | |
return kind == reflect.Array || kind == reflect.Slice | |
} | |
func originalValue(value reflect.Value) reflect.Value { | |
for { | |
switch value.Kind() { | |
case reflect.Ptr: | |
value = value.Elem() | |
case reflect.Interface: | |
value = reflect.ValueOf(value.Interface()) | |
default: | |
return value | |
} | |
} | |
} |
A general method of generating pre string.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
input
output