【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!")
相关推荐
lars_lhuan8 小时前
Go WaitGroup 源码解析
golang
人间打气筒(Ada)13 小时前
如何基于 Go-kit 开发 Web 应用:从接口层到业务层再到数据层
开发语言·后端·golang
笨笨狗吞噬者15 小时前
【uniapp】微信小程序实现自定义 tabBar
前端·微信小程序·uni-app
2501_9339072115 小时前
如何选择性价比高的宁波小程序开发服务公司?
科技·微信小程序·小程序
阿珊和她的猫17 小时前
微信小程序 WXSS 与 CSS 的区别
css·微信小程序·notepad++
想搞艺术的程序员18 小时前
Go RWMutex 源码分析:一个计数器,如何把“读多写少”做得又快又稳
开发语言·redis·golang
喵了几个咪19 小时前
GoWind Content Hub|风行,开箱即用的企业级前后端一体内容中台
vue.js·golang·react·taro
人间打气筒(Ada)19 小时前
go实战案例:如何基于 Conul 给微服务添加服务注册与发现?
开发语言·微服务·zookeeper·golang·kubernetes·etcd·consul
nhc08820 小时前
贵阳纳海川科技・棋牌室行业数字化解决方案
科技·微信小程序·小程序·软件开发·小程序开发
superantwmhsxx20 小时前
[golang][MAC]Go环境搭建+VsCode配置
vscode·macos·golang