345 lines
13 KiB
Java
345 lines
13 KiB
Java
package com.gxwebsoft.bszx.controller;
|
||
|
||
import cn.hutool.core.date.DateField;
|
||
import cn.hutool.core.date.DateUtil;
|
||
import cn.hutool.core.util.NumberUtil;
|
||
import cn.hutool.core.util.ObjectUtil;
|
||
import cn.hutool.core.util.StrUtil;
|
||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||
import com.gxwebsoft.bszx.entity.BszxBm;
|
||
import com.gxwebsoft.bszx.service.BszxBmService;
|
||
import com.wechat.pay.java.core.notification.*;
|
||
import com.gxwebsoft.common.core.config.ConfigProperties;
|
||
import com.gxwebsoft.common.core.security.JwtUtil;
|
||
import com.gxwebsoft.common.core.utils.RedisUtil;
|
||
import com.gxwebsoft.common.core.web.BaseController;
|
||
import com.gxwebsoft.bszx.service.BszxPayService;
|
||
import com.gxwebsoft.bszx.entity.BszxPay;
|
||
import com.gxwebsoft.bszx.param.BszxPayParam;
|
||
import com.gxwebsoft.common.core.web.ApiResult;
|
||
import com.gxwebsoft.common.core.web.PageResult;
|
||
import com.gxwebsoft.common.core.web.BatchParam;
|
||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||
import com.gxwebsoft.common.system.entity.Payment;
|
||
import com.gxwebsoft.common.system.entity.User;
|
||
import com.gxwebsoft.shop.entity.ShopOrder;
|
||
import com.gxwebsoft.shop.service.ShopOrderService;
|
||
import com.wechat.pay.java.core.notification.RequestParam;
|
||
import com.wechat.pay.java.service.partnerpayments.jsapi.JsapiService;
|
||
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
|
||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||
import io.swagger.v3.oas.annotations.media.Schema;
|
||
import io.swagger.v3.oas.annotations.Operation;
|
||
import org.springframework.beans.factory.annotation.Value;
|
||
import org.springframework.security.access.prepost.PreAuthorize;
|
||
import org.springframework.web.bind.annotation.*;
|
||
|
||
import javax.annotation.Resource;
|
||
import javax.servlet.http.HttpServletRequest;
|
||
import java.math.BigDecimal;
|
||
import java.util.*;
|
||
|
||
/**
|
||
* 百色中学-捐款记录控制器
|
||
*
|
||
* @author 科技小王子
|
||
* @since 2025-03-06 22:50:25
|
||
*/
|
||
@Tag(name = "百色中学-捐款记录管理")
|
||
@RestController
|
||
@RequestMapping("/api/bszx/bszx-pay")
|
||
public class BszxPayController extends BaseController {
|
||
public static JsapiService service;
|
||
@Resource
|
||
private BszxPayService bszxPayService;
|
||
@Resource
|
||
private BszxBmService bszxBmService;
|
||
@Resource
|
||
private RedisUtil redisUtil;
|
||
@Resource
|
||
private ShopOrderService shopOrderService;
|
||
@Resource
|
||
private ConfigProperties conf;
|
||
@Value("${spring.profiles.active}")
|
||
String active;
|
||
|
||
@PreAuthorize("hasAuthority('bszx:bszxPay:list')")
|
||
@Operation(summary = "分页查询百色中学-捐款记录")
|
||
@GetMapping("/page")
|
||
public ApiResult<PageResult<BszxPay>> page(BszxPayParam param) {
|
||
// 使用关联查询
|
||
return success(bszxPayService.pageRel(param));
|
||
}
|
||
|
||
@PreAuthorize("hasAuthority('bszx:bszxPay:list')")
|
||
@Operation(summary = "查询全部百色中学-捐款记录")
|
||
@GetMapping()
|
||
public ApiResult<List<BszxPay>> list(BszxPayParam param) {
|
||
// 使用关联查询
|
||
return success(bszxPayService.listRel(param));
|
||
}
|
||
|
||
@PreAuthorize("hasAuthority('bszx:bszxPay:list')")
|
||
@Operation(summary = "根据id查询百色中学-捐款记录")
|
||
@GetMapping("/{id}")
|
||
public ApiResult<BszxPay> get(@PathVariable("id") Integer id) {
|
||
// 使用关联查询
|
||
return success(bszxPayService.getByIdRel(id));
|
||
}
|
||
|
||
@OperationLog
|
||
@Operation(summary = "活动捐款")
|
||
@PostMapping()
|
||
public ApiResult<?> save(@RequestBody BszxPay bszxPay, HttpServletRequest request) {
|
||
if (bszxPay.getPrice().compareTo(BigDecimal.ZERO) == 0) {
|
||
return fail("金额不能为0");
|
||
}
|
||
// 记录当前登录用户id
|
||
User loginUser = getLoginUser();
|
||
if (loginUser != null) {
|
||
String access_token = JwtUtil.getAccessToken(request);
|
||
bszxPay.setUserId(loginUser.getUserId());
|
||
// 微信openid(必填)
|
||
if (StrUtil.isBlank(loginUser.getOpenid())) {
|
||
return fail("微信openid(必填)");
|
||
}
|
||
final BszxBm bmInfo = bszxBmService.getByUserId(loginUser.getUserId());
|
||
bszxPay.setName(bmInfo.getName());
|
||
bszxPay.setSex(bmInfo.getSex());
|
||
bszxPay.setPhone(bmInfo.getPhone());
|
||
bszxPay.setBranchName(bmInfo.getBranchName());
|
||
bszxPay.setGradeName(bmInfo.getGradeName());
|
||
bszxPay.setClassName(bmInfo.getClassName());
|
||
bszxPay.setAddress(bmInfo.getAddress());
|
||
bszxPay.setWorkUnit(bmInfo.getWorkUnit());
|
||
bszxPay.setPosition(bmInfo.getPosition());
|
||
bszxPay.setAge(bmInfo.getAge());
|
||
bszxPay.setNumber(bmInfo.getNumber());
|
||
}
|
||
if (bszxPayService.save(bszxPay)) {
|
||
// 调起支付
|
||
return success("下单成功", bszxPay);
|
||
}
|
||
return fail("添加失败");
|
||
}
|
||
|
||
@PreAuthorize("hasAuthority('bszx:bszxPay:update')")
|
||
@OperationLog
|
||
@Operation(summary = "修改百色中学-捐款记录")
|
||
@PutMapping()
|
||
public ApiResult<?> update(@RequestBody BszxPay bszxPay) {
|
||
if (bszxPayService.updateById(bszxPay)) {
|
||
return success("修改成功");
|
||
}
|
||
return fail("修改失败");
|
||
}
|
||
|
||
@PreAuthorize("hasAuthority('bszx:bszxPay:remove')")
|
||
@OperationLog
|
||
@Operation(summary = "删除百色中学-捐款记录")
|
||
@DeleteMapping("/{id}")
|
||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||
if (bszxPayService.removeById(id)) {
|
||
return success("删除成功");
|
||
}
|
||
return fail("删除失败");
|
||
}
|
||
|
||
@PreAuthorize("hasAuthority('bszx:bszxPay:save')")
|
||
@OperationLog
|
||
@Operation(summary = "批量添加百色中学-捐款记录")
|
||
@PostMapping("/batch")
|
||
public ApiResult<?> saveBatch(@RequestBody List<BszxPay> list) {
|
||
if (bszxPayService.saveBatch(list)) {
|
||
return success("添加成功");
|
||
}
|
||
return fail("添加失败");
|
||
}
|
||
|
||
@PreAuthorize("hasAuthority('bszx:bszxPay:update')")
|
||
@OperationLog
|
||
@Operation(summary = "批量修改百色中学-捐款记录")
|
||
@PutMapping("/batch")
|
||
public ApiResult<?> removeBatch(@RequestBody BatchParam<BszxPay> batchParam) {
|
||
if (batchParam.update(bszxPayService, "id")) {
|
||
return success("修改成功");
|
||
}
|
||
return fail("修改失败");
|
||
}
|
||
|
||
@PreAuthorize("hasAuthority('bszx:bszxPay:remove')")
|
||
@OperationLog
|
||
@Operation(summary = "批量删除百色中学-捐款记录")
|
||
@DeleteMapping("/batch")
|
||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||
if (bszxPayService.removeByIds(ids)) {
|
||
return success("删除成功");
|
||
}
|
||
return fail("删除失败");
|
||
}
|
||
|
||
@Operation(summary = "查询我的报名记录")
|
||
@GetMapping("/myPage")
|
||
public ApiResult<PageResult<BszxPay>> myPage(BszxPayParam param) {
|
||
// 使用关联查询
|
||
if (getLoginUser() != null) {
|
||
param.setUserId(getLoginUserId());
|
||
return success(bszxPayService.pageRel(param));
|
||
}
|
||
return fail("请先登录", null);
|
||
}
|
||
|
||
@Operation(summary = "统计捐款总金额与人次")
|
||
@GetMapping("/getCount")
|
||
public ApiResult<?> getCount() {
|
||
final HashMap<String, Object> map = new HashMap<>();
|
||
final LambdaQueryWrapper<BszxPay> wrapper = new LambdaQueryWrapper<>();
|
||
final BigDecimal bigDecimal = bszxPayService.sumMoney(wrapper);
|
||
Long count = (long) bszxPayService.count(new LambdaQueryWrapper<BszxPay>());
|
||
map.put("numbers", count);
|
||
map.put("totalMoney", bigDecimal);
|
||
return success(map);
|
||
}
|
||
|
||
@Schema(description = "异步通知")
|
||
@PostMapping("/notify/{tenantId}")
|
||
public String wxNotify(@RequestHeader Map<String, String> header, @RequestBody String body,HttpServletRequest request, @PathVariable("tenantId") Integer tenantId) {
|
||
// 获取支付配置信息用于解密 - 优先使用 Payment:1* 格式
|
||
String key = "Payment:11"; // 微信支付类型为1,使用 Payment:11 格式
|
||
Payment payment = redisUtil.get(key, Payment.class);
|
||
|
||
// 如果 Payment:1* 格式不存在,尝试原有格式
|
||
if (payment == null) {
|
||
String fallbackKey = "Payment:1:".concat(tenantId.toString());
|
||
payment = redisUtil.get(fallbackKey, Payment.class);
|
||
}
|
||
String uploadPath = conf.getUploadPath();
|
||
|
||
// 开发环境
|
||
String mid = "1242289702";
|
||
String apiV3Key = "0b2996803383c3e3391abd9183b54key";
|
||
String serialNumber = "3B458EB14A28160DC094431A21C0508EFA712D1C";
|
||
String privateKey = "/Users/gxwebsoft/JAVA/site-java/cert/bszx/apiclient_key.pem";
|
||
String apiclientCert = "/Users/gxwebsoft/JAVA/site-java/cert/bszx/apiclient_cert.pem";
|
||
String pubKey = "/Users/gxwebsoft/JAVA/site-java/cert/bszx/0f65a8517c284acb90aa83dd0c23e8f6.pem";
|
||
String pubId = "PUB_KEY_ID_0112422897022025011300326200001208";
|
||
// 生产环境
|
||
if (ObjectUtil.isNotEmpty(payment)) {
|
||
// 检查 payment 字段是否为空,并避免直接解析为数字
|
||
mid = payment.getMchId();
|
||
apiV3Key = payment.getApiKey();
|
||
serialNumber = payment.getMerchantSerialNumber();
|
||
// 生产环境使用容器证书路径 /www/wwwroot/file.ws
|
||
privateKey = "/www/wwwroot/file.ws" + payment.getApiclientKey();
|
||
apiclientCert = "/www/wwwroot/file.ws" + payment.getApiclientCert();
|
||
pubKey = "/www/wwwroot/file.ws" + payment.getPubKey();
|
||
pubId = payment.getPubKeyId();
|
||
}
|
||
RequestParam requestParam = new RequestParam.Builder()
|
||
.serialNumber(header.get("wechatpay-serial"))
|
||
.nonce(header.get("wechatpay-nonce"))
|
||
.signature(header.get("wechatpay-signature"))
|
||
.timestamp(header.get("wechatpay-timestamp"))
|
||
.body(body)
|
||
.build();
|
||
|
||
|
||
// NotificationConfig config = new RSAPublicKeyConfig.Builder()
|
||
// .merchantId(mid)
|
||
// .publicKeyFromPath(pubKey)
|
||
// .publicKeyId(pubId)
|
||
// .privateKeyFromPath(privateKey)
|
||
// .merchantSerialNumber(serialNumber)
|
||
// .apiV3Key(apiV3Key)
|
||
// .build();
|
||
|
||
NotificationConfig config = new RSAPublicKeyNotificationConfig.Builder()
|
||
.publicKeyFromPath(pubKey)
|
||
.publicKeyId(pubId)
|
||
.apiV3Key(apiV3Key)
|
||
.build();
|
||
|
||
|
||
// 初始化 NotificationParser
|
||
NotificationParser parser = new NotificationParser(config);
|
||
|
||
// 以支付通知回调为例,验签、解密并转换成 Transaction
|
||
try {
|
||
Transaction transaction = parser.parse(requestParam, Transaction.class);
|
||
final String outTradeNo = transaction.getOutTradeNo();
|
||
final String transactionId = transaction.getTransactionId();
|
||
final Integer total = transaction.getAmount().getTotal();
|
||
final String tradeStateDesc = transaction.getTradeStateDesc();
|
||
final Transaction.TradeStateEnum tradeState = transaction.getTradeState();
|
||
final Transaction.TradeTypeEnum tradeType = transaction.getTradeType();
|
||
System.out.println("transaction = " + transaction);
|
||
System.out.println("tradeStateDesc = " + tradeStateDesc);
|
||
System.out.println("tradeType = " + tradeType);
|
||
System.out.println("tradeState = " + tradeState);
|
||
System.out.println("outTradeNo = " + outTradeNo);
|
||
System.out.println("amount = " + total);
|
||
|
||
if (StrUtil.equals("支付成功", tradeStateDesc)) {
|
||
// 1. 查询要处理的订单
|
||
ShopOrder order = shopOrderService.getByOutTradeNo(outTradeNo);
|
||
// 2. 已支付则跳过
|
||
if (order.getPayStatus().equals(true)) {
|
||
return "SUCCESS";
|
||
}
|
||
// 2. 未支付则处理更新订单状态
|
||
if (order.getPayStatus().equals(false)) {
|
||
// 5. TODO 处理订单状态
|
||
order.setPayTime(DateUtil.date());
|
||
order.setPayStatus(true);
|
||
order.setTransactionId(transactionId);
|
||
order.setPayPrice(new BigDecimal(NumberUtil.decimalFormat("0.00", total * 0.01)));
|
||
order.setExpirationTime(DateUtil.offset(DateUtil.date(), DateField.YEAR, 10));
|
||
System.out.println("实际付款金额 = " + order.getPayPrice());
|
||
return "SUCCESS";
|
||
}
|
||
}
|
||
} catch (Exception $e) {
|
||
System.out.println($e.getMessage());
|
||
System.out.println(Arrays.toString($e.getStackTrace()));
|
||
}
|
||
|
||
return "fail";
|
||
}
|
||
|
||
|
||
@PreAuthorize("hasAuthority('shop:shopOrder:update')")
|
||
@Operation(summary = "修复订单")
|
||
@PutMapping("/repair")
|
||
public ApiResult<?> repair(@RequestBody ShopOrder shopOrder) {
|
||
if (shopOrderService.queryOrderByOutTradeNo(shopOrder)) {
|
||
if (bszxPayService.count(new LambdaQueryWrapper<BszxPay>().eq(BszxPay::getOrderNo, shopOrder.getOrderNo())) == 0) {
|
||
final BszxPay bszxPay = new BszxPay();
|
||
final BszxBm bm = shopOrder.getBm();
|
||
if (ObjectUtil.isNotEmpty(bm)) {
|
||
bszxPay.setName(bm.getName());
|
||
bszxPay.setSex(bm.getSex());
|
||
bszxPay.setClassName(bm.getClassName());
|
||
bszxPay.setGradeName(bm.getGradeName());
|
||
bszxPay.setAddress(bm.getAddress());
|
||
bszxPay.setWorkUnit(bm.getWorkUnit());
|
||
bszxPay.setPosition(bm.getPosition());
|
||
bszxPay.setPrice(shopOrder.getPayPrice());
|
||
bszxPay.setOrderNo(shopOrder.getOrderNo());
|
||
bszxPay.setUserId(shopOrder.getUserId());
|
||
bszxPay.setFormId(shopOrder.getFormId());
|
||
bszxPay.setComments(shopOrder.getComments());
|
||
bszxPayService.save(bszxPay);
|
||
}
|
||
}
|
||
return success("修复成功");
|
||
}
|
||
return fail("修复失败");
|
||
}
|
||
|
||
@Operation(summary = "获取捐款证书")
|
||
@GetMapping("/generatePayCert/{id}")
|
||
public ApiResult<?> generatePayCert(@PathVariable("id") Integer id) throws Exception {
|
||
return success("获取捐款证书", bszxPayService.generatePayCert(id));
|
||
}
|
||
}
|