Files
java-10561/src/main/java/com/gxwebsoft/bszx/controller/BszxPayController.java
2025-09-06 11:58:18 +08:00

344 lines
13 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.gxwebsoft.bszx.controller;
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.time.LocalDateTime;
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(LocalDateTime.now());
order.setPayStatus(true);
order.setTransactionId(transactionId);
order.setPayPrice(new BigDecimal(NumberUtil.decimalFormat("0.00", total * 0.01)));
order.setExpirationTime(LocalDateTime.now().plusYears(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));
}
}