| @@ -19,18 +19,20 @@ import io.swagger.annotations.ApiOperation; | |||||
| @RequestMapping("wxOrder") | @RequestMapping("wxOrder") | ||||
| public class WxOrderController extends BaseController | public class WxOrderController extends BaseController | ||||
| { | { | ||||
| private Logger logger = Logger.getLogger(WxOrderController.class); | |||||
| @Autowired | @Autowired | ||||
| private WxOrderService wxOrderService; | private WxOrderService wxOrderService; | ||||
| private Logger logger = Logger.getLogger(WxOrderController.class); | |||||
| @ApiOperation("分页列表接口") | |||||
| @ApiOperation("分页列表接口") | |||||
| @GetMapping("list") | @GetMapping("list") | ||||
| @ApiImplicitParams({ | |||||
| @ApiImplicitParam(name="pageNum",value="页数",dataType="int", paramType = "query",required=true), | |||||
| @ApiImplicitParam(name="pageSize",value="每页条数",dataType="int", paramType = "query",required=true)}) | |||||
| public ResultData list(@ModelAttribute WxOrder wxOrder,Integer pageNum, Integer pageSize) { | |||||
| if (null == wxOrder) wxOrder = new WxOrder(); | |||||
| @ApiImplicitParams({ | |||||
| @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), | |||||
| @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true), | |||||
| @ApiImplicitParam(name = "status", value = "订单状态:-1全部;0-已下单/待付款;1-已支付;2-已取消(限定时间内未付款);3-未退款/待退款;4-已退款;5-退款失败", defaultValue = "0", required = false, dataType = "Integer") | |||||
| }) | |||||
| public ResultData list(@ModelAttribute WxOrder wxOrder, Integer pageNum, Integer pageSize) { | |||||
| if (null == wxOrder) wxOrder = new WxOrder(); | |||||
| final PageInfo<WxOrder> page = wxOrderService.listAsPage(wxOrder, pageNum, pageSize); | final PageInfo<WxOrder> page = wxOrderService.listAsPage(wxOrder, pageNum, pageSize); | ||||
| return new ResultData(page); | return new ResultData(page); | ||||
| } | } | ||||
| @@ -19,10 +19,11 @@ import io.swagger.annotations.ApiOperation; | |||||
| @RequestMapping("wxPayOrder") | @RequestMapping("wxPayOrder") | ||||
| public class WxPayOrderController extends BaseController | public class WxPayOrderController extends BaseController | ||||
| { | { | ||||
| private Logger logger = Logger.getLogger(WxPayOrderController.class); | |||||
| @Autowired | @Autowired | ||||
| private WxPayOrderService wxPayOrderService; | private WxPayOrderService wxPayOrderService; | ||||
| private Logger logger = Logger.getLogger(WxPayOrderController.class); | |||||
| @ApiOperation("分页列表接口") | @ApiOperation("分页列表接口") | ||||
| @GetMapping("list") | @GetMapping("list") | ||||
| @@ -18,20 +18,21 @@ import io.swagger.annotations.ApiOperation; | |||||
| @RestController | @RestController | ||||
| @RequestMapping("wxOrder") | @RequestMapping("wxOrder") | ||||
| public class WxOrderController extends BaseController | |||||
| { | |||||
| @Autowired | |||||
| public class WxOrderController extends BaseController { | |||||
| private Logger logger = Logger.getLogger(WxOrderController.class); | |||||
| @Autowired | |||||
| private WxOrderService wxOrderService; | private WxOrderService wxOrderService; | ||||
| private Logger logger = Logger.getLogger(WxOrderController.class); | |||||
| @ApiOperation("分页列表接口") | |||||
| @ApiOperation("分页列表接口") | |||||
| @GetMapping("list") | @GetMapping("list") | ||||
| @ApiImplicitParams({ | |||||
| @ApiImplicitParam(name="pageNum",value="页数",dataType="int", paramType = "query",required=true), | |||||
| @ApiImplicitParam(name="pageSize",value="每页条数",dataType="int", paramType = "query",required=true)}) | |||||
| public ResultData list(@ModelAttribute WxOrder wxOrder,Integer pageNum, Integer pageSize) { | |||||
| if (null == wxOrder) wxOrder = new WxOrder(); | |||||
| @ApiImplicitParams({ | |||||
| @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), | |||||
| @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true), | |||||
| @ApiImplicitParam(name = "status", value = "订单状态:-1全部;0-已下单/待付款;1-已支付;2-已取消(限定时间内未付款);3-未退款/待退款;4-已退款;5-退款失败", defaultValue = "0", required = false, dataType = "Integer") | |||||
| }) | |||||
| public ResultData list(@ModelAttribute WxOrder wxOrder, Integer pageNum, Integer pageSize) { | |||||
| if (null == wxOrder) wxOrder = new WxOrder(); | |||||
| final PageInfo<WxOrder> page = wxOrderService.listAsPage(wxOrder, pageNum, pageSize); | final PageInfo<WxOrder> page = wxOrderService.listAsPage(wxOrder, pageNum, pageSize); | ||||
| return new ResultData(page); | return new ResultData(page); | ||||
| } | } | ||||
| @@ -90,7 +91,7 @@ public class WxOrderController extends BaseController | |||||
| return new ResultData(); | return new ResultData(); | ||||
| } | } | ||||
| @ApiOperation("新增接口") | |||||
| @ApiOperation("新增接口") | |||||
| @PostMapping("add") | @PostMapping("add") | ||||
| public ResultData add(@RequestBody WxOrder wxOrder) { | public ResultData add(@RequestBody WxOrder wxOrder) { | ||||
| //Assert.notNull(wxOrder.getName(), "角色名不能为空"); | //Assert.notNull(wxOrder.getName(), "角色名不能为空"); | ||||
| @@ -108,19 +109,18 @@ public class WxOrderController extends BaseController | |||||
| @ApiOperation("根据id删除接口") | @ApiOperation("根据id删除接口") | ||||
| @GetMapping("/del") | @GetMapping("/del") | ||||
| @ApiImplicitParam(name="id",value="id",dataType="Long", paramType = "query",required=true) | |||||
| @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) | |||||
| public ResultData delete(Long id) { | public ResultData delete(Long id) { | ||||
| wxOrderService.deleteById(id); | wxOrderService.deleteById(id); | ||||
| return new ResultData(Result.SUCCESS, "删除成功", null); | return new ResultData(Result.SUCCESS, "删除成功", null); | ||||
| } | } | ||||
| @ApiOperation("根据id查询接口") | |||||
| @GetMapping("/findById") | |||||
| @ApiImplicitParam(name="id",value="id",dataType="Long", paramType = "query",required=true) | |||||
| @ApiOperation("根据id查询接口") | |||||
| @GetMapping("/findById") | |||||
| @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) | |||||
| public ResultData findById(Long id) { | public ResultData findById(Long id) { | ||||
| return new ResultData(Result.SUCCESS,"查询成功",wxOrderService.getById(id)); | |||||
| return new ResultData(Result.SUCCESS, "查询成功", wxOrderService.getById(id)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,6 +1,14 @@ | |||||
| package com.simple.controller; | package com.simple.controller; | ||||
| import com.simple.common.ErrorCode; | |||||
| import com.simple.enums.EnumPayStatus; | |||||
| import com.simple.enums.EnumPayWay; | |||||
| import com.simple.exception.BizMessageException; | |||||
| import com.simple.exception.MallinkException; | |||||
| import com.simple.pay.WxPayment; | |||||
| import com.simple.utils.IPUtil; | |||||
| import org.apache.log4j.Logger; | import org.apache.log4j.Logger; | ||||
| import org.apache.commons.io.IOUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||
| @@ -15,14 +23,85 @@ import io.swagger.annotations.ApiImplicitParam; | |||||
| import io.swagger.annotations.ApiImplicitParams; | import io.swagger.annotations.ApiImplicitParams; | ||||
| import io.swagger.annotations.ApiOperation; | import io.swagger.annotations.ApiOperation; | ||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import java.util.Map; | |||||
| @RestController | @RestController | ||||
| @RequestMapping("wxPayOrder") | @RequestMapping("wxPayOrder") | ||||
| public class WxPayOrderController extends BaseController | |||||
| { | |||||
| public class WxPayOrderController extends BaseController { | |||||
| private Logger logger = Logger.getLogger(WxPayOrderController.class); | |||||
| @Autowired | @Autowired | ||||
| private WxPayOrderService wxPayOrderService; | private WxPayOrderService wxPayOrderService; | ||||
| private Logger logger = Logger.getLogger(WxPayOrderController.class); | |||||
| @ApiOperation(value = "发起微信小程序支付订单") | |||||
| @ApiImplicitParams({ | |||||
| @ApiImplicitParam(name = "cUserId", value = "用户id", required = true, dataType = "Long"), | |||||
| @ApiImplicitParam(name = "orderId", value = "订单ID", required = true, dataType = "Long"), | |||||
| @ApiImplicitParam(name = "payVendor", value = "支付发起渠道:0-微信小程序", defaultValue = "0",required = false, dataType = "Integer") | |||||
| }) | |||||
| @RequestMapping(value = "/create", method = RequestMethod.POST) | |||||
| public ResultData _create(WxPayOrder record, HttpServletRequest request) throws Exception { | |||||
| logger.info("payment wechat, order create, param : " + record.toString()); | |||||
| try { | |||||
| record.setIp(IPUtil.getIpAddr(request)); | |||||
| return wxPayOrderService.createPayOrder(record, EnumPayWay.PAY_WAY_WECHAT); | |||||
| } catch (MallinkException e) { | |||||
| logger.error("payment wechat, order create error, req 2: " + record.toString() + ", e:" + e.getMessage()); | |||||
| return new ResultData(e.getErrorCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| logger.error("payment wechat, order create error, req 3: " + record.toString() + ", e:" + e.getMessage()); | |||||
| } | |||||
| return new ResultData(ErrorCode.PAYORDER_ERROR.getCode(), ErrorCode.PAYORDER_ERROR.getMessage()); | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @return 接收微信异步通知 | |||||
| * @throws Exception 可能产生的任何异常 | |||||
| */ | |||||
| @RequestMapping(value = "/notify", method = RequestMethod.POST) | |||||
| public String __doNotify(HttpServletRequest request) throws Exception { | |||||
| Map<String, String> paramMap = null; | |||||
| String response; | |||||
| try { | |||||
| String xml = IOUtils.toString(request.getInputStream()); | |||||
| paramMap = WxPayment.xmlToMap(xml); | |||||
| logger.info("payment wxpay, notify, param: " + paramMap.toString() ); | |||||
| response = wxPayOrderService.notify(paramMap, EnumPayWay.PAY_WAY_WEAPP); | |||||
| logger.info("payment wxpay, notify success, req : " + paramMap.toString() + ", resp: " + response.toString()); | |||||
| return response; | |||||
| } catch (BizMessageException e) { | |||||
| logger.error("payment wxpay, notify error, req: " + paramMap.toString() + ", e:" + e.getLocalizedMessage()); | |||||
| return e.getMessage(); | |||||
| } catch (MallinkException e) { | |||||
| logger.error("payment wxpay, notify error, req: " + paramMap.toString() + ", e:" +e.getLocalizedMessage()); | |||||
| return e.getMessage(); | |||||
| } catch (Exception e) { | |||||
| logger.error("payment wxpay, order create error, req: " + paramMap.toString() + ", e: " + e.getMessage()); | |||||
| return e.getMessage(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @return 同步回调(订单状态主动检查) | |||||
| * @throws Exception 可能产生的任何异常 | |||||
| */ | |||||
| @RequestMapping(value = "callback", method = {RequestMethod.GET, RequestMethod.POST}) | |||||
| public String __doCallback(HttpServletRequest request) throws Exception { | |||||
| logger.info("payment wxpay, callback,request:" + request.toString()); | |||||
| return "\n" + | |||||
| "\n" + | |||||
| "<xml>\n" + | |||||
| "\n" + | |||||
| " <return_code><![CDATA[SUCCESS]]></return_code>\n" + | |||||
| " <return_msg><![CDATA[OK]]></return_msg>\n" + | |||||
| "</xml>\n"; | |||||
| } | |||||
| @ApiOperation("分页列表接口") | @ApiOperation("分页列表接口") | ||||
| @GetMapping("list") | @GetMapping("list") | ||||
| @@ -10,19 +10,4 @@ | |||||
| <modelVersion>4.0.0</modelVersion> | <modelVersion>4.0.0</modelVersion> | ||||
| <artifactId>mallinkService</artifactId> | <artifactId>mallinkService</artifactId> | ||||
| <dependencies> | |||||
| <!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp --> | |||||
| <dependency> | |||||
| <groupId>com.squareup.okhttp3</groupId> | |||||
| <artifactId>okhttp</artifactId> | |||||
| <version>3.11.0</version> | |||||
| </dependency> | |||||
| <!-- https://mvnrepository.com/artifact/org.dom4j/dom4j --> | |||||
| <dependency> | |||||
| <groupId>org.dom4j</groupId> | |||||
| <artifactId>dom4j</artifactId> | |||||
| <version>2.1.1</version> | |||||
| </dependency> | |||||
| </dependencies> | |||||
| </project> | </project> | ||||
| @@ -47,7 +47,9 @@ public enum ErrorCode{ | |||||
| */ | */ | ||||
| REMAIN_IS_EMPTY(12000, "库存不足"), | REMAIN_IS_EMPTY(12000, "库存不足"), | ||||
| ORDER_IS_FAIL(12001, "订单创建失败"), | ORDER_IS_FAIL(12001, "订单创建失败"), | ||||
| ORDER_IS_NOT_FIND(12002, "订单不存在"); | |||||
| ORDER_IS_NOT_FIND(12002, "订单不存在"), | |||||
| ORDER_IS_NOT_PAY(12003, "订单已不能进行支付"), | |||||
| PAYORDER_ERROR(12004, "支付订单异常"); | |||||
| /** | /** | ||||
| * 支付 | * 支付 | ||||
| @@ -59,8 +59,8 @@ public class WxMerchant implements Serializable { | |||||
| /*银行开户行**/ | /*银行开户行**/ | ||||
| @io.swagger.annotations.ApiModelProperty(value="银行开户行",name="bankName") | @io.swagger.annotations.ApiModelProperty(value="银行开户行",name="bankName") | ||||
| private String bankName; | private String bankName; | ||||
| /*微信支付账号**/ | |||||
| @io.swagger.annotations.ApiModelProperty(value="微信支付账号",name="wxchatAccount") | |||||
| /*微信收款账号**/ | |||||
| @io.swagger.annotations.ApiModelProperty(value="微信收款账号",name="wxchatAccount") | |||||
| private String wxchatAccount; | private String wxchatAccount; | ||||
| /*创建时间**/ | /*创建时间**/ | ||||
| @io.swagger.annotations.ApiModelProperty(value="创建时间",name="createDate") | @io.swagger.annotations.ApiModelProperty(value="创建时间",name="createDate") | ||||
| @@ -68,6 +68,12 @@ public class WxMerchant implements Serializable { | |||||
| /*更新时间**/ | /*更新时间**/ | ||||
| @io.swagger.annotations.ApiModelProperty(value="更新时间",name="updateDate") | @io.swagger.annotations.ApiModelProperty(value="更新时间",name="updateDate") | ||||
| private Date updateDate; | private Date updateDate; | ||||
| /*停车厂商(1:ETCP)**/ | |||||
| @io.swagger.annotations.ApiModelProperty(value="停车厂商(1:ETCP)",name="carVendorType") | |||||
| private Integer carVendorType; | |||||
| /*停车厂商参数**/ | |||||
| @io.swagger.annotations.ApiModelProperty(value="停车厂商参数",name="carParams") | |||||
| private String carParams; | |||||
| public String getTenantId() { | public String getTenantId() { | ||||
| return tenantId; | return tenantId; | ||||
| } | } | ||||
| @@ -122,6 +128,18 @@ public class WxMerchant implements Serializable { | |||||
| public void setUpdateDate(Date _updateDate) { | public void setUpdateDate(Date _updateDate) { | ||||
| updateDate = _updateDate; | updateDate = _updateDate; | ||||
| } | } | ||||
| public Integer getCarVendorType() { | |||||
| return carVendorType; | |||||
| } | |||||
| public void setCarVendorType(Integer _carVendorType) { | |||||
| carVendorType = _carVendorType; | |||||
| } | |||||
| public String getCarParams() { | |||||
| return carParams; | |||||
| } | |||||
| public void setCarParams(String _carParams) { | |||||
| carParams = _carParams; | |||||
| } | |||||
| @@ -137,6 +155,8 @@ public class WxMerchant implements Serializable { | |||||
| ,WxchatAccount_ASC("`wxchatAccount` ASC"),WxchatAccount_DESC("`wxchatAccount` DESC") | ,WxchatAccount_ASC("`wxchatAccount` ASC"),WxchatAccount_DESC("`wxchatAccount` DESC") | ||||
| ,CreateDate_ASC("`createDate` ASC"),CreateDate_DESC("`createDate` DESC") | ,CreateDate_ASC("`createDate` ASC"),CreateDate_DESC("`createDate` DESC") | ||||
| ,UpdateDate_ASC("`updateDate` ASC"),UpdateDate_DESC("`updateDate` DESC") | ,UpdateDate_ASC("`updateDate` ASC"),UpdateDate_DESC("`updateDate` DESC") | ||||
| ,CarVendorType_ASC("`carVendorType` ASC"),CarVendorType_DESC("`carVendorType` DESC") | |||||
| ,CarParams_ASC("`carParams` ASC"),CarParams_DESC("`carParams` DESC") | |||||
| ; | ; | ||||
| private String value; | private String value; | ||||
| Field(String value){ | Field(String value){ | ||||
| @@ -56,6 +56,9 @@ public class WxPayOrder implements Serializable { | |||||
| /*用户ID**/ | /*用户ID**/ | ||||
| @io.swagger.annotations.ApiModelProperty(value="用户ID",name="cUserId") | @io.swagger.annotations.ApiModelProperty(value="用户ID",name="cUserId") | ||||
| private Long cUserId; | private Long cUserId; | ||||
| /*支付IP**/ | |||||
| @io.swagger.annotations.ApiModelProperty(value="支付IP",name="ip") | |||||
| private String ip; | |||||
| /*支付金额(分)**/ | /*支付金额(分)**/ | ||||
| @io.swagger.annotations.ApiModelProperty(value="支付金额(分)",name="payAmount") | @io.swagger.annotations.ApiModelProperty(value="支付金额(分)",name="payAmount") | ||||
| private Integer payAmount; | private Integer payAmount; | ||||
| @@ -65,18 +68,15 @@ public class WxPayOrder implements Serializable { | |||||
| /*支付结束时间(秒)**/ | /*支付结束时间(秒)**/ | ||||
| @io.swagger.annotations.ApiModelProperty(value="支付结束时间(秒)",name="payTimeEnd") | @io.swagger.annotations.ApiModelProperty(value="支付结束时间(秒)",name="payTimeEnd") | ||||
| private Integer payTimeEnd; | private Integer payTimeEnd; | ||||
| /*支付渠道: 0-微信小程序**/ | |||||
| @io.swagger.annotations.ApiModelProperty(value="支付渠道: 0-微信小程序",name="payChannel") | |||||
| private Integer payChannel; | |||||
| /*支付方式: 0-微信小程序支付**/ | |||||
| @io.swagger.annotations.ApiModelProperty(value="支付方式: 0-微信小程序支付",name="payWay") | |||||
| private Integer payWay; | |||||
| /*支付渠道: 0-微信小程序 1--支付宝 2--银联 **/ | |||||
| @io.swagger.annotations.ApiModelProperty(value="支付渠道: 0-微信小程序 1--支付宝 2--银联 ",name="payVendor") | |||||
| private Integer payVendor; | |||||
| /*支付订单号**/ | /*支付订单号**/ | ||||
| @io.swagger.annotations.ApiModelProperty(value="支付订单号",name="payOrderNo") | @io.swagger.annotations.ApiModelProperty(value="支付订单号",name="payOrderNo") | ||||
| private String payOrderNo; | private String payOrderNo; | ||||
| /*支付状态: 0-支付中;1-支付成功;2-支付失败**/ | /*支付状态: 0-支付中;1-支付成功;2-支付失败**/ | ||||
| @io.swagger.annotations.ApiModelProperty(value="支付状态: 0-支付中;1-支付成功;2-支付失败",name="status") | |||||
| private Integer status; | |||||
| @io.swagger.annotations.ApiModelProperty(value="支付状态: 0-支付中;1-支付成功;2-支付失败",name="payOrderStatus") | |||||
| private Integer payOrderStatus; | |||||
| /*支付失败原因**/ | /*支付失败原因**/ | ||||
| @io.swagger.annotations.ApiModelProperty(value="支付失败原因",name="failReason") | @io.swagger.annotations.ApiModelProperty(value="支付失败原因",name="failReason") | ||||
| private String failReason; | private String failReason; | ||||
| @@ -110,6 +110,15 @@ public class WxPayOrder implements Serializable { | |||||
| public void setCUserId(Long _cUserId) { | public void setCUserId(Long _cUserId) { | ||||
| cUserId = _cUserId; | cUserId = _cUserId; | ||||
| } | } | ||||
| public String getIp() { | |||||
| return ip; | |||||
| } | |||||
| public void setIp(String _ip) { | |||||
| this.ip = _ip; | |||||
| } | |||||
| public Integer getPayAmount() { | public Integer getPayAmount() { | ||||
| return payAmount; | return payAmount; | ||||
| } | } | ||||
| @@ -128,17 +137,11 @@ public class WxPayOrder implements Serializable { | |||||
| public void setPayTimeEnd(Integer _payTimeEnd) { | public void setPayTimeEnd(Integer _payTimeEnd) { | ||||
| payTimeEnd = _payTimeEnd; | payTimeEnd = _payTimeEnd; | ||||
| } | } | ||||
| public Integer getPayChannel() { | |||||
| return payChannel; | |||||
| } | |||||
| public void setPayChannel(Integer _payChannel) { | |||||
| payChannel = _payChannel; | |||||
| } | |||||
| public Integer getPayWay() { | |||||
| return payWay; | |||||
| public Integer getPayVendor() { | |||||
| return payVendor; | |||||
| } | } | ||||
| public void setPayWay(Integer _payWay) { | |||||
| payWay = _payWay; | |||||
| public void setPayVendor(Integer _payVendor) { | |||||
| payVendor = _payVendor; | |||||
| } | } | ||||
| public String getPayOrderNo() { | public String getPayOrderNo() { | ||||
| return payOrderNo; | return payOrderNo; | ||||
| @@ -146,11 +149,11 @@ public class WxPayOrder implements Serializable { | |||||
| public void setPayOrderNo(String _payOrderNo) { | public void setPayOrderNo(String _payOrderNo) { | ||||
| payOrderNo = _payOrderNo; | payOrderNo = _payOrderNo; | ||||
| } | } | ||||
| public Integer getStatus() { | |||||
| return status; | |||||
| public Integer getPayOrderStatus() { | |||||
| return payOrderStatus; | |||||
| } | } | ||||
| public void setStatus(Integer _status) { | |||||
| status = _status; | |||||
| public void setPayOrderStatus(Integer _payOrderStatus) { | |||||
| payOrderStatus = _payOrderStatus; | |||||
| } | } | ||||
| public String getFailReason() { | public String getFailReason() { | ||||
| return failReason; | return failReason; | ||||
| @@ -169,13 +172,13 @@ public class WxPayOrder implements Serializable { | |||||
| ,UpdateTime_ASC("`updateTime` ASC"),UpdateTime_DESC("`updateTime` DESC") | ,UpdateTime_ASC("`updateTime` ASC"),UpdateTime_DESC("`updateTime` DESC") | ||||
| ,OrderId_ASC("`orderId` ASC"),OrderId_DESC("`orderId` DESC") | ,OrderId_ASC("`orderId` ASC"),OrderId_DESC("`orderId` DESC") | ||||
| ,CUserId_ASC("`cUserId` ASC"),CUserId_DESC("`cUserId` DESC") | ,CUserId_ASC("`cUserId` ASC"),CUserId_DESC("`cUserId` DESC") | ||||
| ,IP_ASC("`ip` ASC"),IP_DESC("`ip` DESC") | |||||
| ,PayAmount_ASC("`payAmount` ASC"),PayAmount_DESC("`payAmount` DESC") | ,PayAmount_ASC("`payAmount` ASC"),PayAmount_DESC("`payAmount` DESC") | ||||
| ,PayTimeStart_ASC("`payTimeStart` ASC"),PayTimeStart_DESC("`payTimeStart` DESC") | ,PayTimeStart_ASC("`payTimeStart` ASC"),PayTimeStart_DESC("`payTimeStart` DESC") | ||||
| ,PayTimeEnd_ASC("`payTimeEnd` ASC"),PayTimeEnd_DESC("`payTimeEnd` DESC") | ,PayTimeEnd_ASC("`payTimeEnd` ASC"),PayTimeEnd_DESC("`payTimeEnd` DESC") | ||||
| ,PayChannel_ASC("`payChannel` ASC"),PayChannel_DESC("`payChannel` DESC") | |||||
| ,PayWay_ASC("`payWay` ASC"),PayWay_DESC("`payWay` DESC") | |||||
| ,PayVendor_ASC("`payVendor` ASC"),PayVendor_DESC("`payVendor` DESC") | |||||
| ,PayOrderNo_ASC("`payOrderNo` ASC"),PayOrderNo_DESC("`payOrderNo` DESC") | ,PayOrderNo_ASC("`payOrderNo` ASC"),PayOrderNo_DESC("`payOrderNo` DESC") | ||||
| ,Status_ASC("`status` ASC"),Status_DESC("`status` DESC") | |||||
| ,PayOrderStatus_ASC("`payOrderStatus` ASC"),PayOrderStatus_DESC("`payOrderStatus` DESC") | |||||
| ,FailReason_ASC("`failReason` ASC"),FailReason_DESC("`failReason` DESC") | ,FailReason_ASC("`failReason` ASC"),FailReason_DESC("`failReason` DESC") | ||||
| ; | ; | ||||
| private String value; | private String value; | ||||
| @@ -0,0 +1,43 @@ | |||||
| package com.simple.enums; | |||||
| /** | |||||
| * Created by Stormeye on 2018/08/09. | |||||
| */ | |||||
| public enum EnumCouponStatus { | |||||
| // 0-草稿/待生效;1-已生效/已发布/已投放;2-已下架;3-已领取/已购买/未核销/未使用,4:已核销/已使用,5:已过期,6:已退券 | |||||
| COUPON_STATUS_DRAFT(0, "草稿"), | |||||
| COUPON_STATUS_THROW_IN(1, "已投放"), | |||||
| COUPON_STATUS_TAKE_OFFF(2, "已下架"), | |||||
| COUPON_STATUS_NOT_USED(3, "未使用"), | |||||
| COUPON_STATUS_USED(4,"已使用"), | |||||
| COUPON_STATUS_OVER_TIME(5, "已过期"), | |||||
| COUPON_STATUS_BACKED(6, "已退券") | |||||
| ; | |||||
| public static EnumCouponStatus getEnum(Integer code) { | |||||
| for (EnumCouponStatus value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String message; | |||||
| EnumCouponStatus(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -7,9 +7,9 @@ public enum EnumPayWay { | |||||
| PAY_WAY_WEAPP(0, "微信小程序"), | PAY_WAY_WEAPP(0, "微信小程序"), | ||||
| PAY_WAY_WECHAT(1, "微信支付"), | PAY_WAY_WECHAT(1, "微信支付"), | ||||
| PAY_WAY_WECHAT_WAP(2, "微信h5"), | |||||
| PAY_WAY_WECHAT_WAP(2, "微信H5"), | |||||
| PAY_WAY_ALIPAY(3, "支付宝"), | PAY_WAY_ALIPAY(3, "支付宝"), | ||||
| PAY_WAY_ALIPAY_WAP(0, "支付宝h5"); | |||||
| PAY_WAY_ALIPAY_WAP(4, "支付宝H5"); | |||||
| public static EnumPayWay getEnum(Integer code) { | public static EnumPayWay getEnum(Integer code) { | ||||
| for (EnumPayWay value : values()) { | for (EnumPayWay value : values()) { | ||||
| @@ -2,16 +2,42 @@ package com.simple.service; | |||||
| import java.util.*; | import java.util.*; | ||||
| import com.github.pagehelper.PageInfo; | import com.github.pagehelper.PageInfo; | ||||
| import com.simple.common.ResultData; | |||||
| import com.simple.domain.po.WxPayOrder; | import com.simple.domain.po.WxPayOrder; | ||||
| import com.simple.enums.EnumPayWay; | |||||
| public interface WxPayOrderService { | public interface WxPayOrderService { | ||||
| /** | |||||
| * 创建支付订单 | |||||
| * @param record 支付订单请求 | |||||
| * @param payWay | |||||
| * @return | |||||
| */ | |||||
| ResultData createPayOrder(WxPayOrder record, EnumPayWay payWay); | |||||
| /** | |||||
| * 异步通知 | |||||
| * @param paramMap 异步通知参数 | |||||
| * @param payWay 支付方式 | |||||
| * @return | |||||
| */ | |||||
| String notify(Map<String, String> paramMap, EnumPayWay payWay); | |||||
| /** | |||||
| * 页面回调 | |||||
| * @param paramMap 页面通知参数 | |||||
| * @param payWay 支付方式 | |||||
| * @return | |||||
| */ | |||||
| void callback(Map<String, String> paramMap, EnumPayWay payWay); | |||||
| /** | /** | ||||
| * 根据实体查询分页列表 | * 根据实体查询分页列表 | ||||
| * | * | ||||
| * @param record | * @param record | ||||
| * @param offset | |||||
| * @param limit | |||||
| * @param pageIndex | |||||
| * @param pageSize | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| PageInfo<WxPayOrder> listAsPage(WxPayOrder record, Integer pageIndex, Integer pageSize); | PageInfo<WxPayOrder> listAsPage(WxPayOrder record, Integer pageIndex, Integer pageSize); | ||||
| @@ -74,12 +74,14 @@ public class WxOrderServiceImpl implements WxOrderService { | |||||
| throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND); | throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND); | ||||
| } | } | ||||
| Date currentDate = new Date(); | Date currentDate = new Date(); | ||||
| // 支付成功 | |||||
| // 0:待付款 | |||||
| // 1:已支付 | |||||
| if (enumOrderStatus == EnumOrderStatus.ORDER_STATUS_PAYMENT_SUCCESS) { | if (enumOrderStatus == EnumOrderStatus.ORDER_STATUS_PAYMENT_SUCCESS) { | ||||
| updateRecord.setPaymentTime(currentDate); | updateRecord.setPaymentTime(currentDate); | ||||
| } | } | ||||
| // 2:已取消, 库存加1 | |||||
| if (enumOrderStatus == EnumOrderStatus.ORDER_STATUS_OVERTIME_CANCEL) { | if (enumOrderStatus == EnumOrderStatus.ORDER_STATUS_OVERTIME_CANCEL) { | ||||
| //取消订单, 库存加1 | |||||
| WxCoupon coupon = wxCouponMapper.selectByPrimaryKey(updateRecord.getCouponId()); | WxCoupon coupon = wxCouponMapper.selectByPrimaryKey(updateRecord.getCouponId()); | ||||
| if (coupon.getRemainInventory() <= 0) { | if (coupon.getRemainInventory() <= 0) { | ||||
| logger.error("coupon not found, couponId: " + updateRecord.getCouponId()); | logger.error("coupon not found, couponId: " + updateRecord.getCouponId()); | ||||
| @@ -88,6 +90,18 @@ public class WxOrderServiceImpl implements WxOrderService { | |||||
| coupon.setRemainInventory(coupon.getRemainInventory() + 1); | coupon.setRemainInventory(coupon.getRemainInventory() + 1); | ||||
| wxCouponMapper.updateByPrimaryKeySelective(coupon); | wxCouponMapper.updateByPrimaryKeySelective(coupon); | ||||
| } | } | ||||
| // 3:待退款 | |||||
| // 4:已退款 | |||||
| if (enumOrderStatus == EnumOrderStatus.ORDER_STATUS_REFUND_SUCCESS) { | |||||
| WxCoupon coupon = wxCouponMapper.selectByPrimaryKey(updateRecord.getCouponId()); | |||||
| if (coupon.getRemainInventory() <= 0) { | |||||
| logger.error("coupon not found, couponId: " + updateRecord.getCouponId()); | |||||
| throw new MallinkException(ErrorCode.REMAIN_IS_EMPTY); | |||||
| } | |||||
| coupon.setRemainInventory(coupon.getRemainInventory() + 1); | |||||
| wxCouponMapper.updateByPrimaryKeySelective(coupon); | |||||
| } | |||||
| // 5:退款失败 | |||||
| updateRecord.setStatus(enumOrderStatus.getCode()); | updateRecord.setStatus(enumOrderStatus.getCode()); | ||||
| updateRecord.setUpdateDate(currentDate); | updateRecord.setUpdateDate(currentDate); | ||||
| return wxOrderMapper.updateByPrimaryKey(updateRecord); | return wxOrderMapper.updateByPrimaryKey(updateRecord); | ||||
| @@ -1,21 +1,88 @@ | |||||
| package com.simple.service.impl; | package com.simple.service.impl; | ||||
| import java.math.BigDecimal; | |||||
| import java.util.*; | import java.util.*; | ||||
| import com.github.pagehelper.PageHelper; | import com.github.pagehelper.PageHelper; | ||||
| import com.github.pagehelper.PageInfo; | import com.github.pagehelper.PageInfo; | ||||
| import com.simple.common.ErrorCode; | |||||
| import com.simple.common.ResultData; | |||||
| import com.simple.domain.po.WxOrder; | |||||
| import com.simple.domain.po.WxPayOrder; | import com.simple.domain.po.WxPayOrder; | ||||
| import com.simple.enums.EnumOrderStatus; | |||||
| import com.simple.enums.EnumPayStatus; | |||||
| import com.simple.enums.EnumPayWay; | |||||
| import com.simple.exception.BizMessageException; | |||||
| import com.simple.exception.MallinkException; | |||||
| import com.simple.mapper.WxOrderMapper; | |||||
| import com.simple.mapper.WxPayOrderMapper; | import com.simple.mapper.WxPayOrderMapper; | ||||
| import com.simple.service.WxOrderService; | |||||
| import com.simple.service.WxPayOrderService; | import com.simple.service.WxPayOrderService; | ||||
| import com.simple.utils.Utility; | |||||
| import org.apache.log4j.Logger; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import com.simple.common.IdWorker; | import com.simple.common.IdWorker; | ||||
| import org.springframework.transaction.annotation.Propagation; | |||||
| import org.springframework.transaction.annotation.Transactional; | |||||
| @Service | @Service | ||||
| public class WxPayOrderServiceImpl implements WxPayOrderService { | public class WxPayOrderServiceImpl implements WxPayOrderService { | ||||
| private Logger logger = Logger.getLogger(getClass()); | |||||
| @Autowired | |||||
| WxOrderMapper wxOrderMapper; | |||||
| @Autowired | @Autowired | ||||
| WxPayOrderMapper wxPayOrderMapper; | WxPayOrderMapper wxPayOrderMapper; | ||||
| @Override | |||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | |||||
| public ResultData createPayOrder(WxPayOrder record, EnumPayWay payWay) { | |||||
| try { | |||||
| // 1. check 订单 | |||||
| WxOrder order = wxOrderMapper.selectByPrimaryKey(record.getOrderId()); | |||||
| if (order == null) { | |||||
| logger.warn("pay order, order not allow, repaymentReq: " + record.toString() +", payWay: " + payWay.toString()); | |||||
| throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND); | |||||
| } | |||||
| if (order.getStatus() != EnumOrderStatus.ORDER_STATUS_PENDING_PAYMENT.getCode()) { | |||||
| logger.warn("pay order, order status not allow, repaymentReq: " + order.toString() + " , payWay: " + payWay.toString()); | |||||
| throw new MallinkException(ErrorCode.ORDER_IS_NOT_PAY); | |||||
| } | |||||
| // 2. 创建支付订单 | |||||
| Date currentDate = new Date(); | |||||
| final IdWorker idworker = IdWorker.get(); | |||||
| Long id = idworker.nextId(); | |||||
| record.setId(id); | |||||
| record.setCreateTime(currentDate); | |||||
| record.setUpdateTime(currentDate); | |||||
| int currentTime = Utility.convertDate2TimeStamp(currentDate); | |||||
| record.setPayTimeStart(currentTime); | |||||
| record.setPayTimeEnd(currentTime); | |||||
| // 支付单号 | |||||
| record.setPayOrderNo(String.valueOf(id)); | |||||
| BigDecimal pl = order.getPayment().multiply(new BigDecimal(100)); | |||||
| record.setPayAmount(pl.intValue()); | |||||
| record.setPayVendor(EnumPayWay.PAY_WAY_WEAPP.getCode()); | |||||
| record.setPayOrderStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); | |||||
| wxPayOrderMapper.insertSelective(record); | |||||
| return new ResultData(record); | |||||
| } catch (RuntimeException e) { | |||||
| throw new MallinkException(ErrorCode.PAYORDER_ERROR); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public String notify(Map<String, String> paramMap, EnumPayWay payWay) { | |||||
| return ""; | |||||
| } | |||||
| @Override | |||||
| public void callback(Map<String, String> paramMap, EnumPayWay payWay) { | |||||
| } | |||||
| @Override | @Override | ||||
| public PageInfo<WxPayOrder> listAsPage(WxPayOrder record, Integer pageIndex, Integer pageSize) { | public PageInfo<WxPayOrder> listAsPage(WxPayOrder record, Integer pageIndex, Integer pageSize) { | ||||
| @@ -0,0 +1,51 @@ | |||||
| package com.simple.utils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import java.net.InetAddress; | |||||
| import java.net.UnknownHostException; | |||||
| public class IPUtil { | |||||
| private final static Logger logger = LoggerFactory.getLogger(IPUtil.class); | |||||
| public static String getIpAddr(HttpServletRequest request) { | |||||
| String ipAddress = request.getHeader("x-forwarded-for"); | |||||
| if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { | |||||
| ipAddress = request.getHeader("Proxy-Client-IP"); | |||||
| } | |||||
| if (ipAddress == null || ipAddress.length() == 0 || "unknow".equalsIgnoreCase(ipAddress)) { | |||||
| ipAddress = request.getHeader("WL-Proxy-Client-IP"); | |||||
| } | |||||
| if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { | |||||
| ipAddress = request.getHeader("HTTP_CLIENT_IP"); | |||||
| } | |||||
| if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { | |||||
| ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR"); | |||||
| } | |||||
| if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { | |||||
| ipAddress = request.getRemoteAddr(); | |||||
| if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) { | |||||
| //根据网卡获取本机配置的IP地址 | |||||
| InetAddress inetAddress = null; | |||||
| try { | |||||
| inetAddress = InetAddress.getLocalHost(); | |||||
| } catch (UnknownHostException e) { | |||||
| logger.error(e.getMessage()); | |||||
| } | |||||
| ipAddress = inetAddress.getHostAddress(); | |||||
| } | |||||
| } | |||||
| //对于通过多个代理的情况,第一个IP为客户端真实的IP地址,多个IP按照','分割 | |||||
| if (null != ipAddress && ipAddress.length() > 15) { | |||||
| //"***.***.***.***".length() = 15 | |||||
| if (ipAddress.indexOf(",") > 0) { | |||||
| ipAddress = ipAddress.substring(0, ipAddress.indexOf(",")); | |||||
| } | |||||
| } | |||||
| return ipAddress; | |||||
| } | |||||
| } | |||||
| @@ -12,10 +12,12 @@ | |||||
| <result column="wxchat_account" jdbcType="VARCHAR" property="wxchatAccount" /> | <result column="wxchat_account" jdbcType="VARCHAR" property="wxchatAccount" /> | ||||
| <result column="create_date" jdbcType="TIMESTAMP" property="createDate" /> | <result column="create_date" jdbcType="TIMESTAMP" property="createDate" /> | ||||
| <result column="update_date" jdbcType="TIMESTAMP" property="updateDate" /> | <result column="update_date" jdbcType="TIMESTAMP" property="updateDate" /> | ||||
| <result column="car_vendor_type" jdbcType="INTEGER" property="carVendorType" /> | |||||
| <result column="car_params" jdbcType="VARCHAR" property="carParams" /> | |||||
| </resultMap> | </resultMap> | ||||
| <sql id="allColumns"> | <sql id="allColumns"> | ||||
| `id`,`tenant_id`,`img_url`,`name`,`link_phone`,`bank_card`,`bank_name`,`wxchat_account`,`create_date`,`update_date` | |||||
| `id`,`tenant_id`,`img_url`,`name`,`link_phone`,`bank_card`,`bank_name`,`wxchat_account`,`create_date`,`update_date`,`car_vendor_type`,`car_params` | |||||
| </sql> | </sql> | ||||
| <sql id="dynamicWhereConditions"> | <sql id="dynamicWhereConditions"> | ||||
| @@ -69,6 +71,16 @@ | |||||
| <if test=" null != updateDate "> | <if test=" null != updateDate "> | ||||
| and `update_date` = #{updateDate} | and `update_date` = #{updateDate} | ||||
| </if> | |||||
| <if test=" null != carVendorType "> | |||||
| and `car_vendor_type` = #{carVendorType} | |||||
| </if> | |||||
| <if test=" null != carParams "> | |||||
| and `car_params` like concat('%', #{carParams},'%') | |||||
| </if> | </if> | ||||
| <if test=" null != ids "> | <if test=" null != ids "> | ||||
| and id in | and id in | ||||
| @@ -8,18 +8,18 @@ | |||||
| <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> | <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> | ||||
| <result column="order_id" jdbcType="BIGINT" property="orderId" /> | <result column="order_id" jdbcType="BIGINT" property="orderId" /> | ||||
| <result column="c_user_id" jdbcType="BIGINT" property="cUserId" /> | <result column="c_user_id" jdbcType="BIGINT" property="cUserId" /> | ||||
| <result column="ip" jdbcType="String" property="ip" /> | |||||
| <result column="pay_amount" jdbcType="INTEGER" property="payAmount" /> | <result column="pay_amount" jdbcType="INTEGER" property="payAmount" /> | ||||
| <result column="pay_time_start" jdbcType="INTEGER" property="payTimeStart" /> | <result column="pay_time_start" jdbcType="INTEGER" property="payTimeStart" /> | ||||
| <result column="pay_time_end" jdbcType="INTEGER" property="payTimeEnd" /> | <result column="pay_time_end" jdbcType="INTEGER" property="payTimeEnd" /> | ||||
| <result column="pay_channel" jdbcType="INTEGER" property="payChannel" /> | |||||
| <result column="pay_way" jdbcType="INTEGER" property="payWay" /> | |||||
| <result column="pay_vendor" jdbcType="INTEGER" property="payVendor" /> | |||||
| <result column="pay_order_no" jdbcType="VARCHAR" property="payOrderNo" /> | <result column="pay_order_no" jdbcType="VARCHAR" property="payOrderNo" /> | ||||
| <result column="status" jdbcType="INTEGER" property="status" /> | |||||
| <result column="pay_order_status" jdbcType="INTEGER" property="payOrderStatus" /> | |||||
| <result column="fail_reason" jdbcType="VARCHAR" property="failReason" /> | <result column="fail_reason" jdbcType="VARCHAR" property="failReason" /> | ||||
| </resultMap> | </resultMap> | ||||
| <sql id="allColumns"> | <sql id="allColumns"> | ||||
| `id`,`tenant_id`,`create_time`,`update_time`,`order_id`,`c_user_id`,`pay_amount`,`pay_time_start`,`pay_time_end`,`pay_channel`,`pay_way`,`pay_order_no`,`status`,`fail_reason` | |||||
| `id`,`tenant_id`,`create_time`,`update_time`,`order_id`,`c_user_id`,`pay_amount`,`pay_time_start`,`pay_time_end`,`pay_vendor`,`pay_order_no`,`pay_order_status`,`fail_reason` | |||||
| </sql> | </sql> | ||||
| <sql id="dynamicWhereConditions"> | <sql id="dynamicWhereConditions"> | ||||
| @@ -53,7 +53,12 @@ | |||||
| <if test=" null != cUserId "> | <if test=" null != cUserId "> | ||||
| and `c_user_id` = #{cUserId} | and `c_user_id` = #{cUserId} | ||||
| </if> | |||||
| </if> | |||||
| <if test=" null != ip "> | |||||
| and `ip` = #{ip} | |||||
| </if> | |||||
| <if test=" null != payAmount "> | <if test=" null != payAmount "> | ||||
| and `pay_amount` = #{payAmount} | and `pay_amount` = #{payAmount} | ||||
| @@ -70,13 +75,8 @@ | |||||
| </if> | </if> | ||||
| <if test=" null != payChannel "> | |||||
| and `pay_channel` = #{payChannel} | |||||
| </if> | |||||
| <if test=" null != payWay "> | |||||
| and `pay_way` = #{payWay} | |||||
| <if test=" null != payVendor "> | |||||
| and `pay_vendor` = #{payVendor} | |||||
| </if> | </if> | ||||
| @@ -85,8 +85,8 @@ | |||||
| </if> | </if> | ||||
| <if test=" null != status "> | |||||
| and `status` = #{status} | |||||
| <if test=" null != payOrderStatus "> | |||||
| and `pay_order_status` = #{payOrderStatus} | |||||
| </if> | </if> | ||||
| @@ -188,6 +188,19 @@ | |||||
| <version>3.15</version> | <version>3.15</version> | ||||
| </dependency> | </dependency> | ||||
| <!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp --> | |||||
| <dependency> | |||||
| <groupId>com.squareup.okhttp3</groupId> | |||||
| <artifactId>okhttp</artifactId> | |||||
| <version>3.11.0</version> | |||||
| </dependency> | |||||
| <!-- https://mvnrepository.com/artifact/org.dom4j/dom4j --> | |||||
| <dependency> | |||||
| <groupId>org.dom4j</groupId> | |||||
| <artifactId>dom4j</artifactId> | |||||
| <version>2.1.1</version> | |||||
| </dependency> | |||||
| </dependencies> | </dependencies> | ||||