|
@@ -0,0 +1,270 @@
|
|
|
|
+package com.qs.mp.web.controller.api.callback;
|
|
|
|
+
|
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|
|
|
+import com.eptok.yspay.opensdkjava.common.Constants;
|
|
|
|
+import com.eptok.yspay.opensdkjava.fund.MercFundApi;
|
|
|
|
+import com.eptok.yspay.opensdkjava.orderpay.OrderQueryApi;
|
|
|
|
+import com.eptok.yspay.opensdkjava.pojo.vo.OnlineReqDataVo;
|
|
|
|
+import com.eptok.yspay.opensdkjava.util.DateUtil;
|
|
|
|
+import com.eptok.yspay.opensdkjava.util.YsOnlineSignUtils;
|
|
|
|
+import com.eptok.yspay.opensdkjava.util.YsfSignUtil;
|
|
|
|
+import com.qs.mp.common.constant.DivisionLogStatusConstants;
|
|
|
|
+import com.qs.mp.common.constant.YsServerApiConstants;
|
|
|
|
+import com.qs.mp.common.domain.YsCallLog;
|
|
|
|
+import com.qs.mp.common.enums.PayOrderStatusEnum;
|
|
|
|
+import com.qs.mp.common.service.IYsCallLogService;
|
|
|
|
+import com.qs.mp.common.utils.LogUtil;
|
|
|
|
+import com.qs.mp.pay.domain.DivisionLog;
|
|
|
|
+import com.qs.mp.pay.domain.PayOrder;
|
|
|
|
+import com.qs.mp.pay.service.IDivisionLogService;
|
|
|
|
+import com.qs.mp.pay.service.IPayOrderService;
|
|
|
|
+import com.qs.mp.pay.service.IWalletService;
|
|
|
|
+import java.io.IOException;
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
+import java.util.Date;
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.Map;
|
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
+import org.springframework.web.bind.annotation.RequestMethod;
|
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 银盛支付回调控制类
|
|
|
|
+ *
|
|
|
|
+ * @author Evan
|
|
|
|
+ * @date 2023/3/28
|
|
|
|
+ */
|
|
|
|
+@RestController
|
|
|
|
+@RequestMapping("/service/notify")
|
|
|
|
+public class YsPayCallBackController {
|
|
|
|
+
|
|
|
|
+ private final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ @Value("${ys-pay.private-key-path}")
|
|
|
|
+ private String privateKeyPath;
|
|
|
|
+
|
|
|
|
+ @Value("${ys-pay.public-key-path}")
|
|
|
|
+ private String publicKeyPath;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ @Value("${ys-pay.partner-id}")
|
|
|
|
+ private String partnerId;
|
|
|
|
+
|
|
|
|
+ @Value("${ys-pay.private-key-pass}")
|
|
|
|
+ private String privateKeyPass;
|
|
|
|
+
|
|
|
|
+ @Value("${ys-pay.div-notify-url}")
|
|
|
|
+ private String ysDivNotifyUrl;
|
|
|
|
+
|
|
|
|
+ @Value("${ys-pay.master-seller-id}")
|
|
|
|
+ private String masterSellerId;
|
|
|
|
+
|
|
|
|
+ @Value("${ys-pay.child-seller-id}")
|
|
|
|
+ private String childSellerId;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private IPayOrderService payOrderService;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private IWalletService walletService;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private IYsCallLogService ysCallLogService;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private IDivisionLogService divisionLogService;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ @RequestMapping(value = "/ysCallback", method = RequestMethod.GET)
|
|
|
|
+ public void payCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
|
|
|
+ Map<String, String[]> reqParams = request.getParameterMap();
|
|
|
|
+
|
|
|
|
+ Map<String, String> params = new HashMap<>();
|
|
|
|
+ for (String key : reqParams.keySet()) {
|
|
|
|
+ String[] values = reqParams.get(key);
|
|
|
|
+ String valueStr = "";
|
|
|
|
+ for (int i = 0; i < values.length; i++) {
|
|
|
|
+ valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
|
|
|
|
+ }
|
|
|
|
+ params.put(key, valueStr);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ String sign = params.get("sign");
|
|
|
|
+ boolean flag = YsOnlineSignUtils.rsaCheckContent(params, sign, Constants.CHARSET_UTF_8, publicKeyPath);
|
|
|
|
+ if (!flag) {
|
|
|
|
+ logger.error("ys支付回调-check sign error");
|
|
|
|
+ responseWrite(response, "fail");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ String code = params.get("code");
|
|
|
|
+ String tradeNo = params.get("out_trade_no");
|
|
|
|
+ String orderNo = params.get("trade_no");
|
|
|
|
+ String tradeStatus = params.get("trade_status");
|
|
|
|
+ String completeDate = params.get("notify_time");
|
|
|
|
+ int totalAmount = new BigDecimal(request.getParameter("total_amount")).multiply(new BigDecimal(100)).intValue();
|
|
|
|
+ logger.info("data: tradeNo:"+tradeNo +" orderNo:"+orderNo +" totalAmount:"+totalAmount+ "tradeStatus:"+tradeStatus);
|
|
|
|
+
|
|
|
|
+ if (StringUtils.isBlank(code) || StringUtils.isBlank(tradeNo) || StringUtils.isBlank(orderNo) || StringUtils.isBlank(tradeStatus)) {
|
|
|
|
+ logger.error("ys支付回调-参数错误");
|
|
|
|
+ responseWrite(response, "fail");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ PayOrder order = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>()
|
|
|
|
+ .eq(PayOrder::getTradeNo, tradeNo));
|
|
|
|
+
|
|
|
|
+ if (PayOrderStatusEnum.SUCCESS.getValue().equals(order.getOrderStatus())) {
|
|
|
|
+ logger.info("支付订单已成功,消息忽略,shopOrderNo:" + orderNo);
|
|
|
|
+ responseWrite(response,"true");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (!"TRADE_SUCCESS".equals(tradeStatus)) {
|
|
|
|
+ logger.error("ys-非支付成功消息,忽略");
|
|
|
|
+ responseWrite(response,"fail");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //回调金额与订单金额一致性校验
|
|
|
|
+ if(order.getTransactionAmount() != totalAmount){
|
|
|
|
+ logger.error("回调金额与订单金额不一致");
|
|
|
|
+ responseWrite(response,"fail");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ PayOrder payOrder = payOrderService.getById(order.getOrderId());
|
|
|
|
+ payOrder.setOrderNo(orderNo);
|
|
|
|
+ payOrder.setCompleteDate(completeDate);
|
|
|
|
+// payOrder.setChannelNo(channelNo);
|
|
|
|
+ payOrder.setOrderStatus(PayOrderStatusEnum.SUCCESS.getValue());
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ // 更新订单,单个事务处理
|
|
|
|
+ logger.info("ys支付回调消息更新成功 orderId:" + order.getOrderId());
|
|
|
|
+ walletService.payOrderStatusHandle(payOrder);
|
|
|
|
+
|
|
|
|
+ // 订单支付状态单独保存
|
|
|
|
+ LambdaUpdateWrapper<PayOrder> updateWrapper = new LambdaUpdateWrapper<>();
|
|
|
|
+ updateWrapper.eq(PayOrder::getOrderStatus, PayOrderStatusEnum.WAIT.getValue());
|
|
|
|
+ updateWrapper.eq(PayOrder::getOrderId, order.getOrderId());
|
|
|
|
+ boolean ret = payOrderService.update(payOrder, updateWrapper);
|
|
|
|
+ if (!ret) {
|
|
|
|
+ LogUtil.error(logger, "ys支付回调消息更新支付单状态失败 orderId:" + order.getOrderId());
|
|
|
|
+ responseWrite(response,"fail");
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e){
|
|
|
|
+ LogUtil.error(logger, e, "ys支付回调消息处理异常 orderId:" + order.getOrderId());
|
|
|
|
+ responseWrite(response,"fail");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 调用分账登记接口
|
|
|
|
+ OnlineReqDataVo req = new OnlineReqDataVo();
|
|
|
|
+ req.setReqUrl(YsServerApiConstants.COMMON_API);
|
|
|
|
+ req.setNotifyUrl(ysDivNotifyUrl);
|
|
|
|
+ req.setPartnerId(partnerId);
|
|
|
|
+ req.setPrivateKeyFilePath(privateKeyPath);
|
|
|
|
+ req.setPrivateKeyPassword(privateKeyPass);
|
|
|
|
+ req.setYsPublicKeyFilePath(publicKeyPath);
|
|
|
|
+ // 分账登记业务参数
|
|
|
|
+ Map<String, Object> bizContent = new HashMap<>();
|
|
|
|
+ String divTradeNo = DateUtil.getDateNowYmd() + DateUtil.getRandom(14);
|
|
|
|
+ bizContent.put("out_trade_no", divTradeNo);
|
|
|
|
+ bizContent.put("payee_usercode", partnerId);
|
|
|
|
+ bizContent.put("total_amount", request.getParameter("total_amount"));
|
|
|
|
+ bizContent.put("is_divistion", "01");
|
|
|
|
+ bizContent.put("is_again_division", "N");
|
|
|
|
+ bizContent.put("division_mode", "01");
|
|
|
|
+ // 分账明细
|
|
|
|
+ JSONArray divList = new JSONArray();
|
|
|
|
+ JSONObject divObject = new JSONObject();
|
|
|
|
+ divObject.put("division_mer_usercode", partnerId);
|
|
|
|
+ divObject.put("div_ratio", "1");
|
|
|
|
+ divObject.put("is_chargeFee", "02");
|
|
|
|
+ divList.add(divObject);
|
|
|
|
+ //分账明细
|
|
|
|
+ bizContent.put("div_list", divList);
|
|
|
|
+ req.setParamData(bizContent);
|
|
|
|
+ String result = null;
|
|
|
|
+ DivisionLog divisionLog = new DivisionLog();
|
|
|
|
+ YsCallLog ysCallLog = new YsCallLog();
|
|
|
|
+ ysCallLog.setInterfaceId("ysepay.single.division.online.accept");
|
|
|
|
+ ysCallLog.setReqJson(JSONObject.toJSONString(req));
|
|
|
|
+ try{
|
|
|
|
+ logger.info("分账登记调用sdk接口addScanMerc请求入参为:"+ JSONObject.toJSONString(req));
|
|
|
|
+ result = MercFundApi.divisionOnlineAccept(req);
|
|
|
|
+ ysCallLog.setResJson(result);
|
|
|
|
+ logger.info("分账登记调用addScanMerc出参为:"+ result);
|
|
|
|
+ //根据返回结果处理自己的业务逻辑,result内容详见接口文档
|
|
|
|
+ }catch (Exception e){
|
|
|
|
+ logger.error("线上分账登记接口失败:"+ e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ // 保存调用日志
|
|
|
|
+ ysCallLogService.save(ysCallLog);
|
|
|
|
+
|
|
|
|
+ // 保存分账登记记录
|
|
|
|
+ divisionLog.setTradeNo(divTradeNo);
|
|
|
|
+ divisionLog.setStatus(DivisionLogStatusConstants.INIT);
|
|
|
|
+ divisionLog.setAmount(totalAmount);
|
|
|
|
+ divisionLog.setOrderNo(orderNo);
|
|
|
|
+ divisionLog.setBizId(payOrder.getOrderId());
|
|
|
|
+ divisionLogService.save(divisionLog);
|
|
|
|
+ responseWrite(response, "success");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 分账回调
|
|
|
|
+ * @param request
|
|
|
|
+ * @param response
|
|
|
|
+ * @throws Exception
|
|
|
|
+ */
|
|
|
|
+ @RequestMapping(value = "/ysDivCallback", method = RequestMethod.GET)
|
|
|
|
+ public void divCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
|
|
|
+ Map<String, String[]> reqParams = request.getParameterMap();
|
|
|
|
+
|
|
|
|
+ Map<String, String> params = new HashMap<>();
|
|
|
|
+ for (String key : reqParams.keySet()) {
|
|
|
|
+ String[] values = reqParams.get(key);
|
|
|
|
+ String valueStr = "";
|
|
|
|
+ for (int i = 0; i < values.length; i++) {
|
|
|
|
+ valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
|
|
|
|
+ }
|
|
|
|
+ params.put(key, valueStr);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ System.out.println("分账回调的数据 = " + JSONObject.toJSONString(params));
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ String divTradeNo = params.get("out_trade_no");
|
|
|
|
+
|
|
|
|
+ DivisionLog divisionLog = divisionLogService.getOne(
|
|
|
|
+ new LambdaQueryWrapper<DivisionLog>().eq(DivisionLog::getTradeNo, divTradeNo));
|
|
|
|
+
|
|
|
|
+ responseWrite(response, "success");
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ private void responseWrite(HttpServletResponse response,String echostr){
|
|
|
|
+ try {
|
|
|
|
+ response.getWriter().write(echostr);
|
|
|
|
+ response.getWriter().flush();
|
|
|
|
+ response.getWriter().close();
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ LogUtil.error(logger, e, "微信公众号设置url回调处理异常");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|