Browse Source

微信二维码生成

dev
wangfukang 2 years ago
parent
commit
3ffbdbfb5b
  1. 10
      hiver-admin/src/main/resources/application.yml
  2. 16
      hiver-admin/test-output/test-report.html
  3. 6
      hiver-modules/hiver-mall/pom.xml
  4. 114
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/OrderController.java
  5. 58
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/ByteArrayMultipartFile.java

10
hiver-admin/src/main/resources/application.yml

@ -25,8 +25,8 @@ spring:
timeout-per-shutdown-phase: 10S timeout-per-shutdown-phase: 10S
# 数据源 # 数据源
datasource: datasource:
# url: jdbc:mysql://154.8.162.157:3306/hiver_shop?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&allowMultiQueries=true url: jdbc:mysql://154.8.162.157:3306/hiver_shop?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&allowMultiQueries=true
url: jdbc:mysql://8.140.198.243:3306/hiver_shop?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&allowMultiQueries=true # url: jdbc:mysql://8.140.198.243:3306/hiver_shop?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&allowMultiQueries=true
username: reddoor username: reddoor
# Jasypt加密 可到common-utils中找到JasyptUtil加解密工具类生成加密结果 格式为ENC(加密结果) 以下解密结果为123456 # Jasypt加密 可到common-utils中找到JasyptUtil加解密工具类生成加密结果 格式为ENC(加密结果) 以下解密结果为123456
password: ENC(Zla4U4+yRLPhicvuX2TmiEgxEpzP4dk8BHzFDEtiEhwLQIIaftZrrEUJZce6efoe) password: ENC(Zla4U4+yRLPhicvuX2TmiEgxEpzP4dk8BHzFDEtiEhwLQIIaftZrrEUJZce6efoe)
@ -67,8 +67,8 @@ spring:
ddl-auto: update ddl-auto: update
# Redis 若设有密码自行添加配置password # Redis 若设有密码自行添加配置password
redis: redis:
# host: 154.8.162.157 host: 154.8.162.157
host: 8.140.198.243 # host: 8.140.198.243
password: reddoor168 password: reddoor168
# 数据库索引 默认0 # 数据库索引 默认0
database: 1 database: 1
@ -339,6 +339,8 @@ ignored:
- /hiver/app/customer/findByUserPhoneAndShopId - /hiver/app/customer/findByUserPhoneAndShopId
# 分享页获取店铺分类 # 分享页获取店铺分类
- /hiver/app/productCategory/listByShopId - /hiver/app/productCategory/listByShopId
# 获取微信二维码
- /hiver/order/ow/getWechatQrcode
# 临时增加 # 临时增加
- /hiver/app/logisticsOrder/addLogisticsOrder - /hiver/app/logisticsOrder/addLogisticsOrder

16
hiver-admin/test-output/test-report.html

@ -35,7 +35,7 @@
<a href="#"><span class="badge badge-primary">Hiver</span></a> <a href="#"><span class="badge badge-primary">Hiver</span></a>
</li> </li>
<li class="m-r-10"> <li class="m-r-10">
<a href="#"><span class="badge badge-primary">九月 08, 2024 15:39:34</span></a> <a href="#"><span class="badge badge-primary">九月 17, 2024 23:19:41</span></a>
</li> </li>
</ul> </ul>
</div> </div>
@ -84,7 +84,7 @@
<div class="test-detail"> <div class="test-detail">
<span class="meta text-white badge badge-sm"></span> <span class="meta text-white badge badge-sm"></span>
<p class="name">passTest</p> <p class="name">passTest</p>
<p class="text-sm"><span>15:39:35 下午</span> / <span>0.026 secs</span></p> <p class="text-sm"><span>23:19:42 下午</span> / <span>0.018 secs</span></p>
</div> </div>
<div class="test-contents d-none"> <div class="test-contents d-none">
<div class="detail-head"> <div class="detail-head">
@ -92,9 +92,9 @@
<div class="info"> <div class="info">
<div class='float-right'><span class='badge badge-default'>#test-id=1</span></div> <div class='float-right'><span class='badge badge-default'>#test-id=1</span></div>
<h5 class="test-status text-pass">passTest</h5> <h5 class="test-status text-pass">passTest</h5>
<span class='badge badge-success'>09.08.2024 15:39:35</span> <span class='badge badge-success'>09.17.2024 23:19:42</span>
<span class='badge badge-danger'>09.08.2024 15:39:35</span> <span class='badge badge-danger'>09.17.2024 23:19:42</span>
<span class='badge badge-default'>0.026 secs</span> <span class='badge badge-default'>0.018 secs</span>
</div> </div>
<div class="m-t-10 m-l-5"></div> <div class="m-t-10 m-l-5"></div>
</div> </div>
@ -104,7 +104,7 @@
<tbody> <tbody>
<tr class="event-row"> <tr class="event-row">
<td><span class="badge log pass-bg">Pass</span></td> <td><span class="badge log pass-bg">Pass</span></td>
<td>15:39:35</td> <td>23:19:42</td>
<td> <td>
Test passed Test passed
</td> </td>
@ -128,13 +128,13 @@
<div class="col-md-3"> <div class="col-md-3">
<div class="card"><div class="card-body"> <div class="card"><div class="card-body">
<p class="m-b-0">Started</p> <p class="m-b-0">Started</p>
<h3>九月 08, 2024 15:39:34</h3> <h3>九月 17, 2024 23:19:41</h3>
</div></div> </div></div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="card"><div class="card-body"> <div class="card"><div class="card-body">
<p class="m-b-0">Ended</p> <p class="m-b-0">Ended</p>
<h3>九月 08, 2024 15:39:35</h3> <h3>九月 17, 2024 23:19:42</h3>
</div></div> </div></div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">

6
hiver-modules/hiver-mall/pom.xml

@ -28,6 +28,12 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>cc.hiver</groupId>
<artifactId>hiver-file</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

114
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/OrderController.java

@ -2,15 +2,13 @@ package cc.hiver.mall.controller;
import cc.hiver.core.common.constant.SaleConstant; import cc.hiver.core.common.constant.SaleConstant;
import cc.hiver.core.common.exception.HiverException; import cc.hiver.core.common.exception.HiverException;
import cc.hiver.core.common.utils.BeanUtils; import cc.hiver.core.common.utils.*;
import cc.hiver.core.common.utils.PageUtil;
import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.utils.StringUtils;
import cc.hiver.core.common.vo.PageVo; import cc.hiver.core.common.vo.PageVo;
import cc.hiver.core.common.vo.Result; import cc.hiver.core.common.vo.Result;
import cc.hiver.core.common.vo.SearchVo; import cc.hiver.core.common.vo.SearchVo;
import cc.hiver.core.entity.Worker; import cc.hiver.core.entity.Worker;
import cc.hiver.core.service.WorkerService; import cc.hiver.core.service.WorkerService;
import cc.hiver.file.manage.FileManageFactory;
import cc.hiver.mall.common.constant.OrderConstant; import cc.hiver.mall.common.constant.OrderConstant;
import cc.hiver.mall.deductlog.service.DeductLogService; import cc.hiver.mall.deductlog.service.DeductLogService;
import cc.hiver.mall.entity.OrderXd; import cc.hiver.mall.entity.OrderXd;
@ -21,11 +19,19 @@ import cc.hiver.mall.pojo.vo.OrderVO;
import cc.hiver.mall.service.OrderService; import cc.hiver.mall.service.OrderService;
import cc.hiver.mall.service.mybatis.ReturnSaleService; import cc.hiver.mall.service.mybatis.ReturnSaleService;
import cc.hiver.mall.service.mybatis.SaleService; import cc.hiver.mall.service.mybatis.SaleService;
import cc.hiver.mall.utils.ByteArrayMultipartFile;
import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateTime;
import cn.hutool.json.JSONObject;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
@ -33,8 +39,15 @@ import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.Valid; import javax.validation.Valid;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -68,6 +81,10 @@ public class OrderController {
@Autowired @Autowired
private DeductLogService deductLogService; private DeductLogService deductLogService;
@Autowired
private FileManageFactory fileManageFactory;
/** /**
* 该接口即可展示实时物流管理页面可复用 * 该接口即可展示实时物流管理页面可复用
*/ */
@ -226,8 +243,6 @@ public class OrderController {
} }
/** /**
* 待抢单的订单类型 * 待抢单的订单类型
* <p> * <p>
@ -358,7 +373,7 @@ public class OrderController {
final String transCompanyId = sale.getTransCompany(); final String transCompanyId = sale.getTransCompany();
final String shopId = sale.getShopId(); final String shopId = sale.getShopId();
final String saleId = sale.getId(); final String saleId = sale.getId();
String transportType = sale.getTransportType(); final String transportType = sale.getTransportType();
deductLogService.updateRebateAmount(workId, transCompanyId, shopId, saleId, transportType); deductLogService.updateRebateAmount(workId, transCompanyId, shopId, saleId, transportType);
} }
@ -413,7 +428,7 @@ public class OrderController {
/** /**
* 转单接口 * 转单接口
* *
* @param orderXd * @param orderVO
* @return Result * @return Result
* @author 王富康 * @author 王富康
* @date 2024/2/27 * @date 2024/2/27
@ -435,4 +450,87 @@ public class OrderController {
} }
} }
/**
* 获取不限制的小程序码
* 参考链接https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/getUnlimitedQRCode.html
*
* @param scene 最大32个可见字符只支持数字大小写英文以及部分特殊字符!#$&'()*+,/:;=?@-._~其它字符请自行编码为合法字符因不支持%中文无法使用 urlencode 处理请使用其他编码方式
* @param page 默认是主页页面 page例如 pages/index/index根路径前不要填加 /不能携带参数参数请放在scene字段里如果不填写这个字段默认跳主页面scancode_time为系统保留参数不允许配置
* @param envVersion 要打开的小程序版本正式版为 "release"体验版为 "trial"开发版为 "develop"默认是正式版
* @return byte[]
* @author 王富康
* @date 2024/9/14
*/
@RequestMapping(value = "/ow/getWechatQrcode", method = RequestMethod.POST)
@ApiOperation("获取不限制的小程序码")
public Result getWechatQrcodeByOkhttp3(String scene, String page, String envVersion) {
// 非空校验
if (StringUtils.isEmpty(scene)) {
return ResultUtil.error("参数错误");
}
//获取AccessToken地址
String wechatQrcodeAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
wechatQrcodeAccessTokenUrl = wechatQrcodeAccessTokenUrl.replace("APPID", "wx6d7d4fb58d1502db").replace("APPSECRET", "3a2c8cd00926764bbd12fd7361e01f1d");
try {
final URL url = new URL(wechatQrcodeAccessTokenUrl);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/json");
final int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
final BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
final StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
connection.disconnect();
// 解析JSON数据
final JsonObject jsonObject = JsonParser.parseString(content.toString()).getAsJsonObject();
final String wxAccessToken = jsonObject.get("access_token").getAsString();
log.info("获取小程序码getQrtAccessToken成功:{}", wxAccessToken);
//获取小程序码地址
final String wechatQrcodeUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + wxAccessToken;
final OkHttpClient client = new OkHttpClient();
final JSONObject jsonBody = new JSONObject();
jsonBody.set("scene", scene);
jsonBody.set("page", page);
jsonBody.set("env_version", envVersion);
final okhttp3.RequestBody requestBody = okhttp3.RequestBody.create(MediaType.parse("application/json"), jsonBody.toString());
final Request request = new Request.Builder()
.url(wechatQrcodeUrl)
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful() && response.body() != null) {
// 上传到服务器,返回地址。
final byte[] bytes = response.body().bytes();
final String contentType = "image/png"; // 文件类型
// 上传至第三方云服务或服务器
final MultipartFile multipartFile = new ByteArrayMultipartFile(bytes, "qrcode.png", contentType);
final String fKey = CommonUtil.renamePic(multipartFile.getOriginalFilename());
final InputStream inputStream = multipartFile.getInputStream();
final String result = fileManageFactory.getFileManage(null).inputStreamUpload(inputStream, fKey, multipartFile);
return new ResultUtil<String>().setData(result);
} else {
log.error("【小程序码】Failed response, status code: {}", response.code());
}
} catch (IOException e) {
log.error("【小程序码】Request failed", e);
return ResultUtil.error("获取小程序码失败!");
}
} else {
System.err.println("请求失败:" + responseCode);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
} }

58
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/ByteArrayMultipartFile.java

@ -0,0 +1,58 @@
package cc.hiver.mall.utils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
public class ByteArrayMultipartFile implements MultipartFile {
private final byte[] content;
private final String filename;
private final String contentType;
public ByteArrayMultipartFile(byte[] content, String filename, String contentType) {
this.content = content;
this.filename = filename;
this.contentType = contentType;
}
@Override
public String getName() {
return filename;
}
@Override
public String getOriginalFilename() {
return filename;
}
@Override
public String getContentType() {
return contentType;
}
@Override
public boolean isEmpty() {
return content.length == 0;
}
@Override
public long getSize() {
return content.length;
}
@Override
public byte[] getBytes() throws IOException {
return content;
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(content);
}
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
new FileOutputStream(dest).write(content);
}
}
Loading…
Cancel
Save