|
|
@@ -0,0 +1,190 @@
|
|
|
+/*
|
|
|
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
|
|
|
+ *
|
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
|
+ * modification, are permitted provided that the following conditions are met:
|
|
|
+ *
|
|
|
+ * Redistributions of source code must retain the above copyright notice,
|
|
|
+ * this list of conditions and the following disclaimer.
|
|
|
+ * Redistributions in binary form must reproduce the above copyright
|
|
|
+ * notice, this list of conditions and the following disclaimer in the
|
|
|
+ * documentation and/or other materials provided with the distribution.
|
|
|
+ * Neither the name of the dreamlu.net developer nor the names of its
|
|
|
+ * contributors may be used to endorse or promote products derived from
|
|
|
+ * this software without specific prior written permission.
|
|
|
+ * Author: Chill 庄骞 (smallchill@163.com)
|
|
|
+ */
|
|
|
+package org.springblade.weChat.QRCode;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
|
|
+import io.seata.spring.annotation.GlobalTransactional;
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
+import org.springblade.core.boot.ctrl.BladeController;
|
|
|
+import org.springblade.core.secure.utils.AuthUtil;
|
|
|
+import org.springblade.core.tool.api.R;
|
|
|
+import org.springblade.pay.tonglianPayment.entity.Parameters;
|
|
|
+import org.springblade.pay.tonglianPayment.fegin.IPaymentClient;
|
|
|
+import org.springblade.salesPart.entity.PjCorpsDesc;
|
|
|
+import org.springblade.salesPart.feign.IPJCorpClient;
|
|
|
+import org.springframework.web.bind.annotation.GetMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestParam;
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
+
|
|
|
+
|
|
|
+import java.io.*;
|
|
|
+import java.net.HttpURLConnection;
|
|
|
+import java.net.URL;
|
|
|
+import java.nio.file.Files;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 微信小程序二维码
|
|
|
+ *
|
|
|
+ * @author BladeX
|
|
|
+ * @since 2023-08-22
|
|
|
+ */
|
|
|
+@RestController
|
|
|
+@AllArgsConstructor
|
|
|
+@RequestMapping("/weChat/QRcode")
|
|
|
+public class WechatQRCodeController extends BladeController {
|
|
|
+
|
|
|
+ private final IPaymentClient paymentClient;
|
|
|
+
|
|
|
+ private final IPJCorpClient corpClient;
|
|
|
+
|
|
|
+ @GetMapping("/getQRcode")
|
|
|
+ @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
|
|
|
+ public R getQRcode(@RequestParam("corpId") String corpId, @RequestParam("corpName") String corpName,
|
|
|
+ @RequestParam("tenantId") String tenantId) throws Exception {
|
|
|
+ R<Parameters> res = paymentClient.getByTenantId(tenantId);
|
|
|
+ String filePath = "";
|
|
|
+ if (res.isSuccess() && ObjectUtils.isNotNull(res.getData())) {
|
|
|
+ Parameters parameters = res.getData();
|
|
|
+ String access_token = postToken(parameters.getSubAppid(), parameters.getAppSecret());
|
|
|
+ if (ObjectUtils.isNotNull(access_token)) {
|
|
|
+ filePath = filePath(corpName);
|
|
|
+ if (ObjectUtils.isNotNull(filePath)) {
|
|
|
+ generateQrCode(filePath, "pages/login/login", corpId, access_token);
|
|
|
+ PjCorpsDesc corpsDesc = new PjCorpsDesc();
|
|
|
+ corpsDesc.setId(Long.parseLong(corpId));
|
|
|
+ corpsDesc.setFilePath(filePath);
|
|
|
+ corpClient.updateCorps(corpsDesc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return R.data(filePath);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接口调用凭证 access_token
|
|
|
+ */
|
|
|
+ public static String postToken(String appId, String appKey) throws Exception {
|
|
|
+
|
|
|
+ String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appKey;
|
|
|
+ URL url = new URL(requestUrl);
|
|
|
+ // 打开和URL之间的连接
|
|
|
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
|
+ connection.setRequestMethod("POST");
|
|
|
+ // 设置通用的请求属性
|
|
|
+ connection.setRequestProperty("Content-Type", "application/json");
|
|
|
+ connection.setRequestProperty("Connection", "Keep-Alive");
|
|
|
+ connection.setUseCaches(false);
|
|
|
+ connection.setDoOutput(true);
|
|
|
+ connection.setDoInput(true);
|
|
|
+
|
|
|
+ // 得到请求的输出流对象
|
|
|
+ DataOutputStream out = new DataOutputStream(connection.getOutputStream());
|
|
|
+ out.writeBytes("");
|
|
|
+ out.flush();
|
|
|
+ out.close();
|
|
|
+
|
|
|
+ // 建立实际的连接
|
|
|
+ connection.connect();
|
|
|
+ // 定义 BufferedReader输入流来读取URL的响应
|
|
|
+ BufferedReader in;
|
|
|
+ if (requestUrl.contains("nlp"))
|
|
|
+ in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "GBK"));
|
|
|
+ else
|
|
|
+ in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
|
|
|
+ StringBuilder result = new StringBuilder();
|
|
|
+ String getLine;
|
|
|
+ while ((getLine = in.readLine()) != null) {
|
|
|
+ result.append(getLine);
|
|
|
+ }
|
|
|
+ in.close();
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(result.toString());
|
|
|
+ return jsonObject.getString("access_token");
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String filePath(String corpName) throws Exception {
|
|
|
+ //创建文件夹
|
|
|
+ File packageFile = new File("/home/minio/file/" + AuthUtil.getTenantId() + "-bladex/upload");
|
|
|
+ //文件夹是否创建成功
|
|
|
+ if (!packageFile.getParentFile().exists()) {
|
|
|
+ boolean a = packageFile.mkdirs();
|
|
|
+ if (a) {
|
|
|
+ System.out.println("文件夹创建成功");
|
|
|
+ } else {
|
|
|
+ System.out.println("文件夹创建失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //创建二维码图片
|
|
|
+ File qRCodeFile = new File(packageFile, corpName + ".jpg");
|
|
|
+ qRCodeFile.createNewFile();
|
|
|
+ //替换地址
|
|
|
+ return qRCodeFile.getAbsolutePath().replace("/home/minio", "http://121.37.83.47");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成微信小程序二维码
|
|
|
+ *
|
|
|
+ * @param filePath 本地生成二维码路径
|
|
|
+ * @param page 当前小程序相对页面 必须是已经发布的小程序存在的页面(否则报错),例如 pages/index/index, 根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面
|
|
|
+ * @param scene 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)
|
|
|
+ * @param accessToken 接口调用凭证
|
|
|
+ */
|
|
|
+ public static void generateQrCode(String filePath, String page, String scene, String accessToken) {
|
|
|
+ try {
|
|
|
+ //调用微信接口生成二维码
|
|
|
+ URL url = new URL("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken);
|
|
|
+ HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
|
|
|
+ httpURLConnection.setRequestMethod("POST");// 提交模式
|
|
|
+ // conn.setConnectTimeout(10000);//连接超时 单位毫秒
|
|
|
+ // conn.setReadTimeout(2000);//读取超时 单位毫秒
|
|
|
+ // 发送POST请求必须设置如下两行
|
|
|
+ httpURLConnection.setDoOutput(true);
|
|
|
+ httpURLConnection.setDoInput(true);
|
|
|
+ // 获取URLConnection对象对应的输出流
|
|
|
+ PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
|
|
|
+ // 发送请求参数
|
|
|
+ JSONObject paramJson = new JSONObject();
|
|
|
+ //这就是你二维码里携带的参数 String型 名称不可变
|
|
|
+ paramJson.put("scene", scene);
|
|
|
+ //注意该接口传入的是page而不是path
|
|
|
+ paramJson.put("page", page);
|
|
|
+ //这是设置扫描二维码后跳转的页面
|
|
|
+ paramJson.put("width", 200);
|
|
|
+ paramJson.put("is_hyaline", true);
|
|
|
+ paramJson.put("auto_color", true);
|
|
|
+ printWriter.write(paramJson.toString());
|
|
|
+ // flush输出流的缓冲
|
|
|
+ printWriter.flush();
|
|
|
+
|
|
|
+ //开始获取数据
|
|
|
+ BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream());
|
|
|
+ OutputStream os = Files.newOutputStream(new File(filePath).toPath());
|
|
|
+ int len;
|
|
|
+ byte[] arr = new byte[1024];
|
|
|
+ while ((len = bis.read(arr)) != -1) {
|
|
|
+ os.write(arr, 0, len);
|
|
|
+ os.flush();
|
|
|
+ }
|
|
|
+ os.close();
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ System.out.println("打开地址查看生成的二维码:" + filePath);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|