mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-06-15 04:39:50 +08:00
update
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
package com.jsowell.api.uniapp.customer;
|
||||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.jsowell.common.core.controller.BaseController;
|
||||
import com.jsowell.common.core.domain.AjaxResult;
|
||||
import com.jsowell.pile.domain.CouponTemplate;
|
||||
import com.jsowell.pile.domain.MemberCoupon;
|
||||
import com.jsowell.pile.service.MemberCouponService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 优惠券用户端 API(小程序/App)
|
||||
*/
|
||||
@Api(tags = "优惠券-用户端")
|
||||
@RestController
|
||||
@RequestMapping("/coupon")
|
||||
public class CouponController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private MemberCouponService memberCouponService;
|
||||
|
||||
/** 二维码签名密钥,配置在 application.yml */
|
||||
@Value("${coupon.qrcode.secret:coupon_qrcode_secret}")
|
||||
private String qrcodeSecret;
|
||||
|
||||
/** 二维码 token 有效期(秒),默认 5 分钟 */
|
||||
private static final int QRCODE_TOKEN_TTL_SECONDS = 300;
|
||||
|
||||
/**
|
||||
* 获取可兑换券模板列表
|
||||
*/
|
||||
@ApiOperation("可兑换券列表")
|
||||
@GetMapping("/template/list")
|
||||
public AjaxResult templateList(
|
||||
@ApiParam("会员ID") @RequestParam String memberId,
|
||||
@ApiParam("当前所在站点ID,用于 scope 过滤") @RequestParam(required = false) Long stationId,
|
||||
@RequestParam(defaultValue = "1") int pageNum,
|
||||
@RequestParam(defaultValue = "10") int pageSize) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<CouponTemplate> list = memberCouponService.listAvailableTemplates(memberId, stationId);
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分兑换券
|
||||
*/
|
||||
@ApiOperation("积分兑换券")
|
||||
@PostMapping("/exchange")
|
||||
public AjaxResult exchange(
|
||||
@ApiParam("会员ID") @RequestParam String memberId,
|
||||
@ApiParam("模板ID") @RequestParam Long templateId,
|
||||
@ApiParam("客户端幂等键(UUID)") @RequestParam String requestId) {
|
||||
try {
|
||||
MemberCoupon coupon = memberCouponService.exchange(memberId, templateId, requestId);
|
||||
return AjaxResult.success(coupon);
|
||||
} catch (Exception e) {
|
||||
logger.error("兑换失败,memberId: {}, templateId: {}", memberId, templateId, e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 我的券包
|
||||
*/
|
||||
@ApiOperation("我的券包列表")
|
||||
@GetMapping("/my/list")
|
||||
public AjaxResult myList(
|
||||
@RequestParam String memberId,
|
||||
@ApiParam("状态:0=未使用 1=已使用 2=已过期,不传=全部") @RequestParam(required = false) Integer status,
|
||||
@RequestParam(defaultValue = "1") int pageNum,
|
||||
@RequestParam(defaultValue = "10") int pageSize) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<MemberCoupon> list = memberCouponService.myList(memberId, status);
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 券详情(含核销二维码短时 token)
|
||||
*/
|
||||
@ApiOperation("券详情(含二维码token)")
|
||||
@GetMapping("/my/detail/{couponNo}")
|
||||
public AjaxResult detail(
|
||||
@RequestParam String memberId,
|
||||
@PathVariable String couponNo) {
|
||||
try {
|
||||
MemberCoupon coupon = memberCouponService.detail(memberId, couponNo);
|
||||
String qrcodeToken = generateQrcodeToken(couponNo);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("coupon", coupon);
|
||||
result.put("qrcodeToken", qrcodeToken);
|
||||
result.put("qrcodeExpireSeconds", QRCODE_TOKEN_TTL_SECONDS);
|
||||
return AjaxResult.success(result);
|
||||
} catch (Exception e) {
|
||||
logger.error("获取券详情失败,couponNo: {}", couponNo, e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 私有:生成短时签名 token(格式:couponNo.expireTs.hmac)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
private String generateQrcodeToken(String couponNo) {
|
||||
try {
|
||||
long expireTs = System.currentTimeMillis() / 1000 + QRCODE_TOKEN_TTL_SECONDS;
|
||||
String payload = couponNo + "." + expireTs;
|
||||
String hmac = hmacSha256(payload, qrcodeSecret);
|
||||
return Base64.getUrlEncoder().withoutPadding()
|
||||
.encodeToString((payload + "." + hmac).getBytes());
|
||||
} catch (Exception e) {
|
||||
logger.error("生成二维码token失败", e);
|
||||
throw new RuntimeException("生成二维码失败");
|
||||
}
|
||||
}
|
||||
|
||||
private String hmacSha256(String data, String secret) throws Exception {
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
|
||||
return Base64.getUrlEncoder().withoutPadding()
|
||||
.encodeToString(mac.doFinal(data.getBytes("UTF-8")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.jsowell.web.controller.pile;
|
||||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.jsowell.common.core.controller.BaseController;
|
||||
import com.jsowell.common.core.domain.AjaxResult;
|
||||
import com.jsowell.common.core.page.TableDataInfo;
|
||||
import com.jsowell.pile.domain.MemberCoupon;
|
||||
import com.jsowell.pile.service.MemberCouponService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠券兑换记录 & 核销 Controller(管理后台)
|
||||
*/
|
||||
@Api(tags = "优惠券兑换记录管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/coupon")
|
||||
public class CouponRecordController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private MemberCouponService memberCouponService;
|
||||
|
||||
/**
|
||||
* 兑换记录列表
|
||||
*/
|
||||
@ApiOperation("兑换记录查询")
|
||||
@PreAuthorize("@ss.hasPermi('coupon:record:list')")
|
||||
@GetMapping("/record/list")
|
||||
public TableDataInfo recordList(MemberCoupon query,
|
||||
@RequestParam(defaultValue = "1") int pageNum,
|
||||
@RequestParam(defaultValue = "10") int pageSize) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<MemberCoupon> list = memberCouponService.listRecordForAdmin(query);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销券
|
||||
*/
|
||||
@ApiOperation("核销券")
|
||||
@PreAuthorize("@ss.hasPermi('coupon:record:verify')")
|
||||
@PostMapping("/verify")
|
||||
public AjaxResult verify(@RequestParam String couponNo,
|
||||
@RequestParam Long storeId,
|
||||
@RequestParam(required = false) String requestId,
|
||||
@RequestParam(required = false) String operatorId) {
|
||||
try {
|
||||
memberCouponService.verify(couponNo, storeId, requestId, operatorId);
|
||||
return AjaxResult.success("核销成功");
|
||||
} catch (Exception e) {
|
||||
logger.error("核销失败,couponNo: {}", couponNo, e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 人工作废券
|
||||
*/
|
||||
@ApiOperation("人工作废券")
|
||||
@PreAuthorize("@ss.hasPermi('coupon:record:invalidate')")
|
||||
@PostMapping("/invalidate")
|
||||
public AjaxResult invalidate(@RequestParam String couponNo,
|
||||
@RequestParam String reason) {
|
||||
// TODO: 实现人工作废逻辑(需补充 MemberCouponMapper.invalidate + 审计日志)
|
||||
return AjaxResult.error("功能待实现");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.jsowell.web.controller.pile;
|
||||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.jsowell.common.core.controller.BaseController;
|
||||
import com.jsowell.common.core.domain.AjaxResult;
|
||||
import com.jsowell.common.core.page.TableDataInfo;
|
||||
import com.jsowell.pile.domain.CouponTemplate;
|
||||
import com.jsowell.pile.service.CouponTemplateService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠券模板管理 Controller(管理后台)
|
||||
*/
|
||||
@Api(tags = "优惠券模板管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/coupon/template")
|
||||
public class CouponTemplateController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private CouponTemplateService couponTemplateService;
|
||||
|
||||
/**
|
||||
* 列表查询
|
||||
* 运营商管理员调用时,由前端传入 creatorMerchantId(后端也应从登录上下文二次校验)
|
||||
*/
|
||||
@ApiOperation("券模板列表")
|
||||
@PreAuthorize("@ss.hasPermi('coupon:template:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(CouponTemplate query,
|
||||
@RequestParam(defaultValue = "1") int pageNum,
|
||||
@RequestParam(defaultValue = "10") int pageSize) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<CouponTemplate> list = couponTemplateService.listForAdmin(query);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
@ApiOperation("券模板详情")
|
||||
@PreAuthorize("@ss.hasPermi('coupon:template:query')")
|
||||
@GetMapping("/{id}")
|
||||
public AjaxResult getById(@PathVariable Long id) {
|
||||
return AjaxResult.success(couponTemplateService.getById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增券模板
|
||||
* isPlatformAdmin / loginMerchantId 从登录上下文获取(此处简化演示,实际需从 SecurityUtils 取)
|
||||
*/
|
||||
@ApiOperation("新增券模板")
|
||||
@PreAuthorize("@ss.hasPermi('coupon:template:add')")
|
||||
@PostMapping("/add")
|
||||
public AjaxResult add(@RequestBody CouponTemplate template,
|
||||
@ApiParam("是否平台管理员") @RequestParam(defaultValue = "false") boolean isPlatformAdmin,
|
||||
@ApiParam("登录运营商ID(运营商管理员必传)") @RequestParam(required = false) Long loginMerchantId) {
|
||||
try {
|
||||
couponTemplateService.add(template, loginMerchantId, isPlatformAdmin);
|
||||
return AjaxResult.success("新增成功");
|
||||
} catch (Exception e) {
|
||||
logger.error("新增券模板失败", e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑券模板
|
||||
*/
|
||||
@ApiOperation("编辑券模板")
|
||||
@PreAuthorize("@ss.hasPermi('coupon:template:edit')")
|
||||
@PutMapping("/edit")
|
||||
public AjaxResult edit(@RequestBody CouponTemplate template,
|
||||
@RequestParam(defaultValue = "false") boolean isPlatformAdmin,
|
||||
@RequestParam(required = false) Long loginMerchantId) {
|
||||
try {
|
||||
couponTemplateService.edit(template, loginMerchantId, isPlatformAdmin);
|
||||
return AjaxResult.success("编辑成功");
|
||||
} catch (Exception e) {
|
||||
logger.error("编辑券模板失败", e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上下架
|
||||
*/
|
||||
@ApiOperation("上下架券模板")
|
||||
@PreAuthorize("@ss.hasPermi('coupon:template:edit')")
|
||||
@PutMapping("/changeStatus")
|
||||
public AjaxResult changeStatus(@RequestParam Long id,
|
||||
@ApiParam("0=下架 1=上架") @RequestParam Integer status,
|
||||
@RequestParam(defaultValue = "false") boolean isPlatformAdmin,
|
||||
@RequestParam(required = false) Long loginMerchantId) {
|
||||
try {
|
||||
couponTemplateService.changeStatus(id, status, loginMerchantId, isPlatformAdmin);
|
||||
return AjaxResult.success();
|
||||
} catch (Exception e) {
|
||||
logger.error("修改券模板状态失败", e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user