当前位置:   article > 正文

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

【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

Your Image Description

让我们一起支持群主维护simple-admin 社群吧!!!
不能加入星球的朋友记得来点个Star!!
https://github.com/suyuan32/simple-admin-core

2、源码

下面为示意代码,

需要的package如下:

  • github.com/silenceper/wechat/v2
  • github.com/aws/aws-sdk-go/aws
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

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172

3、源码分析

3.1、拿到qrcode二进制

qrRes 为拿到的图片二进制

// -----------------------	生成 微信小程序二维码  使用: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生成小程序二维码失败!")

	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

3.2、二维码存为本地文件

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

// -----------------------	将 微信小程序二维码 生成为本地文件用于存入对象存储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)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

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

通过s3协议上传到对象存储桶 | 腾讯云 cos
这里注意要将刚才保存的图片再次打开 os.Open()

// -----------------------	推送文件到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!")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/624628
推荐阅读
相关标签
  

闽ICP备14008679号