@Service
@Log4j2
public class AppletServiceImpl implements AppletService {
@Autowired
private StringRedisTemplate stringRedis;
private static final TimedCache<String, String> TOKEN_CACHE = CacheUtil.newTimedCache(7200000);
private static final String URL_GET_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
private static final String URL_GET_UNLIMITED = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s";
@Value("${jeecg.path.upload}")
private String upload;
@Autowired
private RestTemplate restTemplate;
@Value("${wechat.miniProgram.appid}")
private String appid;
@Value("${wechat.miniProgram.secret}")
private String secret;
@Value("${wechat.page}")
private String page;
@Override
/*
获取AccessToken
*/
public synchronized String getAccessToken() {
String accessToken = TOKEN_CACHE.get("token");
if (!StringUtils.isNotBlank(accessToken)) {
String url = String.format(URL_GET_ACCESS_TOKEN, appid, secret);
JSONObject result = restTemplate.getForObject(url, JSONObject.class);
if (result != null && result.getIntValue("errcode") == 0) {
accessToken = result.getString("access_token");
int expiresIn = result.getIntValue("expires_in");
TOKEN_CACHE.put("token", accessToken, (expiresIn - 200) * 1000);
}
}
System.out.println(accessToken);
return accessToken;
}
/*
redis里取token
*/
@Override
public String redisUrl() {
String access_token="";
Boolean accessToken = stringRedis.hasKey("accessToken");
if(!accessToken) {
System.out.println("去redis里创建了");
access_token = getAccessToken();
stringRedis.opsForValue().set("accessToken", access_token,7000, TimeUnit.SECONDS);
}else{
access_token = stringRedis.opsForValue().get("accessToken");
}
return access_token;
}
@Override
/*
前台传配置
*/
public String getUnlimited(GetUnlimited getUnlimited) {
String accessToken = getAccessToken();
SerializeConfig config = new SerializeConfig();
config.setPropertyNamingStrategy(PropertyNamingStrategy.SnakeCase);
String body = JSON.toJSONString(getUnlimited, config);
HttpURLConnection httpURLConnection = null;
@Cleanup
PrintWriter printWriter = null;
try {
URL url = new URL(String.format(URL_GET_UNLIMITED, accessToken));
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
httpURLConnection.setRequestMethod("POST");
printWriter = new PrintWriter(httpURLConnection.getOutputStream());
printWriter.write(body);
printWriter.flush();
BufferedImage image = ImageIO.read(httpURLConnection.getInputStream());
return base64image(image);
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
}
@Override
/*
后台固定配置
*/
public String getminiqrQr(String sceneStr) {
//取得accessToken
String accessToken = redisUrl();
//取得太阳码
RestTemplate rest = new RestTemplate();
InputStream inputStream = null;
OutputStream outputStream = null;
try {
String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+accessToken;
Map<String,Object> param = new HashMap<>();
param.put("scene", sceneStr);
param.put("page", page==null?"":page);
param.put("width", 430);
param.put("auto_color", false);
Map<String,Object> line_color = new HashMap<>();
line_color.put("r", 0);
line_color.put("g", 0);
line_color.put("b", 0);
param.put("line_color", line_color);
log.info("调用生成微信URL接口传参:" + param);
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
HttpEntity requestEntity = new HttpEntity(param, headers);
ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
log.info("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());
byte[] result = entity.getBody();
log.info(Base64.encodeBase64String(result));
inputStream = new ByteArrayInputStream(result);
String path = "D:/opt/upFiles/"+sceneStr+".png";
File file = new File(path);
if (!file.exists()){
file.createNewFile();
}
outputStream = new FileOutputStream(file);
int len = 0;
byte[] buf = new byte[1024];
while ((len = inputStream.read(buf, 0, 1024)) != -1) {
outputStream.write(buf, 0, len);
}
outputStream.flush();
File ossfile =new File(path);
FileInputStream fileInputStream =new FileInputStream(file);
String name =sceneStr+".png";
String upload = OssBootUtil.upload(fileInputStream, name);
return upload;
} catch (Exception e) {
log.error("调用小程序生成微信永久小程序码URL接口异常",e);
} finally {
if(inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
@Override
/*
生成二维码
*/
public String creatQRcode(String sceneStr) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateFormat = format.format(new Date());
Map<String,Object> map = new HashMap<>();
map.put("taskId",sceneStr);
map.put("creatTime",dateFormat);
String s = String.valueOf(map);
// 生成的二维码的路径及名称
String destPath = upload+"\\"+sceneStr+".jpg";
//生成二维码
try {
QRUtil.encode(s,destPath);
File file =new File(destPath);
FileInputStream fileInputStream =new FileInputStream(file);
String relativePath = sceneStr+".jpg";
String upload = OssBootUtil.upload(fileInputStream, relativePath);
return upload;
}catch (Exception e){
return null;
}
}
protected String base64image(BufferedImage image) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
return "data:image/png;base64," + DatatypeConverter.printBase64Binary(baos.toByteArray());
}
}
实体
@ApiModel(value = "生成太阳码输入参数", description = "")
@Data
public class GetUnlimited implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "参数", required = true, notes = "最大32个可见字符, 只支持数字, 大小写英文以及部分特殊字符: !#$&'()*+,/:;=?@-._~, 其它字符请自行编码为合法字符(因不支持%, 中文无法使用urlencode处理,请使用其他编码方式)", example = "a=1")
@Size(max = 32, message = "参数可输入最大长度为32个字符")
@Pattern(regexp = "^[a-zA-Z0-9!#$&'()*+,/:;=?@-\\\\._~]{0,32}$", message = "只支持数字, 大小写英文以及部分特殊字符: !#$&'()*+,/:;=?@-._~")
private String scene;
@ApiModelProperty(value = "页面", notes = "必须是已经发布的小程序存在的页面(否则报错), 根路径前不要填加/, 不能携带参数(参数请放在scene字段里), 如果不填写这个字段, 默认跳主页面", example = "pages/index/index")
private String page;
@ApiModelProperty(value = "二维码的宽度", notes = "单位: px, 最小: 280px, 最大: 1280px", example = "360")
@DecimalMin(value = "280", message = "二维码的宽度最小为280")
@DecimalMax(value = "1280", message = "二维码的宽度最大为1280")
private Integer width;
@ApiModelProperty(value = "自动配置线条颜色", notes = "如果颜色依然是黑色, 则说明不建议配置主色调, 默认 false", example = "false")
private Boolean autoColor;
@ApiModelProperty(value = "rgb颜色", notes = "autoColor为false时生效")
@Valid
private LineColor lineColor;
@ApiModelProperty(value = "是否需要透明底色", notes = "为 true时, 生成透明底色的小程序", example = "true")
private Boolean isHyaline;
}
注:page页面必须是已发布的小程序页面
scene 传参长度不超过32位