From fd744700ce5943b49e294c5e02c6568f603734a4 Mon Sep 17 00:00:00 2001 From: gongbiao Date: Tue, 6 Nov 2018 19:19:25 +0800 Subject: [PATCH] =?UTF-8?q?[B=E8=B4=A6=E5=8D=95][=E6=B7=BB=E5=8A=A0][?= =?UTF-8?q?=E8=B4=A6=E5=8D=95=E6=94=AF=E4=BB=98]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/iformall/config/ShiroConfig.java | 1 + .../controller/WxPayBillController.java | 183 ++++ .../iformall/controller/WxBillController.java | 6 +- .../controller/WxPayBillController.java | 152 ++++ .../java/com/iformall/common/ErrorCode.java | 2 +- .../com/iformall/domain/po/WxAppinfo.java | 10 + .../iformall/domain/po/WxPayAccountBill.java | 211 +++++ .../com/iformall/domain/po/WxPayBill.java | 300 +++++++ .../com/iformall/domain/vo/WxBillAll.java | 10 + .../mapper/WxPayAccountBillMapper.java | 20 + .../com/iformall/mapper/WxPayBillMapper.java | 14 + .../iformall/service/WxBillAllService.java | 2 + .../iformall/service/WxPayBillService.java | 74 ++ .../service/impl/WxBillAllServiceImpl.java | 187 +++- .../service/impl/WxPayBillServiceImpl.java | 838 ++++++++++++++++++ .../main/resources/mapper/WxAppinfoMapper.xml | 7 +- .../main/resources/mapper/WxBillAllMapper.xml | 3 +- .../main/resources/mapper/WxPayBillMapper.xml | 120 +++ 18 files changed, 2128 insertions(+), 12 deletions(-) create mode 100644 mallinkAdmin/src/main/java/com/iformall/controller/WxPayBillController.java create mode 100644 mallinkBApi/src/main/java/com/iformall/controller/WxPayBillController.java create mode 100644 mallinkService/src/main/java/com/iformall/domain/po/WxPayAccountBill.java create mode 100644 mallinkService/src/main/java/com/iformall/domain/po/WxPayBill.java create mode 100644 mallinkService/src/main/java/com/iformall/mapper/WxPayAccountBillMapper.java create mode 100644 mallinkService/src/main/java/com/iformall/mapper/WxPayBillMapper.java create mode 100644 mallinkService/src/main/java/com/iformall/service/WxPayBillService.java create mode 100644 mallinkService/src/main/java/com/iformall/service/impl/WxPayBillServiceImpl.java create mode 100644 mallinkService/src/main/resources/mapper/WxPayBillMapper.xml diff --git a/mallinkAdmin/src/main/java/com/iformall/config/ShiroConfig.java b/mallinkAdmin/src/main/java/com/iformall/config/ShiroConfig.java index c34a3015a..28e569320 100644 --- a/mallinkAdmin/src/main/java/com/iformall/config/ShiroConfig.java +++ b/mallinkAdmin/src/main/java/com/iformall/config/ShiroConfig.java @@ -113,6 +113,7 @@ public class ShiroConfig { // } filterChainDefinitionMap.put("/swagger-ui.html", "anon"); filterChainDefinitionMap.put("/wxPay/notify/**", "anon"); + filterChainDefinitionMap.put("/wxPayBill/notify/**", "anon"); filterChainDefinitionMap.put("/v2/**", "anon"); filterChainDefinitionMap.put("/swagger-resources/**", "anon"); filterChainDefinitionMap.put("/webjars/**", "anon"); diff --git a/mallinkAdmin/src/main/java/com/iformall/controller/WxPayBillController.java b/mallinkAdmin/src/main/java/com/iformall/controller/WxPayBillController.java new file mode 100644 index 000000000..be2632faa --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/controller/WxPayBillController.java @@ -0,0 +1,183 @@ +package com.iformall.controller; + +import com.iformall.enums.EnumPayWay; +import com.iformall.exception.BizMessageException; +import com.iformall.exception.MallinkException; +import com.iformall.pay.WxPayment; +import com.iformall.service.WxPayBillService; +import com.iformall.service.WxRefundOrderService; +import com.iformall.utils.XmlUtil; +import org.apache.commons.io.IOUtils; +import org.jdom2.JDOMException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("/wxPayBill/notify") +public class WxPayBillController extends BaseController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxPayBillService wxPayBillService; + + @Autowired + private WxRefundOrderService wxRefundOrderService; + /** + * + * @return 接收微信异步通知 + * @throws Exception 可能产生的任何异常 + */ + @RequestMapping(value = "/pay", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @ResponseBody + public String _payNotify(HttpServletRequest request) throws IOException, JDOMException { + logger.info("微信支付回调"); + InputStream inStream = request.getInputStream(); + ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len = 0; + while ((len = inStream.read(buffer)) != -1) { + outSteam.write(buffer, 0, len); + } + String resultxml = new String(outSteam.toByteArray(), Charset.forName("UTF-8")); + logger.info(resultxml); + + outSteam.close(); + inStream.close(); + + Map paramMap = null; + + try { + paramMap = WxPayment.xmlToMap(resultxml); + logger.info("微信支付回调, notify, param: " + paramMap.toString() ); + String response = wxPayBillService.notify(paramMap, EnumPayWay.PAY_WAY_WEAPP); + logger.info("微信支付回调, notify success, req : " + resultxml + ", resp: " + response.toString()); + return response; + } catch (BizMessageException e) { + if (paramMap == null) { + logger.error("微信支付回调, order create error, e: " + e.getMessage()); + } else { + logger.error("微信支付回调, order create error, req: " + resultxml + ", e: " + e.getMessage()); + } + SortedMap resultMap = new TreeMap<>(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", e.getMessage()); + return XmlUtil.getRequestXml(resultMap); + } catch (MallinkException e) { + if (paramMap == null) { + logger.error("微信支付回调, order create error, e: " + e.getMessage()); + } else { + logger.error("微信支付回调, order create error, req: " + resultxml + ", e: " + e.getMessage()); + } + SortedMap resultMap = new TreeMap<>(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", e.getMessage()); + return XmlUtil.getRequestXml(resultMap); + } catch (Exception e) { + if (paramMap == null) { + logger.error("微信支付回调, order create error, e: " + e.getMessage()); + } else { + logger.error("微信支付回调, order create error, req: " + resultxml + ", e: " + e.getMessage()); + } + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", e.getMessage()); + return XmlUtil.getRequestXml(resultMap); + } + } + + + /** + * + * @return 接收微信退款异步通知 + * @throws Exception 可能产生的任何异常 + */ + @RequestMapping(value = "/refund") + public String __refundNotify(HttpServletRequest request) throws Exception { + Map paramMap = null; + String response = ""; + String xml = ""; + try { + xml = IOUtils.toString(request.getInputStream(), Charset.forName("UTF-8")); + logger.info(xml); + paramMap = WxPayment.xmlToMap(xml); + response = wxRefundOrderService.notify(paramMap, EnumPayWay.PAY_WAY_WEAPP); + logger.info("refund wxpay, notify success, req : " + xml + ", resp: " + response.toString()); + return response; + } catch (BizMessageException e) { + logger.error("refund wxpay, notify error, req: " + xml + ", e:" + e.getLocalizedMessage()); + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", e.getMessage()); + return XmlUtil.getRequestXml(resultMap); + } catch (MallinkException e) { + logger.error("refund wxpay, notify error, req: " + xml + ", e:" +e.getLocalizedMessage()); + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", e.getMessage()); + return XmlUtil.getRequestXml(resultMap); + } catch (Exception e) { + logger.error("refund wxpay, order create error, req: " + xml + ", e: " + e.getMessage()); + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", e.getMessage()); + return XmlUtil.getRequestXml(resultMap); + } + } + + /** + * + * @return 接收微信分账异步通知 + * @throws Exception 可能产生的任何异常 + */ + @RequestMapping(value = "/sharing") + public String __shareNotify(HttpServletRequest request) throws Exception { + Map paramMap = null; + String response = ""; + String xml = ""; + try { + xml = IOUtils.toString(request.getInputStream(), Charset.forName("UTF-8")); + paramMap = WxPayment.xmlToMap(xml); + logger.info("share wxpay, notify, param: " + xml ); + response = wxPayBillService.notify(paramMap, EnumPayWay.PAY_WAY_WEAPP); + logger.info("share wxpay, notify success, req : " + xml + ", resp: " + response.toString()); + return response; + } catch (BizMessageException e) { + logger.error("share wxpay, notify error, req: " + xml + ", e:" + e.getLocalizedMessage()); + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", e.getMessage()); + return XmlUtil.getRequestXml(resultMap); + } catch (MallinkException e) { + logger.error("refund wxpay, notify error, req: " + xml + ", e:" +e.getLocalizedMessage()); + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", e.getMessage()); + return XmlUtil.getRequestXml(resultMap); + } catch (Exception e) { + logger.error("refund wxpay, order create error, req: " + xml + ", e: " + e.getMessage()); + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", e.getMessage()); + return XmlUtil.getRequestXml(resultMap); + } + } + +} diff --git a/mallinkBApi/src/main/java/com/iformall/controller/WxBillController.java b/mallinkBApi/src/main/java/com/iformall/controller/WxBillController.java index 409f25876..e4f584ebd 100644 --- a/mallinkBApi/src/main/java/com/iformall/controller/WxBillController.java +++ b/mallinkBApi/src/main/java/com/iformall/controller/WxBillController.java @@ -79,7 +79,11 @@ public class WxBillController extends BaseController { if(wxMerchant.getStatus().equals(EnumMerchantStatus.NOT_VALID.getCode())){ return new ResultData(ErrorCode.MERCHANT_INFO_NOT_VALID); } - if(StringUtils.isEmpty(wxBillAll.getStarttime()) || StringUtils.isEmpty(wxBillAll.getEndtime())){ + if(!StringUtils.isEmpty(wxBillAll.getStarttime()) && StringUtils.isEmpty(wxBillAll.getEndtime())){ + logger.info("开始时间和结束时间要同时存在或不存在"); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"starttime和endtime要同时存在或不存在"); + } + if(StringUtils.isEmpty(wxBillAll.getStarttime()) && !StringUtils.isEmpty(wxBillAll.getEndtime())){ logger.info("开始时间和结束时间要同时存在或不存在"); return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"starttime和endtime要同时存在或不存在"); } diff --git a/mallinkBApi/src/main/java/com/iformall/controller/WxPayBillController.java b/mallinkBApi/src/main/java/com/iformall/controller/WxPayBillController.java new file mode 100644 index 000000000..769f6bedd --- /dev/null +++ b/mallinkBApi/src/main/java/com/iformall/controller/WxPayBillController.java @@ -0,0 +1,152 @@ +package com.iformall.controller; + +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.config.PayProperty; +import com.iformall.domain.po.WxAppinfo; +import com.iformall.domain.po.WxPayBill; +import com.iformall.enums.EnumPayStatus; +import com.iformall.enums.EnumPayWay; +import com.iformall.exception.MallinkException; +import com.iformall.service.WxPayBillService; +import com.iformall.utils.IPUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("/api/pay") +@Api(description = "账单支付接口") +public class WxPayBillController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private PayProperty payProperty; + + @Autowired + private WxPayBillService wxPayBillService; + + @ApiOperation(value = "发起微信小程序支付订单", notes = "{\"billId\":\"string\",\"appId\":\"string\",\"openId\":\"string\",\"bUserId\":\"string\"}") + @RequestMapping(value = "/create", method = RequestMethod.POST) + public ResultData _create(@RequestBody Map paramMap, HttpServletRequest request) throws Exception { + logger.info("/api/pay/create" + paramMap.toString()); + //bill参数不能为空 + String billIdStr = paramMap.get("billId"); + if (StringUtils.isBlank(billIdStr)) { + logger.info("billId不能为空: " + paramMap.toString()); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "billId不能为空"); + } + //bill参数要为Long + Long billId; + try { + billId = Long.valueOf(billIdStr); + } catch (NumberFormatException e) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "billId参数不正确"); + } + + //b_user_id + String bUserIdStr = paramMap.get("bUserId"); + if (StringUtils.isBlank(bUserIdStr)) { + logger.info("bUserId不能为空: " + paramMap.toString()); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "bUserId不能为空"); + } + + //b_user_id参数要为Long + Long bUserId; + try { + bUserId = Long.valueOf(bUserIdStr); + } catch (NumberFormatException e) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "bUserId参数不正确"); + } + //appid + String appid = paramMap.get("appId"); + //openid + String openid = paramMap.get("openId"); + //获取小程序配置信息 + WxAppinfo appInfo = getAppInfo(appid); + //支付账单参数 + WxPayBill record = new WxPayBill(); + record.setBillId(billId); + record.setOpenId(openid); + record.setbUserId(bUserId); + try { + record.setIp(IPUtil.getIpAddr(request)); + return wxPayBillService.createPayBill(payProperty.isReal(), appInfo, 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.PAY_ORDER_ERROR, e.getMessage()); + } + } + + @ApiOperation(value = "更新支付订单状态", notes = "{\"payBillId\":\"string\",\"billId\":\"string\",\"status\":integer,\"reason\":\"string\"}") + @PostMapping("/updatePayBill") + public ResultData updatePayBill(@RequestBody Map paramMap) { + logger.info("/api/pay/updatePayBill" + paramMap.toString()); + String payBillIdStr = (String) paramMap.get("payBillId"); + String billIdStr = (String) paramMap.get("billId"); + String reasonStr = (String) paramMap.get("reason"); + Integer status = (Integer) paramMap.get("status"); + if (StringUtils.isBlank(billIdStr)) { + logger.info("billId不能为空: " + paramMap.toString()); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "billId不能为空"); + } + Long payBillId = 0L, billId = 0L; + try { + billId = Long.valueOf(billIdStr); + } catch (NumberFormatException e) { + logger.error("billId参数不正确: " + paramMap.toString() + ", e:" + e.getMessage()); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "billId参数不正确"); + } + if (!StringUtils.isBlank(payBillIdStr)) { + try { + payBillId = Long.valueOf(payBillIdStr); + } catch (NumberFormatException e) { + logger.error("payBillId参数不正确: " + paramMap.toString() + ", e:" + e.getMessage()); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "payBillId参数不正确"); + } + } + + WxPayBill payBill = new WxPayBill(); + payBill.setId(payBillId); + payBill.setBillId(billId); + payBill.setPayBillStatus(status); + payBill.setFailReason(reasonStr); + try { + if(status.equals(EnumPayStatus.PAY_WAY_SUCCESS.getCode()) && !payBillIdStr.equals(EnumPayStatus.PAY_WAY_WAIT.getCode())) { + // 有价券不走update, callback更新 + payBill = wxPayBillService.getById(payBillId); + if(payBill.getPayBillStatus().equals(EnumPayStatus.PAY_WAY_SUCCESS.getCode())) { + return new ResultData(Result.SUCCESS, "支付状态更新成功"); + } else { + return new ResultData(ErrorCode.PAY_ORDER_ERROR, "支付未状态,请等待!!"); + } + } else { + wxPayBillService.handlePayBillStatusUpdate(payBill); + } + return new ResultData(Result.SUCCESS, "支付状态更新成功"); + } catch (MallinkException e) { + logger.error("支付状态更新失败2: " + payBill.toString() + ", e:" + e.getMessage()); + return new ResultData(e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + logger.error("支付状态更新失败3: " + payBill.toString() + ", e:" + e.getMessage()); + return new ResultData(ErrorCode.PAY_ORDER_ERROR, "支付状态更新失败3: " + payBill.toString() + ", e:" + e.getMessage()); + } + } + + + +} diff --git a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java index e275cf796..96c4e7599 100644 --- a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java +++ b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java @@ -274,7 +274,7 @@ public enum ErrorCode{ * 日常费用账单 * */ BILL_ROUTINE_IS_NOT_FOUND(21000,"账单不存在"), - + BILL_UPDATE_FAILED(21001,"账单更新失败"), /** * 商铺 * */ diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxAppinfo.java b/mallinkService/src/main/java/com/iformall/domain/po/WxAppinfo.java index f907dfc81..f0b0f212f 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/WxAppinfo.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxAppinfo.java @@ -79,6 +79,16 @@ public class WxAppinfo implements Serializable { private Long payId; @io.swagger.annotations.ApiModelProperty(value="1B端2C端",name="type") private Integer type; + @io.swagger.annotations.ApiModelProperty(value="支付ID,参看wx_pay_account_bill",name="payBillId") + private Long payBillId; + + public Long getPayBillId() { + return payBillId; + } + + public void setPayBillId(Long payBillId) { + this.payBillId = payBillId; + } public String getTenantId() { return tenantId; diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxPayAccountBill.java b/mallinkService/src/main/java/com/iformall/domain/po/WxPayAccountBill.java new file mode 100644 index 000000000..ad1998a5a --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxPayAccountBill.java @@ -0,0 +1,211 @@ +package com.iformall.domain.po; + +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import java.io.Serializable; +import java.util.List; + +/** + * @author gongbiao + */ +@Table(name = "wx_pay_account_bill") +public class WxPayAccountBill implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + protected Long id; + + @Transient + protected List ids; + @Transient + protected String sortColumns; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getSortColumns() { + return sortColumns; + } + + public List getIds() { + return ids; + } + + public void setIds(List ids) { + this.ids = ids; + } + + + /*租户ID**/ + @io.swagger.annotations.ApiModelProperty(value="租户ID",name="tenantId") + private String tenantId; + /**微信商户号/特约服务商号**/ + @io.swagger.annotations.ApiModelProperty(value="微信商户号/特约服务商号",name="mchId") + private String mchId; + /**微信服务商号*/ + @io.swagger.annotations.ApiModelProperty(value="微信服务商号",name="subMchId") + private String subMchId; + /**支付密钥**/ + @io.swagger.annotations.ApiModelProperty(value="支付密钥",name="apiKey") + private String apiKey; + /**微信回调,支持3种回调,(1.url/pay 2.url/refund3.url/separate)**/ + @io.swagger.annotations.ApiModelProperty(value="微信回调,支持3种回调,(1.url/pay 2.url/refund3.url/separate)",name="notifyUrl") + private String notifyUrl; + /**证书本地存放位置**/ + @io.swagger.annotations.ApiModelProperty(value="证书本地存放位置",name="certPath") + private String certPath; + /**商户模式**/ + @io.swagger.annotations.ApiModelProperty(value="商户模式-0:普通商户模式1:服务商模式",name="type") + private Integer type; + /**是否开启分账**/ + @io.swagger.annotations.ApiModelProperty(value="0:未开启分账1:开启分账",name="type") + private boolean share; + /**手续费**/ + @io.swagger.annotations.ApiModelProperty(value="手续费",name="rate") + private Integer rate; + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + public String getMchId() { + return mchId; + } + public void setMchId(String _mchId) { + mchId = _mchId; + } + + public String getSubMchId() { + return subMchId; + } + + public void setSubMchId(String subMchId) { + this.subMchId = subMchId; + } + + public String getApiKey() { + return apiKey; + } + public void setApiKey(String _apiKey) { + apiKey = _apiKey; + } + public String getNotifyUrl() { + return notifyUrl; + } + public void setNotifyUrl(String _notifyUrl) { + notifyUrl = _notifyUrl; + } + public String getCertPath() { + return certPath; + } + public void setCertPath(String _certPath) { + certPath = _certPath; + } + public Integer getType() { + return type; + } + public void setType(Integer type) { + this.type = type; + } + public boolean isShare() { + return share; + } + public void setShare(boolean share) { + this.share = share; + } + + public Integer getRate() { + return rate; + } + + public void setRate(Integer rate) { + this.rate = rate; + } + + public String getPayNotifyUrl() { + return notifyUrl + "/pay"; + } + public String getRefundNotifyUrl() { + return notifyUrl + "/refund"; + } + public String getSeparateNotifyUrl() { + return notifyUrl + "/separate"; + } + + + public static enum Field + { + Id_ASC("`id` ASC"),Id_DESC("`id` DESC") + ,TenantId_ASC("`tenant_id` ASC"),TenantId_DESC("`tenant_id` DESC") + ,MchId_ASC("`mch_id` ASC"),MchId_DESC("`mch_id` DESC") + ,SubMchId_ASC("`sub_mch_id` ASC"),SubMchId_DESC("`sub_mch_id` DESC") + ,ApiKey_ASC("`api_key` ASC"),ApiKey_DESC("`api_key` DESC") + ,NotifyUrl_ASC("`notify_url` ASC"),NotifyUrl_DESC("`notify_url` DESC") + ,CertPath_ASC("`cert_path` ASC"),CertPath_DESC("`cert_path` DESC") + ,Type_ASC("`type` ASC"),Type_DESC("`type` DESC") + ,Share_ASC("`share` ASC"),Share_DESC("`share` DESC") + ,Rate_ASC("`rate` ASC"),Rate_DESC("`rate` DESC") + ; + private String value; + Field(String value){ + this.value = value; + } + public String getValue() { + return value; + } + public void setCol(String value) { + this.value = value; + } + @Override + public String toString() { + return this.getValue(); + } + } + + public void setSortColumns(WxPayAccountBill.Field... fields) + { + if (fields == null || fields.length == 0) { + return; + } + for (int k = 0; k < fields.length; k++) { + if (fields[k] == null) { + return; + } + } + StringBuilder sb = new StringBuilder(fields[0].toString()); + for (int k = 1; k < fields.length; k++) { + sb.append(","); + sb.append(fields[k].toString()); + } + + this.sortColumns = sb.toString(); + + } + + public void setSortColumns(String sortColumns) + { + if (sortColumns == null || "".equals(sortColumns.trim())) { + return; + } + if (sortColumns.contains(",")) { + String[] cols = sortColumns.split(","); + List fList = new java.util.ArrayList(); + for (int k = 0; k < cols.length; k++) { + fList.add(Field.valueOf(cols[k])); + } + this.setSortColumns(fList.toArray(new Field[fList.size()])); + } else { + this.setSortColumns(Field.valueOf(sortColumns)); + } + } +} diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxPayBill.java b/mallinkService/src/main/java/com/iformall/domain/po/WxPayBill.java new file mode 100644 index 000000000..e6163712b --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxPayBill.java @@ -0,0 +1,300 @@ +package com.iformall.domain.po; + +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @author gongbiao + */ +@Table(name = "wx_pay_bill") +public class WxPayBill implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + protected Long id; + + @Transient + protected List ids; + @Transient + protected String sortColumns; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getSortColumns() { + return sortColumns; + } + + public List getIds() { + return ids; + } + + public void setIds(List ids) { + this.ids = ids; + } + + + + /**租户ID**/ + @io.swagger.annotations.ApiModelProperty(value="租户ID",name="tenantId") + private String tenantId; + /**创建时间**/ + @io.swagger.annotations.ApiModelProperty(value="创建时间",name="createTime") + private Date createTime; + /**更新时间**/ + @io.swagger.annotations.ApiModelProperty(value="更新时间",name="updateTime") + private Date updateTime; + /**账单ID**/ + @io.swagger.annotations.ApiModelProperty(value="账单ID",name="billId") + private Long billId; + /**用户ID**/ + @io.swagger.annotations.ApiModelProperty(value="用户ID",name="bUserId") + private Long bUserId; + /**ip地址**/ + @io.swagger.annotations.ApiModelProperty(value="ip地址",name="ip") + private String ip; + /**支付金额(分)**/ + @io.swagger.annotations.ApiModelProperty(value="支付金额(分)",name="payAmount") + private Integer payAmount; + /**支付发起时间**/ + @io.swagger.annotations.ApiModelProperty(value="支付发起时间",name="payTimeStart") + private Date payTimeStart; + /**支付结束时间**/ + @io.swagger.annotations.ApiModelProperty(value="支付结束时间",name="payTimeEnd") + private Date payTimeEnd; + /**微信预支付交易会话标识**/ + @io.swagger.annotations.ApiModelProperty(value="微信预支付交易会话标识",name="prepayId") + private String prepayId; + /**微信生成的订单号**/ + @io.swagger.annotations.ApiModelProperty(value="微信生成的订单号",name="transactionId") + private String transactionId; + /**支付渠道: 0-微信 1-支付宝 2-银联 **/ + @io.swagger.annotations.ApiModelProperty(value="支付渠道: 0-微信 1-支付宝 2-银联 ",name="payVendor") + private Integer payVendor; + /**支付订单号**/ + @io.swagger.annotations.ApiModelProperty(value="支付订单号",name="payBillNo") + private String payBillNo; + /**支付状态: 0-支付中;1-支付成功;2-支付失败**/ + @io.swagger.annotations.ApiModelProperty(value="支付状态: 0-支付中;1-支付成功;2-支付失败",name="payBillStatus") + private Integer payBillStatus; + /**分账状态: 0-未分账;1-分账**/ + @io.swagger.annotations.ApiModelProperty(value="分账状态: 0-未分账;1-分账",name="payBillStatus") + private Integer share; + /**分账金额(总金额扣除手续费后的金额)**/ + @io.swagger.annotations.ApiModelProperty(value="分账金额",name="shareAmount") + private Integer shareAmount; + /**支付失败原因**/ + @io.swagger.annotations.ApiModelProperty(value="支付失败原因",name="failReason") + private String failReason; + + @io.swagger.annotations.ApiModelProperty(value="openId",name="openId") + private String openId; + + public String getOpenId() { + return openId; + } + + public void setOpenId(String openId) { + this.openId = openId; + } + + public String getTenantId() { + return tenantId; + } + public void setTenantId(String _tenantId) { + tenantId = _tenantId; + } + public Date getCreateTime() { + return createTime; + } + public void setCreateTime(Date _createTime) { + createTime = _createTime; + } + public Date getUpdateTime() { + return updateTime; + } + public void setUpdateTime(Date _updateTime) { + updateTime = _updateTime; + } + + public Long getBillId() { + return billId; + } + + public void setBillId(Long billId) { + this.billId = billId; + } + + public Long getbUserId() { + return bUserId; + } + + public void setbUserId(Long bUserId) { + this.bUserId = bUserId; + } + + public String getIp() { + return ip; + } + public void setIp(String _ip) { + ip = _ip; + } + public Integer getPayAmount() { + return payAmount; + } + public void setPayAmount(Integer _payAmount) { + payAmount = _payAmount; + } + public Date getPayTimeStart() { + return payTimeStart; + } + public void setPayTimeStart(Date _payTimeStart) { + payTimeStart = _payTimeStart; + } + public Date getPayTimeEnd() { + return payTimeEnd; + } + public void setPayTimeEnd(Date _payTimeEnd) { + payTimeEnd = _payTimeEnd; + } + + public String getPrepayId() { + return prepayId; + } + + public void setPrepayId(String prepayId) { + this.prepayId = prepayId; + } + + public String getTransactionId() { + return transactionId; + } + public void setTransactionId(String _transactionId) { + transactionId = _transactionId; + } + public Integer getPayVendor() { + return payVendor; + } + public void setPayVendor(Integer _payVendor) { + payVendor = _payVendor; + } + public String getPayBillNo() { + return payBillNo; + } + public void setPayBillNo(String _payBillNo) { + payBillNo = _payBillNo; + } + public Integer getPayBillStatus() { + return payBillStatus; + } + public void setPayBillStatus(Integer _payBillStatus) { + payBillStatus = _payBillStatus; + } + + public Integer getShare() { + return share; + } + public void setShare(Integer share) { + this.share = share; + } + + public Integer getShareAmount() { + return shareAmount; + } + + public void setShareAmount(Integer shareAmount) { + this.shareAmount = shareAmount; + } + + public String getFailReason() { + return failReason; + } + public void setFailReason(String _failReason) { + failReason = _failReason; + } + + + + public static enum Field + { + Id_ASC("`id` ASC"),Id_DESC("`id` DESC") + ,TenantId_ASC("`tenant_id` ASC"),TenantId_DESC("`tenant_id` DESC") + ,CreateTime_ASC("`create_time` ASC"),CreateTime_DESC("`create_time` DESC") + ,UpdateTime_ASC("`update_time` ASC"),UpdateTime_DESC("`update_time` DESC") + ,BillId_ASC("`bill_id` ASC"),BillId_DESC("`bill_id` DESC") + ,BUserId_ASC("`b_user_id` ASC"),BUserId_DESC("`b_user_id` DESC") + ,Ip_ASC("`ip` ASC"),Ip_DESC("`ip` DESC") + ,PayAmount_ASC("`pay_amount` ASC"),PayAmount_DESC("`pay_amount` DESC") + ,PayTimeStart_ASC("`pay_time_start` ASC"),PayTimeStart_DESC("`pay_time_start` DESC") + ,PayTimeEnd_ASC("`pay_time_end` ASC"),PayTimeEnd_DESC("`pay_time_end` DESC") + ,PrepayId_ASC("`prepay_id` ASC"),PrepayId_DESC("`transaction_id` DESC") + ,TransactionId_ASC("`transaction_id` ASC"),TransactionId_DESC("`prepay_id` DESC") + ,PayVendor_ASC("`pay_vendor` ASC"),PayVendor_DESC("`pay_vendor` DESC") + ,PayBillNo_ASC("`pay_bill_no` ASC"),PayBillNo_DESC("`pay_bill_no` DESC") + ,PayBillStatus_ASC("`pay_bill_status` ASC"),PayBillStatus_DESC("`pay_bill_status` DESC") + ,Share_ASC("`share` ASC"),Share_DESC("`share` DESC") + ,ShareAmount_ASC("`share_amount` ASC"),ShareAmount_DESC("`share_amount` DESC") + ,FailReason_ASC("`fail_reason` ASC"),FailReason_DESC("`fail_reason` DESC") + ; + private String value; + Field(String value){ + this.value = value; + } + public String getValue() { + return value; + } + public void setCol(String value) { + this.value = value; + } + @Override + public String toString() { + return this.getValue(); + } + } + + public void setSortColumns(WxPayBill.Field... fields) + { + if (fields == null || fields.length == 0) { + return; + } + for (int k = 0; k < fields.length; k++) { + if (fields[k] == null) { + return; + } + } + StringBuilder sb = new StringBuilder(fields[0].toString()); + for (int k = 1; k < fields.length; k++) { + sb.append(","); + sb.append(fields[k].toString()); + } + + this.sortColumns = sb.toString(); + } + + public void setSortColumns(String sortColumns) + { + if (sortColumns == null || "".equals(sortColumns.trim())) { + return; + } + if (sortColumns.contains(",")) { + String[] cols = sortColumns.split(","); + List fList = new ArrayList(); + for (int k = 0; k < cols.length; k++) { + fList.add(Field.valueOf(cols[k])); + } + this.setSortColumns(fList.toArray(new Field[fList.size()])); + } else { + this.setSortColumns(Field.valueOf(sortColumns)); + } + } +} diff --git a/mallinkService/src/main/java/com/iformall/domain/vo/WxBillAll.java b/mallinkService/src/main/java/com/iformall/domain/vo/WxBillAll.java index fe268878d..5f1613248 100644 --- a/mallinkService/src/main/java/com/iformall/domain/vo/WxBillAll.java +++ b/mallinkService/src/main/java/com/iformall/domain/vo/WxBillAll.java @@ -47,6 +47,16 @@ public class WxBillAll { @io.swagger.annotations.ApiModelProperty(value="条数",name="pageSize") private Integer pageSize; + @io.swagger.annotations.ApiModelProperty(value="id",name="id") + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } public String getAppId() { return appId; diff --git a/mallinkService/src/main/java/com/iformall/mapper/WxPayAccountBillMapper.java b/mallinkService/src/main/java/com/iformall/mapper/WxPayAccountBillMapper.java new file mode 100644 index 000000000..deb9f46af --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/mapper/WxPayAccountBillMapper.java @@ -0,0 +1,20 @@ +package com.iformall.mapper; + +import com.iformall.common.CommonMapper; +import com.iformall.domain.po.WxPayAccountBill; + +import java.util.List; + +/** + * @author gongbiao + */ +public interface WxPayAccountBillMapper extends CommonMapper { + + List findList(WxPayAccountBill wxPayAccount); + + + + + + +} diff --git a/mallinkService/src/main/java/com/iformall/mapper/WxPayBillMapper.java b/mallinkService/src/main/java/com/iformall/mapper/WxPayBillMapper.java new file mode 100644 index 000000000..7548daca7 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/mapper/WxPayBillMapper.java @@ -0,0 +1,14 @@ +package com.iformall.mapper; + +import com.iformall.common.CommonMapper; +import com.iformall.domain.po.WxPayBill; + +import java.util.List; + +/** + * @author gongbiao + */ +public interface WxPayBillMapper extends CommonMapper { + + List findList(WxPayBill wxPayBill); +} diff --git a/mallinkService/src/main/java/com/iformall/service/WxBillAllService.java b/mallinkService/src/main/java/com/iformall/service/WxBillAllService.java index d4ca8b342..b50b20cd0 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxBillAllService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxBillAllService.java @@ -17,4 +17,6 @@ public interface WxBillAllService { ResultData listBill(WxBillAll wxBillAll); + int updateBill(Map bill); + } diff --git a/mallinkService/src/main/java/com/iformall/service/WxPayBillService.java b/mallinkService/src/main/java/com/iformall/service/WxPayBillService.java new file mode 100644 index 000000000..de08cd17a --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/WxPayBillService.java @@ -0,0 +1,74 @@ +package com.iformall.service; + +import com.iformall.common.ResultData; +import com.iformall.domain.po.WxAppinfo; +import com.iformall.domain.po.WxPayBill; +import com.iformall.enums.EnumPayWay; + +import java.util.Map; + +/** + * @author gongbiao + */ +public interface WxPayBillService { + + /** + * 创建支付订单 + * + * @param record 支付订单请求 + * @param payWay + * @return + */ + ResultData createPayBill(boolean isReal, WxAppinfo appInfo, WxPayBill record, EnumPayWay payWay); + + /** + * 微信支付订单查询 + * @param appInfo 支付订单Appinfo + * @param record 支付订单 + */ + ResultData payBillQuery(WxAppinfo appInfo, WxPayBill record); + + /** + * 微信支付关闭订单 + * @param appInfo 支付订单Appinfo + * @param record 支付订单 + */ + ResultData payBillClose(WxAppinfo appInfo, WxPayBill record); + + /** + * 异步通知 + * + * @param paramMap 异步通知参数 + * @param payWay 支付方式 + * @return + */ + String notify(Map paramMap, EnumPayWay payWay); + + /** + * 支付成功处理 + * + * @param record + * @param transactionId + */ + void handleBillPaySuccess(WxPayBill record, String transactionId); + + /** + * 支付状态处理 + * + * @param record + */ + void handlePayBillStatusUpdate(WxPayBill record); + + /** + * 页面回调 + * + * @param paramMap 页面通知参数 + * @param payWay 支付方式 + * @return + */ + void callback(Map paramMap, EnumPayWay payWay); + + + WxPayBill getById(Long payBillId); + +} diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxBillAllServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxBillAllServiceImpl.java index 28e33a0e8..0f7ca18cc 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxBillAllServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxBillAllServiceImpl.java @@ -6,22 +6,20 @@ import com.iformall.common.ErrorCode; import com.iformall.common.ResultData; import com.iformall.domain.po.*; import com.iformall.domain.vo.WxBillAll; +import com.iformall.enums.EnumBillDailyStatus; import com.iformall.enums.EnumBillRentStatus; import com.iformall.enums.EnumBillType; import com.iformall.enums.EnumBillTypeParam; -import com.iformall.mapper.WxBillAllMapper; +import com.iformall.exception.MallinkException; +import com.iformall.mapper.*; import com.iformall.service.*; import com.iformall.utils.DateUtils; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author gongbiao @@ -51,6 +49,25 @@ public class WxBillAllServiceImpl implements WxBillAllService { @Autowired WxBillOtherService wxBillOtherService; + @Autowired + WxBillDailyMapper wxBillDailyMapper; + + @Autowired + WxBillDepositMapper wxBillDepositMapper; + + @Autowired + WxBillPropertyDepositMapper wxBillPropertyDepositMapper; + + @Autowired + WxBillPropertyMapper wxBillPropertyMapper; + + @Autowired + WxBillRentMapper wxBillRentMapper; + + @Autowired + WxBillOtherMapper wxBillOtherMapper; + + @Override public Map listAsPage(WxBillAll record, Integer pageIndex, Integer pageSize) { //更新各账单状态 @@ -89,7 +106,7 @@ public class WxBillAllServiceImpl implements WxBillAllService { //更新各账单状态 updateBillStatus(wxBillAll); //账单类型 - if(wxBillAll.getBillTypeValue()!=null){ + if (wxBillAll.getBillTypeValue() != null) { if (wxBillAll.getBillTypeValue().equals(EnumBillType.RENT.getCode())) { wxBillAll.setBillTypeValue(EnumBillTypeParam.RENT.getCode()); } else if (wxBillAll.getBillTypeValue().equals(EnumBillType.DEPOSIT.getCode())) { @@ -111,7 +128,7 @@ public class WxBillAllServiceImpl implements WxBillAllService { return new ResultData(ErrorCode.BILL_ROUTINE_IS_NOT_FOUND); } } - if(wxBillAll.getPageIndex()!=null && wxBillAll.getPageIndex()!=null){ + if (wxBillAll.getPageIndex() != null && wxBillAll.getPageIndex() != null) { PageHelper.startPage(wxBillAll.getPageIndex(), wxBillAll.getPageSize()); List> maps = wxBillAllMapper.listData(wxBillAll); PageInfo> pageInfo = new PageInfo<>(maps); @@ -121,6 +138,160 @@ public class WxBillAllServiceImpl implements WxBillAllService { return new ResultData(maps); } + @Override + public int updateBill(Map bill) { + if (bill == null) { + return 0; + } + Integer billTypeValue = (Integer) bill.get("billTypeValue"); + if (billTypeValue.equals(EnumBillTypeParam.RENT.getCode())) { + //更新租金账单 + return updateBillRent(bill); + } else if (billTypeValue.equals(EnumBillTypeParam.RENT_DEPOSIT.getCode())) { + //更新租金押金账单 + return updateBillRentDeposit(bill); + } else if (billTypeValue.equals(EnumBillTypeParam.PROPERTY.getCode())) { + //更新物业账单 + return updateBillProperty(bill); + } else if (billTypeValue.equals(EnumBillTypeParam.PROPERTY_DEPOSIT.getCode())) { + //更新物业押金账单 + return updateBillPropertyDeposit(bill); + } else if (billTypeValue.equals(EnumBillTypeParam.WATER.getCode())) { + //更新水费账单 + return updateBillDaily(bill); + } else if (billTypeValue.equals(EnumBillTypeParam.POWER.getCode())) { + //更新电费账单 + return updateBillDaily(bill); + } else if (billTypeValue.equals(EnumBillTypeParam.ROUTINE.getCode())) { + //更新其他账单 + return updateBillOther(bill); + } else { + logger.info("账单类型不存在"); + return 0; + } + } + + private int updateBillOther(Map bill) { + Object id = bill.get("id"); + WxBillOther wxBillOther = wxBillOtherMapper.selectByPrimaryKey(id); + if(wxBillOther==null){ + return 0; + } + Date date = new Date(); + wxBillOther.setPayDate(date); + wxBillOther.setPay((Integer) bill.get("owe")); + wxBillOther.setOwe(0); + wxBillOther.setStatus(EnumBillDailyStatus.PAID.getCode()); + wxBillOther.setUpdatetime(date); + try { + return wxBillOtherMapper.updateByPrimaryKeySelective(wxBillOther); + } catch (Exception e) { + logger.error("更新其他账单失败,e:" + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); + } + } + + private int updateBillDaily(Map bill) { + Object id = bill.get("id"); + WxBillDaily wxBillDaily = wxBillDailyMapper.selectByPrimaryKey(id); + if(wxBillDaily==null){ + return 0; + } + Date date = new Date(); + wxBillDaily.setPayDate(date); + wxBillDaily.setPay((Integer) bill.get("owe")); + wxBillDaily.setOwe(0); + wxBillDaily.setStatus(EnumBillDailyStatus.PAID.getCode()); + wxBillDaily.setUpdatetime(date); + try { + return wxBillDailyMapper.updateByPrimaryKeySelective(wxBillDaily); + } catch (Exception e) { + logger.error("更新日常账单失败,e:" + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); + } + } + + private int updateBillPropertyDeposit(Map bill) { + Object id = bill.get("id"); + WxBillPropertyDeposit wxBillPropertyDeposit = wxBillPropertyDepositMapper.selectByPrimaryKey(id); + if(wxBillPropertyDeposit==null){ + return 0; + } + Date date = new Date(); + wxBillPropertyDeposit.setPayDate(date); + wxBillPropertyDeposit.setPay((Integer) bill.get("owe")); + wxBillPropertyDeposit.setOwe(0); + wxBillPropertyDeposit.setStatus(EnumBillDailyStatus.PAID.getCode()); + wxBillPropertyDeposit.setUpdatetime(date); + try { + return wxBillPropertyDepositMapper.updateByPrimaryKeySelective(wxBillPropertyDeposit); + } catch (Exception e) { + logger.error("更新物业押金账单失败,e:" + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); + } + } + + private int updateBillProperty(Map bill) { + Object id = bill.get("id"); + WxBillProperty property = wxBillPropertyMapper.selectByPrimaryKey(id); + if(property==null){ + return 0; + } + Date date = new Date(); + property.setPayDate(date); + property.setPay((Integer) bill.get("owe")); + property.setOwe(0); + property.setStatus(EnumBillDailyStatus.PAID.getCode()); + property.setUpdatetime(date); + try { + return wxBillPropertyMapper.updateByPrimaryKeySelective(property); + } catch (Exception e) { + logger.error("更新物业账单失败,e:" + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); + } + } + + private int updateBillRentDeposit(Map bill) { + Object id = bill.get("id"); + WxBillDeposit wxBillDeposit = wxBillDepositMapper.selectByPrimaryKey(id); + if(wxBillDeposit==null){ + return 0; + } + Date date = new Date(); + wxBillDeposit.setPayDate(date); + wxBillDeposit.setPay((Integer) bill.get("owe")); + wxBillDeposit.setOwe(0); + wxBillDeposit.setStatus(EnumBillDailyStatus.PAID.getCode()); + wxBillDeposit.setUpdatetime(date); + try { + return wxBillDepositMapper.updateByPrimaryKeySelective(wxBillDeposit); + } catch (Exception e) { + logger.error("更新租赁押金账单失败,e:" + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); + } + } + + private int updateBillRent(Map bill) { + Object id = bill.get("id"); + WxBillRent wxBillRent = wxBillRentMapper.selectByPrimaryKey(id); + if(wxBillRent==null){ + return 0; + } + Date date = new Date(); + wxBillRent.setPayDate(date); + wxBillRent.setPay((Integer) bill.get("owe")); + wxBillRent.setOwe(0); + wxBillRent.setStatus(EnumBillDailyStatus.PAID.getCode()); + wxBillRent.setUpdatetime(date); + try { + return wxBillRentMapper.updateByPrimaryKeySelective(wxBillRent); + } catch (Exception e) { + logger.error("更新租金账单失败,e:" + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); + } + } + + private void updateBillStatus(WxBillAll record) { logger.info("更新各账单状态开始"); //更新其他账单 diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxPayBillServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxPayBillServiceImpl.java new file mode 100644 index 000000000..facc63942 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxPayBillServiceImpl.java @@ -0,0 +1,838 @@ +package com.iformall.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.iformall.common.ErrorCode; +import com.iformall.common.IdWorker; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.domain.po.*; +import com.iformall.domain.vo.WxBillAll; +import com.iformall.enums.*; +import com.iformall.exception.MallinkException; +import com.iformall.mapper.*; +import com.iformall.pay.*; +import com.iformall.service.WxBillAllService; +import com.iformall.service.WxPayBillService; +import com.iformall.utils.BeanUtils; +import com.iformall.utils.MapUtil; +import com.iformall.utils.Utility; +import com.iformall.utils.XmlUtil; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.text.ParseException; +import java.util.*; + +/** + * @author gongbiao + */ +@Service +public class WxPayBillServiceImpl implements WxPayBillService { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + WxAppinfoMapper wxAppinfoMapper; + + @Autowired + WxPayAccountBillMapper wxPayAccountBillMapper; + + @Autowired + WxPayBillMapper wxPayBillMapper; + + @Autowired + WxBillAllMapper wxBillAllMapper; + + @Autowired + WxBillAllService wxBillAllService; + + @Autowired + WxMerchantBUserMapper wxMerchantBUserMapper; + + JSONObject errorMap = JSON.parseObject("{" + + "\"NOAUTH\":{\"detail\":\"商户无此接口权限\",\"reason\":\"商户未开通此接口权限\",\"resolution\":\"请商户前往申请此接口权限\"}," + + "\"NOTENOUGH\":{\"detail\":\"余额不足\",\"reason\":\"用户帐号余额不足\",\"resolution\":\"用户帐号余额不足,请用户充值或更换支付卡后再支付\"}," + + "\"ORDERPAID\":{\"detail\":\"商户订单已支付\",\"reason\":\"商户订单已支付,无需重复操作\",\"resolution\":\"商户订单已支付,无需更多操作\"}," + + "\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"当前订单已关闭,无法支付\",\"resolution\":\"当前订单已关闭,请重新下单\"}," + + "\"SYSTEMERROR\":{\"detail\":\"系统错误\t\",\"reason\":\"系统超时\",\"resolution\":\"系统异常,请用相同参数重新调用\"}," + + "\"APPID_NOT_EXIST\":{\"detail\":\"APPID不存在\",\"reason\":\"参数中缺少APPID\",\"resolution\":\"请检查APPID是否正确\"}," + + "\"MCHID_NOT_EXIST\":{\"detail\":\"MCHID不存在\",\"reason\":\"参数中缺少MCHID\",\"resolution\":\"请检查MCHID是否正确\"}," + + "\"APPID_MCHID_NOT_MATCH\":{\"detail\":\"appid和mch_id不匹配\",\"reason\":\"appid和mch_id不匹配\",\"resolution\":\"请确认appid和mch_id是否匹配\"}," + + "\"LACK_PARAMS\":{\"detail\":\"缺少参数\t\",\"reason\":\"缺少必要的请求参数\",\"resolution\":\"请检查参数是否齐全\"}," + + "\"OUT_TRADE_NO_USED\":{\"detail\":\"商户订单号重复\",\"reason\":\"同一笔交易不能多次提交\",\"resolution\":\"请核实商户订单号是否重复提交\"}," + + "\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," + + "\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"resolution\":\"请检查XML参数格式是否正确\"}," + + "\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," + + "\"POST_DATA_EMPTY\":{\"detail\":\"post数据为空\",\"reason\":\"post数据不能为空\",\"resolution\":\"请检查post数据是否为空\"}," + + "\"NOT_UTF8\":{\"detail\":\"编码格式错误\",\"reason\":\"未使用指定编码格式\",\"resolution\":\"请使用UTF-8编码格式\"}}"); + + JSONObject errorMapQuery = JSON.parseObject("{" + + "\"ORDERNOTEXIST\":{\"detail\":\"此交易订单号不存在\",\"reason\":\"查询系统中不存在此交易订单号\",\"resolution\":\"该API只能查提交支付交易返回成功的订单,请商户检查需要查询的订单号是否正确\"},\n" + + "\"SYSTEMERROR\":{\"detail\":\"系统错误\t\",\"reason\":\"后台系统返回错误\",\"resolution\":\"系统异常,请再调用发起查询\"}}"); + + JSONObject errorMapClose = JSON.parseObject("{" + + "\"ORDERPAID\":{\"detail\":\"订单已支付\",\"reason\":\"订单已支付,不能发起关单\",\"resolution\":\"订单已支付,不能发起关单,请当作已支付的正常交易\"}," + + "\"SYSTEMERROR\":{\"detail\":\"系统错误\",\"reason\":\"系统错误\",\"resolution\":\"系统异常,请重新调用该API\"}," + + "\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"订单已关闭,无法重复关闭\",\"resolution\":\"订单已关闭,无需继续调用\"}," + + "\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," + + "\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," + + "\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"reason\":\"请检查XML参数格式是否正确\"}}"); + + @Override + public ResultData createPayBill(boolean isReal, WxAppinfo appInfo, WxPayBill record, EnumPayWay payWay) { + final IdWorker idworker = IdWorker.get(); + + EnumPayShare isShare = EnumPayShare.NO; + + try { + // 1. check 订单 + WxBillAll wxBillAll = new WxBillAll(); + wxBillAll.setId(record.getBillId()); + List> bills = wxBillAllMapper.listData(wxBillAll); + if (bills == null) { + logger.error("pay bill, bill not allow, repaymentReq: " + record.toString() + ", payWay: " + payWay.toString()); + throw new MallinkException(ErrorCode.BILL_ROUTINE_IS_NOT_FOUND); + } + Map bill; + //获取账单数据 + if(bills.size()>0){ + bill = bills.get(0); + }else{ + logger.error("pay bill, bill not allow, repaymentReq: " + record.toString() + ", payWay: " + payWay.toString()); + throw new MallinkException(ErrorCode.BILL_ROUTINE_IS_NOT_FOUND); + } + + WxPayAccountBill payAccount = wxPayAccountBillMapper.selectByPrimaryKey(appInfo.getPayBillId()); + + // 2. check 是否有支付订单 + Date currentDate = new Date(); + record.setPayBillStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); + List list = wxPayBillMapper.findList(record); + String payBillNo; + if (list.size() <= 0) { + // 3. 创建支付订单 + Long id = idworker.nextId(); + payBillNo = String.valueOf(id); + record.setId(id); + record.setTenantId(appInfo.getTenantId()); + record.setbUserId(record.getbUserId()); + record.setCreateTime(currentDate); + record.setUpdateTime(currentDate); + record.setPayTimeStart(currentDate); + record.setPayTimeEnd(currentDate); + // 支付单号 + record.setPayBillNo(payBillNo); + record.setPayAmount((Integer) bill.get("owe")); + record.setPayVendor(EnumPayWay.PAY_WAY_WEAPP.getCode()); + record.setPayBillStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); + record.setShare(isShare.getCode()); + + int sqlRow = wxPayBillMapper.insertSelective(record); + if (sqlRow != 1) { + logger.error("pay bill insert error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + } else { + record = list.get(0); + record.setShare(isShare.getCode()); + payBillNo = String.valueOf(record.getId()); + } + + + if (isReal) { + // 微信实际支付 + if (payAccount.getType().equals(EnumPayMode.MCH.getCode())) { + // 统一下单 普通商户模式 + String noncestr = Utility.generate32UUID(); + WxPayOrderP wxPayBillP = new WxPayOrderP(); + wxPayBillP.setOpenid(record.getOpenId()); + wxPayBillP.setAppid(appInfo.getAppId()); + wxPayBillP.setMch_id(payAccount.getMchId()); + wxPayBillP.setNonce_str(noncestr); + wxPayBillP.setBody(bill.get("billType").toString()); + wxPayBillP.setOut_trade_no(record.getPayBillNo()); + wxPayBillP.setTotal_fee((Integer) bill.get("owe")); + // 终端IP + wxPayBillP.setSpbill_create_ip(record.getIp()); + wxPayBillP.setNotify_url(payAccount.getPayNotifyUrl()); + // 终端类型 + wxPayBillP.setTrade_type(WxPay.TradeType.JSAPI.name()); + // 订单ID + wxPayBillP.setProduct_id(bill.get("id").toString()); + wxPayBillP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate)); + Date futureDate = new Date(); + futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000); + // 15分钟后结束 + wxPayBillP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); + Map payBillMap = BeanUtils.toStringMap(wxPayBillP); + wxPayBillP.setSign(WxPayment.createSign(payBillMap, payAccount.getApiKey())); + String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayBillP)); + logger.info("pay bill, wechat pushBill, " + wxPayBillP.toString() + ", response: " + response); + Map returnMap = WxPayment.xmlToMap(response); + returnMap.put("payBillId", payBillNo); + String result_code = returnMap.get("result_code"); + if ("SUCCESS".equals(result_code)) { + String prepay_id = returnMap.get("prepay_id"); + // update payBill with prepay_id + record.setPrepayId(prepay_id); + record.setUpdateTime(new Date()); + try { + wxPayBillMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay bill update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + + String timestamp = String.valueOf(Utility.getCurrentTimeStamp()); + Map sighMap = MapUtil.getOrderMap(); + sighMap.put("appId", returnMap.get("appid")); + sighMap.put("timeStamp", timestamp); + sighMap.put("nonceStr", noncestr); + sighMap.put("package", "prepay_id=" + prepay_id); + sighMap.put("signType", "MD5"); + String signAgent = WxPayment.createSign(sighMap, payAccount.getApiKey()); + returnMap.put("timeStamp", timestamp); + returnMap.put("nonceStr", noncestr); + returnMap.put("package", "prepay_id=" + prepay_id); + returnMap.put("paySign", signAgent); + logger.info("back to UI: " + returnMap.toString()); + return new ResultData(Result.SUCCESS, "创建支付订单成功", returnMap); + } else { + return updatePayBill(record, returnMap, result_code); + } + } else { + // 统一下单 // 服务商模式 + String noncestr = Utility.generate32UUID(); + WxPayOrderSP wxPayBillSP = new WxPayOrderSP(); + wxPayBillSP.setSub_openid(record.getOpenId()); + wxPayBillSP.setAppid(appInfo.getParentAppId()); + wxPayBillSP.setMch_id(payAccount.getMchId()); + wxPayBillSP.setSub_appid(appInfo.getAppId()); + wxPayBillSP.setSub_mch_id(payAccount.getSubMchId()); + wxPayBillSP.setNonce_str(noncestr); + wxPayBillSP.setBody(bill.get("billType").toString()); + wxPayBillSP.setOut_trade_no(record.getPayBillNo()); + wxPayBillSP.setTotal_fee((Integer) bill.get("owe")); + wxPayBillSP.setSpbill_create_ip(record.getIp()); // 终端IP + wxPayBillSP.setNotify_url(payAccount.getPayNotifyUrl()); + wxPayBillSP.setTrade_type(WxPay.TradeType.JSAPI.name()); // 终端类型 + wxPayBillSP.setProduct_id(String.valueOf(bill.get("id").toString())); // 订单ID + wxPayBillSP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate)); + Date futureDate = new Date(); + futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000); + wxPayBillSP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); // 15分钟后结束 + wxPayBillSP.setSign_type("HMAC-SHA256"); + wxPayBillSP.setProfit_sharing(null); + if (isShare == EnumPayShare.YES) { + wxPayBillSP.setProfit_sharing("Y"); + } + Map payBillMap = BeanUtils.toStringMap(wxPayBillSP); + + wxPayBillSP.setSign(WxPayment.createSignHMAC(payBillMap, payAccount.getApiKey())); + String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayBillSP)); + logger.info("pay bill, wechat pushBill, " + wxPayBillSP.toString() + ", response: " + response.toString()); + Map returnMap = WxPayment.xmlToMap(response); + returnMap.put("payBillId", payBillNo); + String result_code = returnMap.get("result_code"); + if ("SUCCESS".equals(result_code)) { + String prepay_id = returnMap.get("prepay_id"); + // update payBill with prepay_id + record.setPrepayId(prepay_id); + record.setUpdateTime(new Date()); + try { + wxPayBillMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay bill update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + + String timestamp = String.valueOf(Utility.getCurrentTimeStamp()); + Map sighMap = MapUtil.getOrderMap(); + sighMap.put("appId", appInfo.getAppId()); + sighMap.put("timeStamp", timestamp); + sighMap.put("nonceStr", noncestr); + sighMap.put("package", "prepay_id=" + prepay_id); + sighMap.put("signType", "HMAC-SHA256"); + String signAgent = WxPayment.createSignHMAC(sighMap, payAccount.getApiKey()); + returnMap.put("timeStamp", timestamp); + returnMap.put("nonceStr", noncestr); + returnMap.put("package", "prepay_id=" + prepay_id); + returnMap.put("paySign", signAgent); + returnMap.put("signType", "HMAC-SHA256"); + logger.info("back to UI: " + returnMap.toString()); + return new ResultData(Result.SUCCESS, "创建支付订单成功", returnMap); + } else { + return updatePayBill(record, returnMap, result_code); + } + } + } else { + // 虚拟支付 + WxPayOrderP wxPayBillP = new WxPayOrderP(); + wxPayBillP.setOpenid(record.getOpenId()); + wxPayBillP.setAppid(appInfo.getAppId()); + wxPayBillP.setMch_id(payAccount.getMchId()); + wxPayBillP.setBody(bill.get("billType").toString()); + wxPayBillP.setOut_trade_no(record.getPayBillNo()); + wxPayBillP.setTotal_fee((Integer) bill.get("owe")); + // 终端IP + wxPayBillP.setSpbill_create_ip(record.getIp()); + wxPayBillP.setNotify_url(payAccount.getPayNotifyUrl()); + // 终端类型 + wxPayBillP.setTrade_type(WxPay.TradeType.JSAPI.name()); + // 订单ID + wxPayBillP.setProduct_id(bill.get("id").toString()); + wxPayBillP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate)); + Date futureDate = new Date(); + futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000); + // 15分钟后结束 + wxPayBillP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); + wxPayBillP.setSign(WxPayment.createSign(BeanUtils.toStringMap(wxPayBillP), payAccount.getApiKey())); + Map returnMap = BeanUtils.toStringMap(wxPayBillP); + return new ResultData(Result.SUCCESS, "创建支付订单成功", returnMap); + } + } catch (RuntimeException e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } catch (Exception e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } + } + + private ResultData updatePayBill(WxPayBill record, Map returnMap, String result_code) { + String errMsg = ""; + JSONObject errObj = errorMap.getJSONObject(result_code); + if (errObj != null) { + errMsg = errObj.toJSONString(); + record.setFailReason(errMsg); + } else { + errMsg = returnMap.get("return_msg"); + record.setFailReason(errMsg); + } + record.setUpdateTime(new Date()); + try { + wxPayBillMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay bill update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap); + } + + + private String wechatPayBillQuery(WxAppinfo appInfo, WxPayBill record) { + // get payAccount + WxPayAccountBill payAccount = wxPayAccountBillMapper.selectByPrimaryKey(appInfo.getPayBillId()); + if (payAccount.getType().equals(EnumPayMode.MCH.getCode())) { + // 普通商户号模式 + WxPayOrderQ payBillQ = new WxPayOrderQ(); + String noncestr = Utility.generate32UUID(); + payBillQ.setAppid(appInfo.getAppId()); + payBillQ.setMch_id(payAccount.getMchId()); + payBillQ.setNonce_str(noncestr); + payBillQ.setOut_trade_no(record.getPayBillNo()); + + try { + Map map = BeanUtils.toStringMap(payBillQ); + payBillQ.setSign(WxPayment.createSign(map, payAccount.getApiKey())); + map = BeanUtils.toStringMap(payBillQ); + String response = WxPay.orderQuery(map); + return response; + } catch (RuntimeException e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } catch (Exception e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } + } else { + // 服务商模式 + WxPayOrderSQ payBillSQ = new WxPayOrderSQ(); + String noncestr = Utility.generate32UUID(); + payBillSQ.setAppid(appInfo.getParentAppId()); + payBillSQ.setSub_appid(appInfo.getAppId()); + payBillSQ.setMch_id(payAccount.getMchId()); + payBillSQ.setSub_mch_id(payAccount.getSubMchId()); + payBillSQ.setNonce_str(noncestr); + payBillSQ.setOut_trade_no(record.getPayBillNo()); + payBillSQ.setSign_type("HMAC-SHA256"); + + try { + Map map = BeanUtils.toStringMap(payBillSQ); + payBillSQ.setSign(WxPayment.createSignHMAC(map, payAccount.getApiKey())); + map = BeanUtils.toStringMap(payBillSQ); + + String response = WxPay.orderQuery(map); + return response; + } catch (RuntimeException e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } catch (Exception e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } + } + } + + /** + * 微信订单查询 + */ + @Override + public ResultData payBillQuery(WxAppinfo appInfo, WxPayBill record) { + try { + if (StringUtils.isBlank(record.getPayBillNo())){ + record.setPayBillNo(String.valueOf(record.getId())); + } + + String response = wechatPayBillQuery(appInfo, record); + + logger.info("pay bill query, " + record.toString() + ", response: " + response); + Map returnMap = WxPayment.xmlToMap(response); + String result_code = returnMap.get("result_code"); + if ("SUCCESS".equals(result_code)) { + String trade_state = returnMap.get("trade_state"); + //SUCCESS—支付成功 + //REFUND—转入退款 + //NOTPAY—未支付 + //CLOSED—已关闭 + //REVOKED—已撤销(刷卡支付) + //USERPAYING--用户支付中 + //PAYERROR--支付失败(其他原因,如银行返回失败) + if ("SUCCESS".equals(trade_state)) { + record.setPayBillStatus(EnumPayStatus.PAY_WAY_SUCCESS.getCode()); + handlePayBillStatusUpdate(record); + } else if ("USERPAYING".equals(trade_state)) { + record.setPayBillStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); + handlePayBillStatusUpdate(record); + } else { + record.setPayBillStatus(EnumPayStatus.PAY_WAY_FAIL.getCode()); + handlePayBillStatusUpdate(record); + } + return new ResultData(Result.SUCCESS, "订单查询成功", returnMap); + } else { + return updatePayBill(record, returnMap, result_code); + } + } catch (MallinkException e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } catch (RuntimeException e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } catch (Exception e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } + } + + private String wechatPayBillClose(WxAppinfo appInfo, WxPayBill record) { + // get payAccount + WxPayAccountBill payAccount = wxPayAccountBillMapper.selectByPrimaryKey(appInfo.getPayBillId()); + if (payAccount.getType().equals(EnumPayMode.MCH.getCode())) { + // 普通商户号模式 + WxPayOrderQ payBillC = new WxPayOrderQ(); + String noncestr = Utility.generate32UUID(); + payBillC.setAppid(appInfo.getAppId()); + payBillC.setMch_id(payAccount.getMchId()); + payBillC.setNonce_str(noncestr); + payBillC.setOut_trade_no(record.getPayBillNo()); + return closeOrderNormal(payAccount, payBillC); + } else { + // 服务商模式 + WxPayOrderSQ payBillSC = new WxPayOrderSQ(); + String noncestr = Utility.generate32UUID(); + payBillSC.setAppid(appInfo.getParentAppId()); + payBillSC.setSub_appid(appInfo.getAppId()); + payBillSC.setMch_id(payAccount.getMchId()); + payBillSC.setSub_mch_id(payAccount.getSubMchId()); + payBillSC.setNonce_str(noncestr); + payBillSC.setOut_trade_no(record.getPayBillNo()); + payBillSC.setSign_type("HMAC-SHA256"); + return closeOrderServer(payAccount, payBillSC); + } + } + + private String closeOrderServer(WxPayAccountBill payAccount, WxPayOrderSQ payBillSC) { + try { + Map map = BeanUtils.toStringMap(payBillSC); + payBillSC.setSign(WxPayment.createSignHMAC(map, payAccount.getApiKey())); + map = BeanUtils.toStringMap(payBillSC); + String response = WxPay.closeOrder(map); + return response; + } catch (RuntimeException e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } catch (Exception e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } + } + + private String closeOrderNormal(WxPayAccountBill payAccount, WxPayOrderQ payBillC) { + try { + Map map = BeanUtils.toStringMap(payBillC); + payBillC.setSign(WxPayment.createSign(map, payAccount.getApiKey())); + map = BeanUtils.toStringMap(payBillC); + String response = WxPay.closeOrder(map); + return response; + } catch (RuntimeException e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } catch (Exception e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } + } + + /** + * 微信关闭支付订单 + */ + @Override + public ResultData payBillClose(WxAppinfo appInfo, WxPayBill record) { + + try { + String response = wechatPayBillClose(appInfo, record); + + logger.info("pay bill close, " + record.toString() + ", response: " + response); + Map returnMap = WxPayment.xmlToMap(response); + String result_code = returnMap.get("result_code"); + if ("SUCCESS".equals(result_code)) { + record.setPayBillStatus(EnumPayStatus.PAY_WAY_CANCEL.getCode()); + handlePayBillStatusUpdate(record); + return new ResultData(Result.SUCCESS, "订单关闭成功", returnMap); + } else { + String errMsg = ""; + JSONObject errObj = errorMapClose.getJSONObject(result_code); + if (errObj != null) { + errMsg = errObj.toJSONString(); + } else { + errMsg = returnMap.get("return_msg"); + } + record.setFailReason(errMsg); + record.setUpdateTime(new Date()); + try { + wxPayBillMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay bill update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap); + } + } catch (RuntimeException e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } catch (Exception e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } + } + + + /** + * 提供微信支付回调调用 + * + * @param paramMap 异步通知参数 + * @param payWay 支付方式 + * @return + */ + @Override + public String notify(Map paramMap, EnumPayWay payWay) { + // how to get wechatAppId, wechatMchId, partnerKey + String appId = paramMap.get("appid"); + String subAppId = paramMap.get("sub_appid"); + String mchId = paramMap.get("mch_id"); + String subMchId = paramMap.get("sub_mch_id"); + WxAppinfo appinfo = null; + boolean isNormal = true; + if (StringUtils.isBlank(subAppId) && StringUtils.isBlank(subMchId)) { + // 普通商户号 + appinfo = wxAppinfoMapper.findByAppId(appId); + if (appinfo == null) { + throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); + } + isNormal = true; + } else { + // 服务号 现在用hmac-sha256 + appinfo = wxAppinfoMapper.findByAppId(subAppId); + if (appinfo == null) { + throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); + } + isNormal = false; + } + + WxPayAccountBill payAccount = wxPayAccountBillMapper.selectByPrimaryKey(appinfo.getPayBillId()); + if (payAccount == null) { + throw new MallinkException(ErrorCode.MCH_INFO_NOT_FOUND); + } + String partnerKey = payAccount.getApiKey(); + try { + if (payWay == EnumPayWay.PAY_WAY_WEAPP) { + boolean signVerified = false; + if (isNormal) { + // 普通商户号支付 + signVerified = WxPayment.verifyNotify(paramMap, partnerKey); + if (!signVerified) { + logger.warn("notify bill, wxpay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR); + } + } else { + // 服务号 现在用hmac-sha256 + signVerified = WxPayment.verifyNotifyHMAC(paramMap, partnerKey); + if (!signVerified) { + logger.warn("notify bill, wxpay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR); + } + } + + if (!"SUCCESS".equals(paramMap.get("return_code"))) { + logger.warn("notify bill, wxpay status not success, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", "订单状态码非SUCCESS"); + return XmlUtil.getRequestXml(resultMap); + } + + String payBillNo = paramMap.get("out_trade_no"); + String timEndStr = paramMap.get("time_end"); + Long payBillId = Long.valueOf(payBillNo); + WxPayBill payBill = wxPayBillMapper.selectByPrimaryKey(payBillId); + if (payBill == null) { + logger.warn("notify bill, wxpay check pay bill not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", "订单不存在"); + return XmlUtil.getRequestXml(resultMap); + } + // 验证支付金额 + if (!paramMap.get("total_fee").equals(payBill.getPayAmount().toString())) { + logger.warn("notify bill, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", "订单总金额不一致"); + return XmlUtil.getRequestXml(resultMap); + } + + Date timeEnd = null; + + try { + timeEnd = Utility.getDateFromString(timEndStr); + } catch (ParseException e) { + logger.error("解析timeEnd失败"); + timeEnd = new Date(); + } + payBill.setPayTimeEnd(timeEnd); + + // 处理支付成功 + handleBillPaySuccess(payBill, paramMap.get("transaction_id")); + logger.info("notify bill, wxpay checksign success, paramMap:{}, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "SUCCESS"); + resultMap.put("return_msg", "OK"); + return XmlUtil.getRequestXml(resultMap); + } + } catch (RuntimeException e) { + logger.warn("notify bill, checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage()); + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR); + } + + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", "FAILED"); + return XmlUtil.getRequestXml(resultMap); + } + + @Override + public void callback(Map paramMap, EnumPayWay payWay) { + + } + + @Override + public WxPayBill getById(Long id) { + return wxPayBillMapper.selectByPrimaryKey(id); + } + + @Override + @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) + public void handleBillPaySuccess(WxPayBill record, String transactionId) { + Date currentDate = new Date(); + EnumPayStatus payStatus = EnumPayStatus.getEnum(record.getPayBillStatus()); + // 判断支付状态 + if (payStatus == EnumPayStatus.PAY_WAY_SUCCESS) { + // 已经是成功状态,只更新transactionId + try { + record.setUpdateTime(currentDate); + record.setTransactionId(transactionId); + wxPayBillMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return; + } + if (payStatus != EnumPayStatus.PAY_WAY_WAIT) { + logger.error("pay success handle, payBill " + record.getPayBillNo() + + "is paid success , billId : " + record.getBillId()); + return; + } + WxBillAll wxBillAll = new WxBillAll(); + wxBillAll.setId(record.getBillId()); + List> bills = wxBillAllMapper.listData(wxBillAll); + if (bills == null) { + logger.error("pay success handle, bill " + record.getBillId() + " not found , payBillNo : " + record.getPayBillNo()); + throw new MallinkException(ErrorCode.BILL_ROUTINE_IS_NOT_FOUND); + } + Map bill=null; + if(bills.size()>0){ + bill = bills.get(0); + }else{ + logger.error("pay success handle, bill " + record.getBillId() + " not found , payBillNo : " + record.getPayBillNo()); + throw new MallinkException(ErrorCode.BILL_ROUTINE_IS_NOT_FOUND); + } + + // 修改支付订单状态 + WxPayBill updateBill = new WxPayBill(); + updateBill.setId(record.getId()); + updateBill.setBillId(record.getBillId()); + updateBill.setUpdateTime(currentDate); + updateBill.setPayBillStatus(EnumPayStatus.PAY_WAY_SUCCESS.getCode()); + updateBill.setTransactionId(transactionId); + try { + wxPayBillMapper.updateByPrimaryKeySelective(updateBill); + } catch (Exception e) { + logger.error("支付订单数据库更新失败: " + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "支付订单数据库更新失败: " + e.getMessage()); + } + + //修改账单状态 + try { + int _count = wxBillAllService.updateBill(bill); + if (_count > 1) { + throw new MallinkException(ErrorCode.BILL_UPDATE_FAILED); + } + } catch (Exception e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "账单更新"); + } + + } + + @Override + @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) + public void handlePayBillStatusUpdate(WxPayBill record) { + // 判断支付状态 + if (record.getPayBillStatus().equals(EnumPayStatus.PAY_WAY_WAIT.getCode())) { + logger.error("pay handle, payBill " + record.getPayBillNo() + + "is complete, billId : " + record.getBillId()); + return; + } + WxBillAll wxBillAll = new WxBillAll(); + wxBillAll.setId(record.getBillId()); + List> bills = wxBillAllMapper.listData(wxBillAll); + if (bills == null) { + logger.error("pay handle, bill " + record.getBillId() + " not found , payBillGid : " + record.getPayBillNo()); + throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND); + } + WxMerchantBUser user = wxMerchantBUserMapper.selectByPrimaryKey(record.getbUserId()); + if (user == null) { + logger.error("pay handle, bill " + record.getBillId() + " not found , payBillGid : " + record.getPayBillNo()); + throw new MallinkException(ErrorCode.BUSER_NOT_IN_APP); + } + Map bill = bills.get(0); + Integer owe = (Integer) bill.get("owe"); + if (owe > 0) { + // 订单金额不为0时, 支付订单未创建, 返回异常 + if (!(record.getId() >0)) { + throw new MallinkException(ErrorCode.PAY_ORDER_NOT_FOUND); + } + } + + Date currentDate = new Date(); + if (record.getId() > 0) { + // 1. get appinfo + WxAppinfo appInfo = null; + WxAppinfo appinfoQ = new WxAppinfo(); + appinfoQ.setTenantId(bill.get("tenantId").toString()); + appinfoQ.setType(EnumAppType.B.getCode()); + List appList = wxAppinfoMapper.select(appinfoQ); + if (appList.size() > 0) { + appInfo = appList.get(0); + } + + WxPayBill updateBill = null; + + // 检查支付订单状态 + WxPayBill payBillQ = new WxPayBill(); + payBillQ.setId(record.getId()); + payBillQ.setTenantId(bill.get("tenantId").toString()); + payBillQ.setBillId(record.getBillId()); + try { + updateBill = wxPayBillMapper.selectOne(payBillQ); + } catch (Exception e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.PAY_ORDER_NOT_FOUND); + } + + if (record.getPayBillStatus().equals(EnumPayStatus.PAY_WAY_CANCEL.getCode())) { + // 支付订单取消 + if (record.getPayAmount() > 0) { + payBillQ = new WxPayBill(); + payBillQ.setTenantId(bill.get("tenantId").toString()); + payBillQ.setBillId(record.getBillId()); + payBillQ.setPayBillStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); + List payBills = wxPayBillMapper.select(payBillQ); + for (WxPayBill payBill : payBills) { + payBillClose(appInfo, payBill); + } + } + } else { + // 支付订单成功? + if (updateBill.getPayBillStatus().equals(EnumPayStatus.PAY_WAY_SUCCESS.getCode())) { + if (StringUtils.isBlank(updateBill.getTransactionId())) { + // 回调已设置成功 + // 继续修改订单状态 + } else { + // 回调异常 + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), "transactionId未获取"); + } + } else if (updateBill.getPayBillStatus().equals(EnumPayStatus.PAY_WAY_WAIT.getCode())) { + // 回调未返回,主动检查支付订单状态 + try { + record.setPayBillNo(String.valueOf(record.getId())); + String response = wechatPayBillQuery(appInfo, record); + + logger.info("pay bill query, " + record.toString() + ", response: " + response); + Map returnMap = WxPayment.xmlToMap(response); + String result_code = returnMap.get("result_code"); + if ("SUCCESS".equals(result_code)) { + String trade_state = returnMap.get("trade_state"); + //SUCCESS—支付成功 + //REFUND—转入退款 + //NOTPAY—未支付 + //CLOSED—已关闭 + //REVOKED—已撤销(刷卡支付) + //USERPAYING--用户支付中 + //PAYERROR--支付失败(其他原因,如银行返回失败) + if ("SUCCESS".equals(trade_state)) { + // 查询支付订单 -- 已支付 + // 继续更改状态 + } else { + // 支付订单未成功,返回异常 + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), "支付订单未成功"); + } + } + } catch (MallinkException e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } catch (RuntimeException e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } catch (Exception e) { + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); + } + } + } + } + + // 修改账单状态 + if (record.getPayBillStatus().equals(EnumPayStatus.PAY_WAY_SUCCESS.getCode())) { + try { + int _count = wxBillAllService.updateBill(bill); + if (_count > 1) { + throw new MallinkException(ErrorCode.ORDER_IS_FAIL); + } + } catch (Exception e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "账单更新"); + } + } + } + + +} diff --git a/mallinkService/src/main/resources/mapper/WxAppinfoMapper.xml b/mallinkService/src/main/resources/mapper/WxAppinfoMapper.xml index 3fbd2b4b4..ab0f42105 100644 --- a/mallinkService/src/main/resources/mapper/WxAppinfoMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxAppinfoMapper.xml @@ -16,10 +16,12 @@ + + - `id`,`tenant_id`,`app_id`,`parent_app_id`,`name`,`secret`,`token`,`aes_key`,`msg_data_format`,`access_token`,`last_token_time`,`expires_in`,`pay_id`,`type` + `id`,`tenant_id`,`app_id`,`parent_app_id`,`name`,`secret`,`token`,`aes_key`,`msg_data_format`,`access_token`,`last_token_time`,`expires_in`,`pay_id`,`type`,`pay_bill_id` @@ -78,6 +80,9 @@ and `type` = #{type} + + and `pay_bill_id` = #{payBillId} + and id in diff --git a/mallinkService/src/main/resources/mapper/WxBillAllMapper.xml b/mallinkService/src/main/resources/mapper/WxBillAllMapper.xml index 246cd6d6a..c6e8fff63 100644 --- a/mallinkService/src/main/resources/mapper/WxBillAllMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxBillAllMapper.xml @@ -80,7 +80,7 @@ + select + + from wx_pay_bill + + + +