|
|
@@ -1,142 +1,199 @@
|
|
|
package com.ruoyi.app.pay;
|
|
|
|
|
|
-import java.util.List;
|
|
|
-import jakarta.servlet.http.HttpServletResponse;
|
|
|
-
|
|
|
-import com.alibaba.fastjson.JSONObject;
|
|
|
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.ruoyi.app.pay.dto.BankCardSaveDto;
|
|
|
import com.ruoyi.common.annotation.Anonymous;
|
|
|
-import com.ruoyi.system.domain.InfoUser;
|
|
|
-import com.ruoyi.system.utils.Auth;
|
|
|
-import com.ruoyi.system.utils.JwtUtil;
|
|
|
-import org.springframework.security.access.prepost.PreAuthorize;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.web.bind.annotation.*;
|
|
|
-import com.ruoyi.common.annotation.Log;
|
|
|
import com.ruoyi.common.core.controller.BaseController;
|
|
|
import com.ruoyi.common.core.domain.AjaxResult;
|
|
|
-import com.ruoyi.common.enums.BusinessType;
|
|
|
-import com.ruoyi.system.domain.BankCard;
|
|
|
-import com.ruoyi.system.service.IBankCardService;
|
|
|
+import com.ruoyi.common.core.domain.entity.SysDictData;
|
|
|
+import com.ruoyi.common.exception.ServiceException;
|
|
|
+import com.ruoyi.common.utils.DictUtils;
|
|
|
import com.ruoyi.common.utils.MessageUtils;
|
|
|
-import com.ruoyi.common.utils.poi.ExcelUtil;
|
|
|
-import com.ruoyi.common.core.page.TableDataInfo;
|
|
|
+import com.ruoyi.common.utils.StringUtils;
|
|
|
+import com.ruoyi.system.domain.InfoBankCard;
|
|
|
+import com.ruoyi.system.domain.InfoUser;
|
|
|
+import com.ruoyi.system.mapper.InfoBankCardMapper;
|
|
|
+import com.ruoyi.system.mapper.InfoUserMapper;
|
|
|
+import com.ruoyi.system.service.MerchantStoreAccessService;
|
|
|
+import com.ruoyi.system.utils.Auth;
|
|
|
+import com.ruoyi.system.utils.JwtUtil;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.web.bind.annotation.DeleteMapping;
|
|
|
+import org.springframework.web.bind.annotation.GetMapping;
|
|
|
+import org.springframework.web.bind.annotation.PathVariable;
|
|
|
+import org.springframework.web.bind.annotation.PostMapping;
|
|
|
+import org.springframework.web.bind.annotation.PutMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestBody;
|
|
|
+import org.springframework.web.bind.annotation.RequestHeader;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
+
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
|
|
|
/**
|
|
|
- * BankCardController
|
|
|
- *
|
|
|
- * @author ruoyi
|
|
|
- * @date 2023-08-06
|
|
|
+ * 收款银行卡管理接口(031,商家/骑手通用;foodie-store 支付设置页与骑手 App 共用)。
|
|
|
+ * 卡归属:骑手=本人;商家(含子账号)=主账号(连锁共享,与支付方式选择同语义)。
|
|
|
+ * 同一归属同时最多一张启用卡;付款方仅能看到启用卡(bankInfo 已改读启用卡)。
|
|
|
*/
|
|
|
@RestController
|
|
|
-@RequestMapping("/system/card")
|
|
|
-public class BankCardController extends BaseController
|
|
|
-{
|
|
|
- @Autowired
|
|
|
- private IBankCardService bankCardService;
|
|
|
+@RequestMapping("/system/bankCard")
|
|
|
+@Anonymous
|
|
|
+public class BankCardController extends BaseController {
|
|
|
|
|
|
+ /** 单人卡数上限,防止无限囤卡。 */
|
|
|
+ private static final int MAX_CARDS = 10;
|
|
|
|
|
|
- //删除银行卡
|
|
|
- @Anonymous
|
|
|
- @Auth
|
|
|
- @GetMapping("/delebankcard")
|
|
|
- public AjaxResult delebankcard(@RequestParam Long id)
|
|
|
- {
|
|
|
- int org = bankCardService.deleteBankCardById(id);
|
|
|
- if(org==1){
|
|
|
- return success(MessageUtils.message("no.delete.success"));
|
|
|
- }else {
|
|
|
- return error(MessageUtils.message("no.delete.fail"));
|
|
|
- }
|
|
|
+ private final InfoBankCardMapper bankCardMapper;
|
|
|
+ private final InfoUserMapper userMapper;
|
|
|
+ private final MerchantStoreAccessService merchantStoreAccessService;
|
|
|
+
|
|
|
+ public BankCardController(InfoBankCardMapper bankCardMapper,
|
|
|
+ InfoUserMapper userMapper,
|
|
|
+ MerchantStoreAccessService merchantStoreAccessService) {
|
|
|
+ this.bankCardMapper = bankCardMapper;
|
|
|
+ this.userMapper = userMapper;
|
|
|
+ this.merchantStoreAccessService = merchantStoreAccessService;
|
|
|
}
|
|
|
- //用户银行卡列表
|
|
|
- @Anonymous
|
|
|
- @Auth
|
|
|
- @GetMapping("/getbankcard")
|
|
|
- public AjaxResult getbankcard(@RequestHeader String token)
|
|
|
- {
|
|
|
- JwtUtil jwtUtil = new JwtUtil();
|
|
|
- String userid = jwtUtil.getusid(token);
|
|
|
- BankCard bankCard = new BankCard();
|
|
|
- bankCard.setUserId(Long.valueOf(userid));
|
|
|
- List<BankCard> list = bankCardService.selectBankCardList(bankCard);
|
|
|
- return success(MessageUtils.message("no.load.success"), list);
|
|
|
+
|
|
|
+ /** 本人(商家为主账号)卡列表,含启用标记。 */
|
|
|
+ @Auth(session = true)
|
|
|
+ @GetMapping
|
|
|
+ public AjaxResult list(@RequestHeader String token) {
|
|
|
+ Long ownerId = resolveOwner(token);
|
|
|
+ List<InfoBankCard> cards = bankCardMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<InfoBankCard>()
|
|
|
+ .eq(InfoBankCard::getUserId, ownerId)
|
|
|
+ .orderByDesc(InfoBankCard::getIsActive)
|
|
|
+ .orderByDesc(InfoBankCard::getId));
|
|
|
+ return success(cards);
|
|
|
}
|
|
|
- //添加银行卡
|
|
|
- @Anonymous
|
|
|
- @Auth
|
|
|
- @PostMapping("/addbankcard")
|
|
|
- public AjaxResult addbankcard(@RequestHeader String token, @RequestBody BankCard bankCard)
|
|
|
- {
|
|
|
- JwtUtil jwtUtil = new JwtUtil();
|
|
|
- bankCard.setUserId(Long.valueOf(jwtUtil.getusid(token)));
|
|
|
- return toAjax(bankCardService.insertBankCard(bankCard));
|
|
|
+
|
|
|
+ /** 新增卡;首张卡自动启用,否则默认停用。 */
|
|
|
+ @Auth(session = true)
|
|
|
+ @PostMapping
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public AjaxResult add(@RequestHeader String token, @RequestBody BankCardSaveDto dto) {
|
|
|
+ Long ownerId = resolveOwner(token);
|
|
|
+ InfoBankCard card = validated(dto, ownerId);
|
|
|
+ long count = bankCardMapper.selectCount(
|
|
|
+ new LambdaQueryWrapper<InfoBankCard>().eq(InfoBankCard::getUserId, ownerId));
|
|
|
+ if (count >= MAX_CARDS) {
|
|
|
+ throw new ServiceException(MessageUtils.message("pay.bankcard.limit"));
|
|
|
+ }
|
|
|
+ card.setUserId(ownerId);
|
|
|
+ // 首张卡自动启用,避免迁移遗漏或新收款方忘记启用导致线下转账长期不就绪
|
|
|
+ card.setIsActive(count == 0 ? 1 : 0);
|
|
|
+ Date now = new Date();
|
|
|
+ card.setCreateTime(now);
|
|
|
+ card.setUpdateTime(now);
|
|
|
+ bankCardMapper.insert(card);
|
|
|
+ return success(card);
|
|
|
}
|
|
|
- /**
|
|
|
- * 查询BankCard列表
|
|
|
- */
|
|
|
- @PreAuthorize("@ss.hasPermi('system:card:list')")
|
|
|
- @GetMapping("/list")
|
|
|
- public TableDataInfo list(BankCard bankCard)
|
|
|
- {
|
|
|
- startPage();
|
|
|
- List<BankCard> list = bankCardService.selectBankCardList(bankCard);
|
|
|
- return getDataTable(list);
|
|
|
+
|
|
|
+ /** 修改本人卡信息(不改启用状态)。 */
|
|
|
+ @Auth(session = true)
|
|
|
+ @PutMapping
|
|
|
+ public AjaxResult update(@RequestHeader String token, @RequestBody BankCardSaveDto dto) {
|
|
|
+ Long ownerId = resolveOwner(token);
|
|
|
+ if (dto == null || dto.getId() == null) {
|
|
|
+ throw new ServiceException(MessageUtils.message("pay.bankcard.invalid"));
|
|
|
+ }
|
|
|
+ InfoBankCard existing = requireOwnCard(dto.getId(), ownerId);
|
|
|
+ InfoBankCard validated = validated(dto, ownerId);
|
|
|
+ existing.setBankName(validated.getBankName());
|
|
|
+ existing.setAccountNo(validated.getAccountNo());
|
|
|
+ existing.setAccountName(validated.getAccountName());
|
|
|
+ existing.setUpdateTime(new Date());
|
|
|
+ bankCardMapper.updateById(existing);
|
|
|
+ return success();
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 导出BankCard列表
|
|
|
- */
|
|
|
- @PreAuthorize("@ss.hasPermi('system:card:export')")
|
|
|
- @Log(title = "BankCard", businessType = BusinessType.EXPORT)
|
|
|
- @PostMapping("/export")
|
|
|
- public void export(HttpServletResponse response, BankCard bankCard)
|
|
|
- {
|
|
|
- List<BankCard> list = bankCardService.selectBankCardList(bankCard);
|
|
|
- ExcelUtil<BankCard> util = new ExcelUtil<BankCard>(BankCard.class);
|
|
|
- util.exportExcel(response, list, MessageUtils.message("no.export.excel.bankcard"));
|
|
|
+ /** 删除本人卡;删的是启用卡则该归属回到"无启用卡"(线下转账不就绪)。 */
|
|
|
+ @Auth(session = true)
|
|
|
+ @DeleteMapping("/{id}")
|
|
|
+ public AjaxResult delete(@RequestHeader String token, @PathVariable Long id) {
|
|
|
+ Long ownerId = resolveOwner(token);
|
|
|
+ requireOwnCard(id, ownerId);
|
|
|
+ bankCardMapper.deleteById(id);
|
|
|
+ return success();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 获取BankCard详细信息
|
|
|
+ * 启用某卡并同事务停旧卡,保证同一归属最多一张启用;
|
|
|
+ * 付款方下次查询即看到新卡(无缓存)。
|
|
|
*/
|
|
|
- @PreAuthorize("@ss.hasPermi('system:card:query')")
|
|
|
- @GetMapping(value = "/{id}")
|
|
|
- public AjaxResult getInfo(@PathVariable("id") Long id)
|
|
|
- {
|
|
|
- return success(bankCardService.selectBankCardById(id));
|
|
|
+ @Auth(session = true)
|
|
|
+ @PutMapping("/activate/{id}")
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public AjaxResult activate(@RequestHeader String token, @PathVariable Long id) {
|
|
|
+ Long ownerId = resolveOwner(token);
|
|
|
+ requireOwnCard(id, ownerId);
|
|
|
+ Date now = new Date();
|
|
|
+ bankCardMapper.update(null, new LambdaUpdateWrapper<InfoBankCard>()
|
|
|
+ .eq(InfoBankCard::getUserId, ownerId)
|
|
|
+ .set(InfoBankCard::getIsActive, 0)
|
|
|
+ .set(InfoBankCard::getUpdateTime, now));
|
|
|
+ bankCardMapper.update(null, new LambdaUpdateWrapper<InfoBankCard>()
|
|
|
+ .eq(InfoBankCard::getId, id)
|
|
|
+ .set(InfoBankCard::getIsActive, 1)
|
|
|
+ .set(InfoBankCard::getUpdateTime, now));
|
|
|
+ return success();
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 新增BankCard
|
|
|
- */
|
|
|
- @PreAuthorize("@ss.hasPermi('system:card:add')")
|
|
|
- @Log(title = "BankCard", businessType = BusinessType.INSERT)
|
|
|
- @PostMapping
|
|
|
- public AjaxResult add(@RequestBody BankCard bankCard)
|
|
|
- {
|
|
|
- return toAjax(bankCardService.insertBankCard(bankCard));
|
|
|
+ /** 字段校验:必填、长度、银行名必须属于字典 taiwan_bank_list(与商家审核资料同源)。 */
|
|
|
+ private InfoBankCard validated(BankCardSaveDto dto, Long ownerId) {
|
|
|
+ if (dto == null || StringUtils.isBlank(dto.getBankName())
|
|
|
+ || StringUtils.isBlank(dto.getAccountNo()) || StringUtils.isBlank(dto.getAccountName())
|
|
|
+ || dto.getBankName().trim().length() > 64
|
|
|
+ || dto.getAccountNo().trim().length() > 64
|
|
|
+ || dto.getAccountName().trim().length() > 64) {
|
|
|
+ throw new ServiceException(MessageUtils.message("pay.bankcard.invalid"));
|
|
|
+ }
|
|
|
+ boolean bankKnown = false;
|
|
|
+ List<SysDictData> dict = DictUtils.getDictCache("taiwan_bank_list");
|
|
|
+ if (dict != null) {
|
|
|
+ for (SysDictData item : dict) {
|
|
|
+ if (item != null && dto.getBankName().trim().equals(item.getDictLabel())) {
|
|
|
+ bankKnown = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!bankKnown) {
|
|
|
+ throw new ServiceException(MessageUtils.message("pay.bankcard.name.invalid"));
|
|
|
+ }
|
|
|
+ InfoBankCard card = new InfoBankCard();
|
|
|
+ card.setBankName(dto.getBankName().trim());
|
|
|
+ card.setAccountNo(dto.getAccountNo().trim());
|
|
|
+ card.setAccountName(dto.getAccountName().trim());
|
|
|
+ return card;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 修改BankCard
|
|
|
- */
|
|
|
- @PreAuthorize("@ss.hasPermi('system:card:edit')")
|
|
|
- @Log(title = "BankCard", businessType = BusinessType.UPDATE)
|
|
|
- @PutMapping
|
|
|
- public AjaxResult edit(@RequestBody BankCard bankCard)
|
|
|
- {
|
|
|
- return toAjax(bankCardService.updateBankCard(bankCard));
|
|
|
+ /** 只能操作归属自己的卡,统一按无权限处理避免枚举他人卡 ID。 */
|
|
|
+ private InfoBankCard requireOwnCard(Long id, Long ownerId) {
|
|
|
+ InfoBankCard card = id == null ? null : bankCardMapper.selectById(id);
|
|
|
+ if (card == null || !ownerId.equals(card.getUserId())) {
|
|
|
+ throw new ServiceException(MessageUtils.message("no.user.stop"));
|
|
|
+ }
|
|
|
+ return card;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 删除BankCard
|
|
|
- */
|
|
|
- @PreAuthorize("@ss.hasPermi('system:card:remove')")
|
|
|
- @Log(title = "BankCard", businessType = BusinessType.DELETE)
|
|
|
- @DeleteMapping("/{ids}")
|
|
|
- public AjaxResult remove(@PathVariable Long[] ids)
|
|
|
- {
|
|
|
- return toAjax(bankCardService.deleteBankCardByIds(ids));
|
|
|
+ /** token → 卡归属:骑手(2)=本人;商家系(1/3/4/5)=主账号;普通用户不可维护收款卡。 */
|
|
|
+ private Long resolveOwner(String token) {
|
|
|
+ Long userId = Long.valueOf(new JwtUtil().getusid(token));
|
|
|
+ InfoUser user = userMapper.selectById(userId);
|
|
|
+ if (user == null) {
|
|
|
+ throw new ServiceException(MessageUtils.message("no.user.stop"));
|
|
|
+ }
|
|
|
+ if ("2".equals(user.getUserType())) {
|
|
|
+ return userId;
|
|
|
+ }
|
|
|
+ if ("1".equals(user.getUserType()) || "3".equals(user.getUserType())
|
|
|
+ || "4".equals(user.getUserType()) || "5".equals(user.getUserType())) {
|
|
|
+ return merchantStoreAccessService.resolve(userId).ownerUserId();
|
|
|
+ }
|
|
|
+ throw new ServiceException(MessageUtils.message("no.user.stop"));
|
|
|
}
|
|
|
}
|