Golang签名组串QueryString生成

邹英光
2023-12-01
这里以Content-Type=application/json;utf-8场景为例。

话不多说,直接上代码。

package utils

import (
	jsoniter "github.com/json-iterator/go"
	"sort"
	"strings"
)

var jsont = jsoniter.Config{
    //关闭对HTML字符串编码
	EscapeHTML:                    false,
	//json为简单字符串即不进行unescape(do not unescape object field)
	ObjectFieldMustBeSimpleString: true,
	//是否开启Number承载数据(整形、浮点型)
	UseNumber:                     true,
}.Froze()

/**
 * @param data json字符串字节流
 * @desc 用于生成签名拼接字符串QueryString。
 *      1.按ASCII码从小到大排序,空键/值和空字符串不参与组串
 *      2.统一使用UTF8进行编码签名,防止编码方式或特殊字符不兼容问题
 *      3.签名原始串中,字段名和字段值都采用原始值,即不进行URL Encode
 *      4.注意整形、浮点型数据参与签名方式(如:浮点数3.10体现为3.1、0.0体现为0)
 *      5.内嵌JSON或ARRAY解析拼接需转字符串且按紧凑方式,即内嵌各K/V或值之间不应有空格或换行符等等
 *      6.内嵌对象中空对象或空字符串不做任何处理(即保留)
 */
func BuildSignQueryStr(data []byte) (string,error){
	pstr := string(data)
	var tempMap map[string]interface{}
	jsont.Unmarshal([]byte(pstr), &tempMap)
	keys := make([]string,0,len(tempMap))
	for k,_ := range tempMap {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	var sbuilder strings.Builder
	for _,k := range keys {
		if len(k) == 0 || strings.EqualFold("sign", k) {
			continue
		}
		var v string
		tv := tempMap[k]
		if tv == nil {
			continue
		}
		switch tv.(type) {
			case string: v = tv.(string)
			default:
				v,_ = jsont.MarshalToString(tv)
		}
		if len(v) == 0 {
			continue
		}
		if sbuilder.Len() > 0 {
			sbuilder.WriteString("&")
		}
		sbuilder.WriteString(k)
		sbuilder.WriteString("=")
		sbuilder.WriteString(v)
	}
	return sbuilder.String(), nil
}
 类似资料: