项目背景

在自研的系统,需要实现类似草料二维码的功能 将我们自己的小程序,通过代码生成相想要的小程序二维码

代码已经上传到 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如下:

github.com/silenceper/wechat/v2github.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

}

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生成小程序二维码失败!")

}

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)

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!")

精彩文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。