小程序代码迁移完毕

This commit is contained in:
Machengtianjiang 2020-12-24 16:43:08 +08:00
parent aa3e2a4f33
commit ae58cafd81
15 changed files with 577 additions and 12 deletions

View File

@ -22,6 +22,17 @@
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>${wx-java.version}</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>${wx-java.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,91 @@
package com.ruoyi.winery.component;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.winery.domain.WineryMauser;
import com.ruoyi.winery.service.IWineryMauserService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @author tottimctj
* @since 2020-12-15
*/
@Component
@Slf4j
public class MiniComponent {
@Autowired
IWineryMauserService wineryMauserService;
@Autowired
WxMaService wxMaService;
@Autowired
private RedisCache redisCache;
public WxMaJscode2SessionResult login(String code) throws WxErrorException {
WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
WineryMauser user = wineryMauserService.getById(sessionInfo.getOpenid());
String key = sessionInfo.getOpenid();
redisCache.setCacheObject(key, sessionInfo.getSessionKey(), 7200, TimeUnit.SECONDS);
if (user == null) {
user = new WineryMauser();
user.setOpenId(sessionInfo.getOpenid());
log.info("新增user:{}", user);
}
if (StrUtil.isNotBlank(sessionInfo.getUnionid())) {
user.setUnionId(sessionInfo.getUnionid());
}
wineryMauserService.saveOrUpdate(user);
return sessionInfo;
}
/**
* 获取手机号
*
* @param json 微信加密信息
* @return
*/
public String getMobile(JSONObject json) {
String openid = json.getStr("openid");
WineryMauser user = wineryMauserService.getById(openid);
JSONObject detail = json.getJSONObject("detail");
String encryptedData = detail.getStr("encryptedData");
String iv = detail.getStr("iv");
String sessionKey = redisCache.getCacheObject(openid);
if (StrUtil.isBlank(sessionKey)) {
return null;
}
WxMaPhoneNumberInfo mobile = wxMaService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
user.setMobile(mobile.getPhoneNumber());
wineryMauserService.saveOrUpdate(user);
return mobile.getPhoneNumber();
}
}

View File

@ -0,0 +1,132 @@
package com.ruoyi.winery.config.wx;
/**
* @author tottimctj
* @since 2020-12-04
*/
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.File;
import java.util.Map;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Slf4j
@Configuration
@EnableConfigurationProperties(WxMiniProperties.class)
public class WxMaConfiguration {
@Autowired
private WxMiniProperties properties;
private static final Map<String, WxMaMessageRouter> routers = Maps.newHashMap();
public static WxMaMessageRouter getRouter(String appid) {
return routers.get(appid);
}
@Bean
@ConditionalOnMissingBean(name = "wxMaService")
public WxMaService wxMaService() {
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
config.setAppid(properties.getAppId());
config.setSecret(properties.getSecret());
config.setToken(properties.getToken());
config.setAesKey(properties.getAesKey());
config.setMsgDataFormat(properties.getMsgDataFormat());
WxMaService service = new WxMaServiceImpl();
service.setWxMaConfig(config);
routers.put(properties.getAppId(), this.newRouter(service));
return service;
}
private WxMaMessageRouter newRouter(WxMaService service) {
final WxMaMessageRouter router = new WxMaMessageRouter(service);
// router
// .rule().handler(logHandler).next()
// .rule().async(false).content("订阅消息").handler(subscribeMsgHandler).end()
// .rule().async(false).content("文本").handler(textHandler).end()
// .rule().async(false).content("图片").handler(picHandler).end()
// .rule().async(false).content("二维码").handler(qrcodeHandler).end();
return router;
}
// private final WxMaMessageHandler subscribeMsgHandler = (wxMessage, context, service, sessionManager) -> {
// service.getMsgService().sendSubscribeMsg(WxMaSubscribeMessage.builder()
// .templateId("此处更换为自己的模板id")
// .data(Lists.newArrayList(
// new WxMaSubscribeMessage.Data("keyword1", "339208499")))
// .toUser(wxMessage.getFromUser())
// .build());
// return null;
// };
private final WxMaMessageHandler logHandler = (wxMessage, context, service, sessionManager) -> {
log.info("收到消息:" + wxMessage.toString());
service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson())
.toUser(wxMessage.getFromUser()).build());
return null;
};
private final WxMaMessageHandler textHandler = (wxMessage, context, service, sessionManager) -> {
service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息")
.toUser(wxMessage.getFromUser()).build());
return null;
};
private final WxMaMessageHandler picHandler = (wxMessage, context, service, sessionManager) -> {
try {
WxMediaUploadResult uploadResult = service.getMediaService()
.uploadMedia("image", "png",
ClassLoader.getSystemResourceAsStream("tmp.png"));
service.getMsgService().sendKefuMsg(
WxMaKefuMessage
.newImageBuilder()
.mediaId(uploadResult.getMediaId())
.toUser(wxMessage.getFromUser())
.build());
} catch (WxErrorException e) {
e.printStackTrace();
}
return null;
};
private final WxMaMessageHandler qrcodeHandler = (wxMessage, context, service, sessionManager) -> {
try {
final File file = service.getQrcodeService().createQrcode("123", 430);
WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file);
service.getMsgService().sendKefuMsg(
WxMaKefuMessage
.newImageBuilder()
.mediaId(uploadResult.getMediaId())
.toUser(wxMessage.getFromUser())
.build());
} catch (WxErrorException e) {
e.printStackTrace();
}
return null;
};
}

View File

@ -0,0 +1,66 @@
package com.ruoyi.winery.config.wx;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "wxmini")
public class WxMiniProperties {
/**
* 设置微信App的appid
*/
private String appId;
/**
* 微信支付商户号
*/
private String mchId;
/**
* 微信支付商户密钥
*/
private String mchKey;
/**
* 服务商模式下的子商户公众账号ID普通模式请不要配置请在配置文件中将对应项删除
*/
private String subAppId;
/**
* 服务商模式下的子商户号普通模式请不要配置最好是请在配置文件中将对应项删除
*/
private String subMchId;
/**
* apiclient_cert.p12文件的绝对路径或者如果放在项目中请以classpath:开头指定
*/
private String keyPath;
/**
* 通知地址
*/
private String notifyUrl;
/**
* 交易类型
*/
private String tradeType;
/**
* 设置微信小程序的Secret
*/
private String secret;
/**
* 设置微信小程序消息服务器配置的token
*/
private String token;
/**
* 设置微信小程序消息服务器配置的EncodingAESKey
*/
private String aesKey;
/**
* 消息格式XML或者JSON
*/
private String msgDataFormat;
}

View File

@ -0,0 +1,48 @@
package com.ruoyi.winery.config.wx;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author kino
* @create 2019-07-23 14:53
*/
@Configuration
@EnableConfigurationProperties({WxMiniProperties.class})
public class WxPayConfiguration {
private WxMiniProperties miniProperties;
@Autowired
public WxPayConfiguration(WxMiniProperties miniProperties) {
this.miniProperties = miniProperties;
}
@Bean
@ConditionalOnMissingBean(name = "wxServiceMini") //微信小程序
public WxPayService wxServiceMini() {
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(StringUtils.trimToNull(this.miniProperties.getAppId()));
payConfig.setMchId(StringUtils.trimToNull(this.miniProperties.getMchId()));
payConfig.setMchKey(StringUtils.trimToNull(this.miniProperties.getMchKey()));
payConfig.setSubAppId(StringUtils.trimToNull(this.miniProperties.getSubAppId()));
payConfig.setSubMchId(StringUtils.trimToNull(this.miniProperties.getSubMchId()));
payConfig.setKeyPath(StringUtils.trimToNull(this.miniProperties.getKeyPath()));
payConfig.setNotifyUrl(StringUtils.trimToNull(this.miniProperties.getNotifyUrl()));
payConfig.setTradeType(StringUtils.trimToNull(this.miniProperties.getTradeType()));
// 可以指定是否使用沙箱环境
payConfig.setUseSandboxEnv(false);
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
}

View File

@ -1,15 +1,21 @@
package com.ruoyi.winery.controller;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import java.security.Principal;
import java.util.List;
import java.util.Arrays;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
@ -46,6 +52,7 @@ public class WineryCompanyRecordController extends BaseController {
@PreAuthorize("@ss.hasPermi('winery:winery_company_record:list')")
@GetMapping("/list")
public TableDataInfo list(WineryCompanyRecord wineryCompanyRecord) {
startPage();
LambdaQueryWrapper<WineryCompanyRecord> lqw = Wrappers.lambdaQuery(wineryCompanyRecord);
if (StringUtils.isNotBlank(wineryCompanyRecord.getStatus())) {

View File

@ -64,8 +64,8 @@ public class WineryMauserController extends BaseController {
if (wineryMauser.getCreateTime() != null){
lqw.eq(WineryMauser::getCreateTime ,wineryMauser.getCreateTime());
}
if (StringUtils.isNotBlank(wineryMauser.getTenantId())){
lqw.eq(WineryMauser::getTenantId ,wineryMauser.getTenantId());
if (StringUtils.isNotBlank(wineryMauser.getDeptId())){
lqw.eq(WineryMauser::getDeptId ,wineryMauser.getDeptId());
}
List<WineryMauser> list = iWineryMauserService.list(lqw);
return getDataTable(list);
@ -122,4 +122,5 @@ public class WineryMauserController extends BaseController {
public AjaxResult remove(@PathVariable String[] openIds) {
return toAjax(iWineryMauserService.removeByIds(Arrays.asList(openIds)) ? 1 : 0);
}
}

View File

@ -0,0 +1,172 @@
package com.ruoyi.winery.controller.mini;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.winery.component.MiniComponent;
import com.ruoyi.winery.domain.WineryCompanyRecord;
import com.ruoyi.winery.enums.IrrigationTypeEnum;
import com.ruoyi.winery.enums.SoilTypeEnum;
import com.ruoyi.winery.enums.WineryStatusEnum;
import com.ruoyi.winery.service.IWineryCompanyRecordService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author tottimctj
* @since 2020-11-10
*/
@RestController
@RequestMapping("/winery/mini")
@Slf4j
public class MiniController {
@Autowired
MiniComponent miniComponent;
@Autowired
IWineryCompanyRecordService recordWineryService;
/**
* 通过微信api授权获取手机号
*
* @param json
* @return
*/
@Log(title = "发送小程序手机号码", businessType = BusinessType.OTHER)
@PostMapping("/sendMobile")
AjaxResult sendMobile(@RequestBody JSONObject json) {
String mobile = miniComponent.getMobile(json);
if (StrUtil.isBlank(mobile)) {
return AjaxResult.error("获取失败!");
}
JSONObject rsp = new JSONObject();
rsp.set("mobile", mobile);
return AjaxResult.success("获取成功.", rsp);
}
@Log(title = "微信小程序登录", businessType = BusinessType.OTHER)
@GetMapping("/login")
public AjaxResult getSession(@RequestParam("code") String code) throws WxErrorException {
WxMaJscode2SessionResult sessionInfo = miniComponent.login(code);
JSONObject json = new JSONObject();
json.set("openid", sessionInfo.getOpenid());
log.info("微信小程序获取openid信息成功");
return AjaxResult.success(json);
}
@Log(title = "提交酒庄厂家记录", businessType = BusinessType.INSERT)
@PostMapping("/postForm")
AjaxResult postForm(@RequestBody JSONObject json) {
WineryCompanyRecord record = parseRecordWineryModel(json);
WineryCompanyRecord old = recordWineryService.getOne(
new LambdaQueryWrapper<WineryCompanyRecord>().
eq(WineryCompanyRecord::getOpenid, json.getStr("openid")));
if (old != null) {
record.setId(old.getId());
}
return AjaxResult.success(recordWineryService.saveOrUpdate(record));
}
@Log(title = "获取酒庄厂家记录", businessType = BusinessType.OTHER)
@GetMapping("/getForm")
AjaxResult getForm(@RequestParam String openid) {
WineryCompanyRecord record = recordWineryService.getOne(
new LambdaQueryWrapper<WineryCompanyRecord>().
eq(WineryCompanyRecord::getOpenid, openid));
return AjaxResult.success(record);
}
private WineryCompanyRecord parseRecordWineryModel(JSONObject json) {
WineryCompanyRecord record = new WineryCompanyRecord();
record.setOpenid(json.getStr("openid"));
record.setEmail(json.getStr("email"));
record.setPersonName(json.getStr("personName"));
record.setMobile(json.getStr("mobile"));
record.setWineryName(json.getStr("wineryName"));
record.setBuildTime(json.getStr("buildTime"));
record.setRegion(parseArrayToStr(json, "region"));
record.setAddress(json.getStr("address"));
record.setWineryArea(json.getLong("wineryArea"));
record.setBuildArea(json.getLong("buildArea"));
WineryStatusEnum wineryStatus = WineryStatusEnum.parseEnum(json.getStr("wineryStatus"));
record.setWineryStatus(wineryStatus);
record.setPlantArea(json.getLong("plantArea"));
record.setPlantWeight(json.getLong("plantWeight"));
SoilTypeEnum soilType = SoilTypeEnum.parseEnum(json.getStr("soilType"));
record.setSoilType(soilType);
record.setRedVariety(json.getJSONObject("redVariety").toStringPretty());
record.setWhiteVariety(json.getJSONObject("whiteVariety").toStringPretty());
IrrigationTypeEnum irrigationType = IrrigationTypeEnum.parseEnum(json.getStr("irrigationType"));
record.setIrrigationType(irrigationType);
record.setFermentationProcess(parseArrayToStr(json, "fermentationProcess"));
record.setContainer(parseArrayToStr(json, "container"));
record.setClarificationMethod(parseArrayToStr(json, "clarificationMethod"));
record.setAnnualOutput(json.getFloat("annualOutput"));
record.setStock(json.getFloat("stock"));
record.setBucketCount(json.getLong("bucketCount"));
record.setMainPrice(parseArrayToStr(json, "mainPrice"));
record.setSalesMode(parseArrayToStr(json, "salesMode"));
record.setAwards(parseArrayToStr(json, "awards"));
record.setAwardInformation(json.getStr("awardInformation"));
record.setSlogan(json.getStr("slogan"));
return record;
}
private String parseArrayToStr(JSONObject json, String key) {
List<String> list = json.getJSONArray(key).stream().map(x -> (String) x).collect(Collectors.toList());
return String.join(",", list);
}
private String[] parseStrtoArray(JSONObject json, String key) {
return json.getStr(key).split(",");
}
}

View File

@ -131,11 +131,11 @@ private static final long serialVersionUID=1L;
/** 年产量 */
@Excel(name = "年产量")
private Long annualOutput;
private Float annualOutput;
/** 库存 */
@Excel(name = "库存")
private Long stock;
private Float stock;
/** 酒桶数量 */
@Excel(name = "酒桶数量")

View File

@ -63,5 +63,5 @@ private static final long serialVersionUID=1L;
/** 租户id */
@Excel(name = "租户id")
private String tenantId;
private String deptId;
}

View File

@ -34,6 +34,7 @@
<jwt.version>0.9.1</jwt.version>
<mybatis-plus.version>3.4.1</mybatis-plus.version>
<hutool.version>5.4.0</hutool.version>
<wx-java.version>4.0.0</wx-java.version>
</properties>
<!-- 依赖声明 -->

View File

@ -190,3 +190,18 @@ xss:
excludes: /system/notice/*
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*
#微信小程序支付配置
wxmini:
appId: wx76ec015fc31a1946 #微信公众号或者小程序等的appid 必填
mchId: 1486984962
mchKey: 82aZ9Tb6eu5W2HdXKQWZU2SztU8w8nJ8
notifyUrl: http://41.mxl530.top:8087/zhongyihis/wxnotify
subAppId: #服务商模式下的子商户公众账号ID
subMchId: #服务商模式下的子商户号
tradeType: JSAPI #交易类型
keyPath: "classpath:/cert/apiclient_cert1486984962.p12" # p12证书的位置可以指定绝对路径也可以指定类路径以classpath:开头)
secret: 94ee42c0899a6ceccf353e1e729c50d4 #微信小程序的Secret
token: xiao4r #微信小程序消息服务器配置的token
aesKey: jNXajd2sQSMYQNg3rcdMF9HraUJxXF0iswgdMxVik9W #微信小程序消息服务器配置的EncodingAESKey
msgDataFormat: JSON

View File

@ -3,8 +3,12 @@ package com.ruoyi.common.core.controller;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
@ -91,4 +95,20 @@ public class BaseController
{
return StringUtils.format("redirect:{}", url);
}
/**
* 获取部门Id
* @param token
* @return
*/
public String getDeptId(UsernamePasswordAuthenticationToken token) {
JSONObject json = (JSONObject) JSONUtil.parse(token.getPrincipal());
String deptId = json.getJSONObject("user")
.getJSONObject("dept")
.getStr("deptId");
return deptId;
}
}

View File

@ -113,6 +113,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
.antMatchers("/webjars/**").anonymous()
.antMatchers("/*/api-docs").anonymous()
.antMatchers("/druid/**").anonymous()
.antMatchers("/winery/mini/**").anonymous()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()

View File

@ -46,9 +46,9 @@
placeholder="选择创建时间">
</el-date-picker>
</el-form-item>
<el-form-item label="租户id" prop="tenantId">
<el-form-item label="租户id" prop="deptId">
<el-input
v-model="queryParams.tenantId"
v-model="queryParams.deptId"
placeholder="请输入租户id"
clearable
size="small"
@ -115,7 +115,7 @@
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="租户id" align="center" prop="tenantId" />
<el-table-column label="租户id" align="center" prop="deptId" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
@ -165,8 +165,8 @@
<el-form-item label="unionid" prop="unionId">
<el-input v-model="form.unionId" placeholder="请输入unionid" :disabled="true" />
</el-form-item>
<el-form-item label="租户id" prop="tenantId">
<el-input v-model="form.tenantId" placeholder="请输入租户id" />
<el-form-item label="租户id" prop="deptId">
<el-input v-model="form.deptId" placeholder="请输入租户id" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
@ -215,7 +215,7 @@ export default {
nickName: undefined,
unionId: undefined,
createTime: undefined,
tenantId: undefined
deptId: undefined
},
//
form: {},
@ -259,7 +259,7 @@ export default {
unionId: undefined,
createTime: undefined,
updateTime: undefined,
tenantId: undefined
deptId: undefined
};
this.resetForm("form");
},