【Golang 接口自动化06】微信支付md5签名计算及其优化

news2024/11/13 9:49:21

目录

前言

初始方式

代码说明

优化

最终方法

性能对比

参考代码

总结

资料获取方法


前言

可能看过我博客的朋友知道我主要是做的支付这一块的测试工作。而我们都知道现在比较流行的支付方式就是微信支付和支付宝支付,当然最近在使用低手续费大力推广的京东金融(已改名为京东数科)以后也可能站到第一队列,但是要在中国市场走到和财付通、蚂蚁金服一个层级就任重而道远了。

废话不多说,我们一起来看看微信支付签名的官方文档。搜索微信支付--点击支付开发文档--接口规则--安全规范。

我们会看的以下的内容:

签名生成的方法文档已经说的很清晰,下面我们一起来看看怎么使用golang来实现它,以及怎么使用一些更高级的特性来优化。

初始方式

最开始的方式比较直接,能实现这个需求就行:

func GetSign(sourceMap map[string]string, bizKey string) string {
	orderedString := orderParam(sourceMap, bizKey)
	md5Ctx := md5.New()
	md5Ctx.Write([]byte(orderedString))
	signString := md5Ctx.Sum(nil)
	//fmt.Print(hex.EncodeToString(cipherStr))
	return hex.EncodeToString(signString)
}

func orderParam(source map[string]string, bizKey string) string {
	var tempArr []string
	i := 0
	for k, v := range source {
		tempArr = append(tempArr, k+"="+v)
		i++
	}
	sort.Strings(tempArr)
	temString := ""
	for n, v := range tempArr {
		if n+1 < len(tempArr) {
			temString = temString + v + "&"
		} else {
			temString = temString + v + bizKey
		}
	}
	fmt.Println(temString)
	return temString
}

代码说明

  • orderParam主要用来把传递的参数转化为键值对的格式(即key1=value1&key2=value2…)并在最后拼接上key
  • GetSign 获取orderParam拼接之后字符串进行md5加密

后来发现这样的方式有很多的弊端,比如无法处理可能某个参数是数字的情况,无法处理某个参数的value值是map或数组的情况,所以就进行了兼容性和性能上的优化。

优化

这一次的优化主要就是添加了格式的兼容,将传入的参数变成了可以存储任何类型数据的interface{},另外就是优化了拼接字符串的操作。优化后的代码如下

func betterOne(srcmap map[string]interface{}, bizkey string) string {
	md5ctx := md5.New()
	keys := make([]string, 0, len(srcmap))

	for k := range srcmap {
		if k == "sign" {
			continue
		}
		keys = append(keys, k)
	}
	sort.Strings(keys)
	var buf bytes.Buffer
	for _, k := range keys {
		vs := srcmap[k]
		if vs == "" {
			continue
		}
		if buf.Len() > 0 {
			buf.WriteByte('&')
		}

		buf.WriteString(k)
		buf.WriteByte('=')
		switch vv := vs.(type) {
		case string:
			buf.WriteString(vv)
		case int:
			buf.WriteString(strconv.FormatInt(int64(vv), 10))
		default:
			panic("params type not supported")
		}
	}
	buf.WriteString(bizkey)
	md5ctx.Write([]byte(buf.String()))
	return hex.EncodeToString(md5ctx.Sum(nil))
}

buf.WriteString使用buffer来替代循环的字符串操作,来自于基础库http库中的url.encode方法,在此前我的文章有提到过这个方法。理论上来说性能会有一个比较大的提升,实际测试结果如下:

其中ns/opB/opallocs/op分别代表每个操作的耗时、分配内存、分配对象次数。可以看的三者都有较大的提升。

当时在知道这个差距之后,我放下了手上的已经构建得七七八八的自动化代码,专心的研究了一段时间开源项目的源码,所以有了下面这个兼容性更好和性能更平衡的版本。

最终方法

这个版本主要考虑的是不同数据兼容性,兼容了直接传递struct时进行签名的计算(后面会学习到直接把struct当作json发送的方法),并把map[string]stringmap[string]interface{}的数据都进行了对应处理。

性能对比

下面是三者对比的性能测试结果

可以看到最终版比优化版损耗的时间还要略短。

参考代码

// Getsign get the sign info
func Getsign(srcdata interface{}, bizkey string) string {
	md5ctx := md5.New()

	switch v := reflect.ValueOf(srcdata); v.Kind() {
	case reflect.String:
		md5ctx.Write([]byte(v.String() + bizkey))
		return hex.EncodeToString(md5ctx.Sum(nil))
	case reflect.Map:
		orderStr := orderParam(v.Interface(), bizkey)
		md5ctx.Write([]byte(orderStr))
		return hex.EncodeToString(md5ctx.Sum(nil))
	case reflect.Struct:
		orderStr := Struct2map(v.Interface(), bizkey)
		md5ctx.Write([]byte(orderStr))
		return hex.EncodeToString(md5ctx.Sum(nil))
	default:
		return ""
	}
}

func orderParam(source interface{}, bizKey string) (returnStr string) {
	switch v := source.(type) {
	case map[string]string:
		keys := make([]string, 0, len(v))

		for k := range v {
			if k == "sign" {
				continue
			}
			keys = append(keys, k)
		}
		sort.Strings(keys)
		var buf bytes.Buffer
		for _, k := range keys {
			if v[k] == "" {
				continue
			}
			if buf.Len() > 0 {
				buf.WriteByte('&')
			}

			buf.WriteString(k)
			buf.WriteByte('=')
			buf.WriteString(v[k])
		}
		buf.WriteString(bizKey)
		returnStr = buf.String()
	case map[string]interface{}:
		keys := make([]string, 0, len(v))

		for k := range v {
			if k == "sign" {
				continue
			}
			keys = append(keys, k)
		}
		sort.Strings(keys)
		var buf bytes.Buffer
		for _, k := range keys {
			if v[k] == "" {
				continue
			}
			if buf.Len() > 0 {
				buf.WriteByte('&')
			}

			buf.WriteString(k)
			buf.WriteByte('=')
			// buf.WriteString(srcmap[k])
			switch vv := v[k].(type) {
			case string:
				buf.WriteString(vv)
			case int:
				buf.WriteString(strconv.FormatInt(int64(vv), 10))
			default:
				panic("params type not supported")
			}
		}
		buf.WriteString(bizKey)
		returnStr = buf.String()
	}
	// fmt.Println(returnStr)
	return
}

func Struct2map(content interface{}, bizKey string) string {
	var tempArr []string
	temString := ""
	var val map[string]string
	if marshalContent, err := json.Marshal(content); err != nil {
		fmt.Println(err)
	} else {
		d := json.NewDecoder(bytes.NewBuffer(marshalContent))
		d.UseNumber()
		if err := d.Decode(&val); err != nil {
			fmt.Println(err)
		} else {
			for k, v := range val {
				val[k] = v
			}
		}
	}
	i := 0
	for k, v := range val {
		// 去除冗余未赋值struct
		if v == "" {
			continue
		}
		i++
		tempArr = append(tempArr, k+"="+v)
	}
	sort.Strings(tempArr)
	for n, v := range tempArr {
		if n+1 < len(tempArr) {
			temString = temString + v + "&"
		} else {
			temString = temString + v + bizKey
		}
	}
	return temString
}

总结

  • 微信签名
  • buffer
  • 简单性能测试

资料获取方法

【留言777】

各位想获取源码等教程资料的朋友请点赞 + 评论 + 收藏,三连!

三连之后我会在评论区挨个私信发给你们~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/815960.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ELD透明屏在智能家居中有哪些优点展示?

ELD透明屏是一种新型的显示技术&#xff0c;它能够在不需要背光的情况下显示图像和文字。 ELD透明屏的原理是利用电致发光效应&#xff0c;通过在透明基板上涂覆一层特殊的发光材料&#xff0c;当电流通过时&#xff0c;发光材料会发出光线&#xff0c;从而实现显示效果。 ELD…

企业电子招投标采购系统java spring cloud+spring boot功能模块功能描述+数字化采购管理 采购招投标

​功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&#xff0c;为外…

【深度学习】MAT: Mask-Aware Transformer for Large Hole Image Inpainting

论文&#xff1a;https://arxiv.org/abs/2203.15270 代码&#xff1a;https://github.com/fenglinglwb/MAT 文章目录 AbstractIntroductionRelated WorkMethod总体架构卷积头Transformer主体Adjusted Transformer Block Multi-Head Contextual Attention Style Manipulation Mo…

计算机视觉实验:图像处理综合-路沿检测

目录 实验步骤与过程 1. 路沿检测方法设计 2. 路沿检测方法实现 2.1 视频图像提取 2.2 图像预处理 2.3 兴趣区域提取 2.4 边缘检测 ​​​​​​​2.5 Hough变换 ​​​​​​​2.6 线条过滤与图像输出 3. 路沿检测结果展示 4. 其他路沿检测方法 实验结论或体会 实…

防雷保护区如何划分,防雷分区概念LPZ介绍

在防雷设计中&#xff0c;很重要的一点就是防雷分区的划分&#xff0c;只有先划分好防雷区域等级&#xff0c;才好做出比较好的防雷器设计方案。 因为标准对不同区安装的防雷浪涌保护器要求是不一样的。 那么&#xff0c;防雷保护区是如何划分的呢&#xff1f; 如上图所示&…

关于led显示屏编程技术有哪些

LED显示屏编程技术主要涉及控制LED显示屏的内容、亮度、颜色等参数&#xff0c;以及与其他设备或系统的数据交互。下面列举一些常见的LED显示屏编程技术&#xff1a; 1. LED显示屏控制协议&#xff1a; 不同品牌和型号的LED显示屏通常都采用特定的控制协议&#xff0c;如DMX51…

【数据结构】_6.队列

目录 1.概念 2.队列的使用 3.队列模拟实现 4.循环队列 5.双端队列 6.OJ题 6.1 用队列实现栈 6.2 用栈实现队列 1.概念 &#xff08;1&#xff09;队列是只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff1b; &#xff08;2&am…

Linux6.21 ansible playbook 剧本

文章目录 计算机系统5G云计算第一章 LINUX ansible playbook 剧本一、概述二、playbook应用1.示例2.运行playbook3.定义、引用变量4.指定远程主机sudo切换用户5.when条件判断6.迭代7.Templates 模块8.tags 模块 计算机系统 5G云计算 第一章 LINUX ansible playbook 剧本 一、…

金现代LIMS在电子行业的应用

近期&#xff0c;随着国家政策对可靠性检验标准的进一步提升&#xff0c;电子、机械等相关行业对LIMS实验室管理系统的需求愈发迫切。 政策速递&#xff08;一&#xff09; 提升制造业质量与可靠性管理水平 01 2023年6月&#xff0c;工业和信息化部、教育部、科技部、财政部、…

一文带你全面掌握Git技能知识!

简单地说&#xff0c;Git 究竟是怎样的一个系统呢&#xff1f;请注意接下来的内容非常重要&#xff0c;若你理解了 Git 的思想和基本工作原理&#xff0c;用起来就会知其所以然&#xff0c;游刃有余。在学习 Git 时&#xff0c;请尽量理清你对其它版本管理系统已有的认识&#…

Elasticsearch Java客户端和Spring data elasticsearch

文章目录 官网版本组件版本说明实现代码地址es Spring Data Repositories例子&#xff1a;ElasticsearchRepository分析 es Spring Data Repositories 关键字es Spring Data Repositories client 加载rest风格客户端直接执行dsl例子响应式客户端-ReactiveElasticsearchClientpo…

SSD市场上演大洗牌,61TB豪华「别墅」横空出世

最近几年 SSD 售价是肉眼可见的下降&#xff0c;相信大伙儿没少跟着喝汤吃肉吧。 有人将这些变化归结于全球市场过饱和&#xff0c;需求下滑。 也有人认为国产 NAND 闪存崛起是压垮 SSD 高昂售价的最后一根稻草。 在小忆看来&#xff0c;不论是需求矛盾还是国产崛起不过是其中…

Maven右侧依赖Dependencies消失

项目右侧的Maven依赖Dependencies突然消失&#xff0c;项目中的注解都出现报错&#xff0c;出现这种情况应该是因为IDEA版本早于maven版本&#xff0c;重新检查项目中的Maven路径&#xff0c;选择File->Settings->搜索Maven&#xff0c;检查Maven home directory&#xf…

爆肝整理,接口自动化测试-数据驱动框架封装(实战)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 接口自动化框架—…

没有软件测试经验,怎样面试测试工作?

纸上得来终觉浅&#xff0c;所有的面试经验都是要自己去体验&#xff0c;他人说来的都是他人的经验。 同样&#xff0c;每个公司&#xff0c;面对的面试官都会有不同的问题&#xff0c;当然这些问题可能会大同小异&#xff0c;但是也需要自己总结得出&#xff0c;这样的经验不…

1221. 四平方和(超详细!!)

输入样例&#xff1a; 5输出样例&#xff1a; 0 0 1 2 本题思路&#xff1a;以空间换时间 由于暴力解法我们至少要枚举三个数&#xff0c;然后计算出第四个数 呢么需要进行三重循环,时间复杂度大概为O(n3),则会超时 所以我们要进行优化来降低时间复杂度 我们的思路是&#xf…

怎么学习C语言,才能快速掌握?

有多年软件行业经验&#xff0c;期间参与过多个C语言项目。要掌握一门编程语言&#xff0c;仅仅投入时间学习是不够的&#xff0c;关键在于实际项目经验。在没有真正实战经验之前&#xff0c;不宜轻易声称掌握某种编程语言&#xff0c;因为编程是积累性的工作&#xff0c;理论知…

需求太多处理不过来?MoSCoW模型帮你

一、MoSCoW模型是什么 MoSCoW模型 是在项目管理、软件开发中使用的一种排序优先级的方法&#xff0c;以便开发人员、产品经理、客户对每个需求交付的重要性达成共识。 MoSCoW是一个首字母缩略词&#xff0c;代表&#xff1a; M&#xff08;Must have&#xff09;&#xff1a…

IDEA开启并配置services窗口

前言&#xff1a; 一般一个spring cloud项目中大大小小存在几个十几个module编写具体的微服务项目。此时&#xff0c;如果要调试测需要依次启动各个项目比较麻烦。 方法一&#xff1a; 默认第一次打开项目的时候&#xff0c;idea会提示是否增加这个选项卡&#xff0c;如果你没…

NIDEC COMPONENTS尼得科科宝滑动型DIP开关各系列介绍

今天AMEYA360对尼得科科宝电子滑动型DIP开关各系列参数进行详细介绍&#xff0c;方便大家选择适合自己的型号。 系列一、滑动型DIP开关 CVS 针脚数&#xff1a;1, 2, 3, 4, 8 安装类型&#xff1a;表面贴装&#xff0c;通孔 可水洗&#xff1a;无 端子类型&#xff1a;PC引脚(只…