Browse Source

修复下单端系统派单

master
前端-胡立永 2 months ago
parent
commit
9044a4afb2
31 changed files with 1041 additions and 295 deletions
  1. +1
    -1
      CatmDogd-Mall-Front-test/.env.development
  2. +2
    -2
      CatmDogd-Mall-Front-test/.env.production
  3. +18
    -14
      CatmDogd-Mall-Front-test/src/views/model/AppletQuestion/index.vue
  4. +18
    -8
      CatmDogd-Mall-Front-test/src/views/model/AppletUsersTeacher/components/ExamInfo.vue
  5. +8
    -5
      ruoyi-admin/src/main/resources/application-druid-root.yml
  6. +1
    -1
      ruoyi-admin/src/main/resources/application.yml
  7. +9
    -0
      ruoyi-admin/src/main/resources/pub_key.pem
  8. +5
    -1
      ruoyi-catdog/pom.xml
  9. +163
    -5
      ruoyi-catdog/src/main/java/com/ruoyi/applet/contoller/ApiAppletAmountController.java
  10. +192
    -130
      ruoyi-catdog/src/main/java/com/ruoyi/applet/contoller/ApiAppletExaminationController.java
  11. +6
    -1
      ruoyi-catdog/src/main/java/com/ruoyi/applet/pojo/dto/AppletAnswerSubmitBo.java
  12. +148
    -0
      ruoyi-catdog/src/main/java/com/ruoyi/applet/transfer/TransferToUser.java
  13. +381
    -0
      ruoyi-catdog/src/main/java/com/ruoyi/applet/transfer/WXPayUtility.java
  14. +4
    -0
      ruoyi-catdog/src/main/java/com/ruoyi/model/domain/AppletAmountLog.java
  15. +3
    -49
      ruoyi-catdog/src/main/java/com/ruoyi/model/domain/AppletIncrease.java
  16. +4
    -61
      ruoyi-catdog/src/main/java/com/ruoyi/model/domain/AppletQuestion.java
  17. +3
    -1
      ruoyi-catdog/src/main/java/com/ruoyi/model/mapper/AppletAmountLogMapper.java
  18. +3
    -1
      ruoyi-catdog/src/main/java/com/ruoyi/model/mapper/AppletIncreaseMapper.java
  19. +3
    -1
      ruoyi-catdog/src/main/java/com/ruoyi/model/mapper/AppletQuestionMapper.java
  20. +4
    -1
      ruoyi-catdog/src/main/java/com/ruoyi/model/service/IAppletAmountLogService.java
  21. +3
    -1
      ruoyi-catdog/src/main/java/com/ruoyi/model/service/IAppletIncreaseService.java
  22. +3
    -1
      ruoyi-catdog/src/main/java/com/ruoyi/model/service/IAppletQuestionService.java
  23. +1
    -0
      ruoyi-catdog/src/main/java/com/ruoyi/model/service/IAppletUsersTeacherService.java
  24. +6
    -2
      ruoyi-catdog/src/main/java/com/ruoyi/model/service/impl/AppUsersServiceImpl.java
  25. +3
    -1
      ruoyi-catdog/src/main/java/com/ruoyi/model/service/impl/AppletAmountLogServiceImpl.java
  26. +3
    -1
      ruoyi-catdog/src/main/java/com/ruoyi/model/service/impl/AppletIncreaseServiceImpl.java
  27. +3
    -1
      ruoyi-catdog/src/main/java/com/ruoyi/model/service/impl/AppletQuestionServiceImpl.java
  28. +26
    -1
      ruoyi-catdog/src/main/java/com/ruoyi/model/service/impl/AppletUsersTeacherServiceImpl.java
  29. +4
    -1
      ruoyi-catdog/src/main/resources/mapper/model/AppletAmountLogMapper.xml
  30. +3
    -1
      ruoyi-catdog/src/main/resources/mapper/model/AppletIncreaseMapper.xml
  31. +10
    -3
      ruoyi-catdog/src/main/resources/mapper/model/AppletQuestionMapper.xml

+ 1
- 1
CatmDogd-Mall-Front-test/.env.development View File

@ -8,7 +8,7 @@ VUE_APP_TITLE = 下单伴宠师综合管理平台
# VUE_APP_BASE_API = 'https://api.catmdogd.com'
# VUE_APP_BASE_API = 'https://pet-admin.hhlm1688.com/api/'
# VUE_APP_BASE_API = 'http://h5.xzaiyp.top'
VUE_APP_BASE_API = 'http://localhost:8002'
VUE_APP_BASE_API = 'http://localhost:8080'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true


+ 2
- 2
CatmDogd-Mall-Front-test/.env.production View File

@ -5,6 +5,6 @@ VUE_APP_TITLE = 下单伴宠师综合管理平台
ENV = 'production'
# 若依管理系统/生产环境
VUE_APP_BASE_API = '/api'
# VUE_APP_BASE_API = '/prod-api'
# VUE_APP_BASE_API = '/api'
VUE_APP_BASE_API = '/prod-api'
VUE_APP_JUDGE_STAR = 0

+ 18
- 14
CatmDogd-Mall-Front-test/src/views/model/AppletQuestion/index.vue View File

@ -6,10 +6,12 @@
<el-input v-model="queryParams.title" placeholder="请输入题目标题" clearable size="small"
@keyup.enter.native="handleQuery" />
</el-form-item>
<!-- <el-form-item label="题目类型" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择题目类型" clearable size="small">
<el-form-item label="题目类型" prop="typeAnswer">
<el-select v-model="queryParams.typeAnswer" placeholder="请选择题目类型" clearable size="small">
<el-option v-for="dict in dict.type.tm_type" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item> -->
</el-form-item>
<el-form-item label="排序编号" prop="orderNo">
<el-input v-model="queryParams.orderNo" placeholder="请输入排序编号" clearable size="small"
@keyup.enter.native="handleQuery" />
@ -52,9 +54,9 @@
<!-- <el-table-column label="唯一标识" align="center" prop="id" />-->
<el-table-column label="创建时间" align="center" prop="createTime" />
<el-table-column label="题目标题" align="center" prop="title" />
<el-table-column label="题目类型" align="center" prop="type" v-if="columns[1].visible">
<el-table-column label="题目类型" align="center" prop="typeAnswer" v-if="columns[1].visible">
<template slot-scope="scope">
<dict-tag :options="dict.type.tm_type" :value="scope.row.type" />
<dict-tag :options="dict.type.tm_type" :value="scope.row.typeAnswer" />
</template>
</el-table-column>
<el-table-column label="排序编号" align="center" prop="orderNo" />
@ -83,22 +85,22 @@
<el-form-item label="排序编号" prop="orderNo">
<el-input v-model="form.orderNo" placeholder="请输入排序编号" />
</el-form-item>
<!-- <el-form-item label="题目类型" prop="type">
<el-select v-model="form.type" placeholder="请选择题目类型" @change="handleTypeChange">
<el-form-item label="题目类型" prop="typeAnswer">
<el-select v-model="form.typeAnswer" placeholder="请选择题目类型" @change="handleTypeChange">
<el-option v-for="dict in dict.type.tm_type" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
:value="parseInt(dict.value)"></el-option>
</el-select>
</el-form-item> -->
</el-form-item>
<!-- 填空题配置 -->
<template v-if="form.type === '培训'">
<template v-if="form.typeAnswer === 1">
<el-form-item label="最少字数" prop="numberWords">
<el-input-number v-model="form.numberWords" :min="1" :max="1000" placeholder="请输入最少字数限制" />
</el-form-item>
</template>
<!-- 选择题答案配置 -->
<template v-if="form.type === '基本'">
<template v-if="form.typeAnswer === 0">
<el-divider content-position="left">选项设置</el-divider>
<div v-for="(option, index) in form.answerList" :key="index" class="option-item">
<el-row :gutter="10" class="mb-2">
@ -165,7 +167,7 @@ export default {
pageSize: 10,
title: null,
type: null,
typeAnswer: null,
orderNo: null,
@ -175,6 +177,7 @@ export default {
id: null,
title: null,
type: null,
typeAnswer: null,
orderNo: null,
answer: null,
numberWords: 1,
@ -191,7 +194,7 @@ export default {
{ required: true, message: "题目标题不能为空", trigger: "blur" }
],
type: [
typeAnswer: [
{ required: true, message: "题目类型不能为空", trigger: "change" }
],
@ -241,6 +244,7 @@ export default {
id: null,
title: null,
type: null,
typeAnswer: null,
orderNo: null,
answer: null,
numberWords: 1,
@ -306,7 +310,7 @@ export default {
/** 题目类型改变 */
handleTypeChange(value) {
this.form.answer = null;
if (value === '基本') {
if (value === 0) {
//
this.form.answerList = [
{ title: '', isTrue: false, orderNo : 1 },


+ 18
- 8
CatmDogd-Mall-Front-test/src/views/model/AppletUsersTeacher/components/ExamInfo.vue View File

@ -12,16 +12,16 @@
</el-tab-pane> -->
<el-tab-pane label="基本考核" name="base">
<div v-for="(question, index) in examInfo.answerList.filter(n => n.type != '培训')" :key="index" class="question-item">
<div v-for="(question, index) in examInfo.answerList.filter(n => n.type == '基本')" :key="index" class="question-item">
<div class="question-title">
<span class="question-index">{{ index + 1 }}.</span>
<span class="question-type">[{{ question.type === '培训' ? '填空题' : '选择题' }}]</span>
<span class="question-type">[{{ getQuestionType(question) }}]</span>
<span v-if="!isQuestionAnswered(question)" class="unanswered-tag">未答题</span>
<span class="question-content">{{ question.title }}</span>
</div>
<!-- 填空题答案 -->
<template v-if="question.type === '培训'">
<template v-if="question.typeAnswer === 1">
<div class="answer-content">
<div class="answer-label">答案</div>
<div class="answer-text" :class="{ 'no-answer': !isQuestionAnswered(question) }">
@ -53,7 +53,7 @@
</span>
</div>
</div>
<div class="answer-result" :class="{ 'correct': isAnswerCorrect(question), 'wrong': !isAnswerCorrect(question) }">
<div class="answer-result" :class="{ 'correct': isAnswerCorrect(question), 'wrong': !isAnswerCorrect(question) && isQuestionAnswered(question) }">
<i :class="['el-icon-' + (isAnswerCorrect(question) ? 'success' : 'error')]"></i>
{{ isAnswerCorrect(question) ? '回答正确' : '回答错误' }}
</div>
@ -64,13 +64,13 @@
<div v-for="(question, index) in examInfo.answerList.filter(n => n.type == '培训')" :key="index" class="question-item">
<div class="question-title">
<span class="question-index">{{ index + 1 }}.</span>
<span class="question-type">[{{ question.type === '培训' ? '填空题' : '选择题' }}]</span>
<span class="question-type">[{{ getQuestionType(question) }}]</span>
<span v-if="!isQuestionAnswered(question)" class="unanswered-tag">未答题</span>
<span class="question-content">{{ question.title }}</span>
</div>
<!-- 填空题答案 -->
<template v-if="question.type === '培训'">
<template v-if="question.typeAnswer === 1">
<div class="answer-content">
<div class="answer-label">答案</div>
<div class="answer-text" :class="{ 'no-answer': !isQuestionAnswered(question) }">
@ -102,7 +102,7 @@
</span>
</div>
</div>
<div class="answer-result" :class="{ 'correct': isAnswerCorrect(question), 'wrong': !isAnswerCorrect(question) }">
<div class="answer-result" :class="{ 'correct': isAnswerCorrect(question), 'wrong': !isAnswerCorrect(question) && isQuestionAnswered(question) }">
<i :class="['el-icon-' + (isAnswerCorrect(question) ? 'success' : 'error')]"></i>
{{ isAnswerCorrect(question) ? '回答正确' : '回答错误' }}
</div>
@ -186,6 +186,16 @@ export default {
handleClose() {
this.$emit('update:visible', false);
},
//
getQuestionType(question) {
if (question.typeAnswer === 1) {
return '填空题';
} else {
//
const correctAnswersCount = question.answerList.filter(option => option.isTrue).length;
return correctAnswersCount > 1 ? '多选题' : '单选题';
}
},
//
isOptionSelected(question, optionId) {
if (!question.userAnswerBaseList || !question.userAnswerBaseList.length) return false;
@ -212,7 +222,7 @@ export default {
return userAnswerIds.every(answerId => correctOptionIds.includes(answerId));
},
isQuestionAnswered(question) {
if (question.type === '培训') {
if (question.typeAnswer === 1) {
//
return question.userAppletAnswerTrain &&
question.userAppletAnswerTrain.answer &&


+ 8
- 5
ruoyi-admin/src/main/resources/application-druid-root.yml View File

@ -6,7 +6,8 @@ spring:
druid:
# 主库数据源 jdbc:mysql://localhost:3306/catmdogf?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
master:
url: jdbc:mysql://47.97.158.59:3306/catmdogf_prod20250624?useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
url: jdbc:mysql://47.97.158.59:3306/catmdogf_test20250624?useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
# url: jdbc:mysql://47.97.158.59:3306/catmdogf_prod20250624?useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username: root
password: Qweruiop@123
# 从库数据源
@ -63,12 +64,12 @@ wechat:
merchantSerialNumber: 6050244FC18200362585F1F9FD6557A1B291E8C0
apiV3key: 19971022197001121966060120240731
apiV2key: 19961022196901121965060120230731
# notifyUrl: https://api.catmdogd.com/prod-api/no-auth/wechat/notify
# notifyUrlForBCHSH: https://api.catmdogd.com/prod-api/no-auth/wechat/notifyForBCHSH
notifyUrl: https://api.catmdogd.com/prod-api/no-auth/wechat/notify
notifyUrlForBCHSH: https://api.catmdogd.com/prod-api/no-auth/wechat/notifyForBCHSH
# notifyUrl: https://pet-admin.hhlm1688.com/api/no-auth/wechat/notify
# notifyUrlForBCHSH: https://pet-admin.hhlm1688.com/api/no-auth/wechat/notifyForBCHSH
notifyUrl: http://h5.xzaiyp.top/no-auth/wechat/notify
notifyUrlForBCHSH: http://h5.xzaiyp.top/no-auth/wechat/notifyForBCHSH
# notifyUrl: http://h5.xzaiyp.top/no-auth/wechat/notify
# notifyUrlForBCHSH: http://h5.xzaiyp.top/no-auth/wechat/notifyForBCHSH
miniProgramAppId: wxd1a6ba7b5e17a5b6
miniProgramSecret: 06e946a2c9010f8eb9e306018a779a7f
staffAppId: wx01f0f43759922fda
@ -130,6 +131,8 @@ wechat-admin:
miniProgramSecret: 06e946a2c9010f8eb9e306018a779a7f
staffAppId: wx01f0f43759922fda
staffSecret: b0a5617e6e4c387262a32af2b355c8b6
publicKeyPath: E:\\file\\2025\\1\pet-admin\\ruoyi-admin\\src\\main\\resources\\pub_key.pem
publicKeyId: PUB_KEY_ID_0116656396912025062400291558001601
pay:
v3:
# 租户id


+ 1
- 1
ruoyi-admin/src/main/resources/application.yml View File

@ -20,7 +20,7 @@ ruoyi:
# 开发环境配置.0
server:
# 服务器的HTTP端口,默认为8080
port: 8002
port: 8080
servlet:
# 应用的访问路径
context-path: /


+ 9
- 0
ruoyi-admin/src/main/resources/pub_key.pem View File

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxVq1qlE0uup85UF+cq/+
+BqoLrjd2WxsmJff/KGEclX3lZFF8GK0GbZKobSmf+/4JzHUgihJ9H78NXxFoB3n
GWDDgfV8ZkXyV4XUwdIjpegA3MWgUPyKaqe0RyHdxjdGf+JAA0k82kOVWFvbxkRd
CWXJjZJ8nvXXHLiJL6T84q9MscfOtw6DSP3s+/tm3Xlm9v0pKK5tmh1UireZXRsM
0TR0dvx9oyot8hpVjqhxFpQC+ilp4WIdaxHMh2mjFExZvKg5rbk5N0/1PkXcn3Bt
BrTHGZRce8NV/Es6xejM/UIt9ofVRbQl3LHXJkFKmMtCXjjjMD8LEsZ3IiGfTB4l
ZQIDAQAB
-----END PUBLIC KEY-----

+ 5
- 1
ruoyi-catdog/pom.xml View File

@ -38,7 +38,11 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.9</version>
</dependency>
<dependency>
<groupId>cn.felord</groupId>


+ 163
- 5
ruoyi-catdog/src/main/java/com/ruoyi/applet/contoller/ApiAppletAmountController.java View File

@ -1,5 +1,7 @@
package com.ruoyi.applet.contoller;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.ruoyi.applet.transfer.TransferToUser;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.model.domain.AppUsers;
@ -9,18 +11,21 @@ import com.ruoyi.model.service.IAppUsersService;
import com.ruoyi.model.service.IAppletAmountLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.*;
@Api(description = "小程序-金额相关接口")
@RestController
@RequestMapping("/applet/amount")
@Slf4j
public class ApiAppletAmountController {
//金额流水信息
@Autowired
@ -29,12 +34,32 @@ public class ApiAppletAmountController {
private IAppUsersService appUsersService;
/*************************************************************************************/
//微信小程序的 AppID
@Value("${wechat-admin.appId}")
private String appid;
//商户号
@Value("${wechat-admin.merchantId}")
private String mchid;
//商户API私钥路径
@Value("${wechat.privateKeyPath}")
private String privateKeyFilePath;
//商户API公钥路径
@Value("${wechat-admin.publicKeyPath}")
private String wechatPayPublicKeyFilePath;
//商户API公钥ID
@Value("${wechat-admin.publicKeyId}")
private String wechatPayPublicKeyId;
//商户证书序列号
@Value("${wechat-admin.merchantSerialNumber}")
private String certiticateSerialNo;
/*************************************************************************************/
@ApiOperation("小程序-金额流水信息列表数据查询")
@GetMapping("/amountLogList")
public AjaxResult amountLogList(AppletAmountLog appletAmountLog){
List<AppletAmountLog> amountLogList = appletAmountLogService.selectAppletAmountLogList(appletAmountLog);
return AjaxResult.success("金额流水信息列表数据",amountLogList);
return AjaxResult.success("金额流水信息列表数据", amountLogList);
}
@ApiOperation("小程序-充值")
@ -54,6 +79,9 @@ public class ApiAppletAmountController {
if (appletAmountLog.getAmount() == null || appletAmountLog.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
return AjaxResult.error("提现金额必须大于0");
}
if (StringUtils.isEmpty(appletAmountLog.getNameValue())) {
return AjaxResult.error("姓名不能为空");
}
// 查询用户余额
AppUsers user = appUsersService.selectAppUsersByUserId(appletAmountLog.getUserId());
@ -77,6 +105,85 @@ public class ApiAppletAmountController {
}
}
//1.微信提现基础参数
Map map = getMap();
//变化的用户信息参数
map.put("openid", user.getOpenid());//用户openid(小程序)
map.put("userName", appletAmountLog.getNameValue());//用户真实姓名
map.put("transferAmount", appletAmountLog.getAmount());//提现金额, 单位为
String idStr = "H" + IdWorker.getIdStr();
map.put("outBillNo", idStr);//商户单号
TransferToUser client = new TransferToUser(
map.get("mchid").toString(), // 商户号是由微信支付系统生成并分配给每个商户的唯一标识符商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756
map.get("certiticateSerialNo").toString(), // 商户API证书序列号如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053
map.get("privateKeyFilePath").toString(), // 商户API证书私钥文件路径本地文件路径
map.get("wechatPayPublicKeyId").toString(), // 微信支付公钥ID如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816
map.get("wechatPayPublicKeyFilePath").toString() // 微信支付公钥文件路径本地文件路径
);
//2场景信息
TransferToUser.TransferToUserRequest request = new TransferToUser.TransferToUserRequest();
request.appid = map.get("appid").toString();
request.outBillNo = map.get("outBillNo").toString();
request.transferSceneId = map.get("transferSceneId").toString();
request.openid = map.get("openid").toString();
request.userName = client.encrypt(map.get("userName").toString());
request.transferAmount = appletAmountLog.getAmount().longValue()*100;//单位为分
request.transferRemark = map.get("transferRemark").toString();
request.notifyUrl = map.get("notifyUrl").toString();
request.userRecvPerception = map.get("userRecvPerception").toString();
request.transferSceneReportInfos = new ArrayList<>();
{
TransferToUser.TransferSceneReportInfo item0 = new TransferToUser.TransferSceneReportInfo();
item0.infoType = map.get("infoType1").toString();
item0.infoContent = map.get("infoContent1").toString();
request.transferSceneReportInfos.add(item0);
}
String massage = "提现申请失败";
//3执行提现
TransferToUser.TransferToUserResponse response = client.run(request, map);
log.info("提现发起成功,outBillNo:"+response.outBillNo + ",transferBillNo:" +response.transferBillNo + ",state:" +response.state+ ",packageInfo:" + response.packageInfo);
switch (response.state){
case ACCEPTED:
log.info("转账已受理");
massage = "转账已受理";
break;
case PROCESSING:
log.info("转账锁定资金中。如果一直停留在该状态,建议检查账户余额是否足够,如余额不足,可充值后再原单重试");
massage = "转账锁定资金中。如果一直停留在该状态,建议检查账户余额是否足够,如余额不足,可充值后再原单重试";
break;
case WAIT_USER_CONFIRM:
log.info("待收款用户确认,可拉起微信收款确认页面进行收款确认");
massage = "待收款用户确认,可拉起微信收款确认页面进行收款确认";
break;
case TRANSFERING:
log.info("转账中,可拉起微信收款确认页面再次重试确认收款");
massage = "转账中,可拉起微信收款确认页面再次重试确认收款";
break;
case SUCCESS:
log.info("转账成功");
massage = "转账成功";
break;
case FAIL:
log.info("转账失败");
massage = "转账失败";
break;
case CANCELING:
log.info("商户撤销请求受理成功,该笔转账正在撤销中");
massage = "商户撤销请求受理成功,该笔转账正在撤销中";
break;
case CANCELLED:
log.info("转账撤销完成");
massage = "转账撤销完成";
break;
}
log.info("提现结果:" + massage);
try {
// 记录日志
@ -96,7 +203,10 @@ public class ApiAppletAmountController {
moneyLog.setCreateTime(LocalDateTime.now());
moneyLog.setMoneyType(appletAmountLog.getMoneyType());//钱包类型
moneyLog.setNameValue(appletAmountLog.getNameValue());
int i = appletAmountLogService.insertAppletAmountLog(moneyLog);
moneyLog.setPackageInfo(appletAmountLog.getPackageInfo());
appletAmountLogService.save(moneyLog);
// 扣减余额直接更新
if(appletAmountLog.getMoneyType() == 0){
@ -109,10 +219,58 @@ public class ApiAppletAmountController {
appUsersService.updateAppUsers(user);
return AjaxResult.success("提现成功");
HashMap<String, Object> result = new HashMap<>();
result.put("response", response);
result.put("id", moneyLog.getId());
return AjaxResult.success("提现成功", result);
} catch (Exception e) {
return AjaxResult.error("提现处理失败");
}
}
/**
* 微信提现基础参数
* @return
*/
public Map getMap(){
Map<String, Object> map = new HashedMap();//转账接口所需参数
map.put("host", "https://api.mch.weixin.qq.com");//请求地址
map.put("method", "POST");//请求类型
map.put("path", "/v3/fund-app/mch-transfer/transfer-bills");//提现接口
map.put("notifyUrl", "https://www.yurangongfang.com/massage-admin/massage/cash/cashoutNotify/");//回调接口
//微信商户参数
map.put("appid", appid);//小程序appid
map.put("mchid", mchid);//商户号
map.put("certiticateSerialNo", certiticateSerialNo);//商户序列号
map.put("privateKeyFilePath", privateKeyFilePath);//商户私钥证书
map.put("wechatPayPublicKeyId", wechatPayPublicKeyId);//商户公钥id
map.put("wechatPayPublicKeyFilePath", wechatPayPublicKeyFilePath);//商户公钥证书
map.put("transferSceneId", "1010");//商户转账场景ID 1010-二手回收
map.put("transferRemark", "猫妈狗爸");//商户转账场景ID 1010-佣金报酬
map.put("userRecvPerception", "");//商户转账场景ID 1010-佣金报酬
//转账场景报备信息ransfer_scene_report_infos为数组类型参数
map.put("infoType1","提现");
map.put("infoContent1","提现");
return map;
}
@ApiOperation("小程序-提现成功")
@PostMapping("/withdrawalSuccessful")
public AjaxResult withdrawalSuccessful(String id){
AppletAmountLog byId = appletAmountLogService.getById(id);
byId.setState(1);
appletAmountLogService.updateById(byId);
return AjaxResult.success();
}
}

+ 192
- 130
ruoyi-catdog/src/main/java/com/ruoyi/applet/contoller/ApiAppletExaminationController.java View File

@ -18,8 +18,10 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@Api(description = "伴宠师-伴宠师考核")
@RestController
@ -77,14 +79,14 @@ public class ApiAppletExaminationController {
return AjaxResult.success("题目列表数据",questionList);
}
@ApiOperation("伴宠师工作台-根据题目id查询题目答案")
@GetMapping("/insertUser")
public AjaxResult answerListByQuestionId(long questionId){
AppletAnswer appletAnswer = new AppletAnswer();
appletAnswer.setQuestionId(questionId);
List<AppletAnswer> answerList = appletAnswerService.selectAppletAnswerList(appletAnswer);
return AjaxResult.success("答案列表数据",answerList);
}
// @ApiOperation("伴宠师工作台-根据题目id查询题目答案")
// @GetMapping("/insertUser")
// public AjaxResult answerListByQuestionId(long questionId){
// AppletAnswer appletAnswer = new AppletAnswer();
// appletAnswer.setQuestionId(questionId);
// List<AppletAnswer> answerList = appletAnswerService.selectAppletAnswerList(appletAnswer);
// return AjaxResult.success("答案列表数据",answerList);
// }
@ApiOperation("伴宠师工作台-查询宠物类型列表")
@GetMapping("/petTypeList")
@ -100,12 +102,12 @@ public class ApiAppletExaminationController {
return AjaxResult.success("专业执照列表数据",licenseList);
}
@ApiOperation("伴宠师工作台-查询用户基本考核答案列表")
@PostMapping("/answerBaseList")
public AjaxResult answerBaseList(@RequestBody AppletAnswerBase answerBase){
List<AppletAnswerBase> answerBaseList = appletAnswerBaseService.selectAppletAnswerBaseList(answerBase);
return AjaxResult.success("用户基本考核答案列表数据",answerBaseList);
}
// @ApiOperation("伴宠师工作台-查询用户基本考核答案列表")
// @PostMapping("/answerBaseList")
// public AjaxResult answerBaseList(@RequestBody AppletAnswerBase answerBase){
// List<AppletAnswerBase> answerBaseList = appletAnswerBaseService.selectAppletAnswerBaseList(answerBase);
// return AjaxResult.success("用户基本考核答案列表数据",answerBaseList);
// }
@ -133,26 +135,41 @@ public class ApiAppletExaminationController {
// }
//查询基本考核是否完成
@ApiOperation("伴宠师工作台-查询用户基本考核是否完成【废弃】")
@GetMapping("/answeBaseIsFinish")
public AjaxResult answeBaseIsFinish(Long userId){
AppletAnswerBase answerBase = new AppletAnswerBase();
answerBase.setUserId(userId);
List<AppletAnswerBase> answerBaseList = appletAnswerBaseService.selectAppletAnswerBaseList(answerBase);
if(answerBaseList.size() > 0){
return AjaxResult.success("用户基本考核已完成");
}
return AjaxResult.error("用户基本考核未完成");
}
// @ApiOperation("伴宠师工作台-查询用户基本考核是否完成【废弃】")
// @GetMapping("/answeBaseIsFinish")
// public AjaxResult answeBaseIsFinish(Long userId){
// AppletAnswerBase answerBase = new AppletAnswerBase();
// answerBase.setUserId(userId);
// List<AppletAnswerBase> answerBaseList = appletAnswerBaseService.selectAppletAnswerBaseList(answerBase);
// if(answerBaseList.size() > 0){
// return AjaxResult.success("用户基本考核已完成");
// }
// return AjaxResult.error("用户基本考核未完成");
// }
//查询基本考核是否完成
@ApiOperation("伴宠师工作台-查询用户基本考核是否完成")
@GetMapping("/answeBaseIsFinishV2")
public AjaxResult answeBaseIsFinishV2(Long userId){
AppletAnswerBase answerBase = new AppletAnswerBase();
answerBase.setUserId(userId);
List<AppletAnswerBase> answerBaseList = appletAnswerBaseService.selectAppletAnswerBaseList(answerBase);
if(answerBaseList.size() > 0){
List<Long> ids = appletQuestionService.lambdaQuery()
.eq(AppletQuestion::getType, "基本")
.select(AppletQuestion::getId)
.list()
.stream().map(n -> n.getId())
.collect(Collectors.toList());
Integer count = appletAnswerBaseService.lambdaQuery()
.in(AppletAnswerBase::getQuestionId, ids)
.eq(AppletAnswerBase::getUserId, userId)
.count();
Integer count1 = appletAnswerTrainService.lambdaQuery()
.in(AppletAnswerTrain::getQuestionId, ids)
.eq(AppletAnswerTrain::getUserId, userId)
.count();
if((count1 + count) > 0){
return AjaxResult.success(1);
}
return AjaxResult.success(0);
@ -160,68 +177,84 @@ public class ApiAppletExaminationController {
//查询培训考核是否完成
@ApiOperation("伴宠师工作台-查询用户培训考核是否完成【废弃】")
@GetMapping("/answeTrainIsFinish")
public AjaxResult answeTrainIsFinish(Long userId){
AppletAnswerTrain answerTrain = new AppletAnswerTrain();
answerTrain.setUserId(userId);
List<AppletAnswerTrain> answerTrainList = appletAnswerTrainService.selectAppletAnswerTrainList(answerTrain);
if(answerTrainList.size() > 0){
return AjaxResult.success("用户培训考核已完成");
}
return AjaxResult.error("用户培训考核未完成");
}
// @ApiOperation("伴宠师工作台-查询用户培训考核是否完成【废弃】")
// @GetMapping("/answeTrainIsFinish")
// public AjaxResult answeTrainIsFinish(Long userId){
// AppletAnswerTrain answerTrain = new AppletAnswerTrain();
// answerTrain.setUserId(userId);
// List<AppletAnswerTrain> answerTrainList = appletAnswerTrainService.selectAppletAnswerTrainList(answerTrain);
// if(answerTrainList.size() > 0){
// return AjaxResult.success("用户培训考核已完成");
// }
// return AjaxResult.error("用户培训考核未完成");
// }
//查询培训考核是否完成
@ApiOperation("伴宠师工作台-查询用户培训考核是否完成")
@GetMapping("/answeTrainIsFinishV2")
public AjaxResult answeTrainIsFinishV2(Long userId){
AppletAnswerTrain answerTrain = new AppletAnswerTrain();
answerTrain.setUserId(userId);
List<AppletAnswerTrain> answerTrainList = appletAnswerTrainService.selectAppletAnswerTrainList(answerTrain);
if(answerTrainList.size() > 0){
return AjaxResult.success(1);
}
return AjaxResult.success(0);
}
List<Long> ids = appletQuestionService.lambdaQuery()
.eq(AppletQuestion::getType, "培训")
.select(AppletQuestion::getId)
.list()
.stream().map(n -> n.getId())
.collect(Collectors.toList());
Integer count = appletAnswerBaseService.lambdaQuery()
.in(AppletAnswerBase::getQuestionId, ids)
.eq(AppletAnswerBase::getUserId, userId)
.count();
@ApiOperation("伴宠师工作台-根据题目id查询基本考核答案")
@GetMapping("/answeBaseByQuestionId")
public AjaxResult answeBaseByQuestionId(Long questionId, Long userId){
AppletAnswerBase answerBase = new AppletAnswerBase();
answerBase.setQuestionId(questionId);
answerBase.setUserId(userId);
List<AppletAnswerBase> answerBaseList = appletAnswerBaseService.selectAppletAnswerBaseList(answerBase);
Integer count1 = appletAnswerTrainService.lambdaQuery()
.in(AppletAnswerTrain::getQuestionId, ids)
.eq(AppletAnswerTrain::getUserId, userId)
.count();
for (AppletAnswerBase appletAnswerBase : answerBaseList) {
AppletAnswer answer = appletAnswerService.selectAppletAnswerById(appletAnswerBase.getAnswerId());
appletAnswerBase.setAnswer(answer);
if((count1 + count) > 0){
return AjaxResult.success(1);
}
return AjaxResult.success("用户基本考核答案列表数据",answerBaseList);
return AjaxResult.success(0);
}
@ApiOperation("伴宠师工作台-添加用户基本考核答案")
@PostMapping("/addBaseAnswer")
public AjaxResult addBaseAnswer(@RequestBody AppletAnswerBase answerBase){
if(answerBase.getUserId() == null){
return AjaxResult.error("userId用户信息标识不能为空");
}
if(answerBase.getQuestionId() == null){
return AjaxResult.error("questionId标识不能为空");
}
// //选删除之前的答案再去添加新的
LambdaQueryWrapper<AppletAnswerBase> qw = Wrappers.<AppletAnswerBase>lambdaQuery()
.eq(AppletAnswerBase::getUserId, answerBase.getUserId())
.eq(AppletAnswerBase::getQuestionId, answerBase.getQuestionId());
appletAnswerBaseService.remove(qw);
return toAjax(appletAnswerBaseService.insertAppletAnswerBase(answerBase));
}
// @ApiOperation("伴宠师工作台-根据题目id查询基本考核答案")
// @GetMapping("/answeBaseByQuestionId")
// public AjaxResult answeBaseByQuestionId(Long questionId, Long userId){
// AppletAnswerBase answerBase = new AppletAnswerBase();
// answerBase.setQuestionId(questionId);
// answerBase.setUserId(userId);
// List<AppletAnswerBase> answerBaseList = appletAnswerBaseService.selectAppletAnswerBaseList(answerBase);
//
// for (AppletAnswerBase appletAnswerBase : answerBaseList) {
// AppletAnswer answer = appletAnswerService.selectAppletAnswerById(appletAnswerBase.getAnswerId());
// appletAnswerBase.setAnswer(answer);
// }
//
// return AjaxResult.success("用户基本考核答案列表数据",answerBaseList);
// }
// @ApiOperation("伴宠师工作台-添加用户基本考核答案")
// @PostMapping("/addBaseAnswer")
// public AjaxResult addBaseAnswer(@RequestBody AppletAnswerBase answerBase){
//
// if(answerBase.getUserId() == null){
// return AjaxResult.error("userId用户信息标识不能为空");
// }
// if(answerBase.getQuestionId() == null){
// return AjaxResult.error("questionId标识不能为空");
// }
//// //选删除之前的答案再去添加新的
// LambdaQueryWrapper<AppletAnswerBase> qw = Wrappers.<AppletAnswerBase>lambdaQuery()
// .eq(AppletAnswerBase::getUserId, answerBase.getUserId())
// .eq(AppletAnswerBase::getQuestionId, answerBase.getQuestionId());
//
// appletAnswerBaseService.remove(qw);
//
// return toAjax(appletAnswerBaseService.insertAppletAnswerBase(answerBase));
// }
@ApiOperation("伴宠师工作台-添加用户基本考核答案V2")
@ -231,35 +264,64 @@ public class ApiAppletExaminationController {
Long userId = null;
for (AppletAnswerBase appletAnswerBase : answerSubmitBo.getAnswerBase()) {
if(appletAnswerBase.getUserId() == null){
return AjaxResult.error("userId用户信息标识不能为空");
}
if(appletAnswerBase.getQuestionId() == null){
return AjaxResult.error("questionId标识不能为空");
if (answerSubmitBo.getAnswerBase() != null && answerSubmitBo.getAnswerBase().size() > 0){
List<Long> ids = new ArrayList<>();
for (AppletAnswerBase appletAnswerBase : answerSubmitBo.getAnswerBase()) {
if(appletAnswerBase.getUserId() == null){
return AjaxResult.error("userId用户信息标识不能为空");
}
if(appletAnswerBase.getQuestionId() == null){
return AjaxResult.error("questionId标识不能为空");
}
ids.add(appletAnswerBase.getQuestionId());
userId = appletAnswerBase.getUserId();
}
userId = appletAnswerBase.getUserId();
//选删除之前的答案再去添加新的
LambdaQueryWrapper<AppletAnswerBase> qw = Wrappers.<AppletAnswerBase>lambdaQuery()
.in(AppletAnswerBase::getQuestionId, ids)
.eq(AppletAnswerBase::getUserId, userId);
appletAnswerBaseService.remove(qw);
appletAnswerBaseService.saveBatch(answerSubmitBo.getAnswerBase());
}
if (answerSubmitBo.getAnswerTrains() != null && answerSubmitBo.getAnswerTrains().size() > 0) {
List<Long> ids = new ArrayList<>();
for (AppletAnswerTrain appletAnswerTrain : answerSubmitBo.getAnswerTrains()) {
if (appletAnswerTrain.getUserId() == null) {
return AjaxResult.error("userId用户信息标识不能为空");
}
if (appletAnswerTrain.getQuestionId() == null) {
return AjaxResult.error("questionId标识不能为空");
}
ids.add(appletAnswerTrain.getQuestionId());
userId = appletAnswerTrain.getUserId();
}
//选删除之前的答案再去添加新的
LambdaQueryWrapper<AppletAnswerTrain> qwt = Wrappers.<AppletAnswerTrain>lambdaQuery()
.eq(AppletAnswerTrain::getUserId, userId)
.in(AppletAnswerTrain::getQuestionId, ids);
appletAnswerTrainMapper.delete(qwt);
// //选删除之前的答案再去添加新的
LambdaQueryWrapper<AppletAnswerBase> qw = Wrappers.<AppletAnswerBase>lambdaQuery()
.eq(AppletAnswerBase::getUserId, userId);
appletAnswerTrainService.saveBatch(answerSubmitBo.getAnswerTrains());
appletAnswerBaseService.remove(qw);
}
AppletUsersTeacher byId = appletUsersTeacherService.lambdaQuery()
.eq(AppletUsersTeacher::getUserId, userId).one();
//累计考试次数
if (ObjectUtils.isNotEmpty(byId)){
if (ObjectUtils.isNotEmpty(byId) && answerSubmitBo.getType() == 0){
Integer examNumber = byId.getExamNumber() == null ? 0 : byId.getExamNumber();
byId.setExamNumber(examNumber + 1);
byId.setExamTime(LocalDateTime.now());
appletUsersTeacherService.updateById(byId);
}
return toAjax(appletAnswerBaseService.saveBatch(answerSubmitBo.getAnswerBase()));
return toAjax(true);
}
@ApiOperation("伴宠师工作台-查询考试结果对象")
@ -271,55 +333,55 @@ public class ApiAppletExaminationController {
}
@ApiOperation("伴宠师工作台-查询用户培训考核答案列表")
@PostMapping("/answeTrainList")
public AjaxResult answeTrainList(@RequestBody AppletAnswerTrain answerTrain){
List<AppletAnswerTrain> answerTrainList = appletAnswerTrainService.selectAppletAnswerTrainList(answerTrain);
for (AppletAnswerTrain appletAnswerTrain : answerTrainList) {
AppletQuestion question = appletQuestionService.selectAppletQuestionById(appletAnswerTrain.getQuestionId());
appletAnswerTrain.setQuestion(question);
}
return AjaxResult.success("用户培训考核答案列表数据",answerTrainList);
}
// @ApiOperation("伴宠师工作台-查询用户培训考核答案列表")
// @PostMapping("/answeTrainList")
// public AjaxResult answeTrainList(@RequestBody AppletAnswerTrain answerTrain){
// List<AppletAnswerTrain> answerTrainList = appletAnswerTrainService.selectAppletAnswerTrainList(answerTrain);
//
// for (AppletAnswerTrain appletAnswerTrain : answerTrainList) {
// AppletQuestion question = appletQuestionService.selectAppletQuestionById(appletAnswerTrain.getQuestionId());
// appletAnswerTrain.setQuestion(question);
// }
//
// return AjaxResult.success("用户培训考核答案列表数据",answerTrainList);
// }
@ApiOperation("伴宠师工作台-根据题目id查询培训考核答案")
@GetMapping("/answeTrainByQuestionId")
public AjaxResult answeTrainByQuestionId(Long questionId, Long userId){
AppletAnswerTrain answerTrain = new AppletAnswerTrain();
answerTrain.setQuestionId(questionId);
answerTrain.setUserId(userId);
List<AppletAnswerTrain> answerTrainList = appletAnswerTrainService.selectAppletAnswerTrainList(answerTrain);
return AjaxResult.success("用户培训考核答案列表数据",answerTrainList);
}
@ApiOperation("伴宠师工作台-添加用户培训考核答案")
@PostMapping("/addTrainAnswer")
public AjaxResult addTrainAnswer(@RequestBody AppletAnswerTrain answerTrain){
if(answerTrain.getUserId() == null){
return AjaxResult.error("userId用户信息标识不能为空");
}
if(answerTrain.getQuestionId() == null){
return AjaxResult.error("questionId标识不能为空");
}
// //选删除之前的答案再去添加新的
LambdaQueryWrapper<AppletAnswerTrain> qw = Wrappers.<AppletAnswerTrain>lambdaQuery()
.eq(AppletAnswerTrain::getUserId, answerTrain.getUserId())
.eq(AppletAnswerTrain::getQuestionId, answerTrain.getQuestionId());
appletAnswerTrainMapper.delete(qw);
// @ApiOperation("伴宠师工作台-根据题目id查询培训考核答案")
// @GetMapping("/answeTrainByQuestionId")
// public AjaxResult answeTrainByQuestionId(Long questionId, Long userId){
// AppletAnswerTrain answerTrain = new AppletAnswerTrain();
// answerTrain.setQuestionId(questionId);
// answerTrain.setUserId(userId);
// List<AppletAnswerTrain> answerTrainList = appletAnswerTrainService.selectAppletAnswerTrainList(answerTrain);
//
// return AjaxResult.success("用户培训考核答案列表数据",answerTrainList);
// }
return toAjax(appletAnswerTrainService.insertAppletAnswerTrain(answerTrain));
}
// @ApiOperation("伴宠师工作台-添加用户培训考核答案")
// @PostMapping("/addTrainAnswer")
// public AjaxResult addTrainAnswer(@RequestBody AppletAnswerTrain answerTrain){
// if(answerTrain.getUserId() == null){
// return AjaxResult.error("userId用户信息标识不能为空");
// }
// if(answerTrain.getQuestionId() == null){
// return AjaxResult.error("questionId标识不能为空");
// }
//
//// //选删除之前的答案再去添加新的
// LambdaQueryWrapper<AppletAnswerTrain> qw = Wrappers.<AppletAnswerTrain>lambdaQuery()
// .eq(AppletAnswerTrain::getUserId, answerTrain.getUserId())
// .eq(AppletAnswerTrain::getQuestionId, answerTrain.getQuestionId());
//
// appletAnswerTrainMapper.delete(qw);
//
// return toAjax(appletAnswerTrainService.insertAppletAnswerTrain(answerTrain));
// }
//查询培训考核是否完成


+ 6
- 1
ruoyi-catdog/src/main/java/com/ruoyi/applet/pojo/dto/AppletAnswerSubmitBo.java View File

@ -1,6 +1,7 @@
package com.ruoyi.applet.pojo.dto;
import com.ruoyi.model.domain.AppletAnswerBase;
import com.ruoyi.model.domain.AppletAnswerTrain;
import lombok.Data;
import java.util.List;
@ -8,6 +9,10 @@ import java.util.List;
@Data
public class AppletAnswerSubmitBo {
private List<AppletAnswerBase> answerBase;
private List<AppletAnswerBase> answerBase;//基本考核用户答案
private List<AppletAnswerTrain> answerTrains;//培训考核答案
private Integer type;//0基本考试 1培训考核
}

+ 148
- 0
ruoyi-catdog/src/main/java/com/ruoyi/applet/transfer/TransferToUser.java View File

@ -0,0 +1,148 @@
package com.ruoyi.applet.transfer;
import com.google.gson.annotations.SerializedName;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.List;
import java.util.Map;
/**
* 发起转账
*/
@Slf4j
public class TransferToUser {
private final String mchid;
private final String certificateSerialNo;
private final PrivateKey privateKey;
private final String wechatPayPublicKeyId;
private final PublicKey wechatPayPublicKey;
public TransferToUser(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) {
this.mchid = mchid;
this.certificateSerialNo = certificateSerialNo;
this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);
this.wechatPayPublicKeyId = wechatPayPublicKeyId;
this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
}
public TransferToUserResponse run(TransferToUserRequest request, Map map) {
String uri = map.get("path").toString();
String host = map.get("host").toString();
String method = map.get("method").toString();
String reqBody = WXPayUtility.toJson(request);
Request.Builder reqBuilder = new Request.Builder().url(host + uri);
reqBuilder.addHeader("Accept", "application/json");
reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, method, uri, reqBody));
reqBuilder.addHeader("Content-Type", "application/json");
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
reqBuilder.method(method, requestBody);
Request httpRequest = reqBuilder.build();
// 发送HTTP请求
OkHttpClient client = new OkHttpClient.Builder().build();
try (Response httpResponse = client.newCall(httpRequest).execute()) {
String respBody = WXPayUtility.extractBody(httpResponse);
if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
// 2XX 成功验证应答签名
WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
httpResponse.headers(), respBody);
// 从HTTP应答报文构建返回数据
return WXPayUtility.fromJson(respBody, TransferToUserResponse.class);
} else {
throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
}
} catch (IOException e) {
throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
}
}
public String encrypt(String plainText) {
return WXPayUtility.encrypt(this.wechatPayPublicKey, plainText);
}
public static class TransferToUserResponse {
@SerializedName("out_bill_no")
public String outBillNo;
@SerializedName("transfer_bill_no")
public String transferBillNo;
@SerializedName("create_time")
public String createTime;
@SerializedName("state")
public TransferBillStatus state;
@SerializedName("package_info")
public String packageInfo;
}
public enum TransferBillStatus {
@SerializedName("ACCEPTED")
ACCEPTED,
@SerializedName("PROCESSING")
PROCESSING,
@SerializedName("WAIT_USER_CONFIRM")
WAIT_USER_CONFIRM,
@SerializedName("TRANSFERING")
TRANSFERING,
@SerializedName("SUCCESS")
SUCCESS,
@SerializedName("FAIL")
FAIL,
@SerializedName("CANCELING")
CANCELING,
@SerializedName("CANCELLED")
CANCELLED
}
public static class TransferSceneReportInfo {
@SerializedName("info_type")
public String infoType;
@SerializedName("info_content")
public String infoContent;
}
public static class TransferToUserRequest {
@SerializedName("appid")
public String appid;
@SerializedName("out_bill_no")
public String outBillNo;
@SerializedName("transfer_scene_id")
public String transferSceneId;
@SerializedName("openid")
public String openid;
@SerializedName("user_name")
public String userName;
@SerializedName("transfer_amount")
public Long transferAmount;
@SerializedName("transfer_remark")
public String transferRemark;
@SerializedName("notify_url")
public String notifyUrl;
@SerializedName("user_recv_perception")
public String userRecvPerception;
@SerializedName("transfer_scene_report_infos")
public List<TransferSceneReportInfo> transferSceneReportInfos;
}
}

+ 381
- 0
ruoyi-catdog/src/main/java/com/ruoyi/applet/transfer/WXPayUtility.java View File

@ -0,0 +1,381 @@
package com.ruoyi.applet.transfer;
import com.google.gson.*;
import com.google.gson.annotations.Expose;
import okhttp3.Headers;
import okhttp3.Response;
import okio.BufferedSource;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.time.DateTimeException;
import java.time.Duration;
import java.time.Instant;
import java.util.Base64;
import java.util.Map;
import java.util.Objects;
public class WXPayUtility {
private static final Gson gson = new GsonBuilder()
.disableHtmlEscaping()
.addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
final Expose expose = fieldAttributes.getAnnotation(Expose.class);
return expose != null && !expose.serialize();
}
@Override
public boolean shouldSkipClass(Class<?> aClass) {
return false;
}
})
.addDeserializationExclusionStrategy(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
final Expose expose = fieldAttributes.getAnnotation(Expose.class);
return expose != null && !expose.deserialize();
}
@Override
public boolean shouldSkipClass(Class<?> aClass) {
return false;
}
})
.create();
private static final char[] SYMBOLS =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
private static final SecureRandom random = new SecureRandom();
/**
* Object 转换为 JSON 字符串
*/
public static String toJson(Object object) {
return gson.toJson(object);
}
/**
* JSON 字符串解析为特定类型的实例
*/
public static <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
return gson.fromJson(json, classOfT);
}
/**
* 从公私钥文件路径中读取文件内容
*
* @param keyPath 文件路径
* @return 文件内容
*/
private static String readKeyStringFromPath(String keyPath) {
try {
return new String(Files.readAllBytes(Paths.get(keyPath)), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
/**
* 读取 PKCS#8 格式的私钥字符串并加载为私钥对象
*
* @param keyString 私钥文件内容 -----BEGIN PRIVATE KEY----- 开头
* @return PrivateKey 对象
*/
public static PrivateKey loadPrivateKeyFromString(String keyString) {
try {
keyString = keyString.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s+", "");
return KeyFactory.getInstance("RSA").generatePrivate(
new PKCS8EncodedKeySpec(Base64.getDecoder().decode(keyString)));
} catch (NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(e);
} catch (InvalidKeySpecException e) {
throw new IllegalArgumentException(e);
}
}
/**
* PKCS#8 格式的私钥文件中加载私钥
*
* @param keyPath 私钥文件路径
* @return PrivateKey 对象
*/
public static PrivateKey loadPrivateKeyFromPath(String keyPath) {
return loadPrivateKeyFromString(readKeyStringFromPath(keyPath));
}
/**
* 读取 PKCS#8 格式的公钥字符串并加载为公钥对象
*
* @param keyString 公钥文件内容 -----BEGIN PUBLIC KEY----- 开头
* @return PublicKey 对象
*/
public static PublicKey loadPublicKeyFromString(String keyString) {
try {
keyString = keyString.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "")
.replaceAll("\\s+", "");
return KeyFactory.getInstance("RSA").generatePublic(
new X509EncodedKeySpec(Base64.getDecoder().decode(keyString)));
} catch (NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(e);
} catch (InvalidKeySpecException e) {
throw new IllegalArgumentException(e);
}
}
/**
* PKCS#8 格式的公钥文件中加载公钥
*
* @param keyPath 公钥文件路径
* @return PublicKey 对象
*/
public static PublicKey loadPublicKeyFromPath(String keyPath) {
return loadPublicKeyFromString(readKeyStringFromPath(keyPath));
}
/**
* 创建指定长度的随机字符串字符集为[0-9a-zA-Z]可用于安全相关用途
*/
public static String createNonce(int length) {
char[] buf = new char[length];
for (int i = 0; i < length; ++i) {
buf[i] = SYMBOLS[random.nextInt(SYMBOLS.length)];
}
return new String(buf);
}
/**
* 使用公钥按照 RSA_PKCS1_OAEP_PADDING 算法进行加密
*
* @param publicKey 加密用公钥对象
* @param plaintext 待加密明文
* @return 加密后密文
*/
public static String encrypt(PublicKey publicKey, String plaintext) {
final String transformation = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
try {
Cipher cipher = Cipher.getInstance(transformation);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)));
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new IllegalArgumentException("The current Java environment does not support " + transformation, e);
} catch (InvalidKeyException e) {
throw new IllegalArgumentException("RSA encryption using an illegal publicKey", e);
} catch (BadPaddingException | IllegalBlockSizeException e) {
throw new IllegalArgumentException("Plaintext is too long", e);
}
}
/**
* 使用私钥按照指定算法进行签名
*
* @param message 待签名串
* @param algorithm 签名算法 SHA256withRSA
* @param privateKey 签名用私钥对象
* @return 签名结果
*/
public static String sign(String message, String algorithm, PrivateKey privateKey) {
byte[] sign;
try {
Signature signature = Signature.getInstance(algorithm);
signature.initSign(privateKey);
signature.update(message.getBytes(StandardCharsets.UTF_8));
sign = signature.sign();
} catch (NoSuchAlgorithmException e) {
throw new UnsupportedOperationException("The current Java environment does not support " + algorithm, e);
} catch (InvalidKeyException e) {
throw new IllegalArgumentException(algorithm + " signature uses an illegal privateKey.", e);
} catch (SignatureException e) {
throw new RuntimeException("An error occurred during the sign process.", e);
}
return Base64.getEncoder().encodeToString(sign);
}
/**
* 使用公钥按照特定算法验证签名
*
* @param message 待签名串
* @param signature 待验证的签名内容
* @param algorithm 签名算法SHA256withRSA
* @param publicKey 验签用公钥对象
* @return 签名验证是否通过
*/
public static boolean verify(String message, String signature, String algorithm,
PublicKey publicKey) {
try {
Signature sign = Signature.getInstance(algorithm);
sign.initVerify(publicKey);
sign.update(message.getBytes(StandardCharsets.UTF_8));
return sign.verify(Base64.getDecoder().decode(signature));
} catch (SignatureException e) {
return false;
} catch (InvalidKeyException e) {
throw new IllegalArgumentException("verify uses an illegal publickey.", e);
} catch (NoSuchAlgorithmException e) {
throw new UnsupportedOperationException("The current Java environment does not support" + algorithm, e);
}
}
/**
* 根据微信支付APIv3请求签名规则构造 Authorization 签名
*
* @param mchid 商户号
* @param certificateSerialNo 商户API证书序列号
* @param privateKey 商户API证书私钥
* @param method 请求接口的HTTP方法请使用全大写表述 GETPOSTPUTDELETE
* @param uri 请求接口的URL
* @param body 请求接口的Body
* @return 构造好的微信支付APIv3 Authorization
*/
public static String buildAuthorization(String mchid, String certificateSerialNo,
PrivateKey privateKey,
String method, String uri, String body) {
String nonce = createNonce(32);
long timestamp = Instant.now().getEpochSecond();
String message = String.format("%s\n%s\n%d\n%s\n%s\n", method, uri, timestamp, nonce,
body == null ? "" : body);
String signature = sign(message, "SHA256withRSA", privateKey);
return String.format(
"WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",signature=\"%s\"," +
"timestamp=\"%d\",serial_no=\"%s\"",
mchid, nonce, signature, timestamp, certificateSerialNo);
}
/**
* 对参数进行 URL 编码
*
* @param content 参数内容
* @return 编码后的内容
*/
public static String urlEncode(String content) {
try {
return URLEncoder.encode(content, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
/**
* 对参数Map进行 URL 编码生成 QueryString
*
* @param params Query参数Map
* @return QueryString
*/
public static String urlEncode(Map<String, Object> params) {
if (params == null || params.isEmpty()) {
return "";
}
int index = 0;
StringBuilder result = new StringBuilder();
for (Map.Entry<String, Object> entry : params.entrySet()) {
result.append(entry.getKey())
.append("=")
.append(urlEncode(entry.getValue().toString()));
index++;
if (index < params.size()) {
result.append("&");
}
}
return result.toString();
}
/**
* 从应答中提取 Body
*
* @param response HTTP 请求应答对象
* @return 应答中的Body内容Body为空时返回空字符串
*/
public static String extractBody(Response response) {
if (response.body() == null) {
return "";
}
try {
BufferedSource source = response.body().source();
return source.readUtf8();
} catch (IOException e) {
throw new RuntimeException(String.format("An error occurred during reading response body. Status: %d", response.code()), e);
}
}
/**
* 根据微信支付APIv3应答验签规则对应答签名进行验证验证不通过时抛出异常
*
* @param wechatpayPublicKeyId 微信支付公钥ID
* @param wechatpayPublicKey 微信支付公钥对象
* @param headers 微信支付应答 Header 列表
* @param body 微信支付应答 Body
*/
public static void validateResponse(String wechatpayPublicKeyId, PublicKey wechatpayPublicKey,
Headers headers,
String body) {
String timestamp = headers.get("Wechatpay-Timestamp");
try {
Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestamp));
// 拒绝过期请求
if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= 5) {
throw new IllegalArgumentException(
String.format("Validate http response,timestamp[%s] of httpResponse is expires, "
+ "request-id[%s]",
timestamp, headers.get("Request-ID")));
}
} catch (DateTimeException | NumberFormatException e) {
throw new IllegalArgumentException(
String.format("Validate http response,timestamp[%s] of httpResponse is invalid, " +
"request-id[%s]", timestamp,
headers.get("Request-ID")));
}
String message = String.format("%s\n%s\n%s\n", timestamp, headers.get("Wechatpay-Nonce"),
body == null ? "" : body);
String serialNumber = headers.get("Wechatpay-Serial");
if (!Objects.equals(serialNumber, wechatpayPublicKeyId)) {
throw new IllegalArgumentException(
String.format("Invalid Wechatpay-Serial, Local: %s, Remote: %s", wechatpayPublicKeyId,
serialNumber));
}
String signature = headers.get("Wechatpay-Signature");
boolean success = verify(message, signature, "SHA256withRSA", wechatpayPublicKey);
if (!success) {
throw new IllegalArgumentException(
String.format("Validate response failed,the WechatPay signature is incorrect.%n"
+ "Request-ID[%s]\tresponseHeader[%s]\tresponseBody[%.1024s]",
headers.get("Request-ID"), headers, body));
}
}
/**
* 微信支付API错误异常发送HTTP请求成功但返回状态码不是 2XX 时抛出本异常
*/
public static class ApiException extends RuntimeException {
public final int statusCode;
public final String body;
public final Headers headers;
public ApiException(int statusCode, String body, Headers headers) {
super(String.format("微信支付API访问失败,StatusCode: %s, Body: %s", statusCode, body));
this.statusCode = statusCode;
this.body = body;
this.headers = headers;
}
}
}

+ 4
- 0
ruoyi-catdog/src/main/java/com/ruoyi/model/domain/AppletAmountLog.java View File

@ -52,4 +52,8 @@ public class AppletAmountLog extends BaseEntity
/** 提现者姓名 */
@Excel(name = "提现者姓名")
private String nameValue;
/** 提现参数 */
@Excel(name = "提现参数")
private String packageInfo;
}

+ 3
- 49
ruoyi-catdog/src/main/java/com/ruoyi/model/domain/AppletIncrease.java View File

@ -1,5 +1,6 @@
package com.ruoyi.model.domain;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
@ -11,6 +12,7 @@ import com.ruoyi.common.core.domain.BaseEntity;
* @author ruoyi
* @date 2025-03-28
*/
@Data
public class AppletIncrease extends BaseEntity
{
private static final long serialVersionUID = 1L;
@ -29,54 +31,6 @@ public class AppletIncrease extends BaseEntity
/** 删除标识 */
private Integer delFlag;
public void setId(Long id)
{
this.id = id;
}
private String needCertificate;
public Long getId()
{
return id;
}
public void setTitle(String title)
{
this.title = title;
}
public String getTitle()
{
return title;
}
public void setDetail(String detail)
{
this.detail = detail;
}
public String getDetail()
{
return detail;
}
public void setDelFlag(Integer delFlag)
{
this.delFlag = delFlag;
}
public Integer getDelFlag()
{
return delFlag;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("title", getTitle())
.append("detail", getDetail())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

+ 4
- 61
ruoyi-catdog/src/main/java/com/ruoyi/model/domain/AppletQuestion.java View File

@ -38,9 +38,12 @@ public class AppletQuestion extends BaseEntity
/** 删除标识 */
private Integer delFlag;
/** 删除标识 */
/** 字数限制 */
private Integer numberWords;
/** 答题类型 0选这题 1填空题 */
private Integer typeAnswer;
@TableField(exist = false)
private List<AppletAnswer> answerList;
@ -52,64 +55,4 @@ public class AppletQuestion extends BaseEntity
@TableField(exist = false)
private AppletAnswerTrain userAppletAnswerTrain;
// public void setId(Long id)
// {
// this.id = id;
// }
//
// public Long getId()
// {
// return id;
// }
// public void setTitle(String title)
// {
// this.title = title;
// }
//
// public String getTitle()
// {
// return title;
// }
// public void setType(String type)
// {
// this.type = type;
// }
//
// public String getType()
// {
// return type;
// }
// public void setOrderNo(Long orderNo)
// {
// this.orderNo = orderNo;
// }
//
// public Long getOrderNo()
// {
// return orderNo;
// }
// public void setDelFlag(Integer delFlag)
// {
// this.delFlag = delFlag;
// }
//
// public Integer getDelFlag()
// {
// return delFlag;
// }
//
// @Override
// public String toString() {
// return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
// .append("id", getId())
// .append("title", getTitle())
// .append("type", getType())
// .append("orderNo", getOrderNo())
// .append("delFlag", getDelFlag())
// .append("createBy", getCreateBy())
// .append("createTime", getCreateTime())
// .append("updateBy", getUpdateBy())
// .append("updateTime", getUpdateTime())
// .toString();
// }
}

+ 3
- 1
ruoyi-catdog/src/main/java/com/ruoyi/model/mapper/AppletAmountLogMapper.java View File

@ -1,6 +1,8 @@
package com.ruoyi.model.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.model.domain.AppletAmountLog;
/**
@ -9,7 +11,7 @@ import com.ruoyi.model.domain.AppletAmountLog;
* @author ruoyi
* @date 2025-03-28
*/
public interface AppletAmountLogMapper
public interface AppletAmountLogMapper extends BaseMapper<AppletAmountLog>
{
/**
* 查询金额明细


+ 3
- 1
ruoyi-catdog/src/main/java/com/ruoyi/model/mapper/AppletIncreaseMapper.java View File

@ -1,6 +1,8 @@
package com.ruoyi.model.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.model.domain.AppletIncrease;
/**
@ -9,7 +11,7 @@ import com.ruoyi.model.domain.AppletIncrease;
* @author ruoyi
* @date 2025-03-28
*/
public interface AppletIncreaseMapper
public interface AppletIncreaseMapper extends BaseMapper<AppletIncrease>
{
/**
* 查询增值服务


+ 3
- 1
ruoyi-catdog/src/main/java/com/ruoyi/model/mapper/AppletQuestionMapper.java View File

@ -1,6 +1,8 @@
package com.ruoyi.model.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.model.domain.AppletQuestion;
/**
@ -9,7 +11,7 @@ import com.ruoyi.model.domain.AppletQuestion;
* @author ruoyi
* @date 2025-03-28
*/
public interface AppletQuestionMapper
public interface AppletQuestionMapper extends BaseMapper<AppletQuestion>
{
/**
* 查询考核题库


+ 4
- 1
ruoyi-catdog/src/main/java/com/ruoyi/model/service/IAppletAmountLogService.java View File

@ -1,6 +1,9 @@
package com.ruoyi.model.service;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.model.domain.AppletAmountLog;
/**
@ -9,7 +12,7 @@ import com.ruoyi.model.domain.AppletAmountLog;
* @author ruoyi
* @date 2025-03-28
*/
public interface IAppletAmountLogService
public interface IAppletAmountLogService extends IService<AppletAmountLog>
{
/**
* 查询金额明细


+ 3
- 1
ruoyi-catdog/src/main/java/com/ruoyi/model/service/IAppletIncreaseService.java View File

@ -1,6 +1,8 @@
package com.ruoyi.model.service;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.model.domain.AppletIncrease;
/**
@ -9,7 +11,7 @@ import com.ruoyi.model.domain.AppletIncrease;
* @author ruoyi
* @date 2025-03-28
*/
public interface IAppletIncreaseService
public interface IAppletIncreaseService extends IService<AppletIncrease>
{
/**
* 查询增值服务


+ 3
- 1
ruoyi-catdog/src/main/java/com/ruoyi/model/service/IAppletQuestionService.java View File

@ -1,6 +1,8 @@
package com.ruoyi.model.service;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.model.domain.AppletQuestion;
/**
@ -9,7 +11,7 @@ import com.ruoyi.model.domain.AppletQuestion;
* @author ruoyi
* @date 2025-03-28
*/
public interface IAppletQuestionService
public interface IAppletQuestionService extends IService<AppletQuestion>
{
/**
* 查询考核题库


+ 1
- 0
ruoyi-catdog/src/main/java/com/ruoyi/model/service/IAppletUsersTeacherService.java View File

@ -3,6 +3,7 @@ package com.ruoyi.model.service;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.model.domain.AppletQuestion;
import com.ruoyi.model.domain.AppletUsersTeacher;
/**


+ 6
- 2
ruoyi-catdog/src/main/java/com/ruoyi/model/service/impl/AppUsersServiceImpl.java View File

@ -225,8 +225,12 @@ public class AppUsersServiceImpl extends ServiceImpl<AppUsersMapper, AppUsers> i
// 4. 根据地址ID和技师等级查询符合条件的技师
qualifiedTechnicians = appUsersMapper.selectList(
Wrappers.<AppUsers>lambdaQuery()
.eq(ObjectUtils.isNotEmpty(filterVo.getCompanionLevel()),
AppUsers::getUserBcsRole, filterVo.getCompanionLevel())
.eq(ObjectUtils.isNotEmpty(filterVo.getCompanionLevel()),AppUsers::getUserBcsRole, filterVo.getCompanionLevel())
// .and(ObjectUtils.isNotEmpty(filterVo.getCompanionLevel()), n -> {
// n.eq(AppUsers::getUserBcsRole, filterVo.getCompanionLevel())
// .or()
// .in(filterVo.getCompanionLevel() == 0, AppUsers::getUserBcsRole, 1,2);
// })
.in(qualifiedUserId.size() > 0, AppUsers::getUserId, qualifiedUserId)
);
}


+ 3
- 1
ruoyi-catdog/src/main/java/com/ruoyi/model/service/impl/AppletAmountLogServiceImpl.java View File

@ -1,6 +1,8 @@
package com.ruoyi.model.service.impl;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -15,7 +17,7 @@ import com.ruoyi.model.service.IAppletAmountLogService;
* @date 2025-03-28
*/
@Service
public class AppletAmountLogServiceImpl implements IAppletAmountLogService
public class AppletAmountLogServiceImpl extends ServiceImpl<AppletAmountLogMapper, AppletAmountLog> implements IAppletAmountLogService
{
@Autowired
private AppletAmountLogMapper appletAmountLogMapper;


+ 3
- 1
ruoyi-catdog/src/main/java/com/ruoyi/model/service/impl/AppletIncreaseServiceImpl.java View File

@ -1,6 +1,8 @@
package com.ruoyi.model.service.impl;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -15,7 +17,7 @@ import com.ruoyi.model.service.IAppletIncreaseService;
* @date 2025-03-28
*/
@Service
public class AppletIncreaseServiceImpl implements IAppletIncreaseService
public class AppletIncreaseServiceImpl extends ServiceImpl<AppletIncreaseMapper, AppletIncrease> implements IAppletIncreaseService
{
@Autowired
private AppletIncreaseMapper appletIncreaseMapper;


+ 3
- 1
ruoyi-catdog/src/main/java/com/ruoyi/model/service/impl/AppletQuestionServiceImpl.java View File

@ -1,6 +1,8 @@
package com.ruoyi.model.service.impl;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.model.domain.AppletAnswer;
import com.ruoyi.model.mapper.AppletAnswerMapper;
@ -17,7 +19,7 @@ import com.ruoyi.model.service.IAppletQuestionService;
* @date 2025-03-28
*/
@Service
public class AppletQuestionServiceImpl implements IAppletQuestionService
public class AppletQuestionServiceImpl extends ServiceImpl<AppletQuestionMapper, AppletQuestion> implements IAppletQuestionService
{
@Autowired
private AppletQuestionMapper appletQuestionMapper;


+ 26
- 1
ruoyi-catdog/src/main/java/com/ruoyi/model/service/impl/AppletUsersTeacherServiceImpl.java View File

@ -2,6 +2,8 @@ package com.ruoyi.model.service.impl;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.model.domain.*;
@ -55,7 +57,7 @@ public class AppletUsersTeacherServiceImpl extends ServiceImpl<AppletUsersTeache
List<AppletAnswer> appletAnswers = appletAnswerMapper.selectAppletAnswerList(appletAnswer);
appletQuestion.setAnswerList(appletAnswers);
if(appletQuestion.getType().equals("基本")){
if(appletQuestion.getTypeAnswer() == 0){
AppletAnswerBase appletAnswerBase = new AppletAnswerBase();
appletAnswerBase.setQuestionId(appletQuestion.getId());
appletAnswerBase.setUserId(appletUsersTeacher.getUserId());
@ -141,6 +143,13 @@ public class AppletUsersTeacherServiceImpl extends ServiceImpl<AppletUsersTeache
@Override
public int deleteAppletUsersTeacherByIds(Long[] ids)
{
List<AppletUsersTeacher> list = lambdaQuery()
.in(AppletUsersTeacher::getId, ids).list();
for (AppletUsersTeacher teacher : list) {
deleteAnswerByUserId(teacher.getUserId());
}
return appletUsersTeacherMapper.deleteAppletUsersTeacherByIds(ids);
}
@ -153,6 +162,22 @@ public class AppletUsersTeacherServiceImpl extends ServiceImpl<AppletUsersTeache
@Override
public int deleteAppletUsersTeacherById(Long id)
{
AppletUsersTeacher byId = getById(id);
if (byId != null){
deleteAnswerByUserId(byId.getUserId());
}
return appletUsersTeacherMapper.deleteAppletUsersTeacherById(id);
}
public void deleteAnswerByUserId(Long userId){
LambdaQueryWrapper<AppletAnswerBase> qw = Wrappers.<AppletAnswerBase>lambdaQuery()
.eq(AppletAnswerBase::getUserId, userId);
appletAnswerBaseMapper.delete(qw);
LambdaQueryWrapper<AppletAnswerTrain> qw2 = Wrappers.<AppletAnswerTrain>lambdaQuery()
.eq(AppletAnswerTrain::getUserId, userId);
appletAnswerTrainMapper.delete(qw2);
}
}

+ 4
- 1
ruoyi-catdog/src/main/resources/mapper/model/AppletAmountLogMapper.xml View File

@ -18,10 +18,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="state" column="state"/>
<result property="moneyType" column="money_type"/>
<result property="nameValue" column="name_value"/>
<result property="packageInfo" column="package_info"/>
</resultMap>
<sql id="selectAppletAmountLogVo">
select id, title, amount, type, del_flag, create_by, create_time, update_by, update_time, user_id, state , money_type, name_value from applet_amount_log
select id, title, amount, type, del_flag, create_by, create_time, update_by, update_time, user_id, state , money_type, name_value
, package_info
from applet_amount_log
</sql>
<select id="selectAppletAmountLogList" parameterType="AppletAmountLog" resultMap="AppletAmountLogResult">


+ 3
- 1
ruoyi-catdog/src/main/resources/mapper/model/AppletIncreaseMapper.xml View File

@ -13,10 +13,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="needCertificate" column="need_certificate" />
</resultMap>
<sql id="selectAppletIncreaseVo">
select id, title, detail, del_flag, create_by, create_time, update_by, update_time from applet_increase
select id, title, detail, del_flag, create_by, create_time, update_by, update_time,
need_certificate from applet_increase
</sql>
<select id="selectAppletIncreaseList" parameterType="AppletIncrease" resultMap="AppletIncreaseResult">


+ 10
- 3
ruoyi-catdog/src/main/resources/mapper/model/AppletQuestionMapper.xml View File

@ -15,10 +15,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="typeAnswer" column="type_answer" />
</resultMap>
<sql id="selectAppletQuestionVo">
select id, title, type, order_no, del_flag,number_words, create_by, create_time, update_by, update_time from applet_question
select id, title, type, order_no, del_flag,number_words, create_by, create_time, update_by, update_time, type_answer from applet_question
</sql>
<select id="selectAppletQuestionList" parameterType="AppletQuestion" resultMap="AppletQuestionResult">
@ -28,8 +29,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="type != null and type != ''"> and type = #{type}</if>
<if test="orderNo != null "> and order_no = #{orderNo}</if>
<if test="numberWords != null "> and number_words = #{numberWords}</if>
<if test="typeAnswer != null "> and type_answer = #{typeAnswer}</if>
</where>
order by order_no desc
</select>
<select id="selectAppletQuestionById" parameterType="AppletQuestion" resultMap="AppletQuestionResult">
@ -45,11 +47,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="orderNo != null">order_no,</if>
<if test="delFlag != null">del_flag,</if>
<if test="numberWords != null">number_words,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="typeAnswer != null">type_answer,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="title != null and title != ''">#{title},</if>
@ -62,6 +65,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="typeAnswer != null">#{typeAnswer},</if>
</trim>
</insert>
@ -77,6 +82,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="typeAnswer != null">type_answer = #{typeAnswer},</if>
</trim>
where id = #{id}
</update>


Loading…
Cancel
Save