Althars123 4 yıl önce
ebeveyn
işleme
549d8df498

+ 13 - 53
zzjs-admin/src/main/java/com/miaxis/app/controller/film/FilmController.java

@@ -51,6 +51,7 @@ import java.security.PrivateKey;
 import java.security.Signature;
 import java.util.*;
 
+import static com.miaxis.common.constant.Constants.FILM_BLACK_LIST;
 import static com.miaxis.common.utils.OrderCodeFactory.getOrderCode;
 
 /**
@@ -81,7 +82,7 @@ public class FilmController extends BaseController {
     private  String appKey ;
     @Value("${film.appSecret}")
     private  String appSecret ;
-    @Value("${film.notifyUrl}")
+    @Value("${wxpay.notifyUrl}")
     private  String notifyUrl ;
 
 
@@ -128,11 +129,12 @@ public class FilmController extends BaseController {
 
         //本地创建订单
         FilmOrder order = new FilmOrder();
+        order.setShowId(filmOrderCreateDTO.getShowId());
         order.setOutTradeNo(orderCode);
         order.setSeat(filmOrderCreateDTO.getSeat());
         order.setAcceptChangeSeat(filmOrderCreateDTO.getAcceptChangeSeat());
         order.setSeatId(filmOrderCreateDTO.getSeatId());
-        order.setSeatno(filmOrderCreateDTO.getSeatno());
+        order.setSeatNo(filmOrderCreateDTO.getSeatNo());
         order.setReservedPhone(filmOrderCreateDTO.getReservedPhone());
         order.setOpenid(student.getOpenid());
         filmOrderService.save(order);
@@ -178,61 +180,19 @@ public class FilmController extends BaseController {
      */
     @PostMapping(value = "/fileCommonApi")
     @ApiOperation("电影通用接口")
-    public  Response<JSONObject>  httpPostWithForm(@RequestBody FilmDTO filmDTO){
-        // 用于接收返回的结果
-        String resultData ="";
-        try {
-            HttpPost post = new HttpPost("http://movieapi2-test.taototo.cn/"+filmDTO.getUrl());
-            post.setHeader("Content-Type","application/x-www-form-urlencoded");
-            Map<String, Object> sortMap = new TreeMap<String, Object>();
-            String time = String.valueOf(System.currentTimeMillis()/1000);
-            sortMap.put("appKey",appKey);
-            sortMap.put("time",time);
-            //1 将数据拆分成 treemap存储
-            if (!StringUtils.isEmpty(filmDTO.getParamData())){
-                String[] keyValueStr = filmDTO.getParamData().split("&");
-                for(String keyValue : keyValueStr){
-                    String[] arr = keyValue.split("=");
-                    sortMap.put(arr[0],arr[1]) ;
-                }
-            }
-            //2 读取treemap。按固定格式拼接,最后再拼接上 secret
-            StringBuilder builder = new StringBuilder();
-            for (Map.Entry<String, Object> s : sortMap.entrySet()) {
-                String k = s.getKey();
-                Object v = s.getValue();
-                builder.append(k).append("=").append(v).append("&");
-            }
-            builder.append("appSecret="+appSecret);
-            //3 将最后拼接出来的sign传 md5加密
-            String sign = MD5Utils.MD5Encode(builder.toString());
-            List<BasicNameValuePair> pairList = new ArrayList<BasicNameValuePair>();
-            // 迭代Map-->取出key,value放到BasicNameValuePair对象中-->添加到list中
-            for (Map.Entry entry : sortMap.entrySet()) {
-                pairList.add(new BasicNameValuePair(String.valueOf(entry.getKey()) ,String.valueOf(entry.getValue())));
-            }
-            pairList.add(new BasicNameValuePair("sign",sign));
-            UrlEncodedFormEntity uefe = new UrlEncodedFormEntity(pairList, "utf-8");
-            post.setEntity(uefe);
-            // 创建一个http客户端
-            CloseableHttpClient httpClient = HttpClientBuilder.create().build();
-            // 发送post请求
-            HttpResponse response = httpClient.execute(post);
-
-            // 状态码为:200
-            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
-                // 返回数据:
-                resultData = EntityUtils.toString(response.getEntity(),"UTF-8");
-            }else{
-                throw new RuntimeException("接口连接失败!");
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new RuntimeException("接口连接失败!");
+    public  Response<JSONObject>  httpPostWithForm(@RequestBody FilmDTO filmDTO) throws IOException {
+
+        //检查api
+        if (Arrays.asList(FILM_BLACK_LIST).contains(filmDTO.getUrl())){
+            throw new CustomException("该api不允许用户直接访问");
         }
+        // 用于接收返回的结果
+        String resultData = filmOrderService.excuteFilmApi(filmDTO);
         return Response.success(JSONObject.parseObject(resultData));
     }
 
+
+
     /**
      * 获取电影订单详细信息
      */

+ 81 - 2
zzjs-admin/src/main/java/com/miaxis/app/controller/film/NotifyController.java

@@ -7,7 +7,9 @@ import com.miaxis.common.constant.Constants;
 import com.miaxis.common.core.domain.Response;
 import com.miaxis.common.exception.CustomException;
 import com.miaxis.common.utils.AesUtil;
+import com.miaxis.feign.dto.FilmDTO;
 import com.miaxis.film.domain.FilmOrder;
+import com.miaxis.film.dto.FilmOrderNotifyDTO;
 import com.miaxis.film.dto.FilmWxpayDTO;
 import com.miaxis.film.service.IFilmOrderService;
 import io.swagger.annotations.Api;
@@ -18,6 +20,9 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.joda.time.DateTime;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
@@ -43,6 +48,12 @@ public class NotifyController {
     @Autowired
     private IFilmOrderService filmOrderService;
 
+    @Autowired
+    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
+
+    @Value("${film.notifyUrl}")
+    private  String notifyUrl ;
+
     /**
      * 微信支付回调接口
      */
@@ -56,13 +67,43 @@ public class NotifyController {
         JSONObject jsonObject = JSONObject.parseObject(resourceString);
         //将回调数据写入数据库
         writeNotifyDataToDb(jsonObject);
+
+
+
         WxNotifyReturnDTO wxNotifyReturnDTO = new WxNotifyReturnDTO();
         wxNotifyReturnDTO.setCode("SUCCESS");
         wxNotifyReturnDTO.setMessage("成功");
         return wxNotifyReturnDTO;
     }
 
-    private void writeNotifyDataToDb(JSONObject jsonObject) {
+    /**
+     * 电影回调接口
+     */
+    @PostMapping(value = "/filmOrder")
+    @ApiOperation("电影订单回调")
+    public FilmNotifyReturnDTO filmOrderNotify(@RequestBody FilmOrderNotifyDTO filmOrderNotifyDTO) throws GeneralSecurityException, IOException {
+        FilmOrder filmOrder = filmOrderService.getByOutTradeNo(filmOrderNotifyDTO.getThirdOrderId());
+       //todo 检查sign
+        filmOrder.setOrderState(filmOrderNotifyDTO.getEventName());
+        filmOrder.setOrderPrice(Integer.valueOf(filmOrderNotifyDTO.getOrderPrice()));
+        filmOrder.setCloseCause(filmOrderNotifyDTO.getCloseCause());
+        filmOrder.setRealSeat(filmOrderNotifyDTO.getRealSeat());
+        filmOrder.setTicketCode(filmOrderNotifyDTO.getTicketCode());
+        filmOrder.setTicketImage(filmOrderNotifyDTO.getTicketImage());
+        filmOrderService.updateById(filmOrder);
+
+
+        FilmNotifyReturnDTO filmNotifyReturnDTO = new FilmNotifyReturnDTO();
+        filmNotifyReturnDTO.setCode("200");
+        filmNotifyReturnDTO.setMessage("请求成功");
+        return filmNotifyReturnDTO;
+    }
+
+
+
+
+    @Transactional
+    public void writeNotifyDataToDb(JSONObject jsonObject) {
         String outTradeNo = jsonObject.getString("out_trade_no");
         FilmOrder filmOrder = filmOrderService.getByOutTradeNo(outTradeNo);
         if (filmOrder == null) {
@@ -85,8 +126,39 @@ public class NotifyController {
         if (sceneInfo != null){
             filmOrder.setDeviceId(sceneInfo.getString("device_id"));
         }
-        filmOrderService.updateById(filmOrder);
+        //如果订单还未下过电影票订单,则异步调用电影下单api
+        String orderState = filmOrder.getOrderState();
+        if (orderState == null){
+            threadPoolTaskExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
+                    FilmDTO filmDTO = new FilmDTO();
+                    filmDTO.setUrl("api/order/create");
+                    StringBuffer paramData =  new StringBuffer();
+                    paramData.append("showId="+filmOrder.getShowId()+"&");
+                    paramData.append("seat="+filmOrder.getSeat()+"&");
+                    if (filmOrder.getReservedPhone() != null){
+                        paramData.append("reservedPhone="+filmOrder.getReservedPhone()+"&");
+                    }
+                    paramData.append("thirdOrderId="+filmOrder.getOutTradeNo()+"&");
+                    paramData.append("notifyUrl="+notifyUrl+"&");
+                    if (filmOrder.getSeatId() != null){
+                        paramData.append("seatId="+filmOrder.getSeatId()+"&");
+                    }
+                    if (filmOrder.getSeatNo() != null){
+                        paramData.append("seatNo="+filmOrder.getSeatNo()+"&");
+                    }
+                    paramData.append("acceptChangeSeat="+filmOrder.getAcceptChangeSeat());
+                    try {
+                        filmOrderService.excuteFilmApi(filmDTO);
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            });
+        }
 
+        filmOrderService.updateById(filmOrder);
     }
     @Data
     public class WxNotifyReturnDTO {
@@ -94,4 +166,11 @@ public class NotifyController {
         String message;
     }
 
+    @Data
+    public class FilmNotifyReturnDTO {
+        String code;
+        String message;
+        Boolean success;
+    }
+
 }

+ 3 - 2
zzjs-admin/src/main/resources/application.yml

@@ -231,14 +231,15 @@ wxpay:
   merchantId: 1608699504
   serialNumber: 487159E168001CDBA0EFE2C988249A84023AD6CC
   v3key: qqwweerrttyyuuiioopp123456789000
+  notifyUrl: http://218.85.55.253:65535/zzjs-admin/open-api/film/notify/wxpay
 
 
 # 电影
 film:
   appKey: 10000000000
   appSecret: 25f9e794323b453885f5181f1b624d0b
-#  notifyUrl: http://218.85.55.253:65535/zzjs-admin/
-  notifyUrl: http://218.85.55.253:65535/zzjs-admin/open-api/film/notify/wxpay
+  notifyUrl: http://218.85.55.253:65535/zzjs-admin/open-api/film/notify/filmOrder
+
 
 
 

+ 7 - 0
zzjs-common/src/main/java/com/miaxis/common/constant/Constants.java

@@ -156,4 +156,11 @@ public class Constants
      * 学员权限路径
      */
     public static final String STUDENT_PREFIX = "/student";
+
+
+
+    /**
+     * 电影api 黑名单
+     */
+    public static final String[] FILM_BLACK_LIST = new String[]{"api/order/create"};
 }

+ 8 - 2
zzjs-service/src/main/java/com/miaxis/film/domain/FilmOrder.java

@@ -127,6 +127,12 @@ ACCEPT:已接收,等待扣款 */
     @ApiModelProperty(value = "商户端设备号")
     private String deviceId;
 
+    /** 商户端设备号 */
+    @Excel(name = "排期的showId,由影院接口得来")
+    @TableField("show_id")
+    @ApiModelProperty(value = "排期的showId,由影院接口得来")
+    private String showId;
+
     /** 用户所选的座位,例:1排1座,1排2座 以英文的逗号 “ , “隔开。 如果座位是情侣座,请传入 : 1排1座(情侣座),1排2座(情侣座) */
     @Excel(name = "用户所选的座位,例:1排1座,1排2座 以英文的逗号 “ , “隔开。 如果座位是情侣座,请传入 : 1排1座(情侣座),1排2座(情侣座)")
     @TableField("seat")
@@ -153,9 +159,9 @@ ACCEPT:已接收,等待扣款 */
 
     /** 座位接口的seatNo字段,如果有多个,则以竖线分割 */
     @Excel(name = "座位接口的seatNo字段,如果有多个,则以竖线分割")
-    @TableField("seatNo")
+    @TableField("seat_no")
     @ApiModelProperty(value = "座位接口的seatNo字段,如果有多个,则以竖线分割")
-    private String seatno;
+    private String seatNo;
 
     /** 订单状态,枚举值:
 ORDER_CLOSE  关闭

+ 5 - 16
zzjs-service/src/main/java/com/miaxis/film/dto/FilmOrderCreateDTO.java

@@ -16,35 +16,24 @@ public class FilmOrderCreateDTO {
     private String showId;
 
 
-    /** 用户所选的座位,例:1排1座,1排2座 以英文的逗号 “ , “隔开。 如果座位是情侣座,请传入 : 1排1座(情侣座),1排2座(情侣座) */
-    @Excel(name = "用户所选的座位,例:1排1座,1排2座 以英文的逗号 “ , “隔开。 如果座位是情侣座,请传入 : 1排1座(情侣座),1排2座(情侣座)")
-    @TableField("seat")
+
     @ApiModelProperty(value = "用户所选的座位,例:1排1座,1排2座 以英文的逗号 “ , “隔开。 如果座位是情侣座,请传入 : 1排1座(情侣座),1排2座(情侣座)")
     private String seat;
 
-    /** 预留的手机号 */
-    @Excel(name = "预留的手机号")
-    @TableField("reserved_phone")
+
     @ApiModelProperty(value = "预留的手机号")
     private String reservedPhone;
 
-    /** 是否允许调座,1-允许,0-不允许 */
-    @Excel(name = "是否允许调座,1-允许,0-不允许")
-    @TableField("accept_change_seat")
+
     @ApiModelProperty(value = "是否允许调座,1-允许,0-不允许")
     private Integer acceptChangeSeat;
 
-    /** 座位接口的seatId字段, 如果有多个,则以竖线分割 */
-    @Excel(name = "座位接口的seatId字段, 如果有多个,则以竖线分割")
-    @TableField("seat_id")
     @ApiModelProperty(value = "座位接口的seatId字段, 如果有多个,则以竖线分割")
     private String seatId;
 
-    /** 座位接口的seatNo字段,如果有多个,则以竖线分割 */
-    @Excel(name = "座位接口的seatNo字段,如果有多个,则以竖线分割")
-    @TableField("seatNo")
+
     @ApiModelProperty(value = "座位接口的seatNo字段,如果有多个,则以竖线分割")
-    private String seatno;
+    private String seatNo;
 
 
 

+ 59 - 0
zzjs-service/src/main/java/com/miaxis/film/dto/FilmOrderNotifyDTO.java

@@ -0,0 +1,59 @@
+package com.miaxis.film.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 微信支付回调 dto
+ */
+@Data
+public class FilmOrderNotifyDTO {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "签名,接入方需校验签名是否有效。签名规则与下单相同。")
+    private String sign;
+
+    @ApiModelProperty(value = "接入方key (推广位)")
+    private String appKey;
+
+    @ApiModelProperty(value = "时间戳")
+    private String time;
+
+
+    @ApiModelProperty(value = "订单状态发生变更时的事件如: ORDER_CLOSE")
+    private String eventName;
+
+
+    @ApiModelProperty(value = "接入方下单时的订单号")
+    private String thirdOrderId;
+
+    @ApiModelProperty(value = "回调地址,各个场景发生时,将通过此地址通知接入方")
+    private String notifyUrl;
+
+
+
+
+    @ApiModelProperty(value = "api下单成本价(竞价结束回调通知返回:WAIT_TICKET场景)")
+    private String orderPrice;
+
+
+    @ApiModelProperty(value = "如果事件为订单关闭 ORDER_CLOSE 则有此字段")
+    private String closeCause;
+
+    @ApiModelProperty(value = "实际出票座位,仅供参考,可能与票不一样,也可能为空,一般当实际座位与下单座位不一样时会有")
+    private String realSeat;
+
+
+
+    @ApiModelProperty(value = "取票码字符串如: “[\\”123123\\”,\\”4564357\\”]” 直接用json解析可得到数组,如取票失败则用使用原始截图")
+    private String ticketCode;
+
+    @ApiModelProperty(value = "取票码原始截图如: “[\\”http:\\\\/\\\\/shoutudyp.oss-cn-shenzhen.aliyuncs.com\\\\/b768007aa9071eba3e3018a27dcc47c0.png\\”,\\”http:\\\\/\\\\/shoutudyp.oss-cn-shenzhen.aliyuncs.com\\\\/f9774915e35fae41ae96ebf288477394.jpg\\”]” 直接用json解析可得到数组")
+    private String ticketImage;
+
+
+
+
+
+
+}

+ 5 - 0
zzjs-service/src/main/java/com/miaxis/film/service/IFilmOrderService.java

@@ -1,6 +1,9 @@
 package com.miaxis.film.service;
 
+import java.io.IOException;
 import java.util.List;
+
+import com.miaxis.feign.dto.FilmDTO;
 import com.miaxis.film.domain.FilmOrder;
 import com.baomidou.mybatisplus.extension.service.IService;
 
@@ -20,4 +23,6 @@ public interface IFilmOrderService extends IService<FilmOrder>{
     public List<FilmOrder> selectFilmOrderList(FilmOrder filmOrder);
 
     FilmOrder getByOutTradeNo(String outTradeNo);
+
+    String excuteFilmApi(FilmDTO filmDTO) throws IOException;
 }

+ 84 - 1
zzjs-service/src/main/java/com/miaxis/film/service/impl/FilmOrderServiceImpl.java

@@ -1,13 +1,29 @@
 package com.miaxis.film.service.impl;
 
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.miaxis.common.sms.MD5Utils;
 import com.miaxis.common.utils.DateUtils;
+import com.miaxis.common.utils.StringUtils;
+import com.miaxis.feign.dto.FilmDTO;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
-import org.apache.commons.lang3.StringUtils;
 import com.miaxis.film.mapper.FilmOrderMapper;
 import com.miaxis.film.domain.FilmOrder;
 import com.miaxis.film.service.IFilmOrderService;
@@ -23,6 +39,15 @@ public class FilmOrderServiceImpl extends ServiceImpl<FilmOrderMapper, FilmOrder
     @Autowired
     private FilmOrderMapper filmOrderMapper;
 
+
+    @Value("${app.appid}")
+    private String appid;
+    @Value("${film.appKey}")
+    private  String appKey ;
+    @Value("${film.appSecret}")
+    private  String appSecret ;
+
+
     /**
      * 查询电影订单列表
      *
@@ -38,4 +63,62 @@ public class FilmOrderServiceImpl extends ServiceImpl<FilmOrderMapper, FilmOrder
     public FilmOrder getByOutTradeNo(String outTradeNo) {
         return filmOrderMapper.getByOutTradeNo(outTradeNo);
     }
+
+    @Override
+    public String  excuteFilmApi(FilmDTO filmDTO) throws IOException {
+        String resultData ="";
+        // 创建一个http客户端
+        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
+        try {
+            HttpPost post = new HttpPost("http://movieapi2-test.taototo.cn/"+filmDTO.getUrl());
+            post.setHeader("Content-Type","application/x-www-form-urlencoded");
+            Map<String, Object> sortMap = new TreeMap<String, Object>();
+            String time = String.valueOf(System.currentTimeMillis()/1000);
+            sortMap.put("appKey",appKey);
+            sortMap.put("time",time);
+            //1 将数据拆分成 treemap存储
+            if (!StringUtils.isEmpty(filmDTO.getParamData())){
+                String[] keyValueStr = filmDTO.getParamData().split("&");
+                for(String keyValue : keyValueStr){
+                    String[] arr = keyValue.split("=");
+                    sortMap.put(arr[0],arr[1]) ;
+                }
+            }
+            //2 读取treemap。按固定格式拼接,最后再拼接上 secret
+            StringBuilder builder = new StringBuilder();
+            for (Map.Entry<String, Object> s : sortMap.entrySet()) {
+                String k = s.getKey();
+                Object v = s.getValue();
+                builder.append(k).append("=").append(v).append("&");
+            }
+            builder.append("appSecret="+appSecret);
+            //3 将最后拼接出来的sign传 md5加密
+            String sign = MD5Utils.MD5Encode(builder.toString());
+            List<BasicNameValuePair> pairList = new ArrayList<BasicNameValuePair>();
+            // 迭代Map-->取出key,value放到BasicNameValuePair对象中-->添加到list中
+            for (Map.Entry entry : sortMap.entrySet()) {
+                pairList.add(new BasicNameValuePair(String.valueOf(entry.getKey()) ,String.valueOf(entry.getValue())));
+            }
+            pairList.add(new BasicNameValuePair("sign",sign));
+            UrlEncodedFormEntity uefe = new UrlEncodedFormEntity(pairList, "utf-8");
+            post.setEntity(uefe);
+
+            // 发送post请求
+            HttpResponse response = httpClient.execute(post);
+
+            // 状态码为:200
+            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
+                // 返回数据:
+                resultData = EntityUtils.toString(response.getEntity(),"UTF-8");
+            }else{
+                throw new RuntimeException("接口连接失败!");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("接口连接失败!");
+        } finally {
+            httpClient.close();
+        }
+        return null;
+    }
 }

+ 2 - 2
zzjs-service/src/main/resources/mapper/film/FilmOrderMapper.xml

@@ -25,7 +25,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="reservedPhone"    column="reserved_phone"    />
         <result property="acceptChangeSeat"    column="accept_change_seat"    />
         <result property="seatId"    column="seat_id"    />
-        <result property="seatno"    column="seatNo"    />
+        <result property="seatNo"    column="seat_no"    />
         <result property="orderState"    column="order_state"    />
         <result property="orderPrice"    column="order_price"    />
         <result property="closeCause"    column="close_cause"    />
@@ -67,7 +67,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="reservedPhone != null  and reservedPhone != ''"> and reserved_phone = #{reservedPhone}</if>
             <if test="acceptChangeSeat != null "> and accept_change_seat = #{acceptChangeSeat}</if>
             <if test="seatId != null  and seatId != ''"> and seat_id = #{seatId}</if>
-            <if test="seatno != null  and seatno != ''"> and seatNo = #{seatno}</if>
+            <if test="seatno != null  and seatno != ''"> and seat_no = #{seatNo}</if>
             <if test="orderState != null  and orderState != ''"> and order_state = #{orderState}</if>
             <if test="orderPrice != null "> and order_price = #{orderPrice}</if>
             <if test="closeCause != null  and closeCause != ''"> and close_cause = #{closeCause}</if>