| @@ -113,6 +113,7 @@ public class ShiroConfig { | |||||
| // } | // } | ||||
| filterChainDefinitionMap.put("/swagger-ui.html", "anon"); | filterChainDefinitionMap.put("/swagger-ui.html", "anon"); | ||||
| filterChainDefinitionMap.put("/wxPay/notify/**", "anon"); | filterChainDefinitionMap.put("/wxPay/notify/**", "anon"); | ||||
| filterChainDefinitionMap.put("/wxPayBill/notify/**", "anon"); | |||||
| filterChainDefinitionMap.put("/v2/**", "anon"); | filterChainDefinitionMap.put("/v2/**", "anon"); | ||||
| filterChainDefinitionMap.put("/swagger-resources/**", "anon"); | filterChainDefinitionMap.put("/swagger-resources/**", "anon"); | ||||
| filterChainDefinitionMap.put("/webjars/**", "anon"); | filterChainDefinitionMap.put("/webjars/**", "anon"); | ||||
| @@ -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<String, String> 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<String, String> 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<String, String> 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); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -79,7 +79,11 @@ public class WxBillController extends BaseController { | |||||
| if(wxMerchant.getStatus().equals(EnumMerchantStatus.NOT_VALID.getCode())){ | if(wxMerchant.getStatus().equals(EnumMerchantStatus.NOT_VALID.getCode())){ | ||||
| return new ResultData(ErrorCode.MERCHANT_INFO_NOT_VALID); | 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("开始时间和结束时间要同时存在或不存在"); | logger.info("开始时间和结束时间要同时存在或不存在"); | ||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"starttime和endtime要同时存在或不存在"); | return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"starttime和endtime要同时存在或不存在"); | ||||
| } | } | ||||
| @@ -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<String, String> 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<String, Object> 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()); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -274,7 +274,7 @@ public enum ErrorCode{ | |||||
| * 日常费用账单 | * 日常费用账单 | ||||
| * */ | * */ | ||||
| BILL_ROUTINE_IS_NOT_FOUND(21000,"账单不存在"), | BILL_ROUTINE_IS_NOT_FOUND(21000,"账单不存在"), | ||||
| BILL_UPDATE_FAILED(21001,"账单更新失败"), | |||||
| /** | /** | ||||
| * 商铺 | * 商铺 | ||||
| * */ | * */ | ||||
| @@ -79,6 +79,16 @@ public class WxAppinfo implements Serializable { | |||||
| private Long payId; | private Long payId; | ||||
| @io.swagger.annotations.ApiModelProperty(value="1B端2C端",name="type") | @io.swagger.annotations.ApiModelProperty(value="1B端2C端",name="type") | ||||
| private Integer 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() { | public String getTenantId() { | ||||
| return tenantId; | return tenantId; | ||||
| @@ -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<Long> 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<Long> getIds() { | |||||
| return ids; | |||||
| } | |||||
| public void setIds(List<Long> 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<Field> 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)); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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<Long> 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<Long> getIds() { | |||||
| return ids; | |||||
| } | |||||
| public void setIds(List<Long> 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<Field> 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)); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -47,6 +47,16 @@ public class WxBillAll { | |||||
| @io.swagger.annotations.ApiModelProperty(value="条数",name="pageSize") | @io.swagger.annotations.ApiModelProperty(value="条数",name="pageSize") | ||||
| private Integer 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() { | public String getAppId() { | ||||
| return appId; | return appId; | ||||
| @@ -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<WxPayAccountBill, Long> { | |||||
| List<WxPayAccountBill> findList(WxPayAccountBill wxPayAccount); | |||||
| } | |||||
| @@ -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<WxPayBill, Long> { | |||||
| List<WxPayBill> findList(WxPayBill wxPayBill); | |||||
| } | |||||
| @@ -17,4 +17,6 @@ public interface WxBillAllService { | |||||
| ResultData listBill(WxBillAll wxBillAll); | ResultData listBill(WxBillAll wxBillAll); | ||||
| int updateBill(Map<String,Object> bill); | |||||
| } | } | ||||
| @@ -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<String, String> 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<String, String> paramMap, EnumPayWay payWay); | |||||
| WxPayBill getById(Long payBillId); | |||||
| } | |||||
| @@ -6,22 +6,20 @@ import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.ResultData; | import com.iformall.common.ResultData; | ||||
| import com.iformall.domain.po.*; | import com.iformall.domain.po.*; | ||||
| import com.iformall.domain.vo.WxBillAll; | import com.iformall.domain.vo.WxBillAll; | ||||
| import com.iformall.enums.EnumBillDailyStatus; | |||||
| import com.iformall.enums.EnumBillRentStatus; | import com.iformall.enums.EnumBillRentStatus; | ||||
| import com.iformall.enums.EnumBillType; | import com.iformall.enums.EnumBillType; | ||||
| import com.iformall.enums.EnumBillTypeParam; | 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.service.*; | ||||
| import com.iformall.utils.DateUtils; | import com.iformall.utils.DateUtils; | ||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| 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 java.util.ArrayList; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import java.util.*; | |||||
| /** | /** | ||||
| * @author gongbiao | * @author gongbiao | ||||
| @@ -51,6 +49,25 @@ public class WxBillAllServiceImpl implements WxBillAllService { | |||||
| @Autowired | @Autowired | ||||
| WxBillOtherService wxBillOtherService; | WxBillOtherService wxBillOtherService; | ||||
| @Autowired | |||||
| WxBillDailyMapper wxBillDailyMapper; | |||||
| @Autowired | |||||
| WxBillDepositMapper wxBillDepositMapper; | |||||
| @Autowired | |||||
| WxBillPropertyDepositMapper wxBillPropertyDepositMapper; | |||||
| @Autowired | |||||
| WxBillPropertyMapper wxBillPropertyMapper; | |||||
| @Autowired | |||||
| WxBillRentMapper wxBillRentMapper; | |||||
| @Autowired | |||||
| WxBillOtherMapper wxBillOtherMapper; | |||||
| @Override | @Override | ||||
| public Map<String, Object> listAsPage(WxBillAll record, Integer pageIndex, Integer pageSize) { | public Map<String, Object> listAsPage(WxBillAll record, Integer pageIndex, Integer pageSize) { | ||||
| //更新各账单状态 | //更新各账单状态 | ||||
| @@ -89,7 +106,7 @@ public class WxBillAllServiceImpl implements WxBillAllService { | |||||
| //更新各账单状态 | //更新各账单状态 | ||||
| updateBillStatus(wxBillAll); | updateBillStatus(wxBillAll); | ||||
| //账单类型 | //账单类型 | ||||
| if(wxBillAll.getBillTypeValue()!=null){ | |||||
| if (wxBillAll.getBillTypeValue() != null) { | |||||
| if (wxBillAll.getBillTypeValue().equals(EnumBillType.RENT.getCode())) { | if (wxBillAll.getBillTypeValue().equals(EnumBillType.RENT.getCode())) { | ||||
| wxBillAll.setBillTypeValue(EnumBillTypeParam.RENT.getCode()); | wxBillAll.setBillTypeValue(EnumBillTypeParam.RENT.getCode()); | ||||
| } else if (wxBillAll.getBillTypeValue().equals(EnumBillType.DEPOSIT.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); | 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()); | PageHelper.startPage(wxBillAll.getPageIndex(), wxBillAll.getPageSize()); | ||||
| List<Map<String, Object>> maps = wxBillAllMapper.listData(wxBillAll); | List<Map<String, Object>> maps = wxBillAllMapper.listData(wxBillAll); | ||||
| PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(maps); | PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(maps); | ||||
| @@ -121,6 +138,160 @@ public class WxBillAllServiceImpl implements WxBillAllService { | |||||
| return new ResultData(maps); | return new ResultData(maps); | ||||
| } | } | ||||
| @Override | |||||
| public int updateBill(Map<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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) { | private void updateBillStatus(WxBillAll record) { | ||||
| logger.info("更新各账单状态开始"); | logger.info("更新各账单状态开始"); | ||||
| //更新其他账单 | //更新其他账单 | ||||
| @@ -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<Map<String, Object>> 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<String, Object> 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<WxPayBill> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<Map<String, Object>> 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<String, Object> 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<Map<String, Object>> 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<String, Object> 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<WxAppinfo> 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<WxPayBill> 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<String, String> 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(), "账单更新"); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -16,10 +16,12 @@ | |||||
| <result column="expires_in" jdbcType="INTEGER" property="expiresIn"/> | <result column="expires_in" jdbcType="INTEGER" property="expiresIn"/> | ||||
| <result column="pay_id" jdbcType="BIGINT" property="payId"/> | <result column="pay_id" jdbcType="BIGINT" property="payId"/> | ||||
| <result column="type" jdbcType="INTEGER" property="type"/> | <result column="type" jdbcType="INTEGER" property="type"/> | ||||
| <result column="pay_bill_id" jdbcType="BIGINT" property="payBillId"/> | |||||
| </resultMap> | </resultMap> | ||||
| <sql id="allColumns"> | <sql id="allColumns"> | ||||
| `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` | |||||
| </sql> | </sql> | ||||
| <sql id="dynamicWhereConditions"> | <sql id="dynamicWhereConditions"> | ||||
| @@ -78,6 +80,9 @@ | |||||
| <if test=" null != type "> | <if test=" null != type "> | ||||
| and `type` = #{type} | and `type` = #{type} | ||||
| </if> | </if> | ||||
| <if test=" null != payBillId "> | |||||
| and `pay_bill_id` = #{payBillId} | |||||
| </if> | |||||
| <if test=" null != ids "> | <if test=" null != ids "> | ||||
| and id in | and id in | ||||
| <foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")"> | <foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")"> | ||||
| @@ -80,7 +80,7 @@ | |||||
| <select id="listData" resultType="hashmap" parameterType="com.iformall.domain.vo.WxBillAll"> | <select id="listData" resultType="hashmap" parameterType="com.iformall.domain.vo.WxBillAll"> | ||||
| select bill.id,bill.merchant_id merchantId,bill.shop_id shopId,bill.bill_type_value billTypeValue,bill.bill_type billType,bill.need_pay needPay, | select bill.id,bill.merchant_id merchantId,bill.shop_id shopId,bill.bill_type_value billTypeValue,bill.bill_type billType,bill.need_pay needPay, | ||||
| bill.receive_pay receivePay,bill.pay,bill.owe,bill.receive_date receiveDate,bill.pay_date payDate,bill.expired_day expiredDay,bill.status, | bill.receive_pay receivePay,bill.pay,bill.owe,bill.receive_date receiveDate,bill.pay_date payDate,bill.expired_day expiredDay,bill.status, | ||||
| bill.tenant_id tenantId,m.name merchantName,s.shop_number shopNumber,bill.starttime,bill.endtime,bill.name from ( | |||||
| bill.tenant_id tenantId,m.name merchantName,s.shop_number shopNumber,bill.starttime,bill.endtime,bill.name,pb.pay_bill_status payBillStatus from ( | |||||
| select id,merchant_id,shop_id,tenant_id,'租金' name,1 bill_type_value,'租金' bill_type,need_pay,receive_pay,pay,owe,receive_date,pay_date,expired_day,status,starttime,endtime from wx_bill_rent | select id,merchant_id,shop_id,tenant_id,'租金' name,1 bill_type_value,'租金' bill_type,need_pay,receive_pay,pay,owe,receive_date,pay_date,expired_day,status,starttime,endtime from wx_bill_rent | ||||
| union | union | ||||
| select id,merchant_id,shop_id,tenant_id,'租赁押金' name,2 bill_type_value,'租赁押金' bill_type,need_pay,receive_pay,pay,owe,receive_date,pay_date,expired_day,status,starttime,endtime from wx_bill_rent_deposit | select id,merchant_id,shop_id,tenant_id,'租赁押金' name,2 bill_type_value,'租赁押金' bill_type,need_pay,receive_pay,pay,owe,receive_date,pay_date,expired_day,status,starttime,endtime from wx_bill_rent_deposit | ||||
| @@ -97,6 +97,7 @@ | |||||
| ) bill | ) bill | ||||
| left join wx_merchant m on bill.merchant_id=m.id | left join wx_merchant m on bill.merchant_id=m.id | ||||
| left join wx_shop s on bill.shop_id=s.id | left join wx_shop s on bill.shop_id=s.id | ||||
| left join wx_pay_bill pb on bill.id=pb.bill_id | |||||
| where bill.tenant_id=#{tenantId} | where bill.tenant_id=#{tenantId} | ||||
| <if test=" null != merchantId "> | <if test=" null != merchantId "> | ||||
| and bill.merchant_id=#{merchantId} | and bill.merchant_id=#{merchantId} | ||||
| @@ -0,0 +1,120 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||||
| <mapper namespace="com.iformall.mapper.WxPayBillMapper"> | |||||
| <resultMap id="BaseResultMap" type="com.iformall.domain.po.WxPayBill"> | |||||
| <id column="id" jdbcType="BIGINT" property="id"/> | |||||
| <result column="tenant_id" jdbcType="VARCHAR" property="tenantId"/> | |||||
| <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> | |||||
| <result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/> | |||||
| <result column="bill_id" jdbcType="BIGINT" property="billId"/> | |||||
| <result column="b_user_id" jdbcType="BIGINT" property="bUserId"/> | |||||
| <result column="ip" jdbcType="VARCHAR" property="ip"/> | |||||
| <result column="pay_amount" jdbcType="INTEGER" property="payAmount"/> | |||||
| <result column="pay_time_start" jdbcType="TIMESTAMP" property="payTimeStart"/> | |||||
| <result column="pay_time_end" jdbcType="TIMESTAMP" property="payTimeEnd"/> | |||||
| <result column="prepay_id" jdbcType="VARCHAR" property="prepayId"/> | |||||
| <result column="transaction_id" jdbcType="VARCHAR" property="transactionId"/> | |||||
| <result column="pay_vendor" jdbcType="INTEGER" property="payVendor"/> | |||||
| <result column="pay_bill_no" jdbcType="VARCHAR" property="payBillNo"/> | |||||
| <result column="pay_bill_status" jdbcType="INTEGER" property="payBillStatus"/> | |||||
| <result column="share" jdbcType="INTEGER" property="share"/> | |||||
| <result column="share_amount" jdbcType="INTEGER" property="shareAmount"/> | |||||
| <result column="fail_reason" jdbcType="VARCHAR" property="failReason"/> | |||||
| <result column="open_id" jdbcType="VARCHAR" property="openId"/> | |||||
| </resultMap> | |||||
| <sql id="allColumns"> | |||||
| `id`,`tenant_id`,`create_time`,`update_time`,`bill_id`,`b_user_id`,`ip`,`pay_amount`,`pay_time_start`,`pay_time_end`,`prepay_id`,`transaction_id`,`pay_vendor`,`pay_bill_no`,`pay_bill_status`,`share`,`share_amount`,`fail_reason`,`open_id` | |||||
| </sql> | |||||
| <sql id="dynamicWhereConditions"> | |||||
| where 1 = 1 | |||||
| <if test=" null != id "> | |||||
| and `id` = #{id} | |||||
| </if> | |||||
| <if test=" null != tenantId "> | |||||
| and `tenant_id` = #{tenantId} | |||||
| </if> | |||||
| <if test=" null != createTime "> | |||||
| and `create_time` = #{createTime} | |||||
| </if> | |||||
| <if test=" null != updateTime "> | |||||
| and `update_time` = #{updateTime} | |||||
| </if> | |||||
| <if test=" null != billId "> | |||||
| and `bill_id` = #{billId} | |||||
| </if> | |||||
| <if test=" null != cUserId "> | |||||
| and `b_user_id` = #{bUserId} | |||||
| </if> | |||||
| <if test=" null != ip "> | |||||
| and `ip` like concat('%', #{ip},'%') | |||||
| </if> | |||||
| <if test=" null != payAmount "> | |||||
| and `pay_amount` = #{payAmount} | |||||
| </if> | |||||
| <if test=" null != payTimeStart "> | |||||
| and `pay_time_start` = #{payTimeStart} | |||||
| </if> | |||||
| <if test=" null != payTimeEnd "> | |||||
| and `pay_time_end` = #{payTimeEnd} | |||||
| </if> | |||||
| <if test=" null != prepayId "> | |||||
| and `prepay_d` like concat('%', #{prepayId},'%') | |||||
| </if> | |||||
| <if test=" null != transactionId "> | |||||
| and `transaction_id` like concat('%', #{transactionId},'%') | |||||
| </if> | |||||
| <if test=" null != payVendor "> | |||||
| and `pay_vendor` = #{payVendor} | |||||
| </if> | |||||
| <if test=" null != payBillNo "> | |||||
| and `pay_bill_no` like concat('%', #{payBillNo},'%') | |||||
| </if> | |||||
| <if test=" null != payBillStatus "> | |||||
| and `pay_bill_status` = #{payBillStatus} | |||||
| </if> | |||||
| <if test=" null != share "> | |||||
| and `share` = #{share} | |||||
| </if> | |||||
| <if test=" null != shareAmount "> | |||||
| and `share_amount` = #{shareAmount} | |||||
| </if> | |||||
| <if test=" null != failReason "> | |||||
| and `fail_reason` like concat('%', #{failReason},'%') | |||||
| </if> | |||||
| <if test=" null != openId "> | |||||
| and `open_id` = #{openId} | |||||
| </if> | |||||
| <if test=" null != ids "> | |||||
| and id in | |||||
| <foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")"> | |||||
| #{idItem} | |||||
| </foreach> | |||||
| </if> | |||||
| <if test=" null != sortColumns">order by ${sortColumns}</if> | |||||
| </sql> | |||||
| <select id="findList" parameterType="com.iformall.domain.po.WxPayBill" resultMap="BaseResultMap"> | |||||
| select | |||||
| <include refid="allColumns"/> | |||||
| from wx_pay_bill | |||||
| <include refid="dynamicWhereConditions"/> | |||||
| </select> | |||||
| </mapper> | |||||