فهرست منبع

打卡文章红包领取接口

cgp 1 هفته پیش
والد
کامیت
eb531b03ee

+ 5 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java

@@ -22,6 +22,7 @@ import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.param.WxSendRedPacketParam;
 import com.fs.his.service.IFsStorePaymentService;
 import com.fs.qw.domain.BindPhoneRedPacketRecord;
+import com.fs.qw.domain.SignRedPacketRecord;
 import com.fs.qw.mapper.BindPhoneRedPacketRecordMapper;
 import com.fs.system.service.ISysConfigService;
 import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
@@ -151,7 +152,10 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
                 bindPhoneRedPacketRecordMapper.updateBindPhoneRedPacketRecord(record);
                 return R.ok();
             }
-        } else {
+        } else if (outBatchNo.contains("articlePacket")) {
+            //打卡红包回调
+            SignRedPacketRecord record = new SignRedPacketRecord();
+        }else {
             //看课红包回调
             FsCourseRedPacketLog log = fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogByBatchNo(outBatchNo);
             if (log!=null){

+ 29 - 0
fs-service/src/main/java/com/fs/his/param/ClaimArticleRedPacketParam.java

@@ -0,0 +1,29 @@
+package com.fs.his.param;
+
+
+
+import lombok.Data;
+
+@Data
+public class ClaimArticleRedPacketParam {
+    /** 客户id从登录中获取*/
+    private Long userId;
+
+    //来源小程序id
+    private String appId;
+
+    /** 文章id */
+    private Long articleId;
+
+    /** 销售企微用户id 是qw_user表的主键!!!! */
+    private String qwUserId;
+
+    /** 销售ID */
+    private Long companyUserId;
+
+    /** 签到图片/视频地址 */
+    private String signUrl;
+
+    private Integer source=2;//H5、小程序发打卡文章红包时默认为2
+
+}

+ 5 - 0
fs-service/src/main/java/com/fs/his/param/WxSendRedPacketParam.java

@@ -34,4 +34,9 @@ public class WxSendRedPacketParam implements Serializable {
 
     private boolean isPhoneTag;
 
+    /**
+     * 文章红包标识
+     * */
+    private Long sourceType;
+
 }

+ 11 - 0
fs-service/src/main/java/com/fs/his/service/IFsSignArticleReadDetailService.java

@@ -3,6 +3,7 @@ package com.fs.his.service;
 import com.fs.common.core.domain.R;
 import com.fs.his.domain.FsSignArticleReadDetail;
 import com.fs.his.param.APPSignArticleReadDetailParam;
+import com.fs.his.param.ClaimArticleRedPacketParam;
 
 import java.util.List;
 
@@ -68,4 +69,14 @@ public interface IFsSignArticleReadDetailService
      * @return 结果
      */
     R  userReadArticle(APPSignArticleReadDetailParam param);
+
+    /**
+     * 发放文章红包接口
+     * */
+    public R sendArticleRedPack(ClaimArticleRedPacketParam claimArticleRedPacketParam);
+
+    /**
+     * 获取文章红包配置
+     * */
+    public Integer getArticleRedPacketConfig();
 }

+ 5 - 0
fs-service/src/main/java/com/fs/his/service/IFsStorePaymentService.java

@@ -101,6 +101,11 @@ public interface IFsStorePaymentService
      * */
     R sendRedPacketAppReward(WxSendRedPacketParam param);
 
+    /**
+     * 发送文章红包
+     * */
+    R sendArticleRedPack(WxSendRedPacketParam param);
+
     R sendRedPacketV3(WxSendRedPacketParam param);
 
     String transferNotify(String notifyData, HttpServletRequest request);

+ 246 - 21
fs-service/src/main/java/com/fs/his/service/impl/FsSignArticleReadDetailServiceImpl.java

@@ -1,98 +1,150 @@
 package com.fs.his.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
+import com.fs.common.exception.CustomException;
+import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyMapper;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.core.config.WxOpenProperties;
+import com.fs.his.domain.FsSignArticle;
 import com.fs.his.domain.FsSignArticleReadDetail;
+import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserWx;
+import com.fs.his.mapper.FsSignArticleMapper;
 import com.fs.his.mapper.FsSignArticleReadDetailMapper;
+import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.param.ClaimArticleRedPacketParam;
+import com.fs.his.param.WxSendRedPacketParam;
 import com.fs.his.param.APPSignArticleReadDetailParam;
 import com.fs.his.service.IFsSignArticleReadDetailService;
+import com.fs.his.service.IFsStorePaymentService;
+import com.fs.his.service.IFsUserWxService;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.domain.SignRedPacketRecord;
+import com.fs.qw.mapper.QwUserMapper;
+import com.fs.qw.mapper.SignRedPacketRecordMapper;
+import com.fs.system.service.ISysConfigService;
+import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
 import java.util.Date;
+
 import java.util.List;
 
 /**
  * 用户阅读文章明细Service业务层处理
- * 
+ *
  * @author fs
  * @date 2024-01-01
  */
+@Slf4j
 @Service
-public class FsSignArticleReadDetailServiceImpl implements IFsSignArticleReadDetailService
-{
+public class FsSignArticleReadDetailServiceImpl implements IFsSignArticleReadDetailService {
     @Autowired
     private FsSignArticleReadDetailMapper fsSignArticleReadDetailMapper;
 
+    @Autowired
+    private IFsStorePaymentService fsStorePaymentService;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    @Autowired
+    private WxOpenProperties openProperties;
+
+    @Autowired
+    private IFsUserWxService fsUserWxService;
+
+    @Autowired
+    private SignRedPacketRecordMapper signRedPacketRecordMapper;
+
+    @Autowired
+    private FsSignArticleMapper signArticleMapper;
+
+    @Autowired
+    private FsUserMapper userMapper;
+
+    @Autowired
+    private CompanyUserMapper companyUserMapper;
+
+    @Autowired
+    private CompanyMapper companyMapper;
+
+    @Autowired
+    private QwUserMapper qwUserMapper;
+
     /**
      * 查询用户阅读文章明细
-     * 
+     *
      * @param id 用户阅读文章明细主键
      * @return 用户阅读文章明细
      */
     @Override
-    public FsSignArticleReadDetail selectFsSignArticleReadDetailById(Long id)
-    {
+    public FsSignArticleReadDetail selectFsSignArticleReadDetailById(Long id) {
         return fsSignArticleReadDetailMapper.selectFsSignArticleReadDetailById(id);
     }
 
     /**
      * 查询用户阅读文章明细列表
-     * 
+     *
      * @param fsSignArticleReadDetail 用户阅读文章明细
      * @return 用户阅读文章明细
      */
     @Override
-    public List<FsSignArticleReadDetail> selectFsSignArticleReadDetailList(FsSignArticleReadDetail fsSignArticleReadDetail)
-    {
+    public List<FsSignArticleReadDetail> selectFsSignArticleReadDetailList(FsSignArticleReadDetail fsSignArticleReadDetail) {
         return fsSignArticleReadDetailMapper.selectFsSignArticleReadDetailList(fsSignArticleReadDetail);
     }
 
     /**
      * 新增用户阅读文章明细
-     * 
+     *
      * @param fsSignArticleReadDetail 用户阅读文章明细
      * @return 结果
      */
     @Override
-    public int insertFsSignArticleReadDetail(FsSignArticleReadDetail fsSignArticleReadDetail)
-    {
+    public int insertFsSignArticleReadDetail(FsSignArticleReadDetail fsSignArticleReadDetail) {
         fsSignArticleReadDetail.setCreateTime(new java.util.Date());
         return fsSignArticleReadDetailMapper.insertFsSignArticleReadDetail(fsSignArticleReadDetail);
     }
 
     /**
      * 修改用户阅读文章明细
-     * 
+     *
      * @param fsSignArticleReadDetail 用户阅读文章明细
      * @return 结果
      */
     @Override
-    public int updateFsSignArticleReadDetail(FsSignArticleReadDetail fsSignArticleReadDetail)
-    {
+    public int updateFsSignArticleReadDetail(FsSignArticleReadDetail fsSignArticleReadDetail) {
         return fsSignArticleReadDetailMapper.updateFsSignArticleReadDetail(fsSignArticleReadDetail);
     }
 
     /**
      * 批量删除用户阅读文章明细
-     * 
+     *
      * @param ids 需要删除的用户阅读文章明细主键
      * @return 结果
      */
     @Override
-    public int deleteFsSignArticleReadDetailByIds(Long[] ids)
-    {
+    public int deleteFsSignArticleReadDetailByIds(Long[] ids) {
         return fsSignArticleReadDetailMapper.deleteFsSignArticleReadDetailByIds(ids);
     }
 
     /**
      * 删除用户阅读文章明细信息
-     * 
+     *
      * @param id 用户阅读文章明细主键
      * @return 结果
      */
     @Override
-    public int deleteFsSignArticleReadDetailById(Long id)
-    {
+    public int deleteFsSignArticleReadDetailById(Long id) {
         return fsSignArticleReadDetailMapper.deleteFsSignArticleReadDetailById(id);
     }
 
@@ -127,4 +179,177 @@ public class FsSignArticleReadDetailServiceImpl implements IFsSignArticleReadDet
         return R.error();
     }
 
+    /**
+     * 发送文章红包
+     */
+    @Override
+    public R sendArticleRedPack(ClaimArticleRedPacketParam param) {
+
+        // ******************** 阶段一:业务校验 ********************
+        // 1. 是否已有红包记录?
+        SignRedPacketRecord existing = signRedPacketRecordMapper
+                .selectByUserIdAndArticleId(param.getUserId(), param.getArticleId());
+        if (existing != null) {
+            return handleExistingRecord(existing);   // 私有方法1:处理已存在记录
+        }
+
+        // 2. 今日领取次数是否超限?
+        Integer maxNum = getArticleRedPacketConfig();
+        if (maxNum == null || maxNum <= 0) {
+            throw new CustomException("今日领取红包次数已达上限!");
+        }
+        int todayCount = signRedPacketRecordMapper.countTodayCollectedByUserId(param.getUserId());
+        if (todayCount >= maxNum) {
+            throw new CustomException("今日领取红包次数已达上限");
+        }
+
+        // 3. 文章、用户、销售、公司、企微信息是否完整?
+        FsSignArticle article = signArticleMapper.selectFsSignArticleById(param.getArticleId());
+        if (article == null || !Integer.valueOf(1).equals(article.getSignFlag())) {
+            throw new CustomException("文章不可领取红包");
+        }
+        if (article.getAmount() == null || article.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
+            throw new CustomException("红包金额异常");
+        }
+
+        FsUser user = userMapper.selectFsUserById(param.getUserId());
+        if (user == null) throw new CustomException("用户信息缺失");
+
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
+        if (companyUser == null) throw new CustomException("销售信息缺失");
+
+        Company company = companyMapper.selectCompanyById(companyUser.getCompanyId());
+        if (company == null) throw new CustomException("公司信息缺失");
+
+        QwUser qwUser = qwUserMapper.selectQwUserById(Long.valueOf(param.getQwUserId()));
+        if (qwUser == null) throw new CustomException("企微用户信息缺失");
+
+        // 4. 获取用户在该小程序的 openId(若不存在则尝试补救一次)
+        FsUserWx fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(), user.getUserId(), 1);
+        if (fsUserWx == null) {
+            handleFsUserWx(user, param.getAppId());   // 补救逻辑(已存在的老方法)
+            fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(), user.getUserId(), 1);
+        }
+        if (fsUserWx == null || StringUtils.isEmpty(fsUserWx.getOpenId())) {
+            throw new CustomException("用户openId获取失败");
+        }
+
+        // ******************** 阶段二:组装微信参数并发送 ********************
+        WxSendRedPacketParam wxParam = new WxSendRedPacketParam();
+        wxParam.setOpenId(fsUserWx.getOpenId());
+        wxParam.setAmount(article.getAmount());
+        wxParam.setRedPacketMode(1);
+        wxParam.setAppId(param.getAppId());
+        wxParam.setMpAppId(param.getAppId());
+        wxParam.setUser(user);
+        wxParam.setPhoneTag(true);
+        wxParam.setSource(2);
+        wxParam.setCompanyId(companyUser.getCompanyId());
+        wxParam.setSourceType(1L);      // 文章红包标识
+
+        R sendResult = fsStorePaymentService.sendArticleRedPack(wxParam);
+
+        // ******************** 阶段三:处理结果并落库 ********************
+        return saveRecordAndReturn(sendResult, param, user, companyUser, company, qwUser, article);
+    }
+
+// ==================== 私有方法1:处理已存在的红包记录 ====================
+    /**
+     * 根据已有记录的状态返回对应的前端提示
+     */
+    private R handleExistingRecord(SignRedPacketRecord record) {
+        if (record.getCollectType() == 1) {
+            return R.error("您已领取过该文章红包");
+        } else if (record.getCollectType() == 0) {
+            return R.ok(record.getResult());
+        }
+        return R.error("红包状态异常");
+    }
+
+// ==================== 私有方法2:保存红包发放记录 ====================
+    /**
+     * 解析微信返回结果,构建 SignRedPacketRecord 并入库
+     */
+    private R saveRecordAndReturn(R sendResult,
+                                  ClaimArticleRedPacketParam param,
+                                  FsUser user,
+                                  CompanyUser companyUser,
+                                  Company company,
+                                  QwUser qwUser,
+                                  FsSignArticle article) {
+
+        // 修正:code 是 Integer,必须用 equals 比较
+        if (!Integer.valueOf(200).equals(sendResult.get("code"))) {
+            log.error("打卡文章红包-领取失败: {}", sendResult);
+            throw new CustomException("领取失败");
+        }
+
+        SignRedPacketRecord record = new SignRedPacketRecord();
+        record.setResult(JSON.toJSONString(sendResult));
+
+        Object isNew = sendResult.get("isNew");
+        if (Integer.valueOf(1).equals(isNew)) {
+            TransferBillsResult data = (TransferBillsResult) sendResult.get("data");
+            record.setOutBatchNo(data.getOutBillNo());
+            record.setBatchId(data.getTransferBillNo());
+        } else {
+            record.setOutBatchNo(sendResult.get("orderCode").toString());
+            record.setBatchId(sendResult.get("batchId").toString());
+        }
+
+        Date now = DateUtils.getNowDate();
+        record.setSignUrl(param.getSignUrl());
+        record.setCollectTag(0);
+        record.setCollectType(0);
+        record.setSignType(1);                  // 1-直接打卡
+        record.setSendTime(now);
+        record.setUpdateTime(now);
+        record.setCreateTime(now);
+        record.setUserId(param.getUserId());
+        record.setUserName(user.getRealName());
+        record.setCompanyId(companyUser.getCompanyId());
+        record.setCompanyUserId(param.getCompanyUserId());
+        record.setCompanyName(company.getCompanyName());
+        record.setArticleId(param.getArticleId());
+        record.setAmount(article.getAmount());
+        record.setQwUserId(param.getQwUserId());
+        record.setQwUserName(qwUser.getQwUserName());
+
+        signRedPacketRecordMapper.insertSignRedPacketRecord(record);
+        return sendResult;
+    }
+
+    /**
+     * 获取文章红包配置
+     *
+     * @return 领取次数
+     */
+    @Override
+    public Integer getArticleRedPacketConfig() {
+        String json = configService.selectConfigByKey("articleRedPacket.config");
+        if (StringUtils.isNotEmpty(json)) {
+            try {
+                JSONObject jsonObject = JSON.parseObject(json);
+                return jsonObject.getInteger("redPacketNum");
+            } catch (Exception e) {
+                log.error("解析文章红包配置失败, json={}", json, e);
+                return 0;
+            }
+        }
+        return 0; // 默认返回 0次
+    }
+
+    private void handleFsUserWx(FsUser user, String appId) {
+        FsUserWx fsUserWx = new FsUserWx();
+        fsUserWx.setType(1);
+        fsUserWx.setFsUserId(user.getUserId());
+        fsUserWx.setAppId(appId);
+        fsUserWx.setOpenId(user.getCourseMaOpenId());
+        fsUserWx.setUnionId(user.getUnionId());
+        fsUserWx.setCreateTime(new Date());
+        fsUserWx.setUpdateTime(new Date());
+        fsUserWxService.saveOrUpdateByUniqueKey(fsUserWx);
+
+        log.info("【更新或插入用户与小程序{}的绑定关系】:{}", appId, user.getUserId());
+    }
 }

+ 49 - 2
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -630,6 +630,51 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         return result;
     }
 
+    /**
+     *  发文章红包
+     * */
+    @Override
+    public R sendArticleRedPack(WxSendRedPacketParam param) {
+        String json;
+        RedPacketConfig config = new RedPacketConfig();
+        // 根据红包模式获取配置
+        switch (param.getRedPacketMode()) {
+            case 1:
+                json = redisCache.getCacheObject("sys_config:redPacket.config.new");
+                if (StringUtil.isNullOrEmpty(json) || json.isEmpty()) {
+                    json = configService.selectConfigByKey("redPacket.config");
+                }
+                config = JSONUtil.toBean(json, RedPacketConfig.class);
+                break;
+            case 2:
+                json = companyConfigService.selectRedPacketConfigByKey(param.getCompanyId());
+                config = JSONUtil.toBean(json, RedPacketConfig.class);
+                break;
+        }
+        //H5的用公众号的appid发,小程序的用小程序的appid来发
+        if (param.getSource() == 2) {
+            // 传参appId为空时,仍然使用配置里面的
+            String appId = StringUtils.isBlank(param.getAppId()) ? config.getMiniappId() : param.getAppId();
+            config.setAppId(appId);
+        }
+        if (param.getSource() == 3) {
+            // 传参appId为空时,仍然使用配置里面的
+            String appId = param.getAppAppId();
+            config.setAppId(appId);
+        }
+        logger.error("文章领取红包最终传参 {}", config);
+        //益寿缘默认使用新商户号
+        R result = sendRedPacketV3Internal(param, config);
+
+        if (result.getMsg().equals("商家余额不足") && param.getRedPacketMode() == 1) {
+            redisCache.incr("sys_config:redPacket.config.newCount",1L);
+        }
+        result.put("mchId", config.getMchId());
+        result.put("isNew", config.getIsNew());
+        logger.error("文章领取红包:{}", result);
+        return result;
+    }
+
     private static long getExpireSeconds() {
         Calendar calendar = Calendar.getInstance();
         calendar.add(Calendar.DAY_OF_YEAR, 1);
@@ -658,8 +703,10 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         if (StringUtils.isEmpty(code)) {
             return R.error("订单生成失败,请重试");
         }
-        if(ObjectUtil.isNotNull(param.isPhoneTag()) && param.isPhoneTag()) {
-            request.setOutBillNo("phonePacket"+code);
+        if (ObjectUtil.isNotNull(param.isPhoneTag()) && param.isPhoneTag()) {
+            request.setOutBillNo("phonePacket" + code);
+        } else if (param.getSourceType() != null) {
+            request.setOutBillNo("articlePacket" + code);
         } else {
             request.setOutBillNo("fsCourse" + code);
         }

+ 1 - 1
fs-service/src/main/java/com/fs/qw/domain/SignRedPacketRecord.java

@@ -35,7 +35,7 @@ public class SignRedPacketRecord extends BaseEntity{
     private String outBatchNo;
 
     /** $column.columnComment */
-    @Excel(name = "批次单号")
+    @Excel(name = "红包发送结果")
     private String result;
 
     /** 微信批次ID */

+ 17 - 0
fs-service/src/main/java/com/fs/qw/mapper/SignRedPacketRecordMapper.java

@@ -3,6 +3,7 @@ package com.fs.qw.mapper;
 import java.util.List;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.qw.domain.SignRedPacketRecord;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * 签到红包领取记录Mapper接口
@@ -19,6 +20,22 @@ public interface SignRedPacketRecordMapper extends BaseMapper<SignRedPacketRecor
      */
     SignRedPacketRecord selectSignRedPacketRecordById(Long id);
 
+    /**
+     * 根据用户ID和文章ID查询红包记录(唯一记录)
+     * @param userId 用户ID
+     * @param articleId 文章ID
+     * @return 红包记录,不存在返回 null
+     */
+    SignRedPacketRecord selectByUserIdAndArticleId(@Param("userId") Long userId,
+                                                   @Param("articleId") Long articleId);
+
+    /**
+     * 统计指定用户今日领取红包次数
+     * @param userId 用户ID
+     * @return 今日领取次数
+     */
+    int countTodayCollectedByUserId(@Param("userId") Long userId);
+
     /**
      * 查询签到红包领取记录列表
      * 

+ 15 - 1
fs-service/src/main/resources/mapper/qw/SignRedPacketRecordMapper.xml

@@ -58,7 +58,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectSignRedPacketRecordVo"/>
         where id = #{id}
     </select>
-        
+
+    <select id="countTodayCollectedByUserId" resultType="int">
+        SELECT COUNT(*)
+        FROM sign_red_packet_record
+        WHERE user_id = #{userId}
+          AND DATE(collect_time) = CURDATE()
+    </select>
+
+    <!-- 根据用户ID和文章ID查询唯一记录,命中索引 uk_user_article(user_id, article_id) -->
+    <select id="selectByUserIdAndArticleId" resultMap="SignRedPacketRecordResult">
+        <include refid="selectSignRedPacketRecordVo"/>
+        WHERE user_id = #{userId}
+        AND article_id = #{articleId}
+    </select>
+
     <insert id="insertSignRedPacketRecord" parameterType="SignRedPacketRecord">
         insert into sign_red_packet_record
         <trim prefix="(" suffix=")" suffixOverrides=",">

+ 15 - 4
fs-user-app/src/main/java/com/fs/app/controller/SignArticleController.java

@@ -3,14 +3,13 @@ package com.fs.app.controller;
 import com.fs.app.annotation.Login;
 import com.fs.common.core.domain.R;
 import com.fs.his.domain.FsSignArticle;
+import com.fs.his.param.ClaimArticleRedPacketParam;
 import com.fs.his.service.IFsSignArticleService;
+import com.fs.his.service.impl.FsSignArticleReadDetailServiceImpl;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 @Api("打卡文章接口")
 @RestController
@@ -20,6 +19,9 @@ public class SignArticleController extends  AppBaseController  {
     @Autowired
     private IFsSignArticleService signArticleService;
 
+    @Autowired
+    private FsSignArticleReadDetailServiceImpl articleReadDetailService;
+
     @Login
     @ApiOperation("获取打卡文章详情")
     @GetMapping("/detail")
@@ -27,4 +29,13 @@ public class SignArticleController extends  AppBaseController  {
         FsSignArticle article = signArticleService.selectFsSignArticleById(articleId);
         return R.ok().put("article", article);
     }
+
+    @Login
+    @ApiOperation("领取文章红包")
+    @PostMapping("/claimArticleRedPacket")
+    public R claimArticleRedPacket(@RequestBody ClaimArticleRedPacketParam claimArticleRedPacketParam){
+        String userId = getUserId();
+        claimArticleRedPacketParam.setUserId(Long.valueOf(userId));
+        return articleReadDetailService.sendArticleRedPack(claimArticleRedPacketParam);
+    }
 }