Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/activiti
Conflicts: yudao-dependencies/pom.xml yudao-framework/pom.xmlplp
commit
0050b1e46d
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Eslint config file
|
||||||
|
* Documentation: https://eslint.org/docs/user-guide/configuring/
|
||||||
|
* Install the Eslint extension before using this feature.
|
||||||
|
*/
|
||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
es6: true,
|
||||||
|
browser: true,
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
ecmaFeatures: {
|
||||||
|
modules: true,
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2018,
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
wx: true,
|
||||||
|
App: true,
|
||||||
|
Page: true,
|
||||||
|
getCurrentPages: true,
|
||||||
|
getApp: true,
|
||||||
|
Component: true,
|
||||||
|
requirePlugin: true,
|
||||||
|
requireMiniProgram: true,
|
||||||
|
},
|
||||||
|
// extends: 'eslint:recommended',
|
||||||
|
rules: {},
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
临时项目,作为测试微信小程序登陆之用
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
// app.js
|
||||||
|
App({
|
||||||
|
onLaunch() {
|
||||||
|
// 展示本地存储能力
|
||||||
|
const logs = wx.getStorageSync('logs') || []
|
||||||
|
logs.unshift(Date.now())
|
||||||
|
wx.setStorageSync('logs', logs)
|
||||||
|
|
||||||
|
// 登录
|
||||||
|
wx.login({
|
||||||
|
success: res => {
|
||||||
|
// 发送 res.code 到后台换取 openId, sessionKey, unionId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
globalData: {
|
||||||
|
userInfo: null
|
||||||
|
}
|
||||||
|
})
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"pages":[
|
||||||
|
"pages/index/index",
|
||||||
|
"pages/logs/logs"
|
||||||
|
],
|
||||||
|
"window":{
|
||||||
|
"backgroundTextStyle":"light",
|
||||||
|
"navigationBarBackgroundColor": "#fff",
|
||||||
|
"navigationBarTitleText": "Weixin",
|
||||||
|
"navigationBarTextStyle":"black"
|
||||||
|
},
|
||||||
|
"style": "v2",
|
||||||
|
"sitemapLocation": "sitemap.json"
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
/**app.wxss**/
|
||||||
|
.container {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 200rpx 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
<!--index.wxml-->
|
||||||
|
<view class="container">
|
||||||
|
<view class="userinfo">
|
||||||
|
<block wx:if="{{canIUseOpenData}}">
|
||||||
|
|
||||||
|
|
||||||
|
</block>
|
||||||
|
<block wx:elif="{{!hasUserInfo}}">
|
||||||
|
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
|
||||||
|
<button wx:elif="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
|
||||||
|
<view wx:else> 请使用1.4.4及以上版本基础库 </view>
|
||||||
|
</block>
|
||||||
|
<block wx:else>
|
||||||
|
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
|
||||||
|
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
<view class="usermotto">
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<text style="position: relative; left: 1rpx; top: -476rpx">授权登录测试1024</text>
|
||||||
|
|
||||||
|
<button style="position: relative; left: 0rpx; top: -361rpx" type="primary" id="login-button" bindtap="wxLogin">点击授权登录</button>
|
||||||
|
|
||||||
|
<text style="position: relative; left: 1rpx; top: -272rpx" id="login-user-id">{{holderText}}</text>
|
||||||
|
</view>
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
/**index.wxss**/
|
||||||
|
.userinfo {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userinfo-avatar {
|
||||||
|
overflow: hidden;
|
||||||
|
width: 128rpx;
|
||||||
|
height: 128rpx;
|
||||||
|
margin: 20rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.usermotto {
|
||||||
|
margin-top: 200px;
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
// logs.js
|
||||||
|
const util = require('../../utils/util.js')
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: {
|
||||||
|
logs: []
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.setData({
|
||||||
|
logs: (wx.getStorageSync('logs') || []).map(log => {
|
||||||
|
return {
|
||||||
|
date: util.formatTime(new Date(log)),
|
||||||
|
timeStamp: log
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"navigationBarTitleText": "查看启动日志",
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
<!--logs.wxml-->
|
||||||
|
<view class="container log-list">
|
||||||
|
<block wx:for="{{logs}}" wx:key="timeStamp" wx:for-item="log">
|
||||||
|
<text class="log-item">{{index + 1}}. {{log.date}}</text>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
.log-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 40rpx;
|
||||||
|
}
|
||||||
|
.log-item {
|
||||||
|
margin: 10rpx;
|
||||||
|
}
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"description": "项目配置文件",
|
||||||
|
"packOptions": {
|
||||||
|
"ignore": [
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"value": ".eslintrc.js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"setting": {
|
||||||
|
"bundle": false,
|
||||||
|
"userConfirmedBundleSwitch": false,
|
||||||
|
"urlCheck": true,
|
||||||
|
"scopeDataCheck": false,
|
||||||
|
"coverView": true,
|
||||||
|
"es6": true,
|
||||||
|
"postcss": true,
|
||||||
|
"compileHotReLoad": false,
|
||||||
|
"lazyloadPlaceholderEnable": false,
|
||||||
|
"preloadBackgroundData": false,
|
||||||
|
"minified": true,
|
||||||
|
"autoAudits": false,
|
||||||
|
"newFeature": false,
|
||||||
|
"uglifyFileName": false,
|
||||||
|
"uploadWithSourceMap": true,
|
||||||
|
"useIsolateContext": true,
|
||||||
|
"nodeModules": false,
|
||||||
|
"enhance": true,
|
||||||
|
"useMultiFrameRuntime": true,
|
||||||
|
"useApiHook": true,
|
||||||
|
"useApiHostProcess": true,
|
||||||
|
"showShadowRootInWxmlPanel": true,
|
||||||
|
"packNpmManually": false,
|
||||||
|
"enableEngineNative": false,
|
||||||
|
"packNpmRelationList": [],
|
||||||
|
"minifyWXSS": true,
|
||||||
|
"showES6CompileOption": false,
|
||||||
|
"minifyWXML": true
|
||||||
|
},
|
||||||
|
"compileType": "miniprogram",
|
||||||
|
"libVersion": "2.19.4",
|
||||||
|
"appid": "wx44d047d87e6284d8",
|
||||||
|
"appid1": "wx63c280fe3248a3e7",
|
||||||
|
"projectname": "mini-program-test",
|
||||||
|
"debugOptions": {
|
||||||
|
"hidedInDevtools": []
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"staticServerOptions": {
|
||||||
|
"baseURL": "",
|
||||||
|
"servePath": ""
|
||||||
|
},
|
||||||
|
"isGameTourist": false,
|
||||||
|
"condition": {
|
||||||
|
"search": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"conversation": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"plugin": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"gamePlugin": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"miniprogram": {
|
||||||
|
"list": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
|
||||||
|
"rules": [{
|
||||||
|
"action": "allow",
|
||||||
|
"page": "*"
|
||||||
|
}]
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
baseurl: "http://127.0.0.1:28080"
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
const formatTime = date => {
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = date.getMonth() + 1
|
||||||
|
const day = date.getDate()
|
||||||
|
const hour = date.getHours()
|
||||||
|
const minute = date.getMinutes()
|
||||||
|
const second = date.getSeconds()
|
||||||
|
|
||||||
|
return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatNumber = n => {
|
||||||
|
n = n.toString()
|
||||||
|
return n[1] ? n : `0${n}`
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
formatTime
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* 提供 POJO 类的实体转换
|
||||||
|
*
|
||||||
|
* 目前使用 MapStruct 框架
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.adminserver.modules.pay.convert;
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao>
|
||||||
@ -0,0 +1 @@
|
|||||||
|
package cn.iocoder.yudao.adminserver.modules.pay.job;
|
||||||
@ -1,55 +0,0 @@
|
|||||||
package cn.iocoder.yudao.adminserver.modules.system.enums.social;
|
|
||||||
|
|
||||||
import cn.hutool.core.collection.ListUtil;
|
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 社交平台的类型枚举
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@AllArgsConstructor
|
|
||||||
public enum SysSocialTypeEnum implements IntArrayValuable {
|
|
||||||
|
|
||||||
GITEE(10, "GITEE"), // https://gitee.com/api/v5/oauth_doc#/
|
|
||||||
DINGTALK(20, "DINGTALK"), // https://developers.dingtalk.com/document/app/obtain-identity-credentials
|
|
||||||
WECHAT_ENTERPRISE(30, "WECHAT_ENTERPRISE"), // https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html
|
|
||||||
;
|
|
||||||
|
|
||||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysSocialTypeEnum::getType).toArray();
|
|
||||||
|
|
||||||
public static final List<Integer> WECHAT_ALL = ListUtil.toList(WECHAT_ENTERPRISE.type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 类型
|
|
||||||
*/
|
|
||||||
private final Integer type;
|
|
||||||
/**
|
|
||||||
* 类型的标识
|
|
||||||
*/
|
|
||||||
private final String source;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] array() {
|
|
||||||
return ARRAYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SysSocialTypeEnum valueOfType(Integer type) {
|
|
||||||
return ArrayUtil.firstMatch(o -> o.getType().equals(type), values());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Integer> getRelationTypes(Integer type) {
|
|
||||||
if (WECHAT_ALL.contains(type)) {
|
|
||||||
return WECHAT_ALL;
|
|
||||||
}
|
|
||||||
return ListUtil.toList(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo;
|
package cn.iocoder.yudao.coreservice.modules.infra.controller.file.vo;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.iocoder.yudao.adminserver.modules.infra.framework.file.config;
|
package cn.iocoder.yudao.coreservice.modules.infra.framework.file.config;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.iocoder.yudao.adminserver.modules.infra.framework.file.config;
|
package cn.iocoder.yudao.coreservice.modules.infra.framework.file.config;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.infra.service.file.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.FileTypeUtil;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.file.InfFileCoreMapper;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.infra.framework.file.config.FileProperties;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.*;
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* core service 文件实现类
|
||||||
|
*
|
||||||
|
* @author 宋天
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class InfFileCoreServiceImpl implements InfFileCoreService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private InfFileCoreMapper fileMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FileProperties fileProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String createFile(String path, byte[] content) {
|
||||||
|
if (fileMapper.selectCountById(path) > 0) {
|
||||||
|
throw exception(FILE_PATH_EXISTS);
|
||||||
|
}
|
||||||
|
// 保存到数据库
|
||||||
|
InfFileDO file = new InfFileDO();
|
||||||
|
file.setId(path);
|
||||||
|
file.setType(FileTypeUtil.getType(new ByteArrayInputStream(content)));
|
||||||
|
file.setContent(content);
|
||||||
|
fileMapper.insert(file);
|
||||||
|
// 拼接路径返回
|
||||||
|
return fileProperties.getBasePath() + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteFile(String id) {
|
||||||
|
// 校验存在
|
||||||
|
this.validateFileExists(id);
|
||||||
|
// 更新
|
||||||
|
fileMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateFileExists(String id) {
|
||||||
|
if (fileMapper.selectById(id) == null) {
|
||||||
|
throw exception(FILE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InfFileDO getFile(String path) {
|
||||||
|
return fileMapper.selectById(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.convert.order;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
|
||||||
|
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface PayOrderCoreConvert {
|
||||||
|
|
||||||
|
PayOrderCoreConvert INSTANCE = Mappers.getMapper(PayOrderCoreConvert.class);
|
||||||
|
|
||||||
|
PayOrderDO convert(PayOrderCreateReqDTO bean);
|
||||||
|
|
||||||
|
PayOrderExtensionDO convert(PayOrderSubmitReqDTO bean);
|
||||||
|
|
||||||
|
PayOrderUnifiedReqDTO convert2(PayOrderSubmitReqDTO bean);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* 提供 POJO 类的实体转换
|
||||||
|
*
|
||||||
|
* 目前使用 MapStruct 框架
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.convert;
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao>
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface PayAppCoreMapper extends BaseMapperX<PayAppDO> {
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface PayChannelCoreMapper extends BaseMapperX<PayChannelDO> {
|
||||||
|
|
||||||
|
default PayChannelDO selectByAppIdAndCode(Long appId, String code) {
|
||||||
|
return selectOne("app_id", appId, "code", code);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Select("SELECT id FROM pay_channel WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||||
|
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyLogDO;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface PayNotifyLogCoreMapper extends BaseMapperX<PayNotifyLogDO> {
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface PayOrderCoreMapper extends BaseMapperX<PayOrderDO> {
|
||||||
|
|
||||||
|
default PayOrderDO selectByAppIdAndMerchantOrderId(Long appId, String merchantOrderId) {
|
||||||
|
return selectOne(new QueryWrapper<PayOrderDO>().eq("app_id", appId)
|
||||||
|
.eq("merchant_order_id", merchantOrderId));
|
||||||
|
}
|
||||||
|
|
||||||
|
default int updateByIdAndStatus(Long id, Integer status, PayOrderDO update) {
|
||||||
|
return update(update, new QueryWrapper<PayOrderDO>()
|
||||||
|
.eq("id", id).eq("status", status));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface PayOrderExtensionCoreMapper extends BaseMapperX<PayOrderExtensionDO> {
|
||||||
|
|
||||||
|
default PayOrderExtensionDO selectByNo(String no) {
|
||||||
|
return selectOne("no", no);
|
||||||
|
}
|
||||||
|
|
||||||
|
default int updateByIdAndStatus(Long id, Integer status, PayOrderExtensionDO update) {
|
||||||
|
return update(update, new QueryWrapper<PayOrderExtensionDO>()
|
||||||
|
.eq("id", id).eq("status", status));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.dal.redis;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
|
||||||
|
import org.redisson.api.RLock;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.HASH;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock4j Redis Key 枚举类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface PayRedisKeyCoreConstants {
|
||||||
|
|
||||||
|
RedisKeyDefine PAY_NOTIFY_LOCK = new RedisKeyDefine("通知任务的分布式锁",
|
||||||
|
"pay_notify:lock:", // 参数来自 DefaultLockKeyBuilder 类
|
||||||
|
HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.dal.redis.notify;
|
||||||
|
|
||||||
|
import org.redisson.api.RLock;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.coreservice.modules.pay.dal.redis.PayRedisKeyCoreConstants.PAY_NOTIFY_LOCK;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付通知的锁 Redis DAO
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public class PayNotifyLockCoreRedisDAO {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedissonClient redissonClient;
|
||||||
|
|
||||||
|
public void lock(Long id, Long timeoutMillis, Runnable runnable) {
|
||||||
|
String lockKey = formatKey(id);
|
||||||
|
RLock lock = redissonClient.getLock(lockKey);
|
||||||
|
try {
|
||||||
|
lock.lock(timeoutMillis, TimeUnit.MILLISECONDS);
|
||||||
|
// 执行逻辑
|
||||||
|
runnable.run();
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatKey(Long id) {
|
||||||
|
return String.format(PAY_NOTIFY_LOCK.getKeyTemplate(), id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.enums.notify;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付通知状态枚举
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum PayNotifyStatusEnum {
|
||||||
|
|
||||||
|
WAITING(1, "等待通知"),
|
||||||
|
SUCCESS(2, "通知成功"),
|
||||||
|
FAILURE(3, "通知失败"), // 多次尝试,彻底失败
|
||||||
|
REQUEST_SUCCESS(4, "请求成功,但是结果失败"),
|
||||||
|
REQUEST_FAILURE(5, "请求失败"),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*/
|
||||||
|
private final Integer status;
|
||||||
|
/**
|
||||||
|
* 名字
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.enums.notify;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付通知类型
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum PayNotifyTypeEnum {
|
||||||
|
|
||||||
|
ORDER(1, "支付单"),
|
||||||
|
REFUND(2, "退款单"),
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final Integer type;
|
||||||
|
/**
|
||||||
|
* 名字
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.enums.order;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付订单的通知状态枚举
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum PayOrderNotifyStatusEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
NO(0, "未通知"),
|
||||||
|
SUCCESS(10, "通知成功"),
|
||||||
|
FAILURE(20, "通知失败")
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Integer status;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.enums.order;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付订单的退款状态枚举
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum PayOrderRefundStatusEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
NO(0, "未退款"),
|
||||||
|
SOME(10, "部分退款"),
|
||||||
|
ALL(20, "全部退款")
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Integer status;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.enums.order;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付订单的状态枚举
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum PayOrderStatusEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
WAITING(0, "未支付"),
|
||||||
|
SUCCESS(10, "支付成功"),
|
||||||
|
CLOSED(20, "支付关闭"), // 未付款交易超时关闭,或支付完成后全额退款 TODO 芋艿:需要优化下
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Integer status;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.service.merchant.impl;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant.PayAppCoreMapper;
|
||||||
|
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService;
|
||||||
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付应用 Core Service 实现类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Valid
|
||||||
|
@Slf4j
|
||||||
|
public class PayAppCoreServiceImpl implements PayAppCoreService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PayAppCoreMapper payAppCoreMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PayAppDO validPayApp(Long id) {
|
||||||
|
PayAppDO app = payAppCoreMapper.selectById(id);
|
||||||
|
// 校验是否存在
|
||||||
|
if (app == null) {
|
||||||
|
throw exception(PAY_APP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
// 校验是否禁用
|
||||||
|
if (CommonStatusEnum.DISABLE.getStatus().equals(app.getStatus())) {
|
||||||
|
throw exception(PAY_APP_IS_DISABLE);
|
||||||
|
}
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付通知创建 DTO
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PayNotifyTaskCreateReqDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
@NotNull(message = "类型不能为空")
|
||||||
|
private Integer type;
|
||||||
|
/**
|
||||||
|
* 数据编号
|
||||||
|
*/
|
||||||
|
@NotNull(message = "数据编号不能为空")
|
||||||
|
private Long dataId;
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue