【golang】动态生成微信小程序二维码实战上:golang整合github.com/silenceper/wechat/v2 实现生成 小程序二维码图片

项目背景

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

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

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

一、源生实现

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

1、官方API

官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/createQRCode.html

下面是三个官方的API 可以根据需求进行调用

CreateWXAQRCodeURL   = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=%s"
GetWXACodeURL        = "https://api.weixin.qq.com/wxa/getwxacode?access_token=%s"
GetWXACodeUnlimitURL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s"

2、golang 实现源码

go 复制代码
package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
)

const (
	CreateWXAQRCodeURL   = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=%s"
	GetWXACodeURL        = "https://api.weixin.qq.com/wxa/getwxacode?access_token=%s"
	GetWXACodeUnlimitURL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s"
)

const (
	// 替换成你的小程序 appiId 和 secretKey
	MINI_APP_LATEST_ID     string = "wxxxxf6"
	MINI_APP_LATEST_SECRET string = "7dfxxx64a"
)

// 通过 普通的源生请求
func main() {
	// 要生成二维码的路径和参数
	_, err := GetQRCode(58)
	if err != nil {
		fmt.Println("Error getting QR code:", err)
		return
	}

}

func GetQRCode(id int) ([]byte, error) {
	//上面生成的access code 判断为空时重新请求
	accessToken, err := requestToken(MINI_APP_LATEST_ID, MINI_APP_LATEST_SECRET)
	if err != nil {
		return nil, err
	}
	strUrl := fmt.Sprintf(CreateWXAQRCodeURL, accessToken)

	// todo: 这里有bug待完善
	parm := make(map[string]string)
	// path 要以?开始
	parm["path"] = fmt.Sprintf("?pathName=/race/pages/group&id=%d", id)
	// page 起始位置不需要 /
	parm["page"] = fmt.Sprintf("pages/home/index")
	jsonStr, err := json.Marshal(parm)
	if err != nil {
		return nil, errors.New("json Marshal QRCode paramter err :" + err.Error())
	}
	req, err := http.NewRequest("POST", strUrl, bytes.NewBuffer([]byte(jsonStr)))
	if err != nil {
		return nil, errors.New("get QRCode err :" + err.Error())
	}
	// 发起 post 请求
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, errors.New("get QRCode err :" + err.Error())
	}

	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, errors.New("get QRCode err :" + err.Error())
	}

	// 生成图片
	png, err := os.Create("data.png")
	_, err2 := png.Write(body)

	if err2 != nil {
		log.Fatal(err2)
	}
	fmt.Println("QR code saved successfully!")
	return nil, nil
}

func requestToken(appid, secret string) (string, error) {
	u, err := url.Parse("https://api.weixin.qq.com/cgi-bin/token")
	if err != nil {
		log.Fatal(err)
	}
	paras := &url.Values{}
	//设置请求参数
	paras.Set("appid", appid)
	paras.Set("secret", secret)
	paras.Set("grant_type", "client_credential")
	u.RawQuery = paras.Encode()
	resp, err := http.Get(u.String())
	//关闭资源
	if resp != nil && resp.Body != nil {
		defer resp.Body.Close()
	}
	if err != nil {
		return "", errors.New("request token err :" + err.Error())
	}

	jMap := make(map[string]interface{})
	err = json.NewDecoder(resp.Body).Decode(&jMap)
	if err != nil {
		return "", errors.New("request token response json parse err :" + err.Error())
	}
	if jMap["errcode"] == nil || jMap["errcode"] == 0 {
		accessToken, _ := jMap["access_token"].(string)
		return accessToken, nil
	} else {
		//返回错误信息
		errcode := jMap["errcode"].(string)
		errmsg := jMap["errmsg"].(string)
		err = errors.New(errcode + ":" + errmsg)
		return "", err
	}
}

3、代码分析 io.ReadAll 文件流

通过接口返回的 resp中的body,通过 io.ReadAll() 方法返回的body为二进制

go 复制代码
body, err := io.ReadAll(resp.Body)
if err != nil {
	return nil, errors.New("get QRCode err :" + err.Error())
}

我们需要通过文件去接收这个文件流

go 复制代码
// 生成图片
png, err := os.Create("data.png")
_, err2 := png.Write(body)

这样我们就可以看到一个data.png的文件产生

二、框架实现

1、官方API

作者: silenceper/wechat

github地址:https://github.com/silenceper/wechat/v2

文档地址:https://silenceper.com/wechat/miniprogram/qrcode.html

2、golang 实现源码

go 复制代码
package main

import (
	"fmt"
	"github.com/silenceper/wechat/v2"
	"github.com/silenceper/wechat/v2/cache"
	miniConfig "github.com/silenceper/wechat/v2/miniprogram/config"
	"github.com/silenceper/wechat/v2/miniprogram/qrcode"
	"log"
	"os"
)

const (

	// 替换成你的小程序 appiId 和 secretKey
	MINI_APP_LATEST_ID     string = "wxxxxf6"
	MINI_APP_LATEST_SECRET string = "7dfxxx64a"
)

func main() {
	// 初始化 Wechat 实例
	wc := wechat.NewWechat()
	//这里本地内存保存access_token,也可选择redis,memcache或者自定cache
	memory := cache.NewMemory()
	//token, _ := requestToken(MINI_APP_LATEST_ID, MINI_APP_LATEST_SECRET)
	cfg := &miniConfig.Config{
		AppID:     MINI_APP_LATEST_ID,
		AppSecret: MINI_APP_LATEST_SECRET,
		Cache:     memory,
	}

	//officialAccount := wc.GetOfficialAccount(cfg)
	mini := wc.GetMiniProgram(cfg)
	fmt.Println("------------")
	qcode := mini.GetQRCode()
	res, err := qcode.CreateWXAQRCode(qrcode.QRCoder{
		Page: "pages/home/index",
		Path: "?pathName=/race/pages/group&id=58",
		//CheckPath:  nil,
		Width: 300,
		//Scene: "pathName=/race/pages/group&id=58",
		//AutoColor:  false,
		//LineColor:  nil,
		//IsHyaline:  false,
		//EnvVersion: "",
	})
	if err != nil {
		return
	}
	// 生成图片
	png, err := os.Create("race.png")
	_, err2 := png.Write(res)

	if err2 != nil {
		log.Fatal(err2)
	}

	fmt.Println("QR code saved successfully!")

}
相关推荐
中云DDoS CC防护蔡蔡36 分钟前
微信小程序被攻击怎么选择高防产品
服务器·网络安全·微信小程序·小程序·ddos
井眼4 小时前
微信小程序-prettier 格式化
微信小程序·小程序
qq_17448285757 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
wqq_9922502777 小时前
springboot基于微信小程序的食堂预约点餐系统
数据库·微信小程序·小程序
007php00711 小时前
GoZero 上传文件File到阿里云 OSS 报错及优化方案
服务器·开发语言·数据库·python·阿里云·架构·golang
高 朗12 小时前
【GO基础学习】基础语法(2)切片slice
开发语言·学习·golang·slice
IT书架12 小时前
golang面试题
开发语言·后端·golang
licy__13 小时前
微信小程序登录注册页面设计(小程序项目)
微信小程序·小程序
醒过来摸鱼19 小时前
【Golang】协程
开发语言·后端·golang
灼华十一21 小时前
算法编程题-排序
数据结构·算法·golang·排序算法