【golang】动态生成微信小程序二维码实战下:golang 生成 小程序二维码图片 并通过s3协议上传到对象存储桶 | 腾讯云 cos

项目背景

在自研的系统,需要实现类似草料二维码的功能

将我们自己的小程序,通过代码生成相想要的小程序二维码

代码已经上传到 Github 需要的朋友可以自取
https://github.com/ctra-wang/wechat-mini-qrcode

一、生成Qrcode并提交到对象存储

通过源生API实现对小程序二维码的生成

1、s3上传多云对象存储桶

感谢suyuan32同学对代码的开源: https://github.com/suyuan32/simple-admin-file

让我们一起支持群主维护simple-admin 社群吧!!!

不能加入星球的朋友记得来点个Star!!
https://github.com/suyuan32/simple-admin-core

2、源码

下面为示意代码,

需要的package如下:

go 复制代码
func NewVerifyRaceSignTeamLogic(ctx context.Context, svcCtx *svc.ServiceContext) *VerifyRaceSignTeamLogic {
	return &VerifyRaceSignTeamLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx}
}

func (l *VerifyRaceSignTeamLogic) VerifyRaceSignTeam(req *types.RaceSignTeamInfo) (resp *types.BaseMsgResp, err error) {
	deptId := ctxdata.GetIntParamFromJwt(l.ctx, "deptId")

	// 根据具体赛事id查询
	raceSignTeam, err := l.svcCtx.CtraGoRaceRpc.GetRaceSignTeamById(l.ctx, &ctragorace.IDReq{
		Id: *req.Id,
	})
	if err != nil {
		return nil, err
	}

	flag := false
	if int(deptId) != constant.ORG_TYPE_ADMIN {
		// 根据 deptid 换 orgInfo
		orgRes, err := l.svcCtx.CtraGoRaceRpc.GetRaceOrgInfoList(l.ctx, &ctragorace.RaceOrgInfoListReq{
			DeptId: &deptId,
		})
		if err != nil {
			return nil, err
		}

		if orgRes.Total > 0 {
			// 非管理员,查看该权限下所有赛事
			raceList, err := l.svcCtx.CtraGoRaceRpc.GetRaceInfoList(l.ctx, &ctragorace.RaceInfoListReq{
				RaceOrgInfoId: *orgRes.Data[0].Id,
			})
			if err != nil {
				return nil, err
			}
			if raceList.Total > 0 {
				for _, datum := range raceList.Data {
					if *datum.Id == *raceSignTeam.RaceInfoId {
						flag = true
						break
					}
				}
			}
		}
	} else {
		flag = true
	}

	if !flag {
		return nil, errorx.NewCodeAbortedError("该用户暂无权限进行审核!")
	}

	// -----------------------	生成 微信小程序二维码  使用:github.com/silenceper/wechat/v2		-----------------------
	// 初始化 Wechat 实例
	wc := wechat.NewWechat()
	//这里本地内存保存access_token,也可选择redis,memcache或者自定cache
	memory := cache.NewMemory()
	cfg := &miniConfig.Config{
		AppID:     constant.MINI_APP_LATEST_ID,
		AppSecret: constant.MINI_APP_LATEST_SECRET,
		Cache:     memory,
	}
	mini := wc.GetMiniProgram(cfg)
	qr := mini.GetQRCode()
	qrRes, err := qr.CreateWXAQRCode(qrcode.QRCoder{
		Page: l.svcCtx.Config.QrCode.Page,
		Path: fmt.Sprintf(l.svcCtx.Config.QrCode.Path, raceSignTeam.RaceInfoId),
		//CheckPath:  nil,
		Width: l.svcCtx.Config.QrCode.Width,
		//Scene: "pathName=/race/pages/group&id=58",
		//AutoColor:  false,
		//LineColor:  nil,
		//IsHyaline:  false,
		//EnvVersion: "",
	})
	if err != nil {
		return nil, errorx.NewCodeAbortedError("通过微信小程序API生成小程序二维码失败!")

	}
	// -----------------------	将 微信小程序二维码 生成为本地文件用于存入对象存储cos   -----------------------
	// 拼接文件路径
	fileDir := fmt.Sprintf("/upload/race-info/%s/", time.Now().Format("2006_01"))
	newFileName := generatoruuid.GetUuid() + ".jpg"

	// 获取当前 Pod 的工作目录
	pwd, err := os.Getwd()
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("os创建文件夹失败!")
	}
	// 创建文件路径
	err = os.MkdirAll(pwd+fileDir, 0755)
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("os创建文件夹失败!")
	}
	// 复制文件(空文件)到该路径
	qrcodeFile, err := os.Create(pwd + fileDir + newFileName)
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("os创建文件失败!")
	}
	// 将通过API生成小程序二维码->写入到文件中
	_, err = qrcodeFile.Write(qrRes)
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("os创建文件失败!")
	}
	defer qrcodeFile.Close()
	// 删除文件
	defer os.RemoveAll(pwd + fileDir + newFileName)

	// -----------------------	推送文件到tencent对象存储cos   -----------------------
	// 创建s3实例
	sess := session.Must(session.NewSession(
		&aws.Config{
			Region:      aws.String(l.svcCtx.Config.QrCode.Region),
			Credentials: credentials.NewStaticCredentials(l.svcCtx.Config.QrCode.SecretId, l.svcCtx.Config.QrCode.SecretKey, ""),
			Endpoint:    aws.String(l.svcCtx.Config.QrCode.EndPoint),
		},
	))
	CloudStorage := s3.New(sess)

	qrFile, err := os.Open(pwd + fileDir + newFileName)
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("读取新创建qrcode失败!")
	}
	defer qrFile.Close()

	// 处理存放cos的路径
	// - C 端
	// - 赛事报名:race-sign/赛事id/
	// - 赛事信息:race-info/赛事id/ ✅
	// - 用户里程碑:member-moment/用户id/
	// - 用户个人信息: member-info/用户id/
	// - B 端 (不在这里使用)
	// - banner:banner/
	relativeSrc := fmt.Sprintf("%s/%s/%d/%s",
		l.svcCtx.Config.QrCode.Folder,
		"race-info",
		*raceSignTeam.RaceInfoId,
		newFileName)
	//  发送到tencent-cos
	_, err = CloudStorage.PutObjectWithContext(context.Background(), &s3.PutObjectInput{
		Bucket: aws.String(l.svcCtx.Config.QrCode.BucketName),
		Key:    aws.String(relativeSrc),
		Body:   qrFile,
	})
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("文件上传到tencent-cos失败!")
	}

	fmt.Println("QR code upload tencent cos successfully!")

	// -----------------------	更新数据库表 race_sign_team  -----------------------
	// 更新团报状态
	res1, err := l.svcCtx.CtraGoRaceRpc.UpdateRaceSignTeam(l.ctx,
		&ctragorace.RaceSignTeamInfo{
			Id:         req.Id,
			IsValidate: pointy.GetPointer(int32(constant.SIGN_TEAM_IS_VALIDATE_ACCESS)),
			TeamQrcode: &relativeSrc,
		})
	if err != nil {
		return nil, err
	}

	return &types.BaseMsgResp{Msg: res1.Msg}, nil

}

3、源码分析

3.1、拿到qrcode二进制

qrRes 为拿到的图片二进制

go 复制代码
// -----------------------	生成 微信小程序二维码  使用:github.com/silenceper/wechat/v2		-----------------------
	// 初始化 Wechat 实例
	wc := wechat.NewWechat()
	//这里本地内存保存access_token,也可选择redis,memcache或者自定cache
	memory := cache.NewMemory()
	cfg := &miniConfig.Config{
		AppID:     constant.MINI_APP_LATEST_ID,
		AppSecret: constant.MINI_APP_LATEST_SECRET,
		Cache:     memory,
	}
	mini := wc.GetMiniProgram(cfg)
	qr := mini.GetQRCode()
	qrRes, err := qr.CreateWXAQRCode(qrcode.QRCoder{
		Page: l.svcCtx.Config.QrCode.Page,
		Path: fmt.Sprintf(l.svcCtx.Config.QrCode.Path, raceSignTeam.RaceInfoId),
		//CheckPath:  nil,
		Width: l.svcCtx.Config.QrCode.Width,
		//Scene: "pathName=/race/pages/group&id=58",
		//AutoColor:  false,
		//LineColor:  nil,
		//IsHyaline:  false,
		//EnvVersion: "",
	})
	if err != nil {
		return nil, errorx.NewCodeAbortedError("通过微信小程序API生成小程序二维码失败!")

	}

3.2、二维码存为本地文件

将 微信小程序二维码 生成为本地文件用于存入对象存储cos

go 复制代码
// -----------------------	将 微信小程序二维码 生成为本地文件用于存入对象存储cos   -----------------------
	// 拼接文件路径
	fileDir := fmt.Sprintf("/upload/contracts/%s/", time.Now().Format("2006_01"))
	newFileName := generatoruuid.GetUuid() + ".jpg"

	// 获取当前 Pod 的工作目录
	pwd, err := os.Getwd()
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("os创建文件夹失败!")
	}
	// 创建文件路径
	err = os.MkdirAll(pwd+fileDir, 0755)
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("os创建文件夹失败!")
	}
	// 复制文件(空文件)到该路径
	qrcodeFile, err := os.Create(pwd + fileDir + newFileName)
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("os创建文件失败!")
	}
	// 将通过API生成小程序二维码->写入到文件中
	_, err = qrcodeFile.Write(qrRes)
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("os创建文件失败!")
	}
	defer qrcodeFile.Close()
	// 删除文件
	defer os.RemoveAll(pwd + fileDir + newFileName)

3.3、推送文件到tencent对象存储cos

通过s3协议上传到对象存储桶 | 腾讯云 cos

这里注意要将刚才保存的图片再次打开 os.Open()

go 复制代码
// -----------------------	推送文件到tencent对象存储cos   -----------------------
	// 创建s3实例
	sess := session.Must(session.NewSession(
		&aws.Config{
			Region:      aws.String(l.svcCtx.Config.QrCode.Region),
			Credentials: credentials.NewStaticCredentials(l.svcCtx.Config.QrCode.SecretId, l.svcCtx.Config.QrCode.SecretKey, ""),
			Endpoint:    aws.String(l.svcCtx.Config.QrCode.EndPoint),
		},
	))
	CloudStorage := s3.New(sess)

	qrFile, err := os.Open(pwd + fileDir + newFileName)
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("读取新创建qrcode失败!")
	}
	defer qrFile.Close()

	// 处理存放cos的路径
	// - C 端
	// - 赛事报名:race-sign/赛事id/
	// - 赛事信息:race-info/赛事id/ ✅
	// - 用户里程碑:member-moment/用户id/
	// - 用户个人信息: member-info/用户id/
	// - B 端 (不在这里使用)
	// - banner:banner/
	relativeSrc := fmt.Sprintf("%s/%s/%d/%s",
		l.svcCtx.Config.QrCode.Folder,
		"race-info",
		*raceSignTeam.RaceInfoId,
		newFileName)
	//  发送到tencent-cos
	_, err = CloudStorage.PutObjectWithContext(context.Background(), &s3.PutObjectInput{
		Bucket: aws.String(l.svcCtx.Config.QrCode.BucketName),
		Key:    aws.String(relativeSrc),
		Body:   qrFile,
	})
	if err != nil {
		l.Logger.Errorf(err.Error())
		return nil, errorx.NewCodeAbortedError("文件上传到tencent-cos失败!")
	}

	fmt.Println("QR code upload tencent cos successfully!")
相关推荐
醒过来摸鱼6 分钟前
【Golang】协程
开发语言·后端·golang
灼华十一2 小时前
算法编程题-排序
数据结构·算法·golang·排序算法
宋发元2 小时前
Go语言使用 kafka-go 消费 Kafka 消息教程
golang·kafka·linq
宋发元3 小时前
Go消费kafka中kafkaReader.FetchMessage(ctx)和kafkaReader.ReadMessage(ctx)的区别
golang·kafka·linq
wqq_9922502773 小时前
springboot基于微信小程序的农产品交易平台
spring boot·后端·微信小程序
祁许14 小时前
【Golang】手搓DES加密
开发语言·golang·密码学
凡人的AI工具箱14 小时前
15分钟学 Go 实战项目六 :统计分析工具项目(30000字完整例子)
开发语言·数据库·人工智能·后端·golang
王大锤439114 小时前
golang通用后台管理系统10(退出登录,注销token)
golang
ezreal_pan15 小时前
vitess使用:从部署到go客户端连接查询
golang·vitess
0x派大星19 小时前
【Golang】——Gin 框架中的 API 请求处理与 JSON 数据绑定
开发语言·后端·golang·go·json·gin