xh-pan1
2 years ago
51 changed files with 1325 additions and 340 deletions
-
6cereshop-admin/src/main/resources/application-admin-dev.yml
-
10cereshop-admin/src/main/resources/application-admin-prod.yml
-
2cereshop-admin/src/main/resources/mybatis/mapper/order/CereShopOrderDAO.xml
-
30cereshop-admin/src/main/resources/mybatis/mapper/product/CereProductSkuDAO.xml
-
49cereshop-app/src/main/java/com/shop/cereshop/app/controller/extend/XsPayController.java
-
3cereshop-app/src/main/java/com/shop/cereshop/app/dao/buyer/CereBuyerUserDAO.java
-
13cereshop-app/src/main/java/com/shop/cereshop/app/pay/xs/service/XsPayService.java
-
306cereshop-app/src/main/java/com/shop/cereshop/app/pay/xs/service/impl/XsPayServiceImpl.java
-
3cereshop-app/src/main/java/com/shop/cereshop/app/redis/listener/RedisListener.java
-
4cereshop-app/src/main/java/com/shop/cereshop/app/service/buyer/CereBuyerUserService.java
-
13cereshop-app/src/main/java/com/shop/cereshop/app/service/buyer/impl/CereBuyerUserServiceImpl.java
-
2cereshop-app/src/main/java/com/shop/cereshop/app/service/extend/HuaxunService.java
-
19cereshop-app/src/main/java/com/shop/cereshop/app/service/extend/impl/HuaxunServiceImpl.java
-
9cereshop-app/src/main/java/com/shop/cereshop/app/service/order/impl/CereShopOrderServiceImpl.java
-
2cereshop-app/src/main/java/com/shop/cereshop/app/service/order/placeOrderTemplate/LaunchPlaceOrder.java
-
3cereshop-app/src/main/java/com/shop/cereshop/app/service/order/placeOrderTemplate/NormalPlaceOrder.java
-
4cereshop-app/src/main/java/com/shop/cereshop/app/service/order/placeOrderTemplate/PlaceOrderTemplate.java
-
4cereshop-app/src/main/java/com/shop/cereshop/app/service/stock/CrossStockService.java
-
150cereshop-app/src/main/java/com/shop/cereshop/app/service/stock/impl/CrossStockServiceImpl.java
-
14cereshop-app/src/main/resources/application-app-dev.yml
-
4cereshop-app/src/main/resources/application-app-prod.yml
-
12cereshop-app/src/main/resources/application.yml
-
29cereshop-app/src/main/resources/mybatis/mapper/buyer/CereBuyerUserDAO.xml
-
25cereshop-app/src/main/resources/mybatis/mapper/order/CereOrderProductDAO.xml
-
8cereshop-app/src/main/resources/mybatis/mapper/order/CereShopOrderDAO.xml
-
67cereshop-business/src/main/java/com/shop/cereshop/business/controller/HuaxunController.java
-
111cereshop-business/src/main/java/com/shop/cereshop/business/controller/XsPayController.java
-
2cereshop-business/src/main/java/com/shop/cereshop/business/dao/buyer/CereBuyerUserDAO.java
-
4cereshop-business/src/main/java/com/shop/cereshop/business/dao/order/CereOrderProductDAO.java
-
4cereshop-business/src/main/java/com/shop/cereshop/business/dao/order/CereShopOrderDAO.java
-
6cereshop-business/src/main/java/com/shop/cereshop/business/param/product/SkuParam.java
-
227cereshop-business/src/main/java/com/shop/cereshop/business/pay/xs/service/impl/XsPayServiceImpl.java
-
5cereshop-business/src/main/java/com/shop/cereshop/business/service/buyer/CereBuyerUserService.java
-
15cereshop-business/src/main/java/com/shop/cereshop/business/service/buyer/impl/CereBuyerUserServiceImpl.java
-
41cereshop-business/src/main/java/com/shop/cereshop/business/service/extend/HuaxunService.java
-
172cereshop-business/src/main/java/com/shop/cereshop/business/service/extend/impl/HuaxunServiceImpl.java
-
8cereshop-business/src/main/java/com/shop/cereshop/business/service/order/CereOrderDileverService.java
-
6cereshop-business/src/main/java/com/shop/cereshop/business/service/order/CereOrderProductService.java
-
54cereshop-business/src/main/java/com/shop/cereshop/business/service/order/impl/CereOrderDileverServiceImpl.java
-
15cereshop-business/src/main/java/com/shop/cereshop/business/service/order/impl/CereOrderProductServiceImpl.java
-
15cereshop-business/src/main/resources/application-business-dev.yml
-
6cereshop-business/src/main/resources/application-business-prod.yml
-
2cereshop-business/src/main/resources/application-business-test.yml
-
12cereshop-business/src/main/resources/application.yml
-
35cereshop-business/src/main/resources/mybatis/mapper/buyer/CereBuyerUserDAO.xml
-
10cereshop-business/src/main/resources/mybatis/mapper/order/CereOrderProductDAO.xml
-
10cereshop-business/src/main/resources/mybatis/mapper/order/CereShopOrderDAO.xml
-
32cereshop-business/src/main/resources/mybatis/mapper/product/CereProductSkuDAO.xml
-
70cereshop-commons/src/main/java/com/shop/cereshop/commons/config/XspayConfig.java
-
6cereshop-commons/src/main/java/com/shop/cereshop/commons/domain/order/CereOrderProduct.java
-
6cereshop-commons/src/main/java/com/shop/cereshop/commons/domain/product/CereProductSku.java
@ -0,0 +1,67 @@ |
|||
package com.shop.cereshop.business.controller; |
|||
|
|||
import com.google.gson.Gson; |
|||
import com.shop.cereshop.business.service.extend.HuaxunService; |
|||
import com.shop.cereshop.commons.domain.huaxun.HuaxunExpressRequestBo; |
|||
import com.shop.cereshop.commons.domain.huaxun.HuaxunOrderRequestBo; |
|||
import io.swagger.annotations.Api; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
/** |
|||
* 华讯模块 |
|||
*/ |
|||
@RestController |
|||
@RequestMapping("extend/huaxun") |
|||
@Slf4j(topic = "huaxunController") |
|||
@Api(value = "华讯模块", tags = "华讯模块") |
|||
public class HuaxunController { |
|||
|
|||
@Autowired |
|||
private HuaxunService huaxunService; |
|||
|
|||
/** |
|||
* 查询订单接口 |
|||
* @throws Exception |
|||
*/ |
|||
@PostMapping("order/queryOrder") |
|||
public String queryOrder(@RequestParam(name = "pay_start_time") String payStartTime, |
|||
@RequestParam(name = "pay_end_time") String payEndTime, |
|||
@RequestParam(name = "timestamp") Long timestamp, @RequestParam(name = "sign") String sign) throws Exception { |
|||
try { |
|||
HuaxunOrderRequestBo bo = new HuaxunOrderRequestBo(); |
|||
bo.setPayStartTime(payStartTime); |
|||
bo.setPayEndTime(payEndTime); |
|||
bo.setTimestamp(timestamp); |
|||
bo.setSign(sign); |
|||
return new Gson().toJson(huaxunService.queryOrder(bo)); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return "[]"; |
|||
} |
|||
|
|||
/** |
|||
* 物流状态通知 |
|||
* @throws Exception |
|||
*/ |
|||
@PostMapping("express/notifyExpress") |
|||
public String notifyExpress(@RequestParam(name = "data") String data, @RequestParam(name = "timestamp") Long timestamp, @RequestParam(name = "sign") String sign) throws Exception { |
|||
try { |
|||
HuaxunExpressRequestBo bo = new HuaxunExpressRequestBo(); |
|||
bo.setData(data); |
|||
bo.setTimestamp(timestamp); |
|||
bo.setSign(sign); |
|||
if(huaxunService.notifyExpress(bo)){ |
|||
return "success"; |
|||
} |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return "false"; |
|||
} |
|||
} |
@ -0,0 +1,111 @@ |
|||
package com.shop.cereshop.business.controller; |
|||
|
|||
import com.alibaba.fastjson.JSONObject; |
|||
import com.google.gson.Gson; |
|||
import com.shop.cereshop.business.pay.xs.domain.XsCallBackRequestVo; |
|||
import com.shop.cereshop.business.pay.xs.service.XsPayService; |
|||
import com.shop.cereshop.business.service.order.CereShopOrderService; |
|||
import com.shop.cereshop.commons.utils.EmptyUtils; |
|||
import com.shop.cereshop.commons.utils.StringUtils; |
|||
import io.swagger.annotations.Api; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
/** |
|||
* 新生支付模块 |
|||
*/ |
|||
@RestController |
|||
@RequestMapping("extend/xsPay") |
|||
@Slf4j(topic = "xsPayController") |
|||
@Api(value = "新生支付模块", tags = "新生支付模块") |
|||
public class XsPayController { |
|||
|
|||
@Autowired |
|||
private XsPayService xsPayService; |
|||
// |
|||
// |
|||
// @Autowired |
|||
// private HuaxunService huaxunService; |
|||
// |
|||
// |
|||
@Autowired |
|||
private CereShopOrderService cereShopOrderService; |
|||
// /** |
|||
// * 支付通知回调 |
|||
// * @throws Exception |
|||
// */ |
|||
// @PostMapping("pay/notify") |
|||
// public void payNotify(@RequestParam(name = "msg") String msg) throws Exception { |
|||
// try { |
|||
// XsCallBackRequestVo xsCallBackRequestVo = xsPayService.parseCallBackRequestVo(msg); |
|||
// String status = xsCallBackRequestVo.getContent().getString("status"); |
|||
// //0进行中 1成功 2失败 |
|||
// if(StringUtils.equals(status, "1")){ |
|||
// log.info("新生支付回调成功"); |
|||
// //截取订单编号 |
|||
// JSONObject content = xsCallBackRequestVo.getContent(); |
|||
// String merOrderId = content.getString("merOrderId"); |
|||
// String[] split = merOrderId.split("-"); |
|||
// if(!EmptyUtils.isEmpty(split)){ |
|||
// String orderFormId=split[0]; |
|||
// if(!EmptyUtils.isEmpty(orderFormId)){ |
|||
// //支付有礼 |
|||
// cereShopOrderService.payGift(orderFormId); |
|||
// String dealId = content.getString("dealId"); |
|||
// //处理支付成功后的其他逻辑 |
|||
// cereShopOrderService.handleWxLog(orderFormId, dealId, merOrderId); |
|||
// } |
|||
// |
|||
// } |
|||
// //TODO 如果不是跨境支付应该不调用改接口------pxh |
|||
// if(StringUtils.equals(XspayConfig.DEFUALT_TRADE_TYPE, XsPayEnum.TRADE_TYPE_CROSS_BOARD_PAYMENT.getCode())){ |
|||
// String payRequestBodyJson = xsPayService.getPayRequestBodyJson(merOrderId, new BigDecimal(Integer.parseInt(content.getString("orderAmount")) * 1.0f / 100), |
|||
// XsPayEnum.TRADE_TYPE_CROSS_BOARD_PAYMENT.getCode(), content.getString("payType")); |
|||
// huaxunService.pushBaoguanRequest(payRequestBodyJson); |
|||
// |
|||
// String msgStr = new String(Base64.getDecoder().decode(msg)); |
|||
// huaxunService.pushBaoguanRespone(msgStr); |
|||
// } |
|||
// } |
|||
// } catch (Exception e) { |
|||
// e.printStackTrace(); |
|||
// } |
|||
// } |
|||
// |
|||
/** |
|||
* 退款通知回调 |
|||
* @throws Exception |
|||
*/ |
|||
@PostMapping("refund/notify") |
|||
public void refundNotify(@RequestParam(name = "msg") String msg) throws Exception { |
|||
log.info("refundNotify msg:" + msg); |
|||
try { |
|||
XsCallBackRequestVo xsCallBackRequestVo = xsPayService.parseCallBackRequestVo(msg); |
|||
log.info(new Gson().toJson(xsCallBackRequestVo)); |
|||
String status = xsCallBackRequestVo.getContent().getString("status"); |
|||
//2成功 3失败 |
|||
if(StringUtils.equals(status, "0")){ |
|||
log.info("退款回调成功"); |
|||
//截取订单编号 |
|||
JSONObject content = xsCallBackRequestVo.getContent(); |
|||
String merOrderId = content.getString("merOrderId"); |
|||
String[] split = merOrderId.split("-"); |
|||
if(!EmptyUtils.isEmpty(split)){ |
|||
String orderFormId=split[0]; |
|||
if(!EmptyUtils.isEmpty(orderFormId)){ |
|||
String dealId = content.getString("refundOrderNo"); |
|||
//处理支付成功后的其他逻辑 |
|||
cereShopOrderService.handleRefundWxLog(orderFormId, dealId, merOrderId); |
|||
} |
|||
} |
|||
} |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
// |
|||
} |
|||
} |
@ -0,0 +1,41 @@ |
|||
/* |
|||
* Copyright (C) 2017-2021 |
|||
* All rights reserved, Designed By 深圳中科鑫智科技有限公司 |
|||
* Copyright authorization contact 18814114118 |
|||
*/ |
|||
package com.shop.cereshop.business.service.extend; |
|||
|
|||
|
|||
import com.shop.cereshop.commons.domain.huaxun.HuaxunExpressRequestBo; |
|||
import com.shop.cereshop.commons.domain.huaxun.HuaxunOrderRequestBo; |
|||
import com.shop.cereshop.commons.domain.huaxun.OrderListVo; |
|||
import com.shop.cereshop.commons.exception.CoBusinessException; |
|||
|
|||
import java.io.UnsupportedEncodingException; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* <p> |
|||
* 华讯清关业务接口 |
|||
* </p> |
|||
* |
|||
* @author pxh |
|||
* @date 2023-03-10 |
|||
*/ |
|||
public interface HuaxunService { |
|||
|
|||
|
|||
/** |
|||
* 华讯查询订单 |
|||
* @param bo |
|||
* @return |
|||
*/ |
|||
List<OrderListVo> queryOrder(HuaxunOrderRequestBo bo) throws UnsupportedEncodingException, CoBusinessException; |
|||
|
|||
/** |
|||
* 物流消息接收 |
|||
* @param bo |
|||
* @return |
|||
*/ |
|||
boolean notifyExpress(HuaxunExpressRequestBo bo) throws UnsupportedEncodingException, CoBusinessException; |
|||
} |
@ -0,0 +1,172 @@ |
|||
/* |
|||
* Copyright (C) 2017-2021 |
|||
* All rights reserved, Designed By 深圳中科鑫智科技有限公司 |
|||
* Copyright authorization contact 18814114118 |
|||
*/ |
|||
package com.shop.cereshop.business.service.extend.impl; |
|||
|
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.google.gson.Gson; |
|||
import com.shop.cereshop.business.dao.order.CereShopOrderDAO; |
|||
import com.shop.cereshop.business.param.order.OrderDileveryParam; |
|||
import com.shop.cereshop.business.service.buyer.CereBuyerUserService; |
|||
import com.shop.cereshop.business.service.extend.HuaxunService; |
|||
import com.shop.cereshop.business.service.order.CereOrderDileverService; |
|||
import com.shop.cereshop.business.service.order.CereOrderProductService; |
|||
import com.shop.cereshop.commons.config.HuaxunConfig; |
|||
import com.shop.cereshop.commons.domain.buyer.CereBuyerUser; |
|||
import com.shop.cereshop.commons.domain.huaxun.*; |
|||
import com.shop.cereshop.commons.domain.order.CereOrderProduct; |
|||
import com.shop.cereshop.commons.domain.order.CereShopOrder; |
|||
import com.shop.cereshop.commons.exception.CoBusinessException; |
|||
import com.shop.cereshop.commons.utils.EmptyUtils; |
|||
import com.shop.cereshop.commons.utils.MD5Utils; |
|||
import com.shop.cereshop.commons.utils.StringUtils; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.io.UnsupportedEncodingException; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/** |
|||
* <p> |
|||
* 华讯清关业务接口业务实现 |
|||
* </p> |
|||
* |
|||
* @author pxh |
|||
* @date 2023-03-10 |
|||
*/ |
|||
@Slf4j |
|||
@Service |
|||
public class HuaxunServiceImpl implements HuaxunService { |
|||
|
|||
|
|||
@Autowired |
|||
private CereShopOrderDAO cereShopOrderDAO; |
|||
|
|||
@Autowired |
|||
private CereOrderProductService cereOrderProductService; |
|||
|
|||
@Autowired |
|||
private CereBuyerUserService cereBuyerUserService; |
|||
|
|||
@Autowired |
|||
private CereOrderDileverService cereOrderDileverService; |
|||
|
|||
@Override |
|||
public List<OrderListVo> queryOrder(HuaxunOrderRequestBo bo) throws UnsupportedEncodingException, CoBusinessException { |
|||
ValidationSign(bo); |
|||
log.info("华讯查询订单:" + new Gson().toJson(bo)); |
|||
List<OrderListVo> orderListVos = new ArrayList<>(); |
|||
LambdaQueryWrapper<CereShopOrder> wrapper = new LambdaQueryWrapper<>(); |
|||
wrapper.eq(CereShopOrder::getPaymentState, 1) |
|||
.eq(CereShopOrder::getState, 2) |
|||
.eq(CereShopOrder::getIsCross, 1) |
|||
.ge(CereShopOrder::getPaymentTime, bo.getPayStartTime()) |
|||
.lt(CereShopOrder::getPaymentTime, bo.getPayEndTime()); |
|||
List<CereShopOrder> shopOrderList = cereShopOrderDAO.selectList(wrapper); |
|||
if(shopOrderList != null && !shopOrderList.isEmpty()){ |
|||
List<CereOrderProduct> opList = cereOrderProductService.findByOrderIds(shopOrderList.stream().map(CereShopOrder::getOrderId).collect(Collectors.toList())); |
|||
List<CereBuyerUser> buyerUserList = cereBuyerUserService.selectByBuyerUserIdList(shopOrderList.stream().map(CereShopOrder::getBuyerUserId).collect(Collectors.toList())); |
|||
|
|||
orderListVos.addAll(shopOrderList.stream().map(shopOrder -> { |
|||
OrderListVo orderListVo = new OrderListVo(); |
|||
orderListVo.setOrder_no(shopOrder.getOrderFormid()); |
|||
orderListVo.setPay_amount(shopOrder.getOrderPrice().toPlainString()); |
|||
CereBuyerUser buyerUser = buyerUserList.stream().filter(item -> item.getBuyerUserId().equals(shopOrder.getBuyerUserId())).findFirst().orElse(null); |
|||
if(buyerUser != null){ |
|||
orderListVo.setBuyer_name(buyerUser.getRealName()); |
|||
orderListVo.setBuyer_idcard(buyerUser.getIdCard()); |
|||
orderListVo.setBuyer_mobile(buyerUser.getPhone()); |
|||
}else { |
|||
log.info("华讯查询订单:查询不到对应的购买人"); |
|||
} |
|||
orderListVo.setConsignee_name(shopOrder.getReceiveName()); |
|||
orderListVo.setConsignee_mobile(shopOrder.getReceivePhone()); |
|||
orderListVo.setConsignee_address(shopOrder.getReceiveAdress() + shopOrder.getAddress()); |
|||
|
|||
List<GoodListVo> goods = new ArrayList<>(); |
|||
List<CereOrderProduct> orderOpList = opList.stream().filter(op -> op.getOrderId().equals(shopOrder.getId())).collect(Collectors.toList()); |
|||
if(!orderOpList.isEmpty()){ |
|||
goods.addAll(orderOpList.stream().map(orderOp -> { |
|||
GoodListVo good = new GoodListVo(); |
|||
good.setGoods_title(orderOp.getProductName()); |
|||
good.setModel(orderOp.getSKU()); |
|||
good.setNumber(orderOp.getNumber()); |
|||
good.setPrice(orderOp.getProductPrice().doubleValue()); |
|||
return good; |
|||
}).collect(Collectors.toList()) |
|||
); |
|||
} |
|||
orderListVo.setGoods(goods); |
|||
return orderListVo; |
|||
}).collect(Collectors.toList())); |
|||
} |
|||
return orderListVos; |
|||
} |
|||
|
|||
@Override |
|||
public boolean notifyExpress(HuaxunExpressRequestBo bo) throws UnsupportedEncodingException, CoBusinessException { |
|||
ValidationSign(bo); |
|||
log.info("华讯物流状态通知:" + new Gson().toJson(bo)); |
|||
ExpressListVo expressListVo = new Gson().fromJson(bo.getData(), ExpressListVo.class); |
|||
OrderDileveryParam orderDileveryParam = new OrderDileveryParam(); |
|||
|
|||
String orderFormId = expressListVo.getOrder_no(); |
|||
String cereOrderFormId = orderFormId; |
|||
String[] split = orderFormId.split("-"); |
|||
if(!EmptyUtils.isEmpty(split)) { |
|||
cereOrderFormId = split[0]; |
|||
} |
|||
List<CereShopOrder> orderList = cereShopOrderDAO.findByFormid(cereOrderFormId); |
|||
if(orderList == null || orderList.isEmpty()){ |
|||
log.info("查找不到对应的订单"); |
|||
return false; |
|||
} |
|||
|
|||
orderDileveryParam.setOrderId(orderList.get(0).getOrderId()); |
|||
|
|||
if(StringUtils.equals("yuantong", expressListVo.getExpress_code())){ |
|||
//圆通 |
|||
orderDileveryParam.setExpress(136L); |
|||
}else if(StringUtils.equals("zhongtong", expressListVo.getExpress_code())){ |
|||
//中通 |
|||
orderDileveryParam.setExpress(119L); |
|||
}else if(StringUtils.equals("shentong", expressListVo.getExpress_code())){ |
|||
//申通 |
|||
orderDileveryParam.setExpress(122L); |
|||
}else if(StringUtils.equals("yunda", expressListVo.getExpress_code())){ |
|||
//韵达 |
|||
orderDileveryParam.setExpress(117L); |
|||
}else if(StringUtils.equals("shunfeng", expressListVo.getExpress_code())){ |
|||
//顺丰 |
|||
orderDileveryParam.setExpress(118L); |
|||
}else if(StringUtils.equals("ems", expressListVo.getExpress_code())){ |
|||
//邮政EMS |
|||
orderDileveryParam.setExpress(124L); |
|||
}else if(StringUtils.equals("jd", expressListVo.getExpress_code())){ |
|||
//京东 |
|||
orderDileveryParam.setExpress(123L); |
|||
} |
|||
orderDileveryParam.setDeliverFormid(expressListVo.getExpress_no()); |
|||
try { |
|||
cereOrderDileverService.dileveryByCross(orderDileveryParam); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
private void ValidationSign(HuaxunRequestBo bo) throws UnsupportedEncodingException, CoBusinessException { |
|||
String checkSign = bo.getTimestamp()+ HuaxunConfig.KEY; |
|||
String checkSignMd5 = MD5Utils.md5Hex(checkSign, "utf-8"); |
|||
if(!StringUtils.endsWithIgnoreCase(checkSignMd5, bo.getSign())){ |
|||
log.info("华讯接口验签失败:" + new Gson().toJson(bo)); |
|||
throw new CoBusinessException("-1","验签校验失败"); |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue