Просмотр исходного кода

[B账单][添加][账单支付]

release_toaliyun_real
gongbiao 7 лет назад
Родитель
Сommit
fd744700ce
18 измененных файлов: 2128 добавлений и 12 удалений
  1. +1
    -0
      mallinkAdmin/src/main/java/com/iformall/config/ShiroConfig.java
  2. +183
    -0
      mallinkAdmin/src/main/java/com/iformall/controller/WxPayBillController.java
  3. +5
    -1
      mallinkBApi/src/main/java/com/iformall/controller/WxBillController.java
  4. +152
    -0
      mallinkBApi/src/main/java/com/iformall/controller/WxPayBillController.java
  5. +1
    -1
      mallinkService/src/main/java/com/iformall/common/ErrorCode.java
  6. +10
    -0
      mallinkService/src/main/java/com/iformall/domain/po/WxAppinfo.java
  7. +211
    -0
      mallinkService/src/main/java/com/iformall/domain/po/WxPayAccountBill.java
  8. +300
    -0
      mallinkService/src/main/java/com/iformall/domain/po/WxPayBill.java
  9. +10
    -0
      mallinkService/src/main/java/com/iformall/domain/vo/WxBillAll.java
  10. +20
    -0
      mallinkService/src/main/java/com/iformall/mapper/WxPayAccountBillMapper.java
  11. +14
    -0
      mallinkService/src/main/java/com/iformall/mapper/WxPayBillMapper.java
  12. +2
    -0
      mallinkService/src/main/java/com/iformall/service/WxBillAllService.java
  13. +74
    -0
      mallinkService/src/main/java/com/iformall/service/WxPayBillService.java
  14. +179
    -8
      mallinkService/src/main/java/com/iformall/service/impl/WxBillAllServiceImpl.java
  15. +838
    -0
      mallinkService/src/main/java/com/iformall/service/impl/WxPayBillServiceImpl.java
  16. +6
    -1
      mallinkService/src/main/resources/mapper/WxAppinfoMapper.xml
  17. +2
    -1
      mallinkService/src/main/resources/mapper/WxBillAllMapper.xml
  18. +120
    -0
      mallinkService/src/main/resources/mapper/WxPayBillMapper.xml

+ 1
- 0
mallinkAdmin/src/main/java/com/iformall/config/ShiroConfig.java Просмотреть файл

@@ -113,6 +113,7 @@ public class ShiroConfig {
// }
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/wxPay/notify/**", "anon");
filterChainDefinitionMap.put("/wxPayBill/notify/**", "anon");
filterChainDefinitionMap.put("/v2/**", "anon");
filterChainDefinitionMap.put("/swagger-resources/**", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");


+ 183
- 0
mallinkAdmin/src/main/java/com/iformall/controller/WxPayBillController.java Просмотреть файл

@@ -0,0 +1,183 @@
package com.iformall.controller;

import com.iformall.enums.EnumPayWay;
import com.iformall.exception.BizMessageException;
import com.iformall.exception.MallinkException;
import com.iformall.pay.WxPayment;
import com.iformall.service.WxPayBillService;
import com.iformall.service.WxRefundOrderService;
import com.iformall.utils.XmlUtil;
import org.apache.commons.io.IOUtils;
import org.jdom2.JDOMException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
* @author gongbiao
*/
@RestController
@RequestMapping("/wxPayBill/notify")
public class WxPayBillController extends BaseController {

private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private WxPayBillService wxPayBillService;

@Autowired
private WxRefundOrderService wxRefundOrderService;
/**
*
* @return 接收微信异步通知
* @throws Exception 可能产生的任何异常
*/
@RequestMapping(value = "/pay", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String _payNotify(HttpServletRequest request) throws IOException, JDOMException {
logger.info("微信支付回调");
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
String resultxml = new String(outSteam.toByteArray(), Charset.forName("UTF-8"));
logger.info(resultxml);

outSteam.close();
inStream.close();

Map<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);
}
}
}

+ 5
- 1
mallinkBApi/src/main/java/com/iformall/controller/WxBillController.java Просмотреть файл

@@ -79,7 +79,11 @@ public class WxBillController extends BaseController {
if(wxMerchant.getStatus().equals(EnumMerchantStatus.NOT_VALID.getCode())){
return new ResultData(ErrorCode.MERCHANT_INFO_NOT_VALID);
}
if(StringUtils.isEmpty(wxBillAll.getStarttime()) || StringUtils.isEmpty(wxBillAll.getEndtime())){
if(!StringUtils.isEmpty(wxBillAll.getStarttime()) && StringUtils.isEmpty(wxBillAll.getEndtime())){
logger.info("开始时间和结束时间要同时存在或不存在");
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"starttime和endtime要同时存在或不存在");
}
if(StringUtils.isEmpty(wxBillAll.getStarttime()) && !StringUtils.isEmpty(wxBillAll.getEndtime())){
logger.info("开始时间和结束时间要同时存在或不存在");
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"starttime和endtime要同时存在或不存在");
}


+ 152
- 0
mallinkBApi/src/main/java/com/iformall/controller/WxPayBillController.java Просмотреть файл

@@ -0,0 +1,152 @@
package com.iformall.controller;

import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.config.PayProperty;
import com.iformall.domain.po.WxAppinfo;
import com.iformall.domain.po.WxPayBill;
import com.iformall.enums.EnumPayStatus;
import com.iformall.enums.EnumPayWay;
import com.iformall.exception.MallinkException;
import com.iformall.service.WxPayBillService;
import com.iformall.utils.IPUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
* @author gongbiao
*/
@RestController
@RequestMapping("/api/pay")
@Api(description = "账单支付接口")
public class WxPayBillController extends BaseController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private PayProperty payProperty;

@Autowired
private WxPayBillService wxPayBillService;

@ApiOperation(value = "发起微信小程序支付订单", notes = "{\"billId\":\"string\",\"appId\":\"string\",\"openId\":\"string\",\"bUserId\":\"string\"}")
@RequestMapping(value = "/create", method = RequestMethod.POST)
public ResultData _create(@RequestBody Map<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());
}
}



}

+ 1
- 1
mallinkService/src/main/java/com/iformall/common/ErrorCode.java Просмотреть файл

@@ -274,7 +274,7 @@ public enum ErrorCode{
* 日常费用账单
* */
BILL_ROUTINE_IS_NOT_FOUND(21000,"账单不存在"),
BILL_UPDATE_FAILED(21001,"账单更新失败"),
/**
* 商铺
* */


+ 10
- 0
mallinkService/src/main/java/com/iformall/domain/po/WxAppinfo.java Просмотреть файл

@@ -79,6 +79,16 @@ public class WxAppinfo implements Serializable {
private Long payId;
@io.swagger.annotations.ApiModelProperty(value="1B端2C端",name="type")
private Integer type;
@io.swagger.annotations.ApiModelProperty(value="支付ID,参看wx_pay_account_bill",name="payBillId")
private Long payBillId;

public Long getPayBillId() {
return payBillId;
}

public void setPayBillId(Long payBillId) {
this.payBillId = payBillId;
}

public String getTenantId() {
return tenantId;


+ 211
- 0
mallinkService/src/main/java/com/iformall/domain/po/WxPayAccountBill.java Просмотреть файл

@@ -0,0 +1,211 @@
package com.iformall.domain.po;

import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.io.Serializable;
import java.util.List;

/**
* @author gongbiao
*/
@Table(name = "wx_pay_account_bill")
public class WxPayAccountBill implements Serializable {
private static final long serialVersionUID = 1L;

@Id
protected Long id;

@Transient
protected List<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));
}
}
}

+ 300
- 0
mallinkService/src/main/java/com/iformall/domain/po/WxPayBill.java Просмотреть файл

@@ -0,0 +1,300 @@
package com.iformall.domain.po;

import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* @author gongbiao
*/
@Table(name = "wx_pay_bill")
public class WxPayBill implements Serializable {
private static final long serialVersionUID = 1L;

@Id
protected Long id;

@Transient
protected List<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));
}
}
}

+ 10
- 0
mallinkService/src/main/java/com/iformall/domain/vo/WxBillAll.java Просмотреть файл

@@ -47,6 +47,16 @@ public class WxBillAll {
@io.swagger.annotations.ApiModelProperty(value="条数",name="pageSize")
private Integer pageSize;

@io.swagger.annotations.ApiModelProperty(value="id",name="id")
private Long id;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getAppId() {
return appId;


+ 20
- 0
mallinkService/src/main/java/com/iformall/mapper/WxPayAccountBillMapper.java Просмотреть файл

@@ -0,0 +1,20 @@
package com.iformall.mapper;

import com.iformall.common.CommonMapper;
import com.iformall.domain.po.WxPayAccountBill;

import java.util.List;

/**
* @author gongbiao
*/
public interface WxPayAccountBillMapper extends CommonMapper<WxPayAccountBill, Long> {

List<WxPayAccountBill> findList(WxPayAccountBill wxPayAccount);

}

+ 14
- 0
mallinkService/src/main/java/com/iformall/mapper/WxPayBillMapper.java Просмотреть файл

@@ -0,0 +1,14 @@
package com.iformall.mapper;

import com.iformall.common.CommonMapper;
import com.iformall.domain.po.WxPayBill;

import java.util.List;

/**
* @author gongbiao
*/
public interface WxPayBillMapper extends CommonMapper<WxPayBill, Long> {

List<WxPayBill> findList(WxPayBill wxPayBill);
}

+ 2
- 0
mallinkService/src/main/java/com/iformall/service/WxBillAllService.java Просмотреть файл

@@ -17,4 +17,6 @@ public interface WxBillAllService {

ResultData listBill(WxBillAll wxBillAll);

int updateBill(Map<String,Object> bill);

}

+ 74
- 0
mallinkService/src/main/java/com/iformall/service/WxPayBillService.java Просмотреть файл

@@ -0,0 +1,74 @@
package com.iformall.service;

import com.iformall.common.ResultData;
import com.iformall.domain.po.WxAppinfo;
import com.iformall.domain.po.WxPayBill;
import com.iformall.enums.EnumPayWay;

import java.util.Map;

/**
* @author gongbiao
*/
public interface WxPayBillService {

/**
* 创建支付订单
*
* @param record 支付订单请求
* @param payWay
* @return
*/
ResultData createPayBill(boolean isReal, WxAppinfo appInfo, WxPayBill record, EnumPayWay payWay);

/**
* 微信支付订单查询
* @param appInfo 支付订单Appinfo
* @param record 支付订单
*/
ResultData payBillQuery(WxAppinfo appInfo, WxPayBill record);

/**
* 微信支付关闭订单
* @param appInfo 支付订单Appinfo
* @param record 支付订单
*/
ResultData payBillClose(WxAppinfo appInfo, WxPayBill record);

/**
* 异步通知
*
* @param paramMap 异步通知参数
* @param payWay 支付方式
* @return
*/
String notify(Map<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);

}

+ 179
- 8
mallinkService/src/main/java/com/iformall/service/impl/WxBillAllServiceImpl.java Просмотреть файл

@@ -6,22 +6,20 @@ import com.iformall.common.ErrorCode;
import com.iformall.common.ResultData;
import com.iformall.domain.po.*;
import com.iformall.domain.vo.WxBillAll;
import com.iformall.enums.EnumBillDailyStatus;
import com.iformall.enums.EnumBillRentStatus;
import com.iformall.enums.EnumBillType;
import com.iformall.enums.EnumBillTypeParam;
import com.iformall.mapper.WxBillAllMapper;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.*;
import com.iformall.service.*;
import com.iformall.utils.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;

/**
* @author gongbiao
@@ -51,6 +49,25 @@ public class WxBillAllServiceImpl implements WxBillAllService {
@Autowired
WxBillOtherService wxBillOtherService;

@Autowired
WxBillDailyMapper wxBillDailyMapper;

@Autowired
WxBillDepositMapper wxBillDepositMapper;

@Autowired
WxBillPropertyDepositMapper wxBillPropertyDepositMapper;

@Autowired
WxBillPropertyMapper wxBillPropertyMapper;

@Autowired
WxBillRentMapper wxBillRentMapper;

@Autowired
WxBillOtherMapper wxBillOtherMapper;


@Override
public Map<String, Object> listAsPage(WxBillAll record, Integer pageIndex, Integer pageSize) {
//更新各账单状态
@@ -89,7 +106,7 @@ public class WxBillAllServiceImpl implements WxBillAllService {
//更新各账单状态
updateBillStatus(wxBillAll);
//账单类型
if(wxBillAll.getBillTypeValue()!=null){
if (wxBillAll.getBillTypeValue() != null) {
if (wxBillAll.getBillTypeValue().equals(EnumBillType.RENT.getCode())) {
wxBillAll.setBillTypeValue(EnumBillTypeParam.RENT.getCode());
} else if (wxBillAll.getBillTypeValue().equals(EnumBillType.DEPOSIT.getCode())) {
@@ -111,7 +128,7 @@ public class WxBillAllServiceImpl implements WxBillAllService {
return new ResultData(ErrorCode.BILL_ROUTINE_IS_NOT_FOUND);
}
}
if(wxBillAll.getPageIndex()!=null && wxBillAll.getPageIndex()!=null){
if (wxBillAll.getPageIndex() != null && wxBillAll.getPageIndex() != null) {
PageHelper.startPage(wxBillAll.getPageIndex(), wxBillAll.getPageSize());
List<Map<String, Object>> maps = wxBillAllMapper.listData(wxBillAll);
PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(maps);
@@ -121,6 +138,160 @@ public class WxBillAllServiceImpl implements WxBillAllService {
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) {
logger.info("更新各账单状态开始");
//更新其他账单


+ 838
- 0
mallinkService/src/main/java/com/iformall/service/impl/WxPayBillServiceImpl.java Просмотреть файл

@@ -0,0 +1,838 @@
package com.iformall.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iformall.common.ErrorCode;
import com.iformall.common.IdWorker;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.*;
import com.iformall.domain.vo.WxBillAll;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.*;
import com.iformall.pay.*;
import com.iformall.service.WxBillAllService;
import com.iformall.service.WxPayBillService;
import com.iformall.utils.BeanUtils;
import com.iformall.utils.MapUtil;
import com.iformall.utils.Utility;
import com.iformall.utils.XmlUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.*;

/**
* @author gongbiao
*/
@Service
public class WxPayBillServiceImpl implements WxPayBillService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
WxAppinfoMapper wxAppinfoMapper;

@Autowired
WxPayAccountBillMapper wxPayAccountBillMapper;

@Autowired
WxPayBillMapper wxPayBillMapper;

@Autowired
WxBillAllMapper wxBillAllMapper;

@Autowired
WxBillAllService wxBillAllService;

@Autowired
WxMerchantBUserMapper wxMerchantBUserMapper;

JSONObject errorMap = JSON.parseObject("{" +
"\"NOAUTH\":{\"detail\":\"商户无此接口权限\",\"reason\":\"商户未开通此接口权限\",\"resolution\":\"请商户前往申请此接口权限\"}," +
"\"NOTENOUGH\":{\"detail\":\"余额不足\",\"reason\":\"用户帐号余额不足\",\"resolution\":\"用户帐号余额不足,请用户充值或更换支付卡后再支付\"}," +
"\"ORDERPAID\":{\"detail\":\"商户订单已支付\",\"reason\":\"商户订单已支付,无需重复操作\",\"resolution\":\"商户订单已支付,无需更多操作\"}," +
"\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"当前订单已关闭,无法支付\",\"resolution\":\"当前订单已关闭,请重新下单\"}," +
"\"SYSTEMERROR\":{\"detail\":\"系统错误\t\",\"reason\":\"系统超时\",\"resolution\":\"系统异常,请用相同参数重新调用\"}," +
"\"APPID_NOT_EXIST\":{\"detail\":\"APPID不存在\",\"reason\":\"参数中缺少APPID\",\"resolution\":\"请检查APPID是否正确\"}," +
"\"MCHID_NOT_EXIST\":{\"detail\":\"MCHID不存在\",\"reason\":\"参数中缺少MCHID\",\"resolution\":\"请检查MCHID是否正确\"}," +
"\"APPID_MCHID_NOT_MATCH\":{\"detail\":\"appid和mch_id不匹配\",\"reason\":\"appid和mch_id不匹配\",\"resolution\":\"请确认appid和mch_id是否匹配\"}," +
"\"LACK_PARAMS\":{\"detail\":\"缺少参数\t\",\"reason\":\"缺少必要的请求参数\",\"resolution\":\"请检查参数是否齐全\"}," +
"\"OUT_TRADE_NO_USED\":{\"detail\":\"商户订单号重复\",\"reason\":\"同一笔交易不能多次提交\",\"resolution\":\"请核实商户订单号是否重复提交\"}," +
"\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," +
"\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"resolution\":\"请检查XML参数格式是否正确\"}," +
"\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," +
"\"POST_DATA_EMPTY\":{\"detail\":\"post数据为空\",\"reason\":\"post数据不能为空\",\"resolution\":\"请检查post数据是否为空\"}," +
"\"NOT_UTF8\":{\"detail\":\"编码格式错误\",\"reason\":\"未使用指定编码格式\",\"resolution\":\"请使用UTF-8编码格式\"}}");

JSONObject errorMapQuery = JSON.parseObject("{" +
"\"ORDERNOTEXIST\":{\"detail\":\"此交易订单号不存在\",\"reason\":\"查询系统中不存在此交易订单号\",\"resolution\":\"该API只能查提交支付交易返回成功的订单,请商户检查需要查询的订单号是否正确\"},\n" +
"\"SYSTEMERROR\":{\"detail\":\"系统错误\t\",\"reason\":\"后台系统返回错误\",\"resolution\":\"系统异常,请再调用发起查询\"}}");

JSONObject errorMapClose = JSON.parseObject("{" +
"\"ORDERPAID\":{\"detail\":\"订单已支付\",\"reason\":\"订单已支付,不能发起关单\",\"resolution\":\"订单已支付,不能发起关单,请当作已支付的正常交易\"}," +
"\"SYSTEMERROR\":{\"detail\":\"系统错误\",\"reason\":\"系统错误\",\"resolution\":\"系统异常,请重新调用该API\"}," +
"\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"订单已关闭,无法重复关闭\",\"resolution\":\"订单已关闭,无需继续调用\"}," +
"\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," +
"\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," +
"\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"reason\":\"请检查XML参数格式是否正确\"}}");

@Override
public ResultData createPayBill(boolean isReal, WxAppinfo appInfo, WxPayBill record, EnumPayWay payWay) {
final IdWorker idworker = IdWorker.get();

EnumPayShare isShare = EnumPayShare.NO;

try {
// 1. check 订单
WxBillAll wxBillAll = new WxBillAll();
wxBillAll.setId(record.getBillId());
List<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(), "账单更新");
}
}
}


}

+ 6
- 1
mallinkService/src/main/resources/mapper/WxAppinfoMapper.xml Просмотреть файл

@@ -16,10 +16,12 @@
<result column="expires_in" jdbcType="INTEGER" property="expiresIn"/>
<result column="pay_id" jdbcType="BIGINT" property="payId"/>
<result column="type" jdbcType="INTEGER" property="type"/>
<result column="pay_bill_id" jdbcType="BIGINT" property="payBillId"/>

</resultMap>

<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 id="dynamicWhereConditions">
@@ -78,6 +80,9 @@
<if test=" null != type ">
and `type` = #{type}
</if>
<if test=" null != payBillId ">
and `pay_bill_id` = #{payBillId}
</if>
<if test=" null != ids ">
and id in
<foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")">


+ 2
- 1
mallinkService/src/main/resources/mapper/WxBillAllMapper.xml Просмотреть файл

@@ -80,7 +80,7 @@
<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,
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
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
@@ -97,6 +97,7 @@
) bill
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_pay_bill pb on bill.id=pb.bill_id
where bill.tenant_id=#{tenantId}
<if test=" null != merchantId ">
and bill.merchant_id=#{merchantId}


+ 120
- 0
mallinkService/src/main/resources/mapper/WxPayBillMapper.xml Просмотреть файл

@@ -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>

Загрузка…
Отмена
Сохранить