首页 > 编程语言 >springboot获取小程序二维码图片

springboot获取小程序二维码图片

时间:2023-03-29 18:56:23浏览次数:30  
标签:springboot springframework 获取 二维码 QRCodeResp import org new public

获取小程序二维码前需要获取小程序的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

相关文章