202506271817

This commit is contained in:
张潘 2025-06-27 18:17:38 +08:00
parent 323a00026a
commit 999720d16e
4 changed files with 368 additions and 44 deletions

View File

@ -0,0 +1,164 @@
package com.ruoyi.system.controller;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.ControllerUtil.*;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 游标工具控制器
*
* @author Mr. Zhang Pan
* @version 1.0
* @date 2025-01-10
*/
@RestController
public class CursorUtil extends BaseController {
@Autowired
private IServiceGoodsService serviceGoodsService;
@Autowired
private IGoodsOrderCursorService goodsOrderCursorService;
@Autowired
private IUsersService usersService;
@Autowired
private IUserAddressService userAddressService;
@Autowired
private IGoodsOrderService goodsOrderService;
@Autowired
private WechatPayUtil wechatPayUtil;
@Autowired
private IOrderService orderService;
@Autowired
private IOrderLogService orderLogService;
@Autowired
private IOrderCommentService orderCommentService;
@Autowired
private IUsersInvoiceInfoService usersInvoiceInfoService;
/**
* 小程序接口维护用户发票信息新增/修改
* POST /api/user/invoice/info
* @param params 发票信息参数
* @param request 请求对象
* @return AjaxResult
*/
@PostMapping("/api/user/invoice/info")
public AjaxResult saveOrUpdateInvoiceInfo(@RequestBody Map<String, Object> params, HttpServletRequest request) {
// 1. 校验用户登录
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AjaxResult.error("用户未登录或token无效");
}
Users user = (Users) userValidation.get("user");
if (user == null) {
return AjaxResult.error("用户信息获取失败");
}
// 2. 构建发票对象
UsersInvoiceInfo invoiceInfo = new UsersInvoiceInfo();
invoiceInfo.setId(params.get("id") != null ? Integer.valueOf(params.get("id").toString()) : null);
invoiceInfo.setUid(user.getId() != null ? user.getId().intValue() : null);
invoiceInfo.setInvoiceTitle((String) params.get("invoiceTitle"));
invoiceInfo.setTaxNumber((String) params.get("taxNumber"));
invoiceInfo.setBankName((String) params.get("bankName"));
invoiceInfo.setBankAccount((String) params.get("bankAccount"));
invoiceInfo.setAddress((String) params.get("address"));
invoiceInfo.setPhone((String) params.get("phone"));
invoiceInfo.setEmail((String) params.get("email"));
invoiceInfo.setWechat((String) params.get("wechat"));
invoiceInfo.setType(params.get("type") != null ? Integer.valueOf(params.get("type").toString()) : 1);
invoiceInfo.setCategory(params.get("category") != null ? Integer.valueOf(params.get("category").toString()) : 1);
// 3. 保存或更新
try {
if (invoiceInfo.getId() != null) {
usersInvoiceInfoService.updateUsersInvoiceInfo(invoiceInfo);
} else {
usersInvoiceInfoService.insertUsersInvoiceInfo(invoiceInfo);
}
return AjaxResult.success("发票信息保存成功");
} catch (Exception e) {
return AjaxResult.error("发票信息保存失败: " + e.getMessage());
}
}
/**
* 小程序接口查询当前用户所有发票信息
* GET /api/user/invoice/list
* @param request 请求对象
* @return AjaxResult
*/
@GetMapping("/api/user/invoice/list")
public AjaxResult getInvoicelist(HttpServletRequest request) {
// 1. 校验用户登录
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AjaxResult.error("用户未登录或token无效");
}
Users user = (Users) userValidation.get("user");
if (user == null) {
return AjaxResult.error("用户信息获取失败");
}
UsersInvoiceInfo invoiceInfo = new UsersInvoiceInfo();
invoiceInfo.setUid(user.getId() != null ? user.getId().intValue() : null);
// 2. 查询所有发票信息
List<UsersInvoiceInfo> list = usersInvoiceInfoService.selectUsersInvoiceInfoList(invoiceInfo);
return AjaxResult.success(list);
}
/**
* 小程序接口删除用户单个发票信息
* DELETE /api/user/invoice/delete/{id}
* @param id 发票ID
* @param request 请求对象
* @return AjaxResult
*/
@DeleteMapping("/api/user/invoice/delete/{id}")
public AjaxResult deleteInvoiceInfo(@PathVariable Integer id, HttpServletRequest request) {
// 1. 校验用户登录
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AjaxResult.error("用户未登录或token无效");
}
Users user = (Users) userValidation.get("user");
if (user == null) {
return AjaxResult.error("用户信息获取失败");
}
// 2. 删除发票需校验归属
try {
int result = usersInvoiceInfoService.deleteUsersInvoiceInfoById(id);
if (result > 0) {
return AjaxResult.success("删除成功");
} else {
return AjaxResult.error("删除失败或无权限");
}
} catch (Exception e) {
return AjaxResult.error("删除异常: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,204 @@
package com.ruoyi.system.ControllerUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.system.config.WechatConfig;
import com.ruoyi.common.utils.spring.SpringUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.*;
/**
* 微信支付v3工具类小程序支付/退款/提现
* 你需要在WechatConfig中补充apiv3KeyprivateKeyPathserialNo等配置并实现v3签名算法
* 所有v3接口均需用商户API私钥签名回包敏感字段需用apiv3Key解密
* 详细文档见https://pay.weixin.qq.com/wiki/doc/apiv3/
*/
@Component
public class WechatPayV3Util {
private static final RestTemplate restTemplate = createRestTemplate();
private static RestTemplate createRestTemplate() {
RestTemplate template = new RestTemplate();
template.getMessageConverters().forEach(converter -> {
if (converter instanceof org.springframework.http.converter.StringHttpMessageConverter) {
((org.springframework.http.converter.StringHttpMessageConverter) converter)
.setDefaultCharset(java.nio.charset.StandardCharsets.UTF_8);
}
});
return template;
}
private static WechatConfig wechatConfig() {
return SpringUtils.getBean(WechatConfig.class);
}
/**
* v3 小程序支付下单JSAPI
* @param openid 用户openid
* @param orderNo 商户订单号
* @param totalFee 支付金额
* @param body 商品描述
* @param notifyUrl 回调通知地址
* @return 下单结果包含前端调起支付的参数
*/
public Map<String, Object> jsapiPay(String openid, String orderNo, int totalFee, String body, String notifyUrl) {
Map<String, Object> result = new HashMap<>();
try {
String appid = wechatConfig().getAppid();
String mchid = wechatConfig().getMchid();
// TODO: 你需要在WechatConfig中补充apiv3KeyprivateKeyPathserialNo等配置
Map<String, Object> amount = new HashMap<>();
amount.put("total", totalFee);
amount.put("currency", "CNY");
Map<String, Object> payer = new HashMap<>();
payer.put("openid", openid);
Map<String, Object> params = new HashMap<>();
params.put("appid", appid);
params.put("mchid", mchid);
params.put("description", body);
params.put("out_trade_no", orderNo);
params.put("notify_url", notifyUrl);
params.put("amount", amount);
params.put("payer", payer);
String bodyJson = new JSONObject(params).toJSONString();
// 生成v3签名串构造Authorization头
// TODO: 你需要实现v3签名算法生成Authorization头
String authorization = "请实现v3签名算法生成Authorization头";
String v3Url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authorization);
headers.set("Content-Type", "application/json");
headers.set("Accept", "application/json");
HttpEntity<String> requestEntity = new HttpEntity<>(bodyJson, headers);
ResponseEntity<String> response = restTemplate.exchange(v3Url, HttpMethod.POST, requestEntity, String.class);
// 解析响应获取prepay_id
// TODO: 你需要根据微信v3返回结构处理部分字段加密需用apiv3Key解密
result.put("success", true);
result.put("response", response.getBody());
result.put("message", "v3下单接口请求已发送请根据返回内容进一步处理");
} catch (Exception e) {
result.put("success", false);
result.put("message", "v3下单异常" + e.getMessage());
}
return result;
}
/**
* v3 申请退款
* @param orderNo 商户订单号
* @param refundNo 退款单号
* @param totalFee 订单总金额
* @param refundFee 退款金额
* @param reason 退款原因
* @param notifyUrl 退款回调通知地址
* @return 退款结果
*/
public Map<String, Object> refund(String orderNo, String refundNo, int totalFee, int refundFee, String reason, String notifyUrl) {
Map<String, Object> result = new HashMap<>();
try {
String appid = wechatConfig().getAppid();
String mchid = wechatConfig().getMchid();
// TODO: 你需要在WechatConfig中补充apiv3KeyprivateKeyPathserialNo等配置
Map<String, Object> amount = new HashMap<>();
amount.put("refund", refundFee);
amount.put("total", totalFee);
amount.put("currency", "CNY");
Map<String, Object> params = new HashMap<>();
params.put("out_trade_no", orderNo);
params.put("out_refund_no", refundNo);
params.put("reason", reason);
params.put("notify_url", notifyUrl);
params.put("amount", amount);
String bodyJson = new JSONObject(params).toJSONString();
// 生成v3签名串构造Authorization头
// TODO: 你需要实现v3签名算法生成Authorization头
String authorization = "请实现v3签名算法生成Authorization头";
String v3Url = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authorization);
headers.set("Content-Type", "application/json");
headers.set("Accept", "application/json");
HttpEntity<String> requestEntity = new HttpEntity<>(bodyJson, headers);
ResponseEntity<String> response = restTemplate.exchange(v3Url, HttpMethod.POST, requestEntity, String.class);
// 解析响应
// TODO: 你需要根据微信v3返回结构处理部分字段加密需用apiv3Key解密
result.put("success", true);
result.put("response", response.getBody());
result.put("message", "v3退款接口请求已发送请根据返回内容进一步处理");
} catch (Exception e) {
result.put("success", false);
result.put("message", "v3退款异常" + e.getMessage());
}
return result;
}
/**
* v3 商户提现转账到零钱
* @param openid 用户openid
* @param amount 金额
* @param desc 提现描述
* @return 提现结果
*/
public Map<String, Object> withdraw(String openid, int amount, String desc) {
Map<String, Object> result = new HashMap<>();
try {
String appid = wechatConfig().getAppid();
String mchid = wechatConfig().getMchid();
// TODO: 你需要在WechatConfig中补充apiv3KeyprivateKeyPathserialNo等配置
String outBatchNo = "BATCH" + System.currentTimeMillis();
String batchName = "商户提现";
String batchRemark = desc;
String detailNo = "DETAIL" + System.currentTimeMillis();
Map<String, Object> detail = new HashMap<>();
detail.put("out_detail_no", detailNo);
detail.put("transfer_amount", amount);
detail.put("transfer_remark", desc);
detail.put("openid", openid);
List<Map<String, Object>> detailList = new ArrayList<>();
detailList.add(detail);
Map<String, Object> params = new HashMap<>();
params.put("appid", appid);
params.put("out_batch_no", outBatchNo);
params.put("batch_name", batchName);
params.put("batch_remark", batchRemark);
params.put("total_amount", amount);
params.put("total_num", 1);
params.put("transfer_detail_list", detailList);
String bodyJson = new JSONObject(params).toJSONString();
// 生成v3签名串构造Authorization头
// TODO: 你需要实现v3签名算法生成Authorization头
String authorization = "请实现v3签名算法生成Authorization头";
String v3Url = "https://api.mch.weixin.qq.com/v3/transfer/batches";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authorization);
headers.set("Content-Type", "application/json");
headers.set("Accept", "application/json");
HttpEntity<String> requestEntity = new HttpEntity<>(bodyJson, headers);
ResponseEntity<String> response = restTemplate.exchange(v3Url, HttpMethod.POST, requestEntity, String.class);
// 解析响应
// TODO: 你需要根据微信v3返回结构处理部分字段加密需用apiv3Key解密
result.put("success", true);
result.put("response", response.getBody());
result.put("message", "v3提现接口请求已发送请根据返回内容进一步处理");
} catch (Exception e) {
result.put("success", false);
result.put("message", "v3提现异常" + e.getMessage());
}
return result;
}
}

View File

@ -1,44 +0,0 @@
import request from '@/utils/request'
// 查询发票信息列表
export function listInfo(query) {
return request({
url: '/system/info/list',
method: 'get',
params: query
})
}
// 查询发票信息详细
export function getInfo(id) {
return request({
url: '/system/info/' + id,
method: 'get'
})
}
// 新增发票信息
export function addInfo(data) {
return request({
url: '/system/info',
method: 'post',
data: data
})
}
// 修改发票信息
export function updateInfo(data) {
return request({
url: '/system/info',
method: 'put',
data: data
})
}
// 删除发票信息
export function delInfo(id) {
return request({
url: '/system/info/' + id,
method: 'delete'
})
}