|
@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
|
import com.alibaba.fastjson2.JSON;
|
|
import com.alibaba.fastjson2.JSON;
|
|
|
import com.ruoyi.app.order.dto.OrderPushBodyDto;
|
|
import com.ruoyi.app.order.dto.OrderPushBodyDto;
|
|
|
import com.ruoyi.app.order.OrderLifecycleService;
|
|
import com.ruoyi.app.order.OrderLifecycleService;
|
|
|
|
|
+import com.ruoyi.app.pay.dto.OmgCallbackRequest;
|
|
|
|
|
+import com.ruoyi.app.pay.dto.OmgOrderRequest;
|
|
|
import com.ruoyi.app.pay.dto.OmgRefundOutcome;
|
|
import com.ruoyi.app.pay.dto.OmgRefundOutcome;
|
|
|
import com.ruoyi.app.utils.PayPush;
|
|
import com.ruoyi.app.utils.PayPush;
|
|
|
import com.ruoyi.app.utils.event.PushEventService;
|
|
import com.ruoyi.app.utils.event.PushEventService;
|
|
@@ -30,8 +32,8 @@ import com.ruoyi.system.service.IPosStoreOmgService;
|
|
|
import com.ruoyi.system.utils.Auth;
|
|
import com.ruoyi.system.utils.Auth;
|
|
|
import com.ruoyi.system.utils.JwtUtil;
|
|
import com.ruoyi.system.utils.JwtUtil;
|
|
|
import com.ruoyi.system.utils.OrderLogHelper;
|
|
import com.ruoyi.system.utils.OrderLogHelper;
|
|
|
-import jakarta.servlet.http.HttpServletRequest;
|
|
|
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
|
|
|
+import jakarta.validation.Valid;
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
@@ -41,11 +43,12 @@ import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.transaction.support.TransactionSynchronization;
|
|
import org.springframework.transaction.support.TransactionSynchronization;
|
|
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
|
|
|
+import org.springframework.web.bind.annotation.ModelAttribute;
|
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
|
import org.springframework.web.bind.annotation.PostMapping;
|
|
import org.springframework.web.bind.annotation.PostMapping;
|
|
|
|
|
+import org.springframework.web.bind.annotation.RequestHeader;
|
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
import org.springframework.web.bind.annotation.RequestMethod;
|
|
import org.springframework.web.bind.annotation.RequestMethod;
|
|
|
-import org.springframework.web.bind.annotation.RequestParam;
|
|
|
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
@@ -53,7 +56,6 @@ import java.net.URLEncoder;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.charset.StandardCharsets;
|
|
|
import java.text.SimpleDateFormat;
|
|
import java.text.SimpleDateFormat;
|
|
|
import java.util.Date;
|
|
import java.util.Date;
|
|
|
-import java.util.Enumeration;
|
|
|
|
|
import java.util.LinkedHashMap;
|
|
import java.util.LinkedHashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Locale;
|
|
import java.util.Locale;
|
|
@@ -127,8 +129,9 @@ public class OmgPayController extends BaseController {
|
|
|
@RepeatSubmit(interval = 1000, message = "请求过于频繁")
|
|
@RepeatSubmit(interval = 1000, message = "请求过于频繁")
|
|
|
@PostMapping("/create")
|
|
@PostMapping("/create")
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
- public AjaxResult create(@RequestParam String orderid, HttpServletRequest request) {
|
|
|
|
|
- String token = request.getHeader("token");
|
|
|
|
|
|
|
+ public AjaxResult create(@RequestHeader String token,
|
|
|
|
|
+ @Valid @ModelAttribute OmgOrderRequest request) {
|
|
|
|
|
+ String orderid = request.getOrderid();
|
|
|
String userId;
|
|
String userId;
|
|
|
try {
|
|
try {
|
|
|
userId = new JwtUtil().getusid(token);
|
|
userId = new JwtUtil().getusid(token);
|
|
@@ -243,10 +246,11 @@ public class OmgPayController extends BaseController {
|
|
|
@Anonymous
|
|
@Anonymous
|
|
|
@PostMapping(value = "/notify", produces = "text/plain;charset=UTF-8")
|
|
@PostMapping(value = "/notify", produces = "text/plain;charset=UTF-8")
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
- public String notify(HttpServletRequest request) {
|
|
|
|
|
|
|
+ public String notify(@ModelAttribute OmgCallbackRequest callback,
|
|
|
|
|
+ @RequestHeader(value = "X-Forwarded-For", required = false) String forwardedFor) {
|
|
|
Map<String, String> form;
|
|
Map<String, String> form;
|
|
|
try {
|
|
try {
|
|
|
- form = collectForm(request);
|
|
|
|
|
|
|
+ form = callback.toParameterMap();
|
|
|
} catch (IllegalArgumentException e) {
|
|
} catch (IllegalArgumentException e) {
|
|
|
log.warn("OMG callback rejected: {}", e.getMessage());
|
|
log.warn("OMG callback rejected: {}", e.getMessage());
|
|
|
return "1|OK";
|
|
return "1|OK";
|
|
@@ -255,7 +259,7 @@ public class OmgPayController extends BaseController {
|
|
|
// 记录 IPN 日志
|
|
// 记录 IPN 日志
|
|
|
try {
|
|
try {
|
|
|
IpnLog ipnLog = new IpnLog();
|
|
IpnLog ipnLog = new IpnLog();
|
|
|
- ipnLog.setIp(new com.ruoyi.app.utils.IpUtils().getIpAddr(request));
|
|
|
|
|
|
|
+ ipnLog.setIp(callbackIp(forwardedFor));
|
|
|
ipnLog.setIpnLog(auditJson(form));
|
|
ipnLog.setIpnLog(auditJson(form));
|
|
|
ipnLogService.insertIpnLog(ipnLog);
|
|
ipnLogService.insertIpnLog(ipnLog);
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
@@ -377,10 +381,11 @@ public class OmgPayController extends BaseController {
|
|
|
*/
|
|
*/
|
|
|
@Anonymous
|
|
@Anonymous
|
|
|
@RequestMapping(value = "/return", method = {RequestMethod.GET, RequestMethod.POST})
|
|
@RequestMapping(value = "/return", method = {RequestMethod.GET, RequestMethod.POST})
|
|
|
- public void returnCallback(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
|
|
|
|
|
|
+ public void returnCallback(@ModelAttribute OmgCallbackRequest callback,
|
|
|
|
|
+ HttpServletResponse response) throws IOException {
|
|
|
String ddId = "";
|
|
String ddId = "";
|
|
|
try {
|
|
try {
|
|
|
- Map<String, String> form = collectForm(request);
|
|
|
|
|
|
|
+ Map<String, String> form = callback.toParameterMap();
|
|
|
String mtn = form.get("MerchantTradeNo");
|
|
String mtn = form.get("MerchantTradeNo");
|
|
|
// 由 MerchantTradeNo 反查流水拿 ddId(MTN 不再编码 ddId)
|
|
// 由 MerchantTradeNo 反查流水拿 ddId(MTN 不再编码 ddId)
|
|
|
if (mtn != null && !mtn.isEmpty()) {
|
|
if (mtn != null && !mtn.isEmpty()) {
|
|
@@ -410,17 +415,18 @@ public class OmgPayController extends BaseController {
|
|
|
*/
|
|
*/
|
|
|
@Anonymous
|
|
@Anonymous
|
|
|
@PostMapping(value = "/paymentInfo", produces = "text/plain;charset=UTF-8")
|
|
@PostMapping(value = "/paymentInfo", produces = "text/plain;charset=UTF-8")
|
|
|
- public String paymentInfoCallback(HttpServletRequest request) {
|
|
|
|
|
|
|
+ public String paymentInfoCallback(@ModelAttribute OmgCallbackRequest callback,
|
|
|
|
|
+ @RequestHeader(value = "X-Forwarded-For", required = false) String forwardedFor) {
|
|
|
Map<String, String> form;
|
|
Map<String, String> form;
|
|
|
try {
|
|
try {
|
|
|
- form = collectForm(request);
|
|
|
|
|
|
|
+ form = callback.toParameterMap();
|
|
|
} catch (IllegalArgumentException e) {
|
|
} catch (IllegalArgumentException e) {
|
|
|
log.warn("OMG paymentInfo rejected: {}", e.getMessage());
|
|
log.warn("OMG paymentInfo rejected: {}", e.getMessage());
|
|
|
return "1|OK";
|
|
return "1|OK";
|
|
|
}
|
|
}
|
|
|
try {
|
|
try {
|
|
|
IpnLog ipnLog = new IpnLog();
|
|
IpnLog ipnLog = new IpnLog();
|
|
|
- ipnLog.setIp(new com.ruoyi.app.utils.IpUtils().getIpAddr(request));
|
|
|
|
|
|
|
+ ipnLog.setIp(callbackIp(forwardedFor));
|
|
|
ipnLog.setIpnLog(auditJson(form));
|
|
ipnLog.setIpnLog(auditJson(form));
|
|
|
ipnLogService.insertIpnLog(ipnLog);
|
|
ipnLogService.insertIpnLog(ipnLog);
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
@@ -472,14 +478,16 @@ public class OmgPayController extends BaseController {
|
|
|
@Anonymous
|
|
@Anonymous
|
|
|
@Auth
|
|
@Auth
|
|
|
@GetMapping("/paymentInfo/{orderid}")
|
|
@GetMapping("/paymentInfo/{orderid}")
|
|
|
- public AjaxResult getPaymentInfo(@PathVariable String orderid, HttpServletRequest request) {
|
|
|
|
|
- String token = request.getHeader("token");
|
|
|
|
|
|
|
+ public AjaxResult getPaymentInfo(@RequestHeader String token, @PathVariable String orderid) {
|
|
|
String userId;
|
|
String userId;
|
|
|
try {
|
|
try {
|
|
|
userId = new JwtUtil().getusid(token);
|
|
userId = new JwtUtil().getusid(token);
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
return error(MessageUtils.message("no.order.id.error"));
|
|
return error(MessageUtils.message("no.order.id.error"));
|
|
|
}
|
|
}
|
|
|
|
|
+ if (userId == null || userId.isEmpty()) {
|
|
|
|
|
+ return error("请先登录");
|
|
|
|
|
+ }
|
|
|
PosOrder order = posOrderService.getOne(new QueryWrapper<PosOrder>().eq("dd_id", orderid));
|
|
PosOrder order = posOrderService.getOne(new QueryWrapper<PosOrder>().eq("dd_id", orderid));
|
|
|
if (order == null || order.getUserId() == null || !userId.equals(String.valueOf(order.getUserId()))) {
|
|
if (order == null || order.getUserId() == null || !userId.equals(String.valueOf(order.getUserId()))) {
|
|
|
return error("无权操作该订单");
|
|
return error("无权操作该订单");
|
|
@@ -505,14 +513,18 @@ public class OmgPayController extends BaseController {
|
|
|
@Anonymous
|
|
@Anonymous
|
|
|
@Auth
|
|
@Auth
|
|
|
@PostMapping("/refund")
|
|
@PostMapping("/refund")
|
|
|
- public AjaxResult refund(@RequestParam String orderid, HttpServletRequest request) {
|
|
|
|
|
- String token = request.getHeader("token");
|
|
|
|
|
|
|
+ public AjaxResult refund(@RequestHeader String token,
|
|
|
|
|
+ @Valid @ModelAttribute OmgOrderRequest request) {
|
|
|
|
|
+ String orderid = request.getOrderid();
|
|
|
String userId;
|
|
String userId;
|
|
|
try {
|
|
try {
|
|
|
userId = new JwtUtil().getusid(token);
|
|
userId = new JwtUtil().getusid(token);
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
return error(MessageUtils.message("no.order.id.error"));
|
|
return error(MessageUtils.message("no.order.id.error"));
|
|
|
}
|
|
}
|
|
|
|
|
+ if (userId == null || userId.isEmpty()) {
|
|
|
|
|
+ return error("请先登录");
|
|
|
|
|
+ }
|
|
|
PosOrder order = posOrderService.getOne(new QueryWrapper<PosOrder>().eq("dd_id", orderid));
|
|
PosOrder order = posOrderService.getOne(new QueryWrapper<PosOrder>().eq("dd_id", orderid));
|
|
|
if (order == null) {
|
|
if (order == null) {
|
|
|
return error("订单不存在");
|
|
return error("订单不存在");
|
|
@@ -693,8 +705,9 @@ public class OmgPayController extends BaseController {
|
|
|
@Auth
|
|
@Auth
|
|
|
@RepeatSubmit(interval = 2000, message = "查询过于频繁")
|
|
@RepeatSubmit(interval = 2000, message = "查询过于频繁")
|
|
|
@PostMapping("/query")
|
|
@PostMapping("/query")
|
|
|
- public AjaxResult query(@RequestParam String orderid, HttpServletRequest request) {
|
|
|
|
|
- String token = request.getHeader("token");
|
|
|
|
|
|
|
+ public AjaxResult query(@RequestHeader String token,
|
|
|
|
|
+ @Valid @ModelAttribute OmgOrderRequest request) {
|
|
|
|
|
+ String orderid = request.getOrderid();
|
|
|
String userId;
|
|
String userId;
|
|
|
try {
|
|
try {
|
|
|
userId = new JwtUtil().getusid(token);
|
|
userId = new JwtUtil().getusid(token);
|
|
@@ -919,23 +932,12 @@ public class OmgPayController extends BaseController {
|
|
|
|
|
|
|
|
// ============================ 辅助 ============================
|
|
// ============================ 辅助 ============================
|
|
|
|
|
|
|
|
- /** 收集 form-urlencoded 回调参数为 Map(OMG 明文参数,含 CheckMacValue)。 */
|
|
|
|
|
- Map<String, String> collectForm(HttpServletRequest req) {
|
|
|
|
|
- Map<String, String> map = new LinkedHashMap<>();
|
|
|
|
|
- Enumeration<String> names = req.getParameterNames();
|
|
|
|
|
- while (names.hasMoreElements()) {
|
|
|
|
|
- String n = names.nextElement();
|
|
|
|
|
- String[] values = req.getParameterValues(n);
|
|
|
|
|
- if (n == null || n.isEmpty() || n.length() > 100 || values == null || values.length != 1
|
|
|
|
|
- || values[0] == null || values[0].length() > 4096) {
|
|
|
|
|
- throw new IllegalArgumentException("invalid or duplicate callback parameter");
|
|
|
|
|
- }
|
|
|
|
|
- map.put(n, values[0]);
|
|
|
|
|
- if (map.size() > 100) {
|
|
|
|
|
- throw new IllegalArgumentException("too many callback parameters");
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ private String callbackIp(String forwardedFor) {
|
|
|
|
|
+ if (forwardedFor == null || forwardedFor.isBlank()) {
|
|
|
|
|
+ return "unknown";
|
|
|
}
|
|
}
|
|
|
- return map;
|
|
|
|
|
|
|
+ String firstIp = forwardedFor.split(",", 2)[0].trim();
|
|
|
|
|
+ return firstIp.isEmpty() || firstIp.length() > 64 ? "unknown" : firstIp;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private int toInt(String s, int def) {
|
|
private int toInt(String s, int def) {
|