记微信小程序二维码

目录

官方开发文档

错误码:

总结:

 实例代码

 B接口实例代码:

更换中间logo实例代码:



官方开发文档

https://developers.weixin.qq.com/miniprogram/dev/api/qrcode.html

注意点:开发者切记,选用适合的接口开发自己的业务。

  • tip:通过该接口,仅能生成已发布的小程序的二维码。
  • tip:可以在开发者工具预览时生成开发版的带参二维码。
  • tip:接口A加上接口C,总共生成的码数量限制为100,000,请谨慎调用。
  • tip: POST 参数需要转成 json 字符串,不支持 form 表单提交。
  • tip: auto_color line_color 参数仅对小程序码生效。

错误码:

  • 45009:B接口调用分钟频率受限(目前5000次/分钟,会调整),如需大量小程序码,建议预生成。
  • 45029:A接口和C接口生成码个数总和到达最大个数限制。
  • 41030:B接口所传page页面不存在,或者小程序没有发布,请注意B接口没有path参数,传path参数虽然可以生成小程序码,但是只能跳主页面。

总结:

接口A: 适用于需要的码数量较少的业务场景

接口地址:

https://api.weixin.qq.com/wxa/getwxacode?access_token=ACCESS_TOKEN

接口B:适用于需要的码数量极多的业务场景

接口地址:

https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN

接口C:适用于需要的码数量较少的业务场景。

接口地址:

https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=ACCESS_TOKEN

接口A、C虽然能传递path,直接跳转到对应的页面。但由于不能大量的生成,当需要生成的二维码大于的100,000个时候,又想跳转到对应的页面。那么我们需要使用B接口。原因如下:

  1. 生成的二维码数量不限。
  2. B接口带有scene参数,前端能根据扫码得到scene参数进行逻辑的判断,从而跳转到对应的页面。

 实例代码

 B接口实例代码:

/**
     * @Description: 获取二维码
     * @param: @param
     *             m
     * @param: @return
     * @return: Return
     */
    public Return getQr(HashMap<String, Object> m) {

        HttpSession session = getSession();      

        String scene = m.get("scene").toString; // 自定义参数
        String path = "pages/index/index";// 主页地址
        if (!"".equals(Tools.toStr(m.get("page")))) { // 首页地址
            path = Tools.toStr(m.get("page"));
        }
        int width = (Tools.toInt(m.get("width")) == 0) ? 430 : Tools.toInt(m.get("width")); // 二维码的宽度
        Boolean auto_color = Tools.toBoolean(m.get("auto_color")); // 默认false,自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调
        // 当auto_color为false才生效
        JSONObject line_color = new JSONObject();
        line_color.put("r", 0);
        line_color.put("g", 0);
        line_color.put("b", 0);
        boolean is_hyaline = Tools.toBoolean(m.get("is_hyaline"));// 默认false,是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码

        scene = "test";//测试
        auto_color = true;// 测试
        is_hyaline = false;// 测试
        Map<String, Object> params = new HashMap<>();
        params.put("scene", scene);
        params.put("width", width);
        params.put("path", path);
        params.put("auto_color", auto_color);
        params.put("line_color", line_color);
        params.put("is_hyaline", is_hyaline);

        String accessToken = Tools.toStr(session.getAttribute("wxapp_access_token"));//临时令牌,有效期2小时
        if ("".equals(accessToken)) {
            // 获取accessToken
            accessToken = getAccessToken(session);
        }

        // 二维码接口url
        String getwxacodeunlimit = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=";
        String url = getwxacodeunlimit + accessToken;

        // 发起请求
        HttpResponse response;
        InputStream ins = null;
        ByteArrayOutputStream out = new ByteArrayOutputStream();//二进制输出
        FileOutputStream fileOut = null;//图片文件输出
        StringEntity entity;
        try {
            File targetFile = new File("/home/m/桌面/5.jpeg");// 存放位置
            fileOut = new FileOutputStream(targetFile);
            CloseableHttpClient client = HttpClientBuilder.create().build();

            HttpPost httpPost = new HttpPost(url); // 接口
            httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");
            String body = JSON.toJSONString(params); // 必须是json模式的 post
            entity = new StringEntity(body);
            entity.setContentType("image/jpeg");

            httpPost.setEntity(entity);
            response = client.execute(httpPost);
            ins = response.getEntity().getContent();

            byte[] buffer = new byte[8192];
            int bytesRead = 0;
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                fileOut.write(buffer, 0, bytesRead);
                out.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成微信小程序二维码失败,失败原因:" + e.getMessage());
        } finally {
            if (ins != null) {
                try {
                    ins.close();
                } catch (IOException e) {
                    log.error("生成微信小程序二维码失败,失败原因:" + e.getMessage());
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {

                }
            }
            if (fileOut != null) {
                try {
                    fileOut.close();
                } catch (IOException e) {
                    log.error("生成微信小程序二维码失败,失败原因:" + e.getMessage());
                }
            }
        }
        System.out.println("生成完毕!");// 上传时删掉
        return NULL;
    }

/**
     * 获取access_token //
     * https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
     * @param url
     * @param grantType
     * @param appid
     * @param secret
     * @return
     */
    public static String getAccessToken(HttpSession session) {
        // 清除旧accessToken
        if (session.getAttribute("wxapp_access_token") != null) {
            session.removeAttribute("wxapp_access_token");
        }
        String url = SystemGlobals.getValue(WxAppConstants.WXAPP_ACCESS_TOKEN_URL);
        String appid = SystemGlobals.getValue(WxAppConstants.WXAPP_APPID);// appid
        String wxAppKey = SystemGlobals.getValue(WxAppConstants.WXAPP_APPKEY);// secret
      String grantType = SystemGlobals.getValue(WxAppConstants.WXAPP_GRANTTYPE_ACCESS_TOKEN);// grant_type = client_credential
        log.info(url+"      appid:"+appid+"     appkey:"+wxAppKey);                                                                                        
        String access_token = "";
        try {
            String jsonStr = HttpClientUtil.get(MessageFormat.format(url, grantType, appid, wxAppKey));
            com.alibaba.fastjson.JSONObject json = com.alibaba.fastjson.JSONObject.parseObject(jsonStr);
            access_token = Tools.toStr(json.get("access_token"));
        } catch (Exception e) {
            log.error("微信小程序获取access_Token失败:    错误原因:"+e.getMessage());
        }

        // 添加新的accessToken
        session.setAttribute("wxapp_access_token", access_token);
        return access_token;
    }

上面代码能生成带参的二维码。

但由于我们有时候需要更换二维码中间的logo,由于微信小程序默认生成的是我们自己微信小程序的头像。所以需要动点手脚,更换中间logo。

  1. 将需要更换的logo按比例缩小成透明底圆形logo,源logo图片最好是正方形,这样压缩出来的图片就不会变成椭圆形。
  2. 准备一张已生成带有参数的二维码参数,也是正方形的图片。
  3. 将两张图片合并。

更换中间logo实例代码:

实例代码,已抽成工具类

package com.jobcn.wxapp.util;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.imageio.ImageIO;

/**
 * @Description:微信小程序二维码专用工具类  
 * @author: mozhipeng
 * @date:   2018年7月24日 上午11:57:24
 */
public class WxAppImageUtil {
	static String url = "https://avatar.csdn.net/3/1/7/1_qq_27292113.jpg?1488183229974";

	public static void main(String[] args) {
		try {
			// https://avatar.csdn.net/3/1/7/1_qq_27292113.jpg?1488183229974
			// 是头像地址
			// 获取图片的流
			BufferedImage url = getUrlByBufferedImage("http://192.168.61.125/Person/avatar/qN10");

			// Image src = ImageIO.read(new
			// File("C:/Users/Administrator/Desktop/Imag.png"));
			// BufferedImage url = (BufferedImage) src;
			// 处理图片将其压缩成正方形的小图
			BufferedImage convertImage = scaleByPercentage(url, 100, 100);
			// 裁剪成圆形 (传入的图像必须是正方形的 才会 圆形 如果是长方形的比例则会变成椭圆的)
			convertImage = convertCircular(url);
			// 生成的图片位置
			String imagePath = "/home/mozhipeng/桌面/6.jpeg";
			ImageIO.write(convertImage, imagePath.substring(imagePath.lastIndexOf(".") + 1), new File(imagePath));
			System.out.println("ok");

			/// -------------------------------------
			WxAppImageUtil tt = new WxAppImageUtil();

			BufferedImage d = tt.loadImageLocal("/home/mozhipeng/桌面/5.jpeg");
			BufferedImage b = tt.loadImageLocal("/home/mozhipeng/桌面/6.jpeg");
			// 往图片上写文件
			// tt.writeImageLocal("E:\\ploanshare\\2\\22.jpg", tt.modifyImage(d, "000000",
			// 90, 90));

			tt.writeImageLocal("/home/mozhipeng/桌面/7.jpeg", tt.modifyImagetogeter(b, d));
			// 将多张图片合在一起
			System.out.println("success");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * @Description: 合并图片
	 * @param: @param srcImage1 合并图片1.作为首层
	 * @param: @param srcImage2 合并图片2,作为底层
	 * @param: @param destImage 合并后存放的位置     
	 * @return: void
	 */
	public static void mergePictures(String srcImage1,String srcImage2,String destImage) {
		WxAppImageUtil tt = new WxAppImageUtil();

		BufferedImage d = tt.loadImageLocal(srcImage1);
		BufferedImage b = tt.loadImageLocal(srcImage2);
		// 往图片上写文件
		// tt.writeImageLocal("E:\\ploanshare\\2\\22.jpg", tt.modifyImage(d, "000000",
		// 90, 90));
		tt.writeImageLocal(destImage, tt.modifyImagetogeter(b, d));
		// 将多张图片合在一起
		System.out.println("success");
	}

	/**
	 * @Description: 讲图片按比例缩小且裁剪成圆形(图片来源:网络)
	 * @param: @param
	 *             srcUrl 图片源地址
	 * @param: @param
	 *             destUrl 图片存放地址
	 * @param: @param
	 *             type 图片类型(png,jpeg),默认jpeg
	 * @param: @throws
	 *             Exception
	 * @return: void
	 */
	public static void cutPic2Circular(String srcUrl, String destUrl, String type) throws Exception {
		BufferedImage url = getUrlByBufferedImage(srcUrl);

		// Image src = ImageIO.read(new
		// File("C:/Users/Administrator/Desktop/Imag.png"));
		// BufferedImage url = (BufferedImage) src;
		// 处理图片将其压缩成正方形的小图
		BufferedImage convertImage = scaleByPercentage(url, 100, 100);
		// 裁剪成圆形 (传入的图像必须是正方形的 才会 圆形 如果是长方形的比例则会变成椭圆的)
		convertImage = convertCircular(url);
		// 生成的图片位置
		String imagePath = destUrl + "." + type;
		ImageIO.write(convertImage, imagePath.substring(imagePath.lastIndexOf(".") + 1), new File(imagePath));
		System.out.println("ok");
	}

	/**
	 * @Description: 讲图片按比例缩小且裁剪成圆形(图片来源:本地)
	 * @param: @param
	 *             srcUrl 图片源地址
	 * @param: @param
	 *             destUrl 图片存放地址
	 * @param: @param
	 *             type 图片类型(png,jpeg),默认jpeg
	 * @param: @throws
	 *             Exception
	 * @return: void
	 */
	public static void cutPic2CircularLocal(String srcUrl, String destUrl, String type) throws Exception {
		// BufferedImage url = getUrlByBufferedImage(srcUrl);

		Image src = ImageIO.read(new File(srcUrl));
		BufferedImage url = (BufferedImage) src;
		// 处理图片将其压缩成正方形的小图
		BufferedImage convertImage = scaleByPercentage(url, 100, 100);
		// 裁剪成圆形 (传入的图像必须是正方形的 才会 圆形 如果是长方形的比例则会变成椭圆的)
		convertImage = convertCircular(url);
		// 生成的图片位置
		String imagePath = destUrl + "." + type;
		ImageIO.write(convertImage, imagePath.substring(imagePath.lastIndexOf(".") + 1), new File(imagePath));
		System.out.println("ok");
	}

	/**
	 * 缩小Image,此方法返回源图像按给定宽度、高度限制下缩放后的图像
	 * 
	 * @param inputImage
	 * @param maxWidth
	 *            :压缩后宽度
	 * @param maxHeight
	 *            :压缩后高度
	 * @throws java.io.IOException
	 *             return
	 */
	public static BufferedImage scaleByPercentage(BufferedImage inputImage, int newWidth, int newHeight)
			throws Exception {
		// 获取原始图像透明度类型
		int type = inputImage.getColorModel().getTransparency();
		int width = inputImage.getWidth();
		int height = inputImage.getHeight();
		// 开启抗锯齿
		RenderingHints renderingHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		// 使用高质量压缩
		renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
		BufferedImage img = new BufferedImage(newWidth, newHeight, type);
		Graphics2D graphics2d = img.createGraphics();
		graphics2d.setRenderingHints(renderingHints);
		graphics2d.drawImage(inputImage, 0, 0, newWidth, newHeight, 0, 0, width, height, null);
		graphics2d.dispose();
		return img;
	}

	/**
	 * 通过网络获取图片
	 * 
	 * @param url
	 * @return
	 */
	public static BufferedImage getUrlByBufferedImage(String url) {
		try {
			URL urlObj = new URL(url);
			HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection();
			// 连接超时
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setConnectTimeout(25000);
			// 读取超时 --服务器响应比较慢,增大时间
			conn.setReadTimeout(25000);
			conn.setRequestMethod("GET");
			conn.addRequestProperty("Accept-Language", "zh-cn");
			conn.addRequestProperty("Content-type", "image/jpeg");
			conn.addRequestProperty("User-Agent",
					"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");
			conn.connect();
			BufferedImage bufImg = ImageIO.read(conn.getInputStream());
			conn.disconnect();
			return bufImg;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 传入的图像必须是正方形的 才会 圆形 如果是长方形的比例则会变成椭圆的
	 * 
	 * @param url
	 *            用户头像地址
	 * @return
	 * @throws IOException
	 */
	public static BufferedImage convertCircular(BufferedImage bi1) throws IOException {

		// BufferedImage bi1 = ImageIO.read(new File(url));

		// 这种是黑色底的
		// BufferedImage bi2 = new BufferedImage(bi1.getWidth(), bi1.getHeight(),
		// BufferedImage.TYPE_INT_RGB);

		// 透明底的图片
		BufferedImage bi2 = new BufferedImage(bi1.getWidth(), bi1.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
		Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, bi1.getWidth(), bi1.getHeight());
		Graphics2D g2 = bi2.createGraphics();
		g2.setClip(shape);
		// 使用 setRenderingHint 设置抗锯齿
		g2.drawImage(bi1, 0, 0, null);
		// 设置颜色
		g2.setBackground(Color.green);
		g2.dispose();
		return bi2;
	}

	// --------------------------------------------------------------------------------------

	/**
	 * 把两张图片合并
	 * 
	 * @author lizhiyong
	 * @version $Id: Pic.java, v 0.1 2015-6-3 下午3:21:23 1111 Exp $
	 */
	private Font font = new Font("宋体", Font.PLAIN, 12); // 添加字体的属性设置

	private Graphics2D g = null;

	private int fontsize = 0;

	private int x = 0;

	private int y = 0;

	/**
	 * 导入本地图片到缓冲区
	 */
	public BufferedImage loadImageLocal(String imgName) {
		try {
			return ImageIO.read(new File(imgName));
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
		return null;
	}

	/**
	 * 导入网络图片到缓冲区
	 */
	public BufferedImage loadImageUrl(String imgName) {
		try {
			URL url = new URL(imgName);
			return ImageIO.read(url);
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
		return null;
	}

	/**
	 * 生成新图片到本地
	 */
	public void writeImageLocal(String newImage, BufferedImage img) {
		if (newImage != null && img != null) {
			try {
				File outputfile = new File(newImage);
				ImageIO.write(img, "jpg", outputfile);
			} catch (IOException e) {
				System.out.println(e.getMessage());
			}
		}
	}

	/**
	 * 设定文字的字体等
	 */
	public void setFont(String fontStyle, int fontSize) {
		this.fontsize = fontSize;
		this.font = new Font(fontStyle, Font.PLAIN, fontSize);
	}

	/**
	 * 修改图片,返回修改后的图片缓冲区(只输出一行文本)
	 */
	public BufferedImage modifyImage(BufferedImage img, Object content, int x, int y) {

		try {
			int w = img.getWidth();
			int h = img.getHeight();
			g = img.createGraphics();
			g.setBackground(Color.WHITE);
			g.setColor(Color.orange);// 设置字体颜色
			if (this.font != null)
				g.setFont(this.font);
			// 验证输出位置的纵坐标和横坐标
			if (x >= h || y >= w) {
				this.x = h - this.fontsize + 2;
				this.y = w;
			} else {
				this.x = x;
				this.y = y;
			}
			if (content != null) {
				g.drawString(content.toString(), this.x, this.y);
			}
			g.dispose();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}

		return img;
	}

	/**
	 * 修改图片,返回修改后的图片缓冲区(输出多个文本段) xory:true表示将内容在一行中输出;false表示将内容多行输出
	 */
	public BufferedImage modifyImage(BufferedImage img, Object[] contentArr, int x, int y, boolean xory) {
		try {
			int w = img.getWidth();
			int h = img.getHeight();
			g = img.createGraphics();
			g.setBackground(Color.WHITE);
			g.setColor(Color.RED);
			if (this.font != null)
				g.setFont(this.font);
			// 验证输出位置的纵坐标和横坐标
			if (x >= h || y >= w) {
				this.x = h - this.fontsize + 2;
				this.y = w;
			} else {
				this.x = x;
				this.y = y;
			}
			if (contentArr != null) {
				int arrlen = contentArr.length;
				if (xory) {
					for (int i = 0; i < arrlen; i++) {
						g.drawString(contentArr[i].toString(), this.x, this.y);
						this.x += contentArr[i].toString().length() * this.fontsize / 2 + 5;// 重新计算文本输出位置
					}
				} else {
					for (int i = 0; i < arrlen; i++) {
						g.drawString(contentArr[i].toString(), this.x, this.y);
						this.y += this.fontsize + 2;// 重新计算文本输出位置
					}
				}
			}
			g.dispose();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}

		return img;
	}

	/**
	 * 修改图片,返回修改后的图片缓冲区(只输出一行文本)
	 * 
	 * 时间:2007-10-8
	 * 
	 * @param img
	 * @return
	 */
	public BufferedImage modifyImageYe(BufferedImage img) {

		try {
			int w = img.getWidth();
			int h = img.getHeight();
			g = img.createGraphics();
			g.setBackground(Color.WHITE);
			g.setColor(Color.blue);// 设置字体颜色
			if (this.font != null)
				g.setFont(this.font);
			g.drawString("www.hi.baidu.com?xia_mingjian", w - 85, h - 5);
			g.dispose();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}

		return img;
	}

	public BufferedImage modifyImagetogeter(BufferedImage b, BufferedImage d) {

		try {
			int w = b.getWidth();
			int h = b.getHeight();

			g = d.createGraphics();
			g.drawImage(b, 150, 150, w, h, null);
			g.dispose();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}

		return d;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值