package com.ishop.mobile.api; import com.fasterxml.jackson.databind.node.ObjectNode; import com.iplatform.base.PlatformRuntimeException; import com.iplatform.base.WechatConstants; import com.iplatform.base.util.VerifyImgUtil; import com.iplatform.core.BeanContextAware; import com.ishop.mobile.BaseApi; import com.ishop.mobile.util.WechatUtils; import com.ishop.model.vo.QrCodeVo; import com.walker.infrastructure.utils.Base64; import com.walker.infrastructure.utils.FileCopyUtils; import com.walker.infrastructure.utils.StringUtils; import com.walker.web.ResponseValue; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.io.File; import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/front/qrcode") public class QrcodeApi extends BaseApi { @RequestMapping(value = "/get/wechat", method = RequestMethod.POST) public ResponseValue getWechatQrCode(@RequestBody Map data){ if(data == null || data.size() == 0){ return ResponseValue.error("请输入二维码参数"); } StringBuilder scene = new StringBuilder(); String page = StringUtils.EMPTY_STRING; try { for (Map.Entry m : data.entrySet()) { if (m.getKey().equals("path")) { //前端路由, 不需要拼参数 page = m.getValue().toString(); continue; } if (scene.length() > 0) { scene.append(StringUtils.DEFAULT_SPLIT_SEPARATOR); } // 2023-09-17 由于微信对于scene限制32位字符,所以只把json中value用逗号拼接,降低长度。取的时候也按字段顺序取。 // scene.append(m.getKey()).append(StringUtils.SEPARATOR_COLON).append(m.getValue()); scene.append(m.getValue()); } } catch (PlatformRuntimeException ex){ logger.error("生成二维码参数错误:" + data, ex); return ResponseValue.error(ex.getMessage()); } QrCodeVo vo = new QrCodeVo(); String imageBase64 = this.createQrCode(page, scene.length() > 0 ? scene.toString() : StringUtils.EMPTY_STRING); vo.setCode(imageBase64); return ResponseValue.success(vo); } /** * 获取小程序图片二维码Base64内容。 * @param page * @param scene * @return * @date 2023-09-17 */ private String createQrCode(String page, String scene){ logger.debug("page = {}, scene = {}", page, scene); String miniAccessToken = this.acquireMiniAccessToken(); String url = MessageFormat.format(WechatConstants.WECHAT_MINI_QRCODE_UNLIMITED_URL, miniAccessToken); HashMap map = new HashMap<>(); map.put("scene", scene); // map.put("page", page); map.put("path", page); map.put("width", 200); RestTemplate restTemplate = BeanContextAware.getBeanByType(RestTemplate.class); byte[] bytes = restTemplate.postForEntity(url, map, byte[].class).getBody(); if(bytes == null || bytes.length == 0){ throw new PlatformRuntimeException("微信平台接口异常(createQrCode),没任何数据返回!"); } String entity = new String(bytes); if(entity.indexOf("errcode") >= 0){ ObjectNode data = WechatUtils.acquireObjectNode(entity); if (data.get("errcode").asText().equals("40001")) { logger.warn("小程序已获取accessToken失效,需要重新调用接口,error = {}", data); this.getWechatCache().removeMiniAccessToken(); miniAccessToken = this.acquireMiniAccessToken(); url = MessageFormat.format(WechatConstants.WECHAT_MINI_QRCODE_UNLIMITED_URL, miniAccessToken); bytes = restTemplate.postForEntity(url, map, byte[].class).getBody(); entity = new String(bytes); if(entity.indexOf("errcode") >= 0){ logger.error("微信生成小程序码重试异常:" + entity); // JSONObject data2 = JSONObject.parseObject(response); // 保存到微信异常表 // wxExceptionDispose(data2, "微信小程序重试生成小程序码异常"); } else { return VerifyImgUtil.getBase64Image(new String(Base64.encodeBase64(bytes))); } } throw new PlatformRuntimeException("微信生成二维码异常:" + entity); } try { // return CrmebUtil.getBase64Image(org.apache.commons.codec.binary.Base64.encodeBase64String(bytes)); // FileCopyUtils.copy(bytes, new File("e:/demo.png")); return VerifyImgUtil.getBase64Image(new String(Base64.encodeBase64(bytes))); // return VerifyImgUtil.getBase64Image(org.apache.commons.codec.binary.Base64.encodeBase64String(bytes)); } catch (Exception e) { e.printStackTrace(); throw new PlatformRuntimeException("微信小程序码转换Base64异常"); } } /** * 远程图片转base64 * @param url * @return * @date 2023-07-09 */ @RequestMapping(value = "/url/to/base64", method = RequestMethod.POST) public ResponseValue urlToBase64(String url){ if(StringUtils.isEmpty(url)){ return ResponseValue.error("url为空,无法转换"); } logger.debug("...........url = " + url); if(!StringUtils.isHttpLink(url)){ url = this.getCdnUrl() + url; } return ResponseValue.success(this.getQrcodeService().urlToBase64(url)); } }