获取小程序二维码前需要获取小程序的token。这个不赘述了。
获取小程序二维码官方文档上找到2个处理的Api接口。经测试,现有一个能用的
https://api.weixin.qq.com/wxa/getwxacode
直接上代码。官网上对于获取二维码返回参数是一个Buffer类型的buffer字段。所以先定义接收的DTO
@Data public class QRCodeResp extends WxBase { private String contentType; private byte[] buffer; //错误码 private long errcode; //错误信息 private String errmsg; }
因为接收的是一个二进制。用的restTemplate的 messageConverter不支持。所以需要手动加入。
这段自定义的messageConverter来源于网络上其他老哥。
import com.wx.login.entity.wx.resp.QRCodeResp; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.AbstractHttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.util.StreamUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Collections; public class WechatAppletWXACodeHttpMessageConverter extends AbstractHttpMessageConverter<QRCodeResp> { public WechatAppletWXACodeHttpMessageConverter() { super.setSupportedMediaTypes(Collections.singletonList(MediaType.IMAGE_JPEG)); } @Override protected boolean supports(Class<?> clazz) { return QRCodeResp.class == clazz; } @Override protected QRCodeResp readInternal(Class<? extends QRCodeResp> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { long contentLength = inputMessage.getHeaders().getContentLength(); ByteArrayOutputStream bos = new ByteArrayOutputStream(contentLength >= 0 ? (int) contentLength : StreamUtils.BUFFER_SIZE); StreamUtils.copy(inputMessage.getBody(), bos); bos.toByteArray(); QRCodeResp unlimitedRes = new QRCodeResp(); unlimitedRes.setBuffer(bos.toByteArray()); unlimitedRes.setErrcode(0); unlimitedRes.setErrmsg("ok"); return unlimitedRes; } @Override protected void writeInternal(QRCodeResp qrCodeResp, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { StreamUtils.copy(qrCodeResp.getBuffer(), outputMessage.getBody()); } }
接下来就是直接请求:
//根据token获取二维码 public QRCodeResp createQRCode(String path, Integer width){ AccessTokenResp accessToken1 = getAccessToken(); String url = "https://api.weixin.qq.com/wxa/getwxacode?access_token=" + accessToken1.getAccess_token(); HttpHeaders headers = new HttpHeaders(); headers.add("content-type","application/json;charset=utf-8"); HashMap<String, Object> param = new HashMap<>(); param.put("path" ,path); param.put("width" ,width); HttpEntity<Map<String, String>> httpEntity = new HttpEntity(param,headers); WechatAppletWXACodeHttpMessageConverter wechatAppletWXACodeHttpMessageConverter = new WechatAppletWXACodeHttpMessageConverter(); List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(); messageConverters.add(wechatAppletWXACodeHttpMessageConverter); messageConverters.addAll(restTemplate.getMessageConverters()); restTemplate.setMessageConverters(messageConverters); ResponseEntity<QRCodeResp> result = restTemplate.postForEntity(url, httpEntity, QRCodeResp.class); QRCodeResp body = change(result); if(body.getErrcode() != 0){ throw new BusinessException(body.getErrcode(), body.getErrmsg()); } return body; } public <T> T change(ResponseEntity<T> responseEntity){ T body = responseEntity.getBody(); //log.info("wx:code2Session接口返回数据"+ JSON.toJSONString(body)); return body; }
在自己的Controller调用时需要返回的是一个 ContentType是image/jpeg的流,而现在的项目用到了全局拦截。默认都会将返回类型组装成json格式,contentType是application/json。 所以现有的controller和 全局controller需要改造
@SneakyThrows @PostMapping(value = "/getQRCode",produces = MediaType.IMAGE_JPEG_VALUE) @ApiOperation("微信小程序获取二维码") public BufferedImage getQRCode(@RequestBody @Validated WxQRCodeRequest wxQRCodeRequest){ QRCodeResp qrCodeResp = wxService.getQRCodeResp(wxQRCodeRequest.getPath(), wxQRCodeRequest.getWidth()); InputStream inputStream = new ByteArrayInputStream(qrCodeResp.getBuffer()); return ImageIO.read(inputStream); }
改造全局拦截
import com.hy.constants.StandardResult; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import java.util.Objects; /** * * @author chao.tian * @version 1.0.0 */ @Component @ControllerAdvice("com") public class ResponseAdvice implements ResponseBodyAdvice { @Override public Object beforeBodyWrite(Object out, MethodParameter methodParameter, MediaType mediaType, Class clazz, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { if(null == mediaType || (Objects.nonNull(mediaType) && MediaType.APPLICATION_JSON_VALUE.equals(mediaType.toString()))){ if(out instanceof StandardResult) { return out; } return StandardResult.success(out); } return out; } @Override public boolean supports(MethodParameter arg0, Class arg1) { return true; } }
这样前端接收流就可以直接获取到图片了。
标签:springboot,springframework,获取,二维码,QRCodeResp,import,org,new,public From: https://www.cnblogs.com/fuguang/p/17269974.html