add 付费资源

This commit is contained in:
王鹏
2025-12-05 14:18:36 +08:00
parent de0fea0dbd
commit c390e4a033
8 changed files with 124 additions and 19 deletions

View File

@@ -19,6 +19,8 @@ public class CreateOrderReq {
private Long points; private Long points;
private Long resourceId;
public Long getUserId() { public Long getUserId() {
return userId; return userId;
} }
@@ -42,4 +44,12 @@ public class CreateOrderReq {
public void setPoints(Long points) { public void setPoints(Long points) {
this.points = points; this.points = points;
} }
public Long getResourceId() {
return resourceId;
}
public void setResourceId(Long resourceId) {
this.resourceId = resourceId;
}
} }

View File

@@ -79,6 +79,17 @@ public class AppBlogArticle extends BaseEntity
private List<String> picList; private List<String> picList;
/** 关联的资源对象 */
private AppResource appResource;
public AppResource getAppResource() {
return appResource;
}
public void setAppResource(AppResource appResource) {
this.appResource = appResource;
}
public String getOrderType() { public String getOrderType() {
return orderType; return orderType;
} }

View File

@@ -32,6 +32,10 @@ public class AppPayOrder extends BaseEntity
@Excel(name = "用户ID") @Excel(name = "用户ID")
private Long userId; private Long userId;
/** 资源ID */
@Excel(name = "资源ID")
private Long resourceId;
/** openid */ /** openid */
@Excel(name = "openid") @Excel(name = "openid")
private String openId; private String openId;
@@ -135,6 +139,14 @@ public class AppPayOrder extends BaseEntity
return payTime; return payTime;
} }
public Long getResourceId() {
return resourceId;
}
public void setResourceId(Long resourceId) {
this.resourceId = resourceId;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -142,6 +154,7 @@ public class AppPayOrder extends BaseEntity
.append("orderNo", getOrderNo()) .append("orderNo", getOrderNo())
.append("tradeNo", getTradeNo()) .append("tradeNo", getTradeNo())
.append("userId", getUserId()) .append("userId", getUserId())
.append("resourceId", getResourceId())
.append("openId", getOpenId()) .append("openId", getOpenId())
.append("amount", getAmount()) .append("amount", getAmount())
.append("points", getPoints()) .append("points", getPoints())

View File

@@ -4,8 +4,10 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ruoyi.app.domain.AppIntegralRecord; import com.ruoyi.app.domain.AppIntegralRecord;
import com.ruoyi.app.domain.AppPayOrder; import com.ruoyi.app.domain.AppPayOrder;
import com.ruoyi.app.domain.AppResource;
import com.ruoyi.app.mapper.AppIntegralRecordMapper; import com.ruoyi.app.mapper.AppIntegralRecordMapper;
import com.ruoyi.app.mapper.AppPayOrderMapper; import com.ruoyi.app.mapper.AppPayOrderMapper;
import com.ruoyi.app.mapper.AppResourceMapper;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.OrderNoGenerator; import com.ruoyi.common.utils.OrderNoGenerator;
import com.ruoyi.common.wx.*; import com.ruoyi.common.wx.*;
@@ -59,6 +61,8 @@ public class WxMiniappPayServiceImpl implements WxMiniappPayService {
@Autowired @Autowired
private SysUserMapper sysUserMapper; private SysUserMapper sysUserMapper;
@Autowired @Autowired
private AppResourceMapper appResourceMapper;
@Autowired
private AppPayOrderMapper appPayOrderMapper; private AppPayOrderMapper appPayOrderMapper;
@Autowired @Autowired
private AppIntegralRecordMapper appIntegralRecordMapper; private AppIntegralRecordMapper appIntegralRecordMapper;
@@ -72,13 +76,21 @@ public class WxMiniappPayServiceImpl implements WxMiniappPayService {
@Override @Override
public Response createOrder(CreateOrderReq req) { public Response createOrder(CreateOrderReq req) {
SysUser sysUser = sysUserMapper.selectUserById(req.getUserId()); SysUser sysUser = sysUserMapper.selectUserById(req.getUserId());
AppResource appResource = null;
if (!Objects.isNull(req.getResourceId())) {
appResource = appResourceMapper.selectAppResourceById(req.getResourceId());
}
String openId = sysUser.getUserName(); String openId = sysUser.getUserName();
String orderNo = OrderNoGenerator.generatePayOrderNo(); String orderNo = OrderNoGenerator.generatePayOrderNo();
// 创建本地订单 // 创建本地订单
// 这里做本地业务相关的处理,包括生成一个订单号传递给微信,等于通过这个值来形成两边的数据对应。后续微信那边会返回他们的订单编号,也建议存在自己这边的数据库里。 // 这里做本地业务相关的处理,包括生成一个订单号传递给微信,等于通过这个值来形成两边的数据对应。后续微信那边会返回他们的订单编号,也建议存在自己这边的数据库里。
PayOrderInfo order = new PayOrderInfo(); PayOrderInfo order = new PayOrderInfo();
order.setOutTradeNo(orderNo); order.setOutTradeNo(orderNo);
if (Objects.isNull(appResource)) {
order.setDescription("积分充值"); order.setDescription("积分充值");
} else {
order.setDescription("购买资源:" + appResource.getResourceTitle());
}
order.setAmount(new BigDecimal(req.getAmount())); order.setAmount(new BigDecimal(req.getAmount()));
// 请求微信支付相关配置 // 请求微信支付相关配置
@@ -127,19 +139,20 @@ public class WxMiniappPayServiceImpl implements WxMiniappPayService {
} }
// 保存订单信息 // 保存订单信息
saveOrder(orderNo, req.getAmount(), req.getPoints(), req.getUserId(), openId); saveOrder(orderNo, req.getAmount(), req.getPoints(), req.getUserId(), req.getResourceId(), openId);
return Response.success(response); return Response.success(response);
} }
private void saveOrder(String orderNo, Long amount, Long points, Long userId, String openId) { private void saveOrder(String orderNo, Long amount, Long points, Long userId, Long resourceId, String openId) {
AppPayOrder order = appPayOrderMapper.selectAppPayOrderByOrderNo(orderNo); AppPayOrder order = appPayOrderMapper.selectAppPayOrderByOrderNo(orderNo);
if(Objects.isNull(order)){ if (Objects.isNull(order)) {
order = new AppPayOrder(); order = new AppPayOrder();
} }
order.setOrderNo(orderNo); order.setOrderNo(orderNo);
order.setAmount(amount); order.setAmount(amount);
order.setPoints(points); order.setPoints(points);
order.setUserId(userId); order.setUserId(userId);
order.setResourceId(resourceId);
order.setOpenId(openId); order.setOpenId(openId);
order.setStatus(0); order.setStatus(0);
order.setCreateTime(new Date()); order.setCreateTime(new Date());
@@ -221,7 +234,9 @@ public class WxMiniappPayServiceImpl implements WxMiniappPayService {
order.setPayTime(new Date()); order.setPayTime(new Date());
appPayOrderMapper.updateAppPayOrder(order); appPayOrderMapper.updateAppPayOrder(order);
// 更新充值积分 // 更新充值积分
if (order.getPoints() != 0) {
updateUserPoints(order.getUserId(), order.getPoints()); updateUserPoints(order.getUserId(), order.getPoints());
}
returnMap.put("code", "SUCCESS"); returnMap.put("code", "SUCCESS");
returnMap.put("message", "成功"); returnMap.put("message", "成功");
@@ -234,6 +249,7 @@ public class WxMiniappPayServiceImpl implements WxMiniappPayService {
if (sysUser == null) { if (sysUser == null) {
throw new RuntimeException("用户不存在"); throw new RuntimeException("用户不存在");
} }
AppIntegralRecord appIntegralRecord = new AppIntegralRecord(); AppIntegralRecord appIntegralRecord = new AppIntegralRecord();
appIntegralRecord.setUserId(userId); appIntegralRecord.setUserId(userId);
appIntegralRecord.setIntegralNumber(points); appIntegralRecord.setIntegralNumber(points);
@@ -241,6 +257,7 @@ public class WxMiniappPayServiceImpl implements WxMiniappPayService {
appIntegralRecord.setIsAdd(0L); appIntegralRecord.setIsAdd(0L);
appIntegralRecord.setIntegralTime(new Date()); appIntegralRecord.setIntegralTime(new Date());
appIntegralRecordMapper.insertAppIntegralRecord(appIntegralRecord); appIntegralRecordMapper.insertAppIntegralRecord(appIntegralRecord);
// 更新用户积分
sysUser.setIntegral(sysUser.getIntegral() + points.intValue()); sysUser.setIntegral(sysUser.getIntegral() + points.intValue());
sysUserMapper.updateUser(sysUser); sysUserMapper.updateUser(sysUser);
} }

View File

@@ -25,25 +25,65 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="weight" column="weight" /> <result property="weight" column="weight" />
</resultMap> </resultMap>
<resultMap type="AppBlogArticle" id="AppBlogArticleWithResourceResult" extends="AppBlogArticleResult">
<association property="appResource" javaType="AppResource">
<id property="id" column="resource_id" />
<result property="resourceTitle" column="resource_title" />
<result property="showImg" column="resource_show_img" />
<result property="explain" column="resource_explain" />
<result property="resourceType" column="resource_type" />
<result property="keyword" column="resource_keyword" />
<result property="isShow" column="resource_is_show" />
<result property="isAd" column="resource_is_ad" />
<result property="adNumber" column="resource_ad_number" />
<result property="downNum" column="resource_down_num" />
<result property="weight" column="resource_weight" />
<result property="delFlag" column="resource_del_flag" />
<result property="createBy" column="resource_create_by" />
<result property="createTime" column="resource_create_time" />
<result property="remark" column="resource_remark" />
</association>
</resultMap>
<sql id="selectAppBlogArticleVo"> <sql id="selectAppBlogArticleVo">
select id, title, content_info, article_type, keyword, show_img, app_resource_id, look_number, weight, love_number, is_recommendation, is_show, is_ad, ad_number, del_flag, create_by, create_time, remark from app_blog_article select id, title, content_info, article_type, keyword, show_img, app_resource_id, look_number, weight, love_number, is_recommendation, is_show, is_ad, ad_number, del_flag, create_by, create_time, remark from app_blog_article
</sql> </sql>
<select id="selectAppBlogArticleList" parameterType="AppBlogArticle" resultMap="AppBlogArticleResult"> <select id="selectAppBlogArticleList" parameterType="AppBlogArticle" resultMap="AppBlogArticleWithResourceResult">
<include refid="selectAppBlogArticleVo"/> select
a.id, a.title, a.content_info, a.article_type, a.keyword, a.show_img, a.app_resource_id,
a.look_number, a.weight, a.love_number, a.is_recommendation, a.is_show, a.is_ad,
a.ad_number, a.del_flag, a.create_by, a.create_time, a.remark,
r.id as resource_id,
r.resource_title,
r.show_img as resource_show_img,
r.explain as resource_explain,
r.resource_type,
r.keyword as resource_keyword,
r.is_show as resource_is_show,
r.is_ad as resource_is_ad,
r.ad_number as resource_ad_number,
r.down_num as resource_down_num,
r.weight as resource_weight,
r.del_flag as resource_del_flag,
r.create_by as resource_create_by,
r.create_time as resource_create_time,
r.remark as resource_remark
from app_blog_article a
left join app_resource r on a.app_resource_id = r.id
<where> <where>
<if test="title != null and title != ''"> and title like concat('%', #{title}, '%')</if> <if test="title != null and title != ''"> and a.title like concat('%', #{title}, '%')</if>
<if test="contentInfo != null and contentInfo != ''"> and content_info like concat('%', #{contentInfo}, '%')</if> <if test="contentInfo != null and contentInfo != ''"> and a.content_info like concat('%', #{contentInfo}, '%')</if>
<if test="articleType != null "> and article_type = #{articleType}</if> <if test="articleType != null "> and a.article_type = #{articleType}</if>
<if test="appResourceId != null "> and app_resource_id = #{appResourceId}</if> <if test="appResourceId != null "> and a.app_resource_id = #{appResourceId}</if>
<if test="isRecommendation != null "> and is_recommendation = #{isRecommendation}</if> <if test="isRecommendation != null "> and a.is_recommendation = #{isRecommendation}</if>
<if test="isShow != null "> and is_show = #{isShow}</if> <if test="isShow != null "> and a.is_show = #{isShow}</if>
<if test="weight != null "> and weight = #{weight}</if> <if test="weight != null "> and a.weight = #{weight}</if>
<if test="keyword != null and keyword != ''"> and (keyword like concat('%', #{keyword}, '%') or title like concat('%', #{keyword}, '%'))</if> <if test="keyword != null and keyword != ''"> and (a.keyword like concat('%', #{keyword}, '%') or a.title like concat('%', #{keyword}, '%'))</if>
</where> </where>
<choose> <choose>
<when test="orderType == 'look_number'"> ORDER BY look_number desc, create_time desc</when > <when test="orderType == 'look_number'"> ORDER BY a.look_number desc, a.create_time desc</when >
<otherwise> ORDER BY weight desc, create_time desc</otherwise > <otherwise> ORDER BY a.weight desc, a.create_time desc</otherwise >
</choose> </choose>
</select> </select>

View File

@@ -9,6 +9,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="orderNo" column="order_no" /> <result property="orderNo" column="order_no" />
<result property="tradeNo" column="trade_no" /> <result property="tradeNo" column="trade_no" />
<result property="userId" column="user_id" /> <result property="userId" column="user_id" />
<result property="resourceId" column="resource_id" />
<result property="openId" column="open_id" /> <result property="openId" column="open_id" />
<result property="amount" column="amount" /> <result property="amount" column="amount" />
<result property="points" column="points" /> <result property="points" column="points" />
@@ -18,7 +19,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap> </resultMap>
<sql id="selectAppPayOrderVo"> <sql id="selectAppPayOrderVo">
select id, order_no, trade_no, user_id, open_id, amount, points, status, create_time, pay_time from app_pay_order select id, order_no, trade_no, user_id, resource_id, open_id, amount, points, status, create_time, pay_time from app_pay_order
</sql> </sql>
<select id="selectAppPayOrderList" parameterType="AppPayOrder" resultMap="AppPayOrderResult"> <select id="selectAppPayOrderList" parameterType="AppPayOrder" resultMap="AppPayOrderResult">
@@ -49,6 +50,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="orderNo != null and orderNo != ''">order_no,</if> <if test="orderNo != null and orderNo != ''">order_no,</if>
<if test="tradeNo != null and tradeNo != ''">trade_no,</if> <if test="tradeNo != null and tradeNo != ''">trade_no,</if>
<if test="userId != null">user_id,</if> <if test="userId != null">user_id,</if>
<if test="resourceId != null">resource_id,</if>
<if test="openId != null and openId != ''">open_id,</if> <if test="openId != null and openId != ''">open_id,</if>
<if test="amount != null">amount,</if> <if test="amount != null">amount,</if>
<if test="points != null">points,</if> <if test="points != null">points,</if>
@@ -60,6 +62,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="orderNo != null and orderNo != ''">#{orderNo},</if> <if test="orderNo != null and orderNo != ''">#{orderNo},</if>
<if test="tradeNo != null and tradeNo != ''">#{tradeNo},</if> <if test="tradeNo != null and tradeNo != ''">#{tradeNo},</if>
<if test="userId != null">#{userId},</if> <if test="userId != null">#{userId},</if>
<if test="resourceId != null">#{resourceId},</if>
<if test="openId != null and openId != ''">#{openId},</if> <if test="openId != null and openId != ''">#{openId},</if>
<if test="amount != null">#{amount},</if> <if test="amount != null">#{amount},</if>
<if test="points != null">#{points},</if> <if test="points != null">#{points},</if>
@@ -75,6 +78,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="orderNo != null and orderNo != ''">order_no = #{orderNo},</if> <if test="orderNo != null and orderNo != ''">order_no = #{orderNo},</if>
<if test="tradeNo != null and tradeNo != ''">trade_no = #{tradeNo},</if> <if test="tradeNo != null and tradeNo != ''">trade_no = #{tradeNo},</if>
<if test="userId != null">user_id = #{userId},</if> <if test="userId != null">user_id = #{userId},</if>
<if test="resourceId != null">resource_id = #{resourceId},</if>
<if test="openId != null and openId != ''">open_id = #{openId},</if> <if test="openId != null and openId != ''">open_id = #{openId},</if>
<if test="amount != null">amount = #{amount},</if> <if test="amount != null">amount = #{amount},</if>
<if test="points != null">points = #{points},</if> <if test="points != null">points = #{points},</if>

View File

@@ -109,6 +109,7 @@
<el-table-column label="商户单号" align="center" prop="orderNo" /> <el-table-column label="商户单号" align="center" prop="orderNo" />
<el-table-column label="交易单号" align="center" prop="tradeNo" /> <el-table-column label="交易单号" align="center" prop="tradeNo" />
<el-table-column label="用户ID" align="center" prop="userId" /> <el-table-column label="用户ID" align="center" prop="userId" />
<el-table-column label="资源ID" align="center" prop="resourceId" />
<el-table-column label="openid" align="center" prop="openId" /> <el-table-column label="openid" align="center" prop="openId" />
<el-table-column label="支付金额(元)" align="center" prop="amount" /> <el-table-column label="支付金额(元)" align="center" prop="amount" />
<el-table-column label="积分数量" align="center" prop="points" /> <el-table-column label="积分数量" align="center" prop="points" />
@@ -162,6 +163,9 @@
<el-form-item label="用户ID" prop="userId"> <el-form-item label="用户ID" prop="userId">
<el-input v-model="form.userId" placeholder="请输入用户ID" /> <el-input v-model="form.userId" placeholder="请输入用户ID" />
</el-form-item> </el-form-item>
<el-form-item label="资源ID" prop="resourceId">
<el-input v-model="form.resourceId" placeholder="请输入资源ID" />
</el-form-item>
<el-form-item label="openid" prop="openId"> <el-form-item label="openid" prop="openId">
<el-input v-model="form.openId" placeholder="请输入openid" /> <el-input v-model="form.openId" placeholder="请输入openid" />
</el-form-item> </el-form-item>
@@ -291,6 +295,7 @@ export default {
orderNo: null, orderNo: null,
tradeNo: null, tradeNo: null,
userId: null, userId: null,
resourceId: null,
openId: null, openId: null,
amount: null, amount: null,
points: null, points: null,

View File

@@ -67,6 +67,7 @@
<el-tag v-if="scope.row.isAd == 0" type="success">免费</el-tag> <el-tag v-if="scope.row.isAd == 0" type="success">免费</el-tag>
<el-tag v-if="scope.row.isAd == 1" type="info">看广告</el-tag> <el-tag v-if="scope.row.isAd == 1" type="info">看广告</el-tag>
<el-tag v-if="scope.row.isAd == 2" type="danger">积分兑换</el-tag> <el-tag v-if="scope.row.isAd == 2" type="danger">积分兑换</el-tag>
<el-tag v-if="scope.row.isAd == 3" type="warning">付费</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="兑换积分" align="center" prop="adNumber"> <el-table-column label="兑换积分" align="center" prop="adNumber">
@@ -126,12 +127,16 @@
<el-radio :label="0">免费</el-radio> <el-radio :label="0">免费</el-radio>
<el-radio :label="1">看广告</el-radio> <el-radio :label="1">看广告</el-radio>
<el-radio :label="2">积分兑换</el-radio> <el-radio :label="2">积分兑换</el-radio>
<el-radio :label="3">付费</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item v-if="form.isAd == 2" label="兑换积分" prop="adNumber"> <el-form-item v-if="form.isAd == 2" label="兑换积分" prop="adNumber">
<el-input v-model="form.adNumber" placeholder="请输入需要兑换多少积分解锁" /> <el-input v-model="form.adNumber" placeholder="请输入需要兑换多少积分解锁" />
</el-form-item> </el-form-item>
<el-form-item v-if="form.isAd == 3" label="付费金额" prop="adNumber">
<el-input v-model="form.adNumber" placeholder="请输入需要付费多少金额解锁" />
</el-form-item>
<el-form-item label="权重" prop="weight"> <el-form-item label="权重" prop="weight">
<el-input v-model="form.weight" placeholder="请输入权重" /> <el-input v-model="form.weight" placeholder="请输入权重" />
</el-form-item> </el-form-item>