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;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.constants.CS;
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.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayV3Util;
......@@ -76,7 +77,17 @@ public class WxpayPayOrderQueryService implements IPayOrderQueryService {
}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");
if ("SUCCESS".equals(channelState)) {
......
......@@ -76,9 +76,8 @@ public class WxpayV3Util {
return JSON.parseObject(response);
}
public static JSONObject queryOrderV3(String payOrderId, WxPayConfig wxPayConfig) throws WxPayException {
String url = String.format("%s/v3/pay/transactions/out-trade-no/%s", PAY_BASE_URL, payOrderId);
String response = getV3(url, wxPayConfig);
public static JSONObject queryOrderV3(String url, WxPayConfig wxPayConfig) throws WxPayException {
String response = getV3(PAY_BASE_URL + url, wxPayConfig);
return JSON.parseObject(response);
}
......@@ -170,7 +169,7 @@ public class WxpayV3Util {
throw wxPayException;
}
} 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);
} finally {
httpGet.releaseConnection();
......
......@@ -23,6 +23,7 @@ import com.jeequan.jeepay.core.entity.MchPayPassage;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException;
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.SpringBeansUtil;
import com.jeequan.jeepay.core.utils.StringKit;
......@@ -31,7 +32,7 @@ import com.jeequan.jeepay.pay.ctrl.ApiController;
import com.jeequan.jeepay.pay.exception.ChannelException;
import com.jeequan.jeepay.pay.model.IsvConfigContext;
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.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRS;
......@@ -63,7 +64,9 @@ public abstract class AbstractPayOrderController extends ApiController {
@Autowired private ConfigContextService configContextService;
@Autowired private PayMchNotifyService payMchNotifyService;
@Autowired private SysConfigService sysConfigService;
@Autowired private MqQueue4ChannelOrderQuery mqChannelOrderQueryQueue;
@Autowired private MqCommonService mqCommonService;
@Autowired private MqReceiveCommon receiveCommon;
/** 统一下单 (新建订单模式) **/
protected ApiRes unifiedOrder(String wayCode, UnifiedOrderRQ bizRQ){
......@@ -323,7 +326,7 @@ public abstract class AbstractPayOrderController extends ApiController {
//判断是否需要轮询查单
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 @@
* See the License for the specific language governing permissions and
* 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.entity.MchNotifyRecord;
import com.jeequan.jeepay.core.mq.MqCommonService;
import com.jeequan.jeepay.pay.mq.config.MqThreadExecutor;
import com.jeequan.jeepay.service.impl.MchNotifyRecordService;
import com.jeequan.jeepay.service.impl.PayOrderService;
import com.jeequan.jeepay.pay.mq.receive.MqReceiveCommon;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.ScheduledMessage;
import org.apache.activemq.command.ActiveMQQueue;
......@@ -29,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Profile;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.scheduling.annotation.Async;
......@@ -38,41 +36,82 @@ import javax.jms.Queue;
import javax.jms.TextMessage;
/*
* 商户订单回调MQ通知
* 上游渠道订单轮询查单
* 如:微信的条码支付,没有回调接口, 需要轮询查单完成交易结果通知。
*
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:34
* @date 2021/6/8 17:30
*/
@Slf4j
@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(){
return new ActiveMQQueue(CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY);
}
@Lazy
@Autowired
@Qualifier("mqQueue4PayOrderMchNotifyInner")
@Qualifier("activePayOrderMchNotifyInner")
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) {
jmsTemplate.send(mqQueue4PayOrderMchNotifyInner, session -> {
/** 发送订单查询消息 **/
public void channelOrderQuery(String msg) {
this.jmsTemplate.convertAndSend(mqQueue4ChannelOrderQuery, msg);
}
/** 发送订单查询延迟消息 **/
public void channelOrderQueryFixed(String msg, long delay) {
jmsTemplate.send(mqQueue4ChannelOrderQuery, session -> {
TextMessage tm = session.createTextMessage(msg);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, 1*1000);
......@@ -81,61 +120,34 @@ public class MqQueue4PayOrderMchNotify {
});
}
/** 接收 更新系统配置项的消息 **/
@Async(MqThreadExecutor.EXECUTOR_PAYORDER_MCH_NOTIFY)
@JmsListener(destination = CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY)
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);
/** 发送订单回调消息 **/
public void payOrderMchNotify(String msg) {
this.jmsTemplate.convertAndSend(mqQueue4PayOrderMchNotifyInner, msg);
}
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() ){
mchNotifyRecordService.updateNotifyResult(notifyId, MchNotifyRecord.STATE_FAIL, res);
return ;
/** 接收 查单消息 **/
@JmsListener(destination = CS.MQ.QUEUE_CHANNEL_ORDER_QUERY)
public void receiveChannelOrderQuery(String msg) {
mqReceiveCommon.channelOrderQuery(msg);
}
// 继续发送MQ 延迟发送
mchNotifyRecordService.updateNotifyResult(notifyId, MchNotifyRecord.STATE_ING, res);
// 通知延时次数
// 1 2 3 4 5 6
// 0 30 60 90 120 150
send(msg, currentCount * 30 * 1000);
/** 接收 支付订单商户回调消息 **/
@Async(MqThreadExecutor.EXECUTOR_PAYORDER_MCH_NOTIFY)
@JmsListener(destination = CS.MQ.QUEUE_PAYORDER_MCH_NOTIFY)
public void receivePayOrderMchNotify(String msg) {
mqReceiveCommon.payOrderMchNotify(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;
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 @@
* See the License for the specific language governing permissions and
* 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.pay.service.ConfigContextService;
import com.jeequan.jeepay.pay.mq.receive.MqReceiveCommon;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
/*
* 更改商户信
* 接收mq消
*
* @author terrfly
* @site https://www.jeepay.vip
......@@ -32,9 +32,16 @@ import org.springframework.stereotype.Component;
*/
@Slf4j
@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{
* 2. 删除商户时
* **/
@JmsListener(destination = CS.MQ.TOPIC_MODIFY_MCH_INFO, containerFactory = "jmsListenerContainer")
public void receive(String mchNo) {
log.info("接收 [商户配置信息] 的消息, msg={}", mchNo);
configContextService.initMchInfoConfigContext(mchNo);
public void receiveModifyMchInfo(String mchNo) {
mqReceiveCommon.modifyMchInfo(mchNo);
}
/** 接收 [商户应用支付参数配置信息] 的消息
......@@ -54,11 +59,14 @@ public class MqTopic4ModifyMchInfo{
* 2. 删除商户应用配置
* **/
@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);
configContextService.initMchAppConfigContext(jsonObject.getString("mchNo"), jsonObject.getString("appId"));
/** 接收 更新系统配置项的消息 **/
@JmsListener(destination = CS.MQ.TOPIC_MODIFY_SYS_CONFIG, containerFactory = "jmsListenerContainer")
public void receiveModifySysConfig(String msg) {
mqReceiveCommon.initDbConfig(msg);
}
......
......@@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and
* 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.Profile;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.stereotype.Component;
......@@ -30,6 +32,7 @@ import javax.jms.ConnectionFactory;
* @date 2021/6/8 17:31
*/
@Component
@Profile(CS.MQTYPE.ACTIVE_MQ)
public class JMSConfig {
/** 新增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 @@
* See the License for the specific language governing permissions and
* 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.pay.service.ConfigContextService;
import com.jeequan.jeepay.pay.mq.receive.MqReceiveCommon;
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.jms.annotation.JmsListener;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
/*
* 更改ISV信
/**
* 接收mq消
*
* @author terrfly
* @author xiaoyu
* @site https://www.jeepay.vip
* @date 2021/6/8 17:31
* @date 2021/6/25 17:10
*/
@Slf4j
@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")
public void receive(String isvNo) {
/** 接收 更新服务商信息的消息 **/
@RabbitListener(queues = CS.MQ.TOPIC_MODIFY_ISV_INFO)
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;
@Data
public class ChannelUserIdRQ extends AbstractMchAppRQ{
/** 商户号 **/
@NotBlank(message="商户号不能为空")
private String mchNo;
/** 接口代码, AUTO表示:自动获取 **/
@NotBlank(message="接口代码不能为空")
private String ifCode;
......
......@@ -16,12 +16,13 @@
package com.jeequan.jeepay.pay.service;
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.entity.RefundOrder;
import com.jeequan.jeepay.core.mq.MqCommonService;
import com.jeequan.jeepay.core.utils.JeepayKit;
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.refund.QueryRefundOrderRS;
import com.jeequan.jeepay.service.impl.MchNotifyRecordService;
......@@ -42,8 +43,8 @@ import org.springframework.stereotype.Service;
public class PayMchNotifyService {
@Autowired private MchNotifyRecordService mchNotifyRecordService;
@Autowired private MqQueue4PayOrderMchNotify mqPayOrderMchNotifyQueue;
@Autowired private ConfigContextService configContextService;
@Autowired private MqCommonService mqCommonService;
/** 商户通知信息, 只有订单是终态,才会发送通知, 如明确成功和明确失败 **/
......@@ -84,7 +85,7 @@ public class PayMchNotifyService {
//推送到MQ
Long notifyId = mchNotifyRecord.getNotifyId();
mqPayOrderMchNotifyQueue.send(notifyId + "");
mqCommonService.send(notifyId + "", CS.MQ.MQ_TYPE_PAY_ORDER_MCH_NOTIFY);
} catch (Exception e) {
log.error("推送失败!", e);
......@@ -129,7 +130,7 @@ public class PayMchNotifyService {
//推送到MQ
Long notifyId = mchNotifyRecord.getNotifyId();
mqPayOrderMchNotifyQueue.send(notifyId + "");
mqCommonService.send(notifyId + "", CS.MQ.MQ_TYPE_PAY_ORDER_MCH_NOTIFY);
} catch (Exception e) {
log.error("推送失败!", e);
......
......@@ -50,9 +50,25 @@ spring:
timeout: 1000
database: 3 #1库:运营平台 #2库:商户系统 #3库:支付网关
password:
# 注意:以下MQ配置需注意【如需使用activeMQ则需将rabbitMQ配置注释即可】
# profiles:
# include:
# - activeMQ
# - rabbitMQ # 需要安装延迟队列插件:https://www.rabbitmq.com/blog/2015/04/16/scheduling-messages-with-rabbitmq/
#activeMQ配置
activemq:
broker-url: tcp://localhost:61616 #连接地址
# activemq:
# 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配置不生效。
......
......@@ -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<>();
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(dayStart)) param.put("createTimeStart", dayStart);
if (StrUtil.isNotBlank(dayEnd)) param.put("createTimeEnd", dayEnd);
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<>();
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(dayStart)) param.put("createTimeStart", dayStart);
if (StrUtil.isNotBlank(dayEnd)) param.put("createTimeEnd", dayEnd);
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(){
......@@ -190,7 +182,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
String dayStart = DateUtil.beginOfDay(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 (i == 0) {
todayAmount = dayAmount.get("payAmount").toString();
......@@ -219,7 +211,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
// 服务商总数
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("totalIsv", isvCount);
json.put("totalAmount", payCountMap.get("payAmount"));
......@@ -247,9 +239,10 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
param.put("createTimeEnd", createdEnd);
// 查询收款的记录
param.put("state", PayOrder.STATE_SUCCESS);
param.put("refundState", null);
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> returnList = getReturnList(daySpace, createdEnd, payOrderList, refundOrderList);
......@@ -272,7 +265,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
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<>();
......@@ -326,7 +319,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
payListMap.add(payMap);
for (Map refundOrderMap:refundOrderList) {
if (dayMap.get("date").equals(refundOrderMap.get("groupDate"))) {
refundMap.put("payAmount", refundOrderMap.get("payAmount"));
refundMap.put("payAmount", refundOrderMap.get("refundAmount"));
}
}
refundListMap.add(refundMap);
......
......@@ -36,8 +36,6 @@ public interface PayOrderMapper extends BaseMapper<PayOrder> {
List<Map> payTypeCount(Map param);
Map selectTotalCount(Map param);
List<Map> selectOrderCount(Map param);
/** 更新订单退款金额和次数 **/
......
......@@ -45,18 +45,7 @@
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="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="refundState != null"> AND refund_state = #{refundState} </if>
<if test="mchNo != null"> AND mch_no = #{mchNo} </if>
<if test="createTimeStart != null"> AND created_at &gt;= #{createTimeStart} </if>
<if test="createTimeEnd != null"> AND created_at &lt;= #{createTimeEnd} </if>
......@@ -69,6 +58,7 @@
FROM t_pay_order
WHERE 1=1
<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="createTimeStart != null"> AND created_at &gt;= #{createTimeStart} </if>
<if test="createTimeEnd != null"> AND created_at &lt;= #{createTimeEnd} </if>
......@@ -77,10 +67,14 @@
<!--成功、退款订单统计-->
<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
WHERE 1=1
<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="createTimeStart != null"> AND created_at &gt;= #{createTimeStart} </if>
<if test="createTimeEnd != null"> AND created_at &lt;= #{createTimeEnd} </if>
......
......@@ -34,7 +34,7 @@
<properties>
<java.version>1.8</java.version> <!-- 指定java版本号 -->
<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>
......
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