Commit cf2a0c61 authored by dingzhiwei's avatar dingzhiwei
Browse files

Merge branch 'dev'

parents 387e9627 0ec9d1c0
...@@ -22,6 +22,7 @@ import com.github.binarywang.wxpay.exception.WxPayException; ...@@ -22,6 +22,7 @@ import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.constants.CS; import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder; import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.model.params.wxpay.WxpayIsvsubMchParams;
import com.jeequan.jeepay.pay.channel.IPayOrderQueryService; import com.jeequan.jeepay.pay.channel.IPayOrderQueryService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit; import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayV3Util; import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayV3Util;
...@@ -76,7 +77,17 @@ public class WxpayPayOrderQueryService implements IPayOrderQueryService { ...@@ -76,7 +77,17 @@ public class WxpayPayOrderQueryService implements IPayOrderQueryService {
}else if (CS.PAY_IF_VERSION.WX_V3.equals(mchAppConfigContext.getWxServiceWrapper().getApiVersion())) { //V3 }else if (CS.PAY_IF_VERSION.WX_V3.equals(mchAppConfigContext.getWxServiceWrapper().getApiVersion())) { //V3
JSONObject resultJSON = WxpayV3Util.queryOrderV3(payOrder.getPayOrderId(), mchAppConfigContext.getWxServiceWrapper().getWxPayService().getConfig()); String reqUrl;
String query;
if(mchAppConfigContext.isIsvsubMch()){ // 特约商户
WxpayIsvsubMchParams isvsubMchParams = mchAppConfigContext.getIsvsubMchParamsByIfCode(CS.IF_CODE.WXPAY, WxpayIsvsubMchParams.class);
reqUrl = String.format("/v3/pay/partner/transactions/out-trade-no/%s", payOrder.getPayOrderId());
query = String.format("?sp_mchid=%s&sub_mchid=%s", mchAppConfigContext.getWxServiceWrapper().getWxPayService().getConfig().getMchId(), isvsubMchParams.getSubMchId());
}else {
reqUrl = String.format("/v3/pay/transactions/out-trade-no/%s", payOrder.getPayOrderId());
query = String.format("?mchid=%s", mchAppConfigContext.getWxServiceWrapper().getWxPayService().getConfig().getMchId());
}
JSONObject resultJSON = WxpayV3Util.queryOrderV3(reqUrl + query, mchAppConfigContext.getWxServiceWrapper().getWxPayService().getConfig());
String channelState = resultJSON.getString("trade_state"); String channelState = resultJSON.getString("trade_state");
if ("SUCCESS".equals(channelState)) { if ("SUCCESS".equals(channelState)) {
......
...@@ -76,9 +76,8 @@ public class WxpayV3Util { ...@@ -76,9 +76,8 @@ public class WxpayV3Util {
return JSON.parseObject(response); return JSON.parseObject(response);
} }
public static JSONObject queryOrderV3(String payOrderId, WxPayConfig wxPayConfig) throws WxPayException { public static JSONObject queryOrderV3(String url, WxPayConfig wxPayConfig) throws WxPayException {
String url = String.format("%s/v3/pay/transactions/out-trade-no/%s", PAY_BASE_URL, payOrderId); String response = getV3(PAY_BASE_URL + url, wxPayConfig);
String response = getV3(url, wxPayConfig);
return JSON.parseObject(response); return JSON.parseObject(response);
} }
...@@ -170,7 +169,7 @@ public class WxpayV3Util { ...@@ -170,7 +169,7 @@ public class WxpayV3Util {
throw wxPayException; throw wxPayException;
} }
} catch (Exception e) { } catch (Exception e) {
log.error("\n【异常信息】:{}", url, e.getMessage()); log.error("\n【异常信息】:{},e={}", url, e.getMessage());
throw (e instanceof WxPayException) ? (WxPayException) e : new WxPayException(e.getMessage(), e); throw (e instanceof WxPayException) ? (WxPayException) e : new WxPayException(e.getMessage(), e);
} finally { } finally {
httpGet.releaseConnection(); httpGet.releaseConnection();
......
...@@ -23,6 +23,7 @@ import com.jeequan.jeepay.core.entity.MchPayPassage; ...@@ -23,6 +23,7 @@ import com.jeequan.jeepay.core.entity.MchPayPassage;
import com.jeequan.jeepay.core.entity.PayOrder; import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException; import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes; import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.mq.MqCommonService;
import com.jeequan.jeepay.core.utils.SeqKit; import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.core.utils.SpringBeansUtil; import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.core.utils.StringKit; import com.jeequan.jeepay.core.utils.StringKit;
...@@ -31,7 +32,7 @@ import com.jeequan.jeepay.pay.ctrl.ApiController; ...@@ -31,7 +32,7 @@ import com.jeequan.jeepay.pay.ctrl.ApiController;
import com.jeequan.jeepay.pay.exception.ChannelException; import com.jeequan.jeepay.pay.exception.ChannelException;
import com.jeequan.jeepay.pay.model.IsvConfigContext; import com.jeequan.jeepay.pay.model.IsvConfigContext;
import com.jeequan.jeepay.pay.model.MchAppConfigContext; import com.jeequan.jeepay.pay.model.MchAppConfigContext;
import com.jeequan.jeepay.pay.mq.queue.MqQueue4ChannelOrderQuery; import com.jeequan.jeepay.pay.mq.receive.MqReceiveCommon;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ; import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRS; import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRS;
...@@ -63,7 +64,9 @@ public abstract class AbstractPayOrderController extends ApiController { ...@@ -63,7 +64,9 @@ public abstract class AbstractPayOrderController extends ApiController {
@Autowired private ConfigContextService configContextService; @Autowired private ConfigContextService configContextService;
@Autowired private PayMchNotifyService payMchNotifyService; @Autowired private PayMchNotifyService payMchNotifyService;
@Autowired private SysConfigService sysConfigService; @Autowired private SysConfigService sysConfigService;
@Autowired private MqQueue4ChannelOrderQuery mqChannelOrderQueryQueue; @Autowired private MqCommonService mqCommonService;
@Autowired private MqReceiveCommon receiveCommon;
/** 统一下单 (新建订单模式) **/ /** 统一下单 (新建订单模式) **/
protected ApiRes unifiedOrder(String wayCode, UnifiedOrderRQ bizRQ){ protected ApiRes unifiedOrder(String wayCode, UnifiedOrderRQ bizRQ){
...@@ -323,7 +326,7 @@ public abstract class AbstractPayOrderController extends ApiController { ...@@ -323,7 +326,7 @@ public abstract class AbstractPayOrderController extends ApiController {
//判断是否需要轮询查单 //判断是否需要轮询查单
if(channelRetMsg.isNeedQuery()){ if(channelRetMsg.isNeedQuery()){
mqChannelOrderQueryQueue.send(MqQueue4ChannelOrderQuery.buildMsg(payOrderId, 1), 5 * 1000); mqCommonService.send(receiveCommon.buildMsg(payOrderId, 1), 5 * 1000, CS.MQ.MQ_TYPE_CHANNEL_ORDER_QUERY);
} }
} }
......
...@@ -13,15 +13,12 @@ ...@@ -13,15 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jeequan.jeepay.pay.mq.queue; package com.jeequan.jeepay.pay.mq;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpUtil;
import com.jeequan.jeepay.core.constants.CS; import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchNotifyRecord; import com.jeequan.jeepay.core.mq.MqCommonService;
import com.jeequan.jeepay.pay.mq.config.MqThreadExecutor; import com.jeequan.jeepay.pay.mq.config.MqThreadExecutor;
import com.jeequan.jeepay.service.impl.MchNotifyRecordService; import com.jeequan.jeepay.pay.mq.receive.MqReceiveCommon;
import com.jeequan.jeepay.service.impl.PayOrderService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.ScheduledMessage; import org.apache.activemq.ScheduledMessage;
import org.apache.activemq.command.ActiveMQQueue; import org.apache.activemq.command.ActiveMQQueue;
...@@ -29,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -29,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Profile;
import org.springframework.jms.annotation.JmsListener; import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.core.JmsTemplate;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
...@@ -38,41 +36,82 @@ import javax.jms.Queue; ...@@ -38,41 +36,82 @@ import javax.jms.Queue;
import javax.jms.TextMessage; import javax.jms.TextMessage;
/* /*
* 商户订单回调MQ通知 * 上游渠道订单轮询查单
* 如:微信的条码支付,没有回调接口, 需要轮询查单完成交易结果通知。
*
* *
* @author terrfly * @author terrfly
* @site https://www.jeepay.vip * @site https://www.jeepay.vip
* @date 2021/6/8 17:34 * @date 2021/6/8 17:30
*/ */
@Slf4j @Slf4j
@Component @Component
public class MqQueue4PayOrderMchNotify { @Profile(CS.MQTYPE.ACTIVE_MQ)
public class ActiveMqMessage extends MqCommonService {
@Bean("mqQueue4PayOrderMchNotifyInner") @Autowired private JmsTemplate jmsTemplate;
@Lazy
@Autowired
private MqReceiveCommon mqReceiveCommon;
@Bean("activeChannelOrderQuery")
public Queue mqQueue4ChannelOrderQuery(){
return new ActiveMQQueue(CS.MQ.QUEUE_CHANNEL_ORDER_QUERY);
}
@Lazy
@Autowired
@Qualifier("activeChannelOrderQuery")
private Queue mqQueue4ChannelOrderQuery;
@Bean("activePayOrderMchNotifyInner")
public Queue mqQueue4PayOrderMchNotifyInner(){ public Queue mqQueue4PayOrderMchNotifyInner(){
return new ActiveMQQueue(CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY); return new ActiveMQQueue(CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY);
} }
@Lazy @Lazy
@Autowired @Autowired
@Qualifier("mqQueue4PayOrderMchNotifyInner") @Qualifier("activePayOrderMchNotifyInner")
private Queue mqQueue4PayOrderMchNotifyInner; private Queue mqQueue4PayOrderMchNotifyInner;
@Autowired private JmsTemplate jmsTemplate;
@Autowired private MchNotifyRecordService mchNotifyRecordService;
@Autowired private PayOrderService payOrderService;
public MqQueue4PayOrderMchNotify(){ /**
super(); * 发送消息
* @param msg
* @param sendType
*/
@Override
public void send(String msg, String sendType) {
if (sendType.equals(CS.MQ.MQ_TYPE_CHANNEL_ORDER_QUERY)) {
channelOrderQuery(msg);
}else if (sendType.equals(CS.MQ.MQ_TYPE_PAY_ORDER_MCH_NOTIFY)) {
payOrderMchNotify(msg);
}
} }
/** 发送MQ消息 **/ /**
public void send(String msg) { * 发送延迟消息
this.jmsTemplate.convertAndSend(mqQueue4PayOrderMchNotifyInner, msg); * @param msg
* @param delay
* @param sendType
*/
@Override
public void send(String msg, long delay, String sendType) {
if (sendType.equals(CS.MQ.MQ_TYPE_CHANNEL_ORDER_QUERY)) {
channelOrderQueryFixed(msg, delay);
}else if (sendType.equals(CS.MQ.MQ_TYPE_PAY_ORDER_MCH_NOTIFY)) {
payOrderMchNotifyFixed(msg, delay);
}
} }
/** 发送MQ消息 **/ /** 发送订单查询消息 **/
public void send(String msg, long delay) { public void channelOrderQuery(String msg) {
jmsTemplate.send(mqQueue4PayOrderMchNotifyInner, session -> { this.jmsTemplate.convertAndSend(mqQueue4ChannelOrderQuery, msg);
}
/** 发送订单查询延迟消息 **/
public void channelOrderQueryFixed(String msg, long delay) {
jmsTemplate.send(mqQueue4ChannelOrderQuery, session -> {
TextMessage tm = session.createTextMessage(msg); TextMessage tm = session.createTextMessage(msg);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay); tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, 1*1000); tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, 1*1000);
...@@ -81,61 +120,34 @@ public class MqQueue4PayOrderMchNotify { ...@@ -81,61 +120,34 @@ public class MqQueue4PayOrderMchNotify {
}); });
} }
/** 接收 更新系统配置项的消息 **/ /** 发送订单回调消息 **/
@Async(MqThreadExecutor.EXECUTOR_PAYORDER_MCH_NOTIFY) public void payOrderMchNotify(String msg) {
@JmsListener(destination = CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY) this.jmsTemplate.convertAndSend(mqQueue4PayOrderMchNotifyInner, msg);
public void receive(String msg) {
log.info("接收商户通知MQ, msg={}", msg);
Long notifyId = Long.parseLong(msg);
MchNotifyRecord record = mchNotifyRecordService.getById(notifyId);
if(record == null || record.getState() != MchNotifyRecord.STATE_ING){
log.info("查询通知记录不存在或状态不是通知中");
return ;
}
if( record.getNotifyCount() >= record.getNotifyCountLimit() ){
log.info("已达到最大发送次数");
return ;
}
//1. (发送结果最多6次)
Integer currentCount = record.getNotifyCount() + 1;
String notifyUrl = record.getNotifyUrl();
String res = "";
try {
res = HttpUtil.createPost(notifyUrl).timeout(20000).execute().body();
} catch (HttpException e) {
log.error("http error", e);
} }
if(currentCount == 1){ //第一次通知: 更新为已通知 /** 发送订单回调延迟消息 **/
payOrderService.updateNotifySent(record.getOrderId()); public void payOrderMchNotifyFixed(String msg, long delay) {
jmsTemplate.send(mqQueue4PayOrderMchNotifyInner, session -> {
TextMessage tm = session.createTextMessage(msg);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, 1*1000);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, 1);
return tm;
});
} }
//通知成功
if("SUCCESS".equalsIgnoreCase(res)){
mchNotifyRecordService.updateNotifyResult(notifyId, MchNotifyRecord.STATE_SUCCESS, res);
return ;
}
//通知次数 >= 最大通知次数时, 更新响应结果为异常, 不在继续延迟发送消息 /** 接收 查单消息 **/
if( currentCount >= record.getNotifyCountLimit() ){ @JmsListener(destination = CS.MQ.QUEUE_CHANNEL_ORDER_QUERY)
mchNotifyRecordService.updateNotifyResult(notifyId, MchNotifyRecord.STATE_FAIL, res); public void receiveChannelOrderQuery(String msg) {
return ; mqReceiveCommon.channelOrderQuery(msg);
} }
// 继续发送MQ 延迟发送 /** 接收 支付订单商户回调消息 **/
mchNotifyRecordService.updateNotifyResult(notifyId, MchNotifyRecord.STATE_ING, res); @Async(MqThreadExecutor.EXECUTOR_PAYORDER_MCH_NOTIFY)
@JmsListener(destination = CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY)
// 通知延时次数 public void receivePayOrderMchNotify(String msg) {
// 1 2 3 4 5 6 mqReceiveCommon.payOrderMchNotify(msg);
// 0 30 60 90 120 150
send(msg, currentCount * 30 * 1000);
} }
} }
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.mq;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.mq.MqCommonService;
import com.jeequan.jeepay.pay.mq.receive.MqReceiveCommon;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
/**
* RabbitMQ
* 上游渠道订单轮询查单
* 如:微信的条码支付,没有回调接口, 需要轮询查单完成交易结果通知。
*
*
* @author xiaoyu
* @site https://www.jeepay.vip
* @date 2021/6/25 17:10
*/
@Slf4j
@Component
@Profile(CS.MQTYPE.RABBIT_MQ)
public class RabbitMqMessage extends MqCommonService {
@Autowired private RabbitTemplate rabbitTemplate;
@Lazy
@Autowired
private MqReceiveCommon mqReceiveCommon;
@Override
public void send(String msg, String sendType) {
if (sendType.equals(CS.MQ.MQ_TYPE_CHANNEL_ORDER_QUERY)) {
channelOrderQuery(msg);
}else if (sendType.equals(CS.MQ.MQ_TYPE_PAY_ORDER_MCH_NOTIFY)) {
payOrderMchNotify(msg);
}
}
@Override
public void send(String msg, long delay, String sendType) {
if (sendType.equals(CS.MQ.MQ_TYPE_CHANNEL_ORDER_QUERY)) {
channelOrderQueryFixed(msg, delay);
}else if (sendType.equals(CS.MQ.MQ_TYPE_PAY_ORDER_MCH_NOTIFY)) {
payOrderMchNotifyFixed(msg, delay);
}
}
/** 发送订单查询消息 **/
public void channelOrderQuery(String msg) {
rabbitTemplate.convertAndSend(CS.MQ.QUEUE_CHANNEL_ORDER_QUERY, msg);
}
/** 发送订单查询延迟消息 **/
public void channelOrderQueryFixed(String msg, long delay) {
rabbitTemplate.convertAndSend(CS.DELAYED_EXCHANGE, CS.MQ.QUEUE_CHANNEL_ORDER_QUERY, msg, a ->{
a.getMessageProperties().setDelay(Math.toIntExact(delay));
return a;
});
}
/** 发送订单回调消息 **/
public void payOrderMchNotify(String msg) {
rabbitTemplate.convertAndSend(CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY, msg);
}
/** 发送订单回调延迟消息 **/
public void payOrderMchNotifyFixed(String msg, long delay) {
rabbitTemplate.convertAndSend(CS.DELAYED_EXCHANGE, CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY, msg, a ->{
a.getMessageProperties().setDelay(Math.toIntExact(delay));
return a;
});
}
/** 接收 查单消息 **/
@RabbitListener(queues = CS.MQ.QUEUE_CHANNEL_ORDER_QUERY)
public void receiveChannelOrderQuery(String msg) {
mqReceiveCommon.channelOrderQuery(msg);
}
/** 接收 支付订单商户回调消息 **/
@RabbitListener(queues = CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY)
public void receivePayOrderMchNotify(String msg) {
mqReceiveCommon.payOrderMchNotify(msg);
}
}
...@@ -13,18 +13,18 @@ ...@@ -13,18 +13,18 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jeequan.jeepay.pay.mq.topic; package com.jeequan.jeepay.pay.mq.activemq.topic;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS; import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.pay.service.ConfigContextService; import com.jeequan.jeepay.pay.mq.receive.MqReceiveCommon;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.jms.annotation.JmsListener; import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/* /*
* 更改商户信 * 接收mq消
* *
* @author terrfly * @author terrfly
* @site https://www.jeepay.vip * @site https://www.jeepay.vip
...@@ -32,9 +32,16 @@ import org.springframework.stereotype.Component; ...@@ -32,9 +32,16 @@ import org.springframework.stereotype.Component;
*/ */
@Slf4j @Slf4j
@Component @Component
public class MqTopic4ModifyMchInfo{ @Profile(CS.MQTYPE.ACTIVE_MQ)
public class MqTopicReceive {
@Autowired private ConfigContextService configContextService; @Autowired private MqReceiveCommon mqReceiveCommon;
/** 接收 更新服务商信息的消息 **/
@JmsListener(destination = CS.MQ.TOPIC_MODIFY_ISV_INFO, containerFactory = "jmsListenerContainer")
public void receiveModifyIsvInfo(String isvNo) {
mqReceiveCommon.modifyIsvInfo(isvNo);
}
/** 接收 [商户配置信息] 的消息 /** 接收 [商户配置信息] 的消息
* 已知推送节点: * 已知推送节点:
...@@ -42,10 +49,8 @@ public class MqTopic4ModifyMchInfo{ ...@@ -42,10 +49,8 @@ public class MqTopic4ModifyMchInfo{
* 2. 删除商户时 * 2. 删除商户时
* **/ * **/
@JmsListener(destination = CS.MQ.TOPIC_MODIFY_MCH_INFO, containerFactory = "jmsListenerContainer") @JmsListener(destination = CS.MQ.TOPIC_MODIFY_MCH_INFO, containerFactory = "jmsListenerContainer")
public void receive(String mchNo) { public void receiveModifyMchInfo(String mchNo) {
mqReceiveCommon.modifyMchInfo(mchNo);
log.info("接收 [商户配置信息] 的消息, msg={}", mchNo);
configContextService.initMchInfoConfigContext(mchNo);
} }
/** 接收 [商户应用支付参数配置信息] 的消息 /** 接收 [商户应用支付参数配置信息] 的消息
...@@ -54,11 +59,14 @@ public class MqTopic4ModifyMchInfo{ ...@@ -54,11 +59,14 @@ public class MqTopic4ModifyMchInfo{
* 2. 删除商户应用配置 * 2. 删除商户应用配置
* **/ * **/
@JmsListener(destination = CS.MQ.TOPIC_MODIFY_MCH_APP, containerFactory = "jmsListenerContainer") @JmsListener(destination = CS.MQ.TOPIC_MODIFY_MCH_APP, containerFactory = "jmsListenerContainer")
public void receiveMchApp(String mchNoAndAppId) { public void receiveModifyMchApp(String mchNoAndAppId) {
mqReceiveCommon.modifyMchApp(mchNoAndAppId);
}
log.info("接收 [商户应用支付参数配置信息] 的消息, msg={}", mchNoAndAppId); /** 接收 更新系统配置项的消息 **/
JSONObject jsonObject = (JSONObject) JSONObject.parse(mchNoAndAppId); @JmsListener(destination = CS.MQ.TOPIC_MODIFY_SYS_CONFIG, containerFactory = "jmsListenerContainer")
configContextService.initMchAppConfigContext(jsonObject.getString("mchNo"), jsonObject.getString("appId")); public void receiveModifySysConfig(String msg) {
mqReceiveCommon.initDbConfig(msg);
} }
......
...@@ -13,9 +13,11 @@ ...@@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jeequan.jeepay.pay.mq.topic; package com.jeequan.jeepay.pay.mq.config;
import com.jeequan.jeepay.core.constants.CS;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory; import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory; import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
...@@ -30,6 +32,7 @@ import javax.jms.ConnectionFactory; ...@@ -30,6 +32,7 @@ import javax.jms.ConnectionFactory;
* @date 2021/6/8 17:31 * @date 2021/6/8 17:31
*/ */
@Component @Component
@Profile(CS.MQTYPE.ACTIVE_MQ)
public class JMSConfig { public class JMSConfig {
/** 新增jmsListenerContainer, 用于接收topic类型的消息 **/ /** 新增jmsListenerContainer, 用于接收topic类型的消息 **/
......
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.mq.config;
import com.jeequan.jeepay.core.constants.CS;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import java.util.HashMap;
import java.util.Map;
/**
* RabbitMq
* 延迟消息队列绑定交换机
* @author xiaoyu
* @site https://www.jeepay.vip
* @date 2021/6/25 17:10
*/
@Configuration
@Profile(CS.MQTYPE.RABBIT_MQ)
public class RabbitMqConfig {
@Bean("channelOrderQuery")
public Queue channelOrderQuery() {
return new Queue(CS.MQ.QUEUE_CHANNEL_ORDER_QUERY,true);
}
@Bean("payOrderMchNotify")
public Queue payOrderMchNotify() {
return new Queue(CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY,true);
}
//创建 custom 交换机
@Bean
CustomExchange customExchange() {
Map<String, Object> args = new HashMap<>();
args.put("x-delayed-type", "direct");
return new CustomExchange(CS.DELAYED_EXCHANGE, "x-delayed-message", true, false, args);
}
//绑定 将队列和交换机绑定, 并设置用于匹配键:QUEUE_CHANNEL_ORDER_QUERY
@Bean
Binding bindingChannelOrderQuery(@Qualifier("channelOrderQuery") Queue channelOrderQuery) {
return BindingBuilder.bind(channelOrderQuery).to(customExchange()).with(CS.MQ.QUEUE_CHANNEL_ORDER_QUERY).noargs();
}
//绑定 将队列和交换机绑定, 并设置用于匹配键:QUEUE_PAYORDER_MCH_NOTIFY
@Bean
Binding bindingPayOrderNotify(@Qualifier("payOrderMchNotify") Queue payOrderMchNotify) {
return BindingBuilder.bind(payOrderMchNotify).to(customExchange()).with(CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY).noargs();
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.mq.queue;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.service.ChannelOrderReissueService;
import com.jeequan.jeepay.service.impl.PayOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.ScheduledMessage;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
import javax.jms.TextMessage;
/*
* 上游渠道订单轮询查单
* 如:微信的条码支付,没有回调接口, 需要轮询查单完成交易结果通知。
*
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:30
*/
@Slf4j
@Component
public class MqQueue4ChannelOrderQuery extends ActiveMQQueue{
@Autowired private JmsTemplate jmsTemplate;
@Autowired private PayOrderService payOrderService;
@Autowired private ChannelOrderReissueService channelOrderReissueService;
public static final String buildMsg(String payOrderId, int count){
return payOrderId + "," + count;
}
/** 构造函数 */
public MqQueue4ChannelOrderQuery(){
super(CS.MQ.QUEUE_CHANNEL_ORDER_QUERY);
}
/** 发送MQ消息 **/
public void send(String msg) {
this.jmsTemplate.convertAndSend(this, msg);
}
/** 发送MQ消息 **/
public void send(String msg, long delay) {
jmsTemplate.send(this, session -> {
TextMessage tm = session.createTextMessage(msg);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, 1*1000);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, 1);
return tm;
});
}
/** 接收 更新系统配置项的消息 **/
@JmsListener(destination = CS.MQ.QUEUE_CHANNEL_ORDER_QUERY)
public void receive(String msg) {
String [] arr = msg.split(",");
String payOrderId = arr[0];
int currentCount = Integer.parseInt(arr[1]);
log.info("接收轮询查单通知MQ, payOrderId={}, count={}", payOrderId, currentCount);
currentCount++ ;
PayOrder payOrder = payOrderService.getById(payOrderId);
if(payOrder == null) {
log.warn("查询支付订单为空,payOrderId={}", payOrderId);
return;
}
if(payOrder.getState() != PayOrder.STATE_ING) {
log.warn("订单状态不是支付中,不需查询渠道.payOrderId={}", payOrderId);
return;
}
ChannelRetMsg channelRetMsg = channelOrderReissueService.processPayOrder(payOrder);
//返回null 可能为接口报错等, 需要再次轮询
if(channelRetMsg == null || channelRetMsg.getChannelState() == null || channelRetMsg.getChannelState().equals(ChannelRetMsg.ChannelState.WAITING)){
//最多查询6次
if(currentCount <= 6){
send(buildMsg(payOrderId, currentCount), 5 * 1000); //延迟5s再次查询
}else{
//TODO 调用【撤销订单】接口
}
}else{ //其他状态, 不需要再次轮询。
}
return;
}
}
...@@ -13,36 +13,65 @@ ...@@ -13,36 +13,65 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jeequan.jeepay.pay.mq.topic; package com.jeequan.jeepay.pay.mq.rabbitmq;
import com.jeequan.jeepay.core.constants.CS; import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.pay.service.ConfigContextService; import com.jeequan.jeepay.pay.mq.receive.MqReceiveCommon;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener; import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/* /**
* 更改ISV信 * 接收mq消
* *
* @author terrfly * @author xiaoyu
* @site https://www.jeepay.vip * @site https://www.jeepay.vip
* @date 2021/6/8 17:31 * @date 2021/6/25 17:10
*/ */
@Slf4j @Slf4j
@Component @Component
public class MqTopic4ModifyIsvInfo{ @Profile(CS.MQTYPE.RABBIT_MQ)
public class RabbitMqDirectReceive {
@Autowired private ConfigContextService configContextService; @Autowired private MqReceiveCommon mqReceiveCommon;
/** 接收 更新系统配置项的消息 **/ /** 接收 更新服务商信息的消息 **/
@JmsListener(destination = CS.MQ.TOPIC_MODIFY_ISV_INFO, containerFactory = "jmsListenerContainer") @RabbitListener(queues = CS.MQ.TOPIC_MODIFY_ISV_INFO)
public void receive(String isvNo) { public void receiveModifyIsvInfo(String isvNo) {
mqReceiveCommon.modifyIsvInfo(isvNo);
}
/** 接收 [商户配置信息] 的消息
* 已知推送节点:
* 1. 更新商户基本资料和状态
* 2. 删除商户时
* **/
@RabbitListener(queues = CS.MQ.TOPIC_MODIFY_MCH_INFO)
public void receiveModifyMchInfo(String mchNo) {
mqReceiveCommon.modifyMchInfo(mchNo);
}
log.info("重置ISV信息, msg={}", isvNo); /** 接收 [商户应用支付参数配置信息] 的消息
configContextService.initIsvConfigContext(isvNo); * 已知推送节点:
* 1. 更新商户应用配置
* 2. 删除商户应用配置
* **/
@RabbitListener(queues = CS.MQ.TOPIC_MODIFY_MCH_APP)
public void receiveModifyMchApp(String mchNoAndAppId) {
mqReceiveCommon.modifyMchApp(mchNoAndAppId);
} }
/** 接收 更新系统配置项的消息 **/
@RabbitListener(bindings = {@QueueBinding(value = @Queue(),exchange = @Exchange(name = CS.FANOUT_EXCHANGE_SYS_CONFIG,type = "fanout"))})
public void receiveModifySysConfig(String msg) {
mqReceiveCommon.initDbConfig(msg);
}
} }
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.mq.receive;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchNotifyRecord;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.mq.MqCommonService;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.service.ChannelOrderReissueService;
import com.jeequan.jeepay.pay.service.ConfigContextService;
import com.jeequan.jeepay.service.impl.MchNotifyRecordService;
import com.jeequan.jeepay.service.impl.PayOrderService;
import com.jeequan.jeepay.service.impl.SysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
/**
* 处理公共接收消息方法
*
* @author xiaoyu
* @site https://www.jeepay.vip
* @date 2021/6/25 17:10
*/
@Slf4j
@Service
public class MqReceiveCommon {
@Autowired
private SysConfigService sysConfigService;
@Autowired
private ConfigContextService configContextService;
@Autowired
private PayOrderService payOrderService;
@Autowired
private ChannelOrderReissueService channelOrderReissueService;
@Autowired
private MchNotifyRecordService mchNotifyRecordService;
@Autowired
private MqCommonService mqCommonService;
/** 接收 [商户配置信息] 的消息 **/
public void modifyMchInfo(String mchNo) {
log.info("接收 [商户配置信息] 的消息, msg={}", mchNo);
configContextService.initMchInfoConfigContext(mchNo);
}
/** 接收 [商户应用支付参数配置信息] 的消息 **/
public void modifyMchApp(String mchNoAndAppId) {
log.info("接收 [商户应用支付参数配置信息] 的消息, msg={}", mchNoAndAppId);
JSONObject jsonObject = (JSONObject) JSONObject.parse(mchNoAndAppId);
configContextService.initMchAppConfigContext(jsonObject.getString("mchNo"), jsonObject.getString("appId"));
}
/** 重置ISV信息 **/
public void modifyIsvInfo(String isvNo) {
log.info("重置ISV信息, msg={}", isvNo);
configContextService.initIsvConfigContext(isvNo);
}
/** 接收商户订单回调通知 **/
public void payOrderMchNotify(String msg) {
try {
log.info("接收商户通知MQ, msg={}", msg);
Long notifyId = Long.parseLong(msg);
MchNotifyRecord record = mchNotifyRecordService.getById(notifyId);
if(record == null || record.getState() != MchNotifyRecord.STATE_ING){
log.info("查询通知记录不存在或状态不是通知中");
return;
}
if( record.getNotifyCount() >= record.getNotifyCountLimit() ){
log.info("已达到最大发送次数");
return;
}
//1. (发送结果最多6次)
Integer currentCount = record.getNotifyCount() + 1;
String notifyUrl = record.getNotifyUrl();
String res = "";
try {
res = HttpUtil.createPost(notifyUrl).timeout(20000).execute().body();
} catch (HttpException e) {
log.error("http error", e);
}
if(currentCount == 1){ //第一次通知: 更新为已通知
payOrderService.updateNotifySent(record.getOrderId());
}
//通知成功
if("SUCCESS".equalsIgnoreCase(res)){
mchNotifyRecordService.updateNotifyResult(notifyId, MchNotifyRecord.STATE_SUCCESS, res);
}
//通知次数 >= 最大通知次数时, 更新响应结果为异常, 不在继续延迟发送消息
if( currentCount >= record.getNotifyCountLimit() ){
mchNotifyRecordService.updateNotifyResult(notifyId, MchNotifyRecord.STATE_FAIL, res);
}
// 继续发送MQ 延迟发送
mchNotifyRecordService.updateNotifyResult(notifyId, MchNotifyRecord.STATE_ING, res);
// 通知延时次数
// 1 2 3 4 5 6
// 0 30 60 90 120 150
mqCommonService.send(msg, currentCount * 30 * 1000, CS.MQ.MQ_TYPE_PAY_ORDER_MCH_NOTIFY);
return;
}catch (Exception e) {
log.error(e.getMessage());
return;
}
}
/** 接收订单查单通知 **/
public void channelOrderQuery(String msg) {
try {
String [] arr = msg.split(",");
String payOrderId = arr[0];
int currentCount = Integer.parseInt(arr[1]);
log.info("接收轮询查单通知MQ, payOrderId={}, count={}", payOrderId, currentCount);
currentCount++ ;
PayOrder payOrder = payOrderService.getById(payOrderId);
if(payOrder == null) {
log.warn("查询支付订单为空,payOrderId={}", payOrderId);
return;
}
if(payOrder.getState() != PayOrder.STATE_ING) {
log.warn("订单状态不是支付中,不需查询渠道.payOrderId={}", payOrderId);
return;
}
if (payOrder == null) return;
ChannelRetMsg channelRetMsg = channelOrderReissueService.processPayOrder(payOrder);
//返回null 可能为接口报错等, 需要再次轮询
if(channelRetMsg == null || channelRetMsg.getChannelState() == null || channelRetMsg.getChannelState().equals(ChannelRetMsg.ChannelState.WAITING)){
//最多查询6次
if(currentCount <= 6){
mqCommonService.send(buildMsg(payOrderId, currentCount), 5 * 1000, CS.MQ.MQ_TYPE_CHANNEL_ORDER_QUERY); //延迟5s再次查询
}else{
//TODO 调用【撤销订单】接口
}
}else{ //其他状态, 不需要再次轮询。
}
}catch (Exception e) {
log.error(e.getMessage());
return;
}
}
/** 接收系统配置修改通知 **/
public void initDbConfig(String msg) {
log.info("成功接收更新系统配置的订阅通知, msg={}", msg);
sysConfigService.initDBConfig(msg);
log.info("系统配置静态属性已重置");
}
public static final String buildMsg(String payOrderId, int count){
return payOrderId + "," + count;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.mq.topic;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.service.impl.SysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
/*
* 更改系统配置参数
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:35
*/
@Slf4j
@Component
public class MqTopic4ModifySysConfig{
@Autowired private SysConfigService sysConfigService;
/** 接收 更新系统配置项的消息 **/
@JmsListener(destination = CS.MQ.TOPIC_MODIFY_SYS_CONFIG, containerFactory = "jmsListenerContainer")
public void receive(String msg) {
log.info("成功接收更新系统配置的订阅通知, msg={}", msg);
sysConfigService.initDBConfig(msg);
log.info("系统配置静态属性已重置");
}
}
...@@ -29,10 +29,6 @@ import javax.validation.constraints.NotBlank; ...@@ -29,10 +29,6 @@ import javax.validation.constraints.NotBlank;
@Data @Data
public class ChannelUserIdRQ extends AbstractMchAppRQ{ public class ChannelUserIdRQ extends AbstractMchAppRQ{
/** 商户号 **/
@NotBlank(message="商户号不能为空")
private String mchNo;
/** 接口代码, AUTO表示:自动获取 **/ /** 接口代码, AUTO表示:自动获取 **/
@NotBlank(message="接口代码不能为空") @NotBlank(message="接口代码不能为空")
private String ifCode; private String ifCode;
......
...@@ -16,12 +16,13 @@ ...@@ -16,12 +16,13 @@
package com.jeequan.jeepay.pay.service; package com.jeequan.jeepay.pay.service;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchNotifyRecord; import com.jeequan.jeepay.core.entity.MchNotifyRecord;
import com.jeequan.jeepay.core.entity.PayOrder; import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.entity.RefundOrder; import com.jeequan.jeepay.core.entity.RefundOrder;
import com.jeequan.jeepay.core.mq.MqCommonService;
import com.jeequan.jeepay.core.utils.JeepayKit; import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.core.utils.StringKit; import com.jeequan.jeepay.core.utils.StringKit;
import com.jeequan.jeepay.pay.mq.queue.MqQueue4PayOrderMchNotify;
import com.jeequan.jeepay.pay.rqrs.payorder.QueryPayOrderRS; import com.jeequan.jeepay.pay.rqrs.payorder.QueryPayOrderRS;
import com.jeequan.jeepay.pay.rqrs.refund.QueryRefundOrderRS; import com.jeequan.jeepay.pay.rqrs.refund.QueryRefundOrderRS;
import com.jeequan.jeepay.service.impl.MchNotifyRecordService; import com.jeequan.jeepay.service.impl.MchNotifyRecordService;
...@@ -42,8 +43,8 @@ import org.springframework.stereotype.Service; ...@@ -42,8 +43,8 @@ import org.springframework.stereotype.Service;
public class PayMchNotifyService { public class PayMchNotifyService {
@Autowired private MchNotifyRecordService mchNotifyRecordService; @Autowired private MchNotifyRecordService mchNotifyRecordService;
@Autowired private MqQueue4PayOrderMchNotify mqPayOrderMchNotifyQueue;
@Autowired private ConfigContextService configContextService; @Autowired private ConfigContextService configContextService;
@Autowired private MqCommonService mqCommonService;
/** 商户通知信息, 只有订单是终态,才会发送通知, 如明确成功和明确失败 **/ /** 商户通知信息, 只有订单是终态,才会发送通知, 如明确成功和明确失败 **/
...@@ -84,7 +85,7 @@ public class PayMchNotifyService { ...@@ -84,7 +85,7 @@ public class PayMchNotifyService {
//推送到MQ //推送到MQ
Long notifyId = mchNotifyRecord.getNotifyId(); Long notifyId = mchNotifyRecord.getNotifyId();
mqPayOrderMchNotifyQueue.send(notifyId + ""); mqCommonService.send(notifyId + "", CS.MQ.MQ_TYPE_PAY_ORDER_MCH_NOTIFY);
} catch (Exception e) { } catch (Exception e) {
log.error("推送失败!", e); log.error("推送失败!", e);
...@@ -129,7 +130,7 @@ public class PayMchNotifyService { ...@@ -129,7 +130,7 @@ public class PayMchNotifyService {
//推送到MQ //推送到MQ
Long notifyId = mchNotifyRecord.getNotifyId(); Long notifyId = mchNotifyRecord.getNotifyId();
mqPayOrderMchNotifyQueue.send(notifyId + ""); mqCommonService.send(notifyId + "", CS.MQ.MQ_TYPE_PAY_ORDER_MCH_NOTIFY);
} catch (Exception e) { } catch (Exception e) {
log.error("推送失败!", e); log.error("推送失败!", e);
......
...@@ -50,9 +50,25 @@ spring: ...@@ -50,9 +50,25 @@ spring:
timeout: 1000 timeout: 1000
database: 3 #1库:运营平台 #2库:商户系统 #3库:支付网关 database: 3 #1库:运营平台 #2库:商户系统 #3库:支付网关
password: password:
# 注意:以下MQ配置需注意【如需使用activeMQ则需将rabbitMQ配置注释即可】
# profiles:
# include:
# - activeMQ
# - rabbitMQ # 需要安装延迟队列插件:https://www.rabbitmq.com/blog/2015/04/16/scheduling-messages-with-rabbitmq/
#activeMQ配置 #activeMQ配置
activemq: # activemq:
broker-url: tcp://localhost:61616 #连接地址 # broker-url: tcp://localhost:61616 #连接地址
#rabbitmq配置
# rabbitmq:
# addresses: 127.0.0.1:5672
# username: guest
# password: guest
# dynamic: true
# virtual-host: /
#日志配置参数。 #日志配置参数。
# 当存在logback-spring.xml文件时: 该配置将引进到logback配置, springboot配置不生效。 # 当存在logback-spring.xml文件时: 该配置将引进到logback配置, springboot配置不生效。
......
...@@ -125,34 +125,26 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> { ...@@ -125,34 +125,26 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
} }
public Map payCount(String mchNo, Byte state, String dayStart, String dayEnd) { public Map payCount(String mchNo, Byte state, Byte refundState, String dayStart, String dayEnd) {
Map param = new HashMap<>(); Map param = new HashMap<>();
if (state != null) param.put("state", state); if (state != null) param.put("state", state);
if (refundState != null) param.put("refundState", refundState);
if (StrUtil.isNotBlank(mchNo)) param.put("mchNo", mchNo); if (StrUtil.isNotBlank(mchNo)) param.put("mchNo", mchNo);
if (StrUtil.isNotBlank(dayStart)) param.put("createTimeStart", dayStart); if (StrUtil.isNotBlank(dayStart)) param.put("createTimeStart", dayStart);
if (StrUtil.isNotBlank(dayEnd)) param.put("createTimeEnd", dayEnd); if (StrUtil.isNotBlank(dayEnd)) param.put("createTimeEnd", dayEnd);
return payOrderMapper.payCount(param); return payOrderMapper.payCount(param);
} }
public List<Map> payTypeCount(String mchNo, Byte state, String dayStart, String dayEnd) { public List<Map> payTypeCount(String mchNo, Byte state, Byte refundState, String dayStart, String dayEnd) {
Map param = new HashMap<>(); Map param = new HashMap<>();
if (state != null) param.put("state", state); if (state != null) param.put("state", state);
if (refundState != null) param.put("refundState", refundState);
if (StrUtil.isNotBlank(mchNo)) param.put("mchNo", mchNo); if (StrUtil.isNotBlank(mchNo)) param.put("mchNo", mchNo);
if (StrUtil.isNotBlank(dayStart)) param.put("createTimeStart", dayStart); if (StrUtil.isNotBlank(dayStart)) param.put("createTimeStart", dayStart);
if (StrUtil.isNotBlank(dayEnd)) param.put("createTimeEnd", dayEnd); if (StrUtil.isNotBlank(dayEnd)) param.put("createTimeEnd", dayEnd);
return payOrderMapper.payTypeCount(param); return payOrderMapper.payTypeCount(param);
} }
public Map selectTotalCount(String mchNo, Byte state, String dayStart, String dayEnd) {
Map param = new HashMap<>();
if (state != null) param.put("state", state);
if (StrUtil.isNotBlank(mchNo)) param.put("mchNo", mchNo);
if (StrUtil.isNotBlank(dayStart)) param.put("createTimeStart", dayStart);
if (StrUtil.isNotBlank(dayEnd)) param.put("createTimeEnd", dayEnd);
return payOrderMapper.selectTotalCount(param);
}
/** 更新订单为 超时状态 **/ /** 更新订单为 超时状态 **/
public Integer updateOrderExpired(){ public Integer updateOrderExpired(){
...@@ -190,7 +182,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> { ...@@ -190,7 +182,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
String dayStart = DateUtil.beginOfDay(date).toString(DatePattern.NORM_DATETIME_MINUTE_PATTERN); String dayStart = DateUtil.beginOfDay(date).toString(DatePattern.NORM_DATETIME_MINUTE_PATTERN);
String dayEnd = DateUtil.endOfDay(date).toString(DatePattern.NORM_DATETIME_MINUTE_PATTERN); String dayEnd = DateUtil.endOfDay(date).toString(DatePattern.NORM_DATETIME_MINUTE_PATTERN);
// 每日交易金额查询 // 每日交易金额查询
dayAmount = payCount(mchNo, PayOrder.STATE_SUCCESS, dayStart, dayEnd); dayAmount = payCount(mchNo, PayOrder.STATE_SUCCESS, null, dayStart, dayEnd);
if (dayAmount != null) payAmount = new BigDecimal(dayAmount.get("payAmount").toString()); if (dayAmount != null) payAmount = new BigDecimal(dayAmount.get("payAmount").toString());
if (i == 0) { if (i == 0) {
todayAmount = dayAmount.get("payAmount").toString(); todayAmount = dayAmount.get("payAmount").toString();
...@@ -219,7 +211,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> { ...@@ -219,7 +211,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
// 服务商总数 // 服务商总数
int isvCount = isvInfoMapper.selectCount(IsvInfo.gw()); int isvCount = isvInfoMapper.selectCount(IsvInfo.gw());
// 总交易金额 // 总交易金额
Map<String, String> payCountMap = payCount(mchNo, PayOrder.STATE_SUCCESS, null, null); Map<String, String> payCountMap = payCount(mchNo, PayOrder.STATE_SUCCESS, null, null, null);
json.put("totalMch", mchCount); json.put("totalMch", mchCount);
json.put("totalIsv", isvCount); json.put("totalIsv", isvCount);
json.put("totalAmount", payCountMap.get("payAmount")); json.put("totalAmount", payCountMap.get("payAmount"));
...@@ -247,9 +239,10 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> { ...@@ -247,9 +239,10 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
param.put("createTimeEnd", createdEnd); param.put("createTimeEnd", createdEnd);
// 查询收款的记录 // 查询收款的记录
param.put("state", PayOrder.STATE_SUCCESS); param.put("state", PayOrder.STATE_SUCCESS);
param.put("refundState", null);
List<Map> payOrderList = payOrderMapper.selectOrderCount(param); List<Map> payOrderList = payOrderMapper.selectOrderCount(param);
// 查询退款的记录 // 查询退款的记录
param.put("state", PayOrder.STATE_REFUND); param.put("refundState", PayOrder.STATE_REFUND);
List<Map> refundOrderList = payOrderMapper.selectOrderCount(param); List<Map> refundOrderList = payOrderMapper.selectOrderCount(param);
// 生成前端返回参数类型 // 生成前端返回参数类型
List<Map> returnList = getReturnList(daySpace, createdEnd, payOrderList, refundOrderList); List<Map> returnList = getReturnList(daySpace, createdEnd, payOrderList, refundOrderList);
...@@ -272,7 +265,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> { ...@@ -272,7 +265,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
createdEnd = end + " 23:59:59"; createdEnd = end + " 23:59:59";
} }
// 统计列表 // 统计列表
List<Map> payCountMap = payTypeCount(mchNo, PayOrder.STATE_SUCCESS, createdStart, createdEnd); List<Map> payCountMap = payTypeCount(mchNo, PayOrder.STATE_SUCCESS, null, createdStart, createdEnd);
// 得到所有支付方式 // 得到所有支付方式
Map<String, String> payWayNameMap = new HashMap<>(); Map<String, String> payWayNameMap = new HashMap<>();
...@@ -326,7 +319,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> { ...@@ -326,7 +319,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
payListMap.add(payMap); payListMap.add(payMap);
for (Map refundOrderMap:refundOrderList) { for (Map refundOrderMap:refundOrderList) {
if (dayMap.get("date").equals(refundOrderMap.get("groupDate"))) { if (dayMap.get("date").equals(refundOrderMap.get("groupDate"))) {
refundMap.put("payAmount", refundOrderMap.get("payAmount")); refundMap.put("payAmount", refundOrderMap.get("refundAmount"));
} }
} }
refundListMap.add(refundMap); refundListMap.add(refundMap);
......
...@@ -36,8 +36,6 @@ public interface PayOrderMapper extends BaseMapper<PayOrder> { ...@@ -36,8 +36,6 @@ public interface PayOrderMapper extends BaseMapper<PayOrder> {
List<Map> payTypeCount(Map param); List<Map> payTypeCount(Map param);
Map selectTotalCount(Map param);
List<Map> selectOrderCount(Map param); List<Map> selectOrderCount(Map param);
/** 更新订单退款金额和次数 **/ /** 更新订单退款金额和次数 **/
......
...@@ -45,18 +45,7 @@ ...@@ -45,18 +45,7 @@
FROM t_pay_order FROM t_pay_order
WHERE 1=1 WHERE 1=1
<if test="state != null"> AND state = #{state} </if> <if test="state != null"> AND state = #{state} </if>
<if test="mchNo != null"> AND mch_no = #{mchNo} </if> <if test="refundState != null"> AND refund_state = #{refundState} </if>
<if test="createTimeStart != null"> AND created_at &gt;= #{createTimeStart} </if>
<if test="createTimeEnd != null"> AND created_at &lt;= #{createTimeEnd} </if>
;
</select>
<!--总交易统计-->
<select id="selectTotalCount" resultType="java.util.Map" parameterType="java.util.Map" >
SELECT ROUND(IFNULL(SUM(amount), 0)/100, 2) AS totalAmount, IFNULL(COUNT(1), 0) AS totalCount
FROM t_pay_order
WHERE 1=1
<if test="state != null"> AND state = #{state} </if>
<if test="mchNo != null"> AND mch_no = #{mchNo} </if> <if test="mchNo != null"> AND mch_no = #{mchNo} </if>
<if test="createTimeStart != null"> AND created_at &gt;= #{createTimeStart} </if> <if test="createTimeStart != null"> AND created_at &gt;= #{createTimeStart} </if>
<if test="createTimeEnd != null"> AND created_at &lt;= #{createTimeEnd} </if> <if test="createTimeEnd != null"> AND created_at &lt;= #{createTimeEnd} </if>
...@@ -69,6 +58,7 @@ ...@@ -69,6 +58,7 @@
FROM t_pay_order FROM t_pay_order
WHERE 1=1 WHERE 1=1
<if test="state != null"> AND state = #{state} </if> <if test="state != null"> AND state = #{state} </if>
<if test="refundState != null"> AND refund_state = #{refundState} </if>
<if test="mchNo != null"> AND mch_no = #{mchNo} </if> <if test="mchNo != null"> AND mch_no = #{mchNo} </if>
<if test="createTimeStart != null"> AND created_at &gt;= #{createTimeStart} </if> <if test="createTimeStart != null"> AND created_at &gt;= #{createTimeStart} </if>
<if test="createTimeEnd != null"> AND created_at &lt;= #{createTimeEnd} </if> <if test="createTimeEnd != null"> AND created_at &lt;= #{createTimeEnd} </if>
...@@ -77,10 +67,14 @@ ...@@ -77,10 +67,14 @@
<!--成功、退款订单统计--> <!--成功、退款订单统计-->
<select id="selectOrderCount" resultType="java.util.Map" parameterType="java.util.Map" > <select id="selectOrderCount" resultType="java.util.Map" parameterType="java.util.Map" >
SELECT DATE_FORMAT(FLOOR(created_at),'%m-%d') groupDate, ROUND(IFNULL(SUM(amount), 0)/100, 2) AS payAmount SELECT DATE_FORMAT(FLOOR(created_at),'%m-%d') groupDate, ROUND(IFNULL(SUM(amount), 0)/100, 2) AS payAmount,
ROUND(IFNULL(SUM(refund_amount), 0)/100, 2) AS refundAmount
FROM t_pay_order FROM t_pay_order
WHERE 1=1 WHERE 1=1
<if test="state != null"> AND state = #{state} </if> <if test="state != null"> AND state = #{state} </if>
<if test="refundState == 0"> AND refund_state = #{refundState} </if>
<if test="refundState == 1"> AND refund_state = #{refundState} </if>
<if test="refundState == 2"> AND refund_state != 0 </if>
<if test="mchNo != null"> AND mch_no = #{mchNo} </if> <if test="mchNo != null"> AND mch_no = #{mchNo} </if>
<if test="createTimeStart != null"> AND created_at &gt;= #{createTimeStart} </if> <if test="createTimeStart != null"> AND created_at &gt;= #{createTimeStart} </if>
<if test="createTimeEnd != null"> AND created_at &lt;= #{createTimeEnd} </if> <if test="createTimeEnd != null"> AND created_at &lt;= #{createTimeEnd} </if>
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
<properties> <properties>
<java.version>1.8</java.version> <!-- 指定java版本号 --> <java.version>1.8</java.version> <!-- 指定java版本号 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 项目构建输出编码 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 项目构建输出编码 -->
<isys.version>1.1.1</isys.version> <!-- 指定当前[项目]版本号 --> <isys.version>1.2.0</isys.version> <!-- 指定当前[项目]版本号 -->
<!-- 其他工具包 --> <!-- 其他工具包 -->
<jeepay.sdk.java.version>1.1.0</jeepay.sdk.java.version> <jeepay.sdk.java.version>1.1.0</jeepay.sdk.java.version>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment