View Javadoc
1   package com.foxinmy.weixin4j.wxa.api;
2   
3   import java.awt.Color;
4   import java.util.Properties;
5   
6   import com.alibaba.fastjson.JSON;
7   import com.foxinmy.weixin4j.exception.WeixinException;
8   import com.foxinmy.weixin4j.http.ContentType;
9   import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
10  import com.foxinmy.weixin4j.token.TokenManager;
11  
12  /**
13   * 获取二维码。
14   *
15   * <p>
16   *   通过后台接口可以获取小程序任意页面的二维码,扫描该二维码可以直接进入小程序对应的页面。
17   *   目前微信支持两种二维码,小程序码,小程序二维码。
18   * </p>
19   *
20   * @see <a href="https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/qr-code.html">获取二维码</a>
21   * @since 1.8
22   */
23  public class QrCodeApi extends TokenManagerApi {
24  
25  	public QrCodeApi(TokenManager tokenManager) {
26  		this(tokenManager, null);
27  	}
28  
29  	public QrCodeApi(TokenManager tokenManager, Properties properties) {
30  		super(tokenManager, properties);
31  	}
32  
33  	/**
34  	 * 获取小程序码.
35  	 *
36  	 * <p>接口A: 适用于需要的码数量较少的业务场景</p>
37  	 * <p>
38  	 *   注意:通过该接口生成的小程序码,永久有效,数量限制见微信小程序文档文末说明,请谨慎使用。
39  	 *   用户扫描该码进入小程序后,将直接进入 path 对应的页面。
40  	 * </p>
41  	 *
42  	 * @param path 不能为空,最大长度 128 字节
43  	 * @param width 二维码的宽度,默认值 430
44  	 * @param autoColor 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调
45  	 * @param lineColor <code>authColor</code> 为 false 时生效
46  	 * @param hyaline 是否需要透明底色, 为true时,生成透明底色的小程序码
47  	 * @return image bytes of WXA code.
48  	 * @throws WeixinException indicates getting access token failed or getting WXA code failed.
49  	 *
50  	 * @see <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.get.html">获取小程序码</a>
51  	 */
52  	public byte[] getWxaCode(
53  		String path,
54  		Integer width,
55  		Boolean autoColor,
56  		Color lineColor,
57  		Boolean hyaline
58  	) throws WeixinException {
59  		final String getWxaCodeUri = this.getAccessTokenRequestUri("wxa_getwxacode");
60  		final WxaCodeParameter param = new WxaCodeParameter(path, width, autoColor, lineColor, hyaline);
61  		return this.postAsImageBytes(getWxaCodeUri, param);
62  	}
63  
64  	/**
65  	 * 获取小程序码.
66  	 *
67  	 * <p>接口B:适用于需要的码数量极多的业务场景</p>
68  	 * <p>
69  	 *   注意:通过该接口生成的小程序码,永久有效,数量暂无限制。
70  	 *   用户扫描该码进入小程序后,开发者需在对应页面获取的码中 scene 字段的值,再做处理逻辑。
71  	 *   使用如下代码可以获取到二维码中的 scene 字段的值。
72  	 *   调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,
73  	 *   开发工具模拟时的 scene 的参数值需要进行 urlencode。
74  	 * <p>
75  	 * <pre>
76  	 * // 这是首页的 js
77  	 * Page({
78  	 *   onLoad: function(options) {
79  	 *     // options 中的 scene 需要使用 decodeURIComponent 才能获取到生成二维码时传入的 scene
80  	 *     var scene = decodeURIComponent(options.scene)
81  	 *   }
82  	 * })
83  	 * </pre>
84  	 *
85  	 * @param scene 最大32个可见字符,只支持数字,
86  	 * 大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,
87  	 * 其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)
88  	 * @param page 必须是已经发布的小程序存在的页面(否则报错),
89  	 * 例如 "pages/index/index",根路径前不要填加'/',
90  	 * 不能携带参数(参数请放在scene字段里),
91  	 * 如果不填写这个字段,默认跳主页面
92  	 * @param width 二维码的宽度,默认值 430
93  	 * @param autoColor 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认值 false
94  	 * @param lineColor <code>autoColor</code> 为 false 时生效,使用 rgb 设置颜色
95  	 * @param hyaline 是否需要透明底色,为true时,生成透明底色的小程序码
96  	 * @return image bytes of WXA code.
97  	 * @throws WeixinException indicates getting access token failed or getting WXA code failed.
98  	 *
99  	 * @see <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html">获取小程序码</a>
100 	 */
101 	public byte[] getWxaCodeUnlimit(
102 		String scene,
103 		String page,
104 		Integer width,
105 		Boolean autoColor,
106 		Color lineColor,
107 		Boolean hyaline
108 	) throws WeixinException {
109 		final String getWxaCodeUnlimitUri = this.getAccessTokenRequestUri("wxa_getwxacodeunlimit");
110 		final WxaCodeUnlimitParameter param = new WxaCodeUnlimitParameter(scene, page, width, autoColor, lineColor, hyaline);
111 		return this.postAsImageBytes(getWxaCodeUnlimitUri, param);
112 	}
113 
114 	/**
115 	 * 获取小程序二维码.
116 	 *
117 	 * <p>接口C:适用于需要的码数量较少的业务场景</p>
118 	 * <p>
119 	 *   注意:通过该接口生成的小程序二维码,永久有效,数量限制见微信小程序文档文末说明,请谨慎使用。
120 	 *   用户扫描该码进入小程序后,将直接进入 path 对应的页面。
121 	 * </p>
122 	 *
123 	 * @param path 不能为空,最大长度 128 字节
124 	 * @param width 二维码的宽度,默认值 430
125 	 * @return image bytes of WXA QR code.
126 	 * @throws WeixinException indicates getting access token failed or getting WXA QR code failed.
127 	 *
128 	 * @see <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.createQRCode.html">获取小程序二维码</a>
129 	 */
130 	public byte[] createWxaQrCode(
131 		String path,
132 		Integer width
133 	) throws WeixinException {
134 		final String createWxaQrCode = this.getAccessTokenRequestUri("wxaapp_createwxaqrcode");
135 		final WxaQrCodeParameter param = new WxaQrCodeParameter(path, width);
136 		return this.postAsImageBytes(createWxaQrCode, param);
137 	}
138 
139 	private byte[] postAsImageBytes(String uri, Object param) throws WeixinException {
140 		final String body = JSON.toJSONString(param);
141 		final WeixinResponse response = this.weixinExecutor.post(uri, body);
142 		return toImageBytes(response);
143 	}
144 
145 	private byte[] toImageBytes(WeixinResponse response) throws WeixinException {
146 		final String contentType = response.getHeaders().getContentType();
147 		if (contentType != null && contentType.equals(ContentType.APPLICATION_JSON.getMimeType().getType())) {
148 			final WxaApiResult r = response.getAsObject(WxaApiResult.TYPE_REFERENCE);
149 			throw r.toWeixinException();
150 		} else {
151 			return response.getContent();
152 		}
153 	}
154 
155 }