202506271817
This commit is contained in:
parent
323a00026a
commit
999720d16e
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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中补充apiv3Key、privateKeyPath、serialNo等配置,并实现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中补充apiv3Key、privateKeyPath、serialNo等配置
|
||||||
|
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中补充apiv3Key、privateKeyPath、serialNo等配置
|
||||||
|
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中补充apiv3Key、privateKeyPath、serialNo等配置
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue