diff --git a/mallinkAdmin/src/main/java/com/iformall/controller/WxMallConfigController.java b/mallinkAdmin/src/main/java/com/iformall/controller/WxMallConfigController.java index 3dc09c0e1..4acb68444 100644 --- a/mallinkAdmin/src/main/java/com/iformall/controller/WxMallConfigController.java +++ b/mallinkAdmin/src/main/java/com/iformall/controller/WxMallConfigController.java @@ -21,7 +21,7 @@ public class WxMallConfigController extends BaseController { private WxMallConfigService wxMallConfigService; @ApiOperation("获取停车劵开关") - @GetMapping("getStopCarConpon") + @GetMapping("getStopCarCoupon") public ResultData getStopCarConpon() { WxMallConfig wxMallConfig = new WxMallConfig(); wxMallConfig.setKey("stopCarCouponSwitch"); @@ -35,10 +35,10 @@ public class WxMallConfigController extends BaseController { } @ApiOperation("获取核销劵开关") - @GetMapping("getVerifyConpon") + @GetMapping("getVerifyCoupon") public ResultData getVerifyConpon() { WxMallConfig wxMallConfig = new WxMallConfig(); - wxMallConfig.setKey("verifyConponSwitch"); + wxMallConfig.setKey("verifyCouponSwitch"); wxMallConfig.setTenantId(getTenantId()); PageInfo page = wxMallConfigService.listAsPage(wxMallConfig, 1, 1); if (page.getSize() > 0) { @@ -48,8 +48,22 @@ public class WxMallConfigController extends BaseController { return new ResultData(); } - @PostMapping("updateStopCarConpon") - @ApiOperation("修改停车开关") + @ApiOperation("获取B端刷卡支付发劵开关") + @GetMapping("getMicroPayCouponSwitch") + public ResultData getMicroPayConpon() { + WxMallConfig wxMallConfig = new WxMallConfig(); + wxMallConfig.setKey("microPayCouponSwitch"); + wxMallConfig.setTenantId(getTenantId()); + PageInfo page = wxMallConfigService.listAsPage(wxMallConfig, 1, 1); + if (page.getSize() > 0) { + WxMallConfig config = page.getList().get(0); + return new ResultData(config); + } + return new ResultData(); + } + + @PostMapping("updateStopCarCoupon") + @ApiOperation("修改停车发券开关") public ResultData updateStopCarConpon(@RequestBody WxMallConfig wxMallConfig) { WxMallConfig temp = new WxMallConfig(); // temp.setKey("stopCarCouponSwitch"); @@ -59,11 +73,23 @@ public class WxMallConfigController extends BaseController { return new ResultData(); } - @PostMapping("updateVerifyConpon") - @ApiOperation("修改核销开关") + @PostMapping("updateVerifyCoupon") + @ApiOperation("修改核销发券开关") public ResultData updateVerifyConpon(@RequestBody WxMallConfig wxMallConfig) { WxMallConfig temp = new WxMallConfig(); -// temp.setKey("verifyConponSwitch"); +// temp.setKey("verifyCouponSwitch"); + temp.setValue(wxMallConfig.getValue()); + temp.setId(wxMallConfig.getId()); + wxMallConfigService.saveOrUpdate(temp); + return new ResultData(); + } + + + @PostMapping("updateMicroPayCouponSwitch") + @ApiOperation("修改刷卡支付发券开关") + public ResultData updateMicroPayCoupon(@RequestBody WxMallConfig wxMallConfig) { + WxMallConfig temp = new WxMallConfig(); +// temp.setKey("verifyCouponSwitch"); temp.setValue(wxMallConfig.getValue()); temp.setId(wxMallConfig.getId()); wxMallConfigService.saveOrUpdate(temp); diff --git a/mallinkBApi/src/main/java/com/iformall/controller/WxDateAmountRecordController.java b/mallinkBApi/src/main/java/com/iformall/controller/WxDateAmountRecordController.java index 5d2d56589..d120669a7 100644 --- a/mallinkBApi/src/main/java/com/iformall/controller/WxDateAmountRecordController.java +++ b/mallinkBApi/src/main/java/com/iformall/controller/WxDateAmountRecordController.java @@ -45,7 +45,13 @@ public class WxDateAmountRecordController extends BaseController { return list(EnumDateAmtType.VERIFY_RECORD.getCode()); } - private ResultData list(int status) { + @ApiOperation("首页查询刷卡金额记录接口") + @GetMapping("listMicropay") + public ResultData listMicropay() { + return list(EnumDateAmtType.MICROPAY_RECORD.getCode()); + } + + private ResultData list(int dateAmtType) { List list = new ArrayList<>(); @@ -53,7 +59,7 @@ public class WxDateAmountRecordController extends BaseController { WxMerchantBUser u = getUser(); temp.setTenantId(u.getTenantId()); temp.setMerchantId(u.getMerchantId()); - temp.setType(status); + temp.setType(dateAmtType); temp.setSortColumns(WxDateAmountRecord.Field.UpdateDate_DESC); SimpleDateFormat fmt = new SimpleDateFormat("MM/dd"); diff --git a/mallinkBApi/src/main/java/com/iformall/controller/WxMicroPayController.java b/mallinkBApi/src/main/java/com/iformall/controller/WxMicroPayController.java new file mode 100644 index 000000000..fccd25ee9 --- /dev/null +++ b/mallinkBApi/src/main/java/com/iformall/controller/WxMicroPayController.java @@ -0,0 +1,267 @@ +package com.iformall.controller; + + +import com.iformall.common.ErrorCode; +import com.iformall.common.ResultData; +import com.iformall.config.PayProperty; +import com.iformall.domain.po.*; +import com.iformall.enums.EnumAppType; +import com.iformall.enums.EnumOrderType; +import com.iformall.enums.EnumPayWay; +import com.iformall.enums.EnumRefundWay; +import com.iformall.exception.MallinkException; +import com.iformall.service.*; +import com.iformall.utils.IPUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +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 Stormeye Wu wuguoqiang@iformall.com + */ +@RestController +@Api(description = "刷卡支付") +@RequestMapping("/api/micropay") +public class WxMicroPayController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private PayProperty payProperty; + + @Autowired + WxMerchantBUserService wxMerchantBUserService; + + @Autowired + WxMerchantService wxMerchantService; + + @Autowired + WxOrderService wxOrderService; + + @Autowired + WxPayOrderService wxPayOrderService; + + @Autowired + WxRefundOrderService wxRefundOrderService; + + @Autowired + WxAppinfoService wxAppinfoService; + + @ApiOperation(value = "刷卡支付订单", notes = "params:{\"authCode\":\"String\",\"totalFee\":\"String\"},\n" + + "注意:\n" + + "提醒1:提交支付请求后微信会同步返回支付结果。当返回结果为“系统错误”时,商户系统等待5秒后调用【查询订单API】,查询支付实际交易结果;当返回结果为“USERPAYING”时,商户系统可设置间隔时间(建议10秒)重新查询支付结果,直到支付成功或超时(建议30秒);\n" + + "提醒2:在调用查询接口返回后,如果交易状况不明晰,请调用【撤销订单API】,此时如果交易失败则关闭订单,该单不能再支付成功;如果交易成功,则将扣款退回到用户账户。当撤销无返回或错误时,请再次调用。注意:请勿扣款后立即调用【撤销订单API】,建议至少15秒后再调用。撤销订单API需要双向证书。") + @PostMapping("order_create") + public ResultData saveMicopayOrder(@RequestBody Map paramMap, HttpServletRequest request) { + logger.info("saveMicopayOrder: " + paramMap.toString()); + //Assert.notNull(wxOrders.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + String authCode = paramMap.get("authCode"); + String totalFeeStr = paramMap.get("totalFee"); + + if (StringUtils.isBlank(authCode)) { + logger.error("authCode不能为空"); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "authCode不能为空"); + } + if (StringUtils.isBlank(totalFeeStr)) { + logger.error("totalFee不能为空"); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "totalFee不能为空"); + } + + String ipStr = IPUtil.getIpAddr(request); + + WxMerchantBUser user = getUser(); + + WxOrder order = null; + try { + order = wxOrderService.saveMicroOrder(user, totalFeeStr); + } catch (MallinkException e) { + logger.error("saveMicopayOrder 1" + e.getMessage()); + return new ResultData(e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + logger.error("saveMicopayOrder 2" + e.getMessage()); + return new ResultData(ErrorCode.ORDER_IS_FAIL, e.getMessage()); + } + + WxPayOrder record = new WxPayOrder(); + record.setTenantId(user.getTenantId()); + record.setOrderId(order.getId()); + record.setAuthCode(authCode); + record.setPayAmount(order.getPayment()); + record.setIp(ipStr); + + try { + return wxPayOrderService.createMicroPayOrder(payProperty.isReal(), user, 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 = "{\"payOrderId\":\"String\",\"orderId\":\"String\"}") + @PostMapping("order_query") + public ResultData queryMicopayOrder(@RequestBody Map paramMap) { + logger.info("queryMicopayOrder: " + paramMap.toString()); + String payOrderIdStr = paramMap.get("payOrderId"); + String orderIdStr = paramMap.get("orderId"); + + if (StringUtils.isBlank(payOrderIdStr)) { + logger.error("payOrderId不能为空"); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "payOrderId不能为空"); + } + if (StringUtils.isBlank(orderIdStr)) { + logger.error("orderId不能为空"); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "orderId不能为空"); + } + WxMerchantBUser user = getUser(); + + Long payOrderId = 0L; + Long orderId = 0L; + try { + payOrderId = Long.valueOf(payOrderIdStr); + } catch (NumberFormatException e) { + payOrderId = 0L; + logger.error("payOrderId参数不正确: " + paramMap.toString()); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + try { + orderId = Long.valueOf(orderIdStr); + } catch (NumberFormatException e) { + orderId = 0L; + logger.error("orderId参数不正确: " + paramMap.toString()); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + + WxPayOrder record = new WxPayOrder(); + record.setTenantId(user.getTenantId()); + record.setId(payOrderId); + record.setbUserId(user.getId()); + record.setOrderId(orderId); + + try { + ResultData resultData = wxPayOrderService.payOrderQuery(record); + return resultData; + } catch (MallinkException e) { + logger.error("payment wechat, order query error, req 2: " + record.toString() + ", e:" + e.getMessage()); + return new ResultData(e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + logger.error("payment wechat, order query error, req 3: " + record.toString() + ", e:" + e.getMessage()); + return new ResultData(ErrorCode.PAY_ORDER_QUERY_ERROR, e.getMessage()); + } + } + + @ApiOperation(value = "撤销刷卡支付订单", notes = "{\"payOrderId\":\"String\",\"orderId\":\"String\"}") + @PostMapping("order_reverse") + public ResultData reverseMicopayOrder(@RequestBody Map paramMap) { + logger.info("reverseMicopayOrder: " + paramMap.toString()); + String payOrderIdStr = paramMap.get("payOrderId"); + String orderIdStr = paramMap.get("orderId"); + + if (StringUtils.isBlank(payOrderIdStr)) { + logger.error("payOrderId不能为空"); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "payOrderId不能为空"); + } + if (StringUtils.isBlank(orderIdStr)) { + logger.error("orderId不能为空"); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "orderId不能为空"); + } + WxMerchantBUser user = getUser(); + + Long payOrderId = 0L; + Long orderId = 0L; + try { + payOrderId = Long.valueOf(payOrderIdStr); + } catch (NumberFormatException e) { + payOrderId = 0L; + logger.error("payOrderId参数不正确: " + paramMap.toString()); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + try { + orderId = Long.valueOf(orderIdStr); + } catch (NumberFormatException e) { + orderId = 0L; + logger.error("orderId参数不正确: " + paramMap.toString()); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + + WxPayOrder record = new WxPayOrder(); + record.setTenantId(user.getTenantId()); + record.setId(payOrderId); + record.setPayOrderNo(payOrderIdStr); + record.setbUserId(user.getId()); + record.setOrderId(orderId); + + try { + return wxPayOrderService.payOrderReverse(record); + } catch (MallinkException e) { + logger.error("payment wechat, order query error, req 2: " + record.toString() + ", e:" + e.getMessage()); + return new ResultData(e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + logger.error("payment wechat, order query error, req 3: " + record.toString() + ", e:" + e.getMessage()); + return new ResultData(ErrorCode.PAY_ORDER_ERROR, e.getMessage()); + } + } + + @ApiOperation("刷卡支付交易流水分页列表接口") + @GetMapping("listMicroPay") + @ApiImplicitParams({ + @ApiImplicitParam(name = "date", value = "日期yyyy-MM-dd", dataType = "string", paramType = "query"), + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query",required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query",required = true)}) + public ResultData listUnverified(String date, Integer pageNum, Integer pageSize) { + return wxOrderService.microPayListOnDateAsPage(getUser().getId(), EnumOrderType.MICROPAY.getCode(), date, pageNum, pageSize); + } + + @ApiOperation("刷卡支付某日期交易总流水") + @GetMapping("getMicroPayAmountOnDate") + @ApiImplicitParams({ + @ApiImplicitParam(name = "date", value = "日期yyyy-MM-dd", dataType = "string", paramType = "query")}) + public ResultData getMicroPayAmountOnDate(String date) { + return wxOrderService.microPayListOnDateAsPage(getUser().getId(), EnumOrderType.MICROPAY.getCode(), date, null, null); + } + + + @ApiOperation(value = "刷卡支付退款", notes = "{\"orderId\":\"string\"}") + @PostMapping("/microPayRefund") + public ResultData create(@RequestBody Map paramMap) { + //Assert.notNull(wxRefundOrder.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + logger.info(paramMap.toString()); + String orderIdStr = paramMap.get("orderId"); + if (StringUtils.isBlank(orderIdStr)) { + logger.error("orderId不能为空: " + paramMap.toString()); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + Long orderId = 0L; + try { + orderId = Long.valueOf(orderIdStr); + } catch (NumberFormatException e) { + logger.error("orderId参数不正确: " + paramMap.toString()); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + + WxMerchantBUser bUser = getUser(); + WxAppinfo appinfo = getAppInfo(bUser.getAppId()); + try { + ResultData rd = wxRefundOrderService.createRefundOrderFromMicroPay(payProperty.isReal(), appinfo, orderId, EnumRefundWay.B, bUser.getId()); + return rd; + } catch (MallinkException e) { + logger.error("退款 1:" + e.getMessage()); + return new ResultData(e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + logger.error("退款 2:" + e.getMessage()); + return new ResultData(ErrorCode.REFUND_ORDER_ERROR); + } + } +} diff --git a/mallinkBApi/src/main/java/com/iformall/tenant/TenantInfoImpl.java b/mallinkBApi/src/main/java/com/iformall/tenant/TenantInfoImpl.java index 3d2cc5e8c..cedf53734 100644 --- a/mallinkBApi/src/main/java/com/iformall/tenant/TenantInfoImpl.java +++ b/mallinkBApi/src/main/java/com/iformall/tenant/TenantInfoImpl.java @@ -15,13 +15,13 @@ public class TenantInfoImpl implements TenantInfo { @Override public String getTenantId() { - String tenantId = ""; + String tenantId = null; try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); tenantId = (String) request.getAttribute(AuthorizationInterceptor.TENANT_ID); return tenantId; } catch (Exception e) { - logger.error(e.getMessage()); + logger.error("getTenantId: " + e.getMessage()); } return tenantId; } diff --git a/mallinkBApi/src/main/resources/application-dev.yml b/mallinkBApi/src/main/resources/application-dev.yml index 2aba3a991..76fc19988 100644 --- a/mallinkBApi/src/main/resources/application-dev.yml +++ b/mallinkBApi/src/main/resources/application-dev.yml @@ -1,7 +1,7 @@ spring: # JDBC datasource: - url: jdbc:mysql://202.165.179.86:3306/mallink?useUnicode=true&characterEncoding=UTF-8&useSSL=false + url: jdbc:mysql://202.165.179.86:3306/mallink?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false username: ENC(dZ8fmrtuBMQYaRytKQgTqg==) password: ENC(OZXsE6/Tj+V1Yu2wdjnIGbNOaBVQzi9W) type: com.alibaba.druid.pool.DruidDataSource @@ -24,9 +24,9 @@ spring: # REDIS redis: - host: 202.165.179.86 + host: localhost port: 6379 - password: ENC(aYJ3Wr2UWtkORRQjjrWWpz2ZeTISsHOA) + password: F2ol8m@11 timeout: 3600 expire: 1800 #30分钟 database: 1 diff --git a/mallinkBApi/src/main/resources/application.yml b/mallinkBApi/src/main/resources/application.yml index 3aa2fe4cb..83ae69c9e 100644 --- a/mallinkBApi/src/main/resources/application.yml +++ b/mallinkBApi/src/main/resources/application.yml @@ -1,3 +1,4 @@ +debug: true server: port: 8000 servlet: diff --git a/mallinkCApi/src/main/java/com/iformall/controller/WxOrderController.java b/mallinkCApi/src/main/java/com/iformall/controller/WxOrderController.java index 0a8c2509e..b38851bd6 100644 --- a/mallinkCApi/src/main/java/com/iformall/controller/WxOrderController.java +++ b/mallinkCApi/src/main/java/com/iformall/controller/WxOrderController.java @@ -10,6 +10,7 @@ import com.iformall.domain.po.WxOrder; import com.iformall.domain.vo.WxOrderCVo; import com.iformall.enums.EnumCouponChannelStatus; import com.iformall.enums.EnumOrderStatus; +import com.iformall.enums.EnumOrderType; import com.iformall.exception.MallinkException; import com.iformall.service.WxCouponChannelService; import com.iformall.service.WxOrderService; diff --git a/mallinkCApi/src/main/java/com/iformall/controller/WxPayOrderController.java b/mallinkCApi/src/main/java/com/iformall/controller/WxPayOrderController.java index fa48cd4e9..e59e1cb2f 100644 --- a/mallinkCApi/src/main/java/com/iformall/controller/WxPayOrderController.java +++ b/mallinkCApi/src/main/java/com/iformall/controller/WxPayOrderController.java @@ -106,10 +106,10 @@ public class WxPayOrderController extends BaseController { payOrder.setPayOrderStatus(status); payOrder.setFailReason(reasonStr); try { - if(status.equals(EnumPayStatus.PAY_WAY_SUCCESS.getCode()) && !payOrderIdStr.equals("0")) { + if(status.equals(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()) && !payOrderIdStr.equals("0")) { // 有价券不走update, callback更新 payOrder = wxPayOrderService.getById(payOrderId); - if(payOrder.getPayOrderStatus().equals(EnumPayStatus.PAY_WAY_SUCCESS.getCode())) { + if(payOrder.getPayOrderStatus().equals(EnumPayStatus.PAY_STATUS_SUCCESS.getCode())) { return new ResultData(Result.SUCCESS, "支付状态更新成功"); } else { return new ResultData(ErrorCode.PAY_ORDER_ERROR, "支付未状态,请等待!!"); diff --git a/mallinkSchedule/src/main/java/com/iformall/schedule/DaliyAmountSchedule.java b/mallinkSchedule/src/main/java/com/iformall/schedule/DaliyAmountSchedule.java index 6f937a759..3c4db504a 100644 --- a/mallinkSchedule/src/main/java/com/iformall/schedule/DaliyAmountSchedule.java +++ b/mallinkSchedule/src/main/java/com/iformall/schedule/DaliyAmountSchedule.java @@ -1,10 +1,7 @@ package com.iformall.schedule; import com.iformall.common.IdWorker; -import com.iformall.domain.po.WxCouponOrder; -import com.iformall.domain.po.WxDateAmountRecord; -import com.iformall.domain.po.WxMall; -import com.iformall.domain.po.WxMerchant; +import com.iformall.domain.po.*; import com.iformall.enums.EnumDateAmtType; import com.iformall.enums.EnumMerchantStatus; import com.iformall.mapper.*; @@ -17,6 +14,7 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; @@ -40,11 +38,13 @@ public class DaliyAmountSchedule { @Autowired private WxDateAmountRecordService wxDateAmountRecordService; + @Autowired + private WxOrderMapper wxOrderMapper; - @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点盘点前一天的数据 - //@Scheduled(cron = "*/30 * * * * ?") // 测试10秒中一次 + //@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点盘点前一天的数据 + @Scheduled(cron = "*/30 * * * * ?") // 测试10秒中一次 @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) public void daliyAmountSchedule() { @@ -125,6 +125,17 @@ public class DaliyAmountSchedule { dateAmountRecord.setType(EnumDateAmtType.VERIFY_RECORD.getCode()); wxDateAmountRecordService.saveAmount(dateAmountRecord); + Map microPayMap = wxOrderMapper.dayMicroPayAmountList(dateMap); + Long countMic = (Long) microPayMap.get("count"); + BigDecimal totalPriceMic = (BigDecimal) microPayMap.get("total_price"); + logger.info("find " + countMic + " order " + "\n" + + "from " + startDate + " to " + new Date() + "\n" + + "TOTAL Payment=" + totalPriceMic); + + dateAmountRecord.setPayPrice(totalPriceMic.intValue()); + dateAmountRecord.setType(EnumDateAmtType.MICROPAY_RECORD.getCode()); + wxDateAmountRecordService.saveAmount(dateAmountRecord); + } } } diff --git a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java index 96c4e7599..54889d0c8 100644 --- a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java +++ b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java @@ -159,6 +159,11 @@ public enum ErrorCode{ /** * 支付 */ + PAY_ORDER_REFUND(11994, "订单退款中"), + PAY_ORDER_PAYING(11995, "订单支付中"), + PAY_ORDER_NOT_PAY(11996, "订单未支付"), + PAY_ORDER_CLOSED(11997, "订单已关闭"), + PAY_ORDER_REVERSE(11998, "订单已撤销"), PAY_ORDER_NOT_FOUND(12000, "支付订单不存在"), PAY_ORDER_EXIST(12001, "支付订单已存在"), PAY_ORDER_ERROR(12002, "支付订单异常"), @@ -166,6 +171,7 @@ public enum ErrorCode{ PAY_ORDER_IS_ZERO(12004, "支付订单金额为0"), PAY_ORDER_IS_NOT_PAYMENT(12005, "不是支付订单"), PREPAY_ID_IS_EMPTY(12006, "prepay_id是空值"), + PAY_ORDER_QUERY_ERROR(12007, "支付订单查询异常"), REFUND_ORDER_EXIST(12010, "退款订单已存在"), REFUND_PAY_ORDER_IS_NOT_EXIST(12011, "退款支付订单不存在"), diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxCUser.java b/mallinkService/src/main/java/com/iformall/domain/po/WxCUser.java index 5665984fa..0b5c72a9c 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/WxCUser.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxCUser.java @@ -129,14 +129,9 @@ public class WxCUser implements Serializable { /*附加信息**/ @io.swagger.annotations.ApiModelProperty(value="附加信息",name="extraInfo") private String extraInfo; - - public String getExtraInfo() { - return extraInfo; - } - - public void setExtraInfo(String extraInfo) { - this.extraInfo = extraInfo; - } + /**是否关注公众号**/ + @io.swagger.annotations.ApiModelProperty(value="是否关注公众号",name="isSubscribe") + private Integer isSubscribe; //渠道名称 @@ -364,6 +359,22 @@ public class WxCUser implements Serializable { this.sceneDescription = sceneDescription; } + public String getExtraInfo() { + return extraInfo; + } + + public void setExtraInfo(String extraInfo) { + this.extraInfo = extraInfo; + } + + public Integer getIsSubscribe() { + return isSubscribe; + } + + public void setIsSubscribe(Integer isSubscribe) { + this.isSubscribe = isSubscribe; + } + public static enum Field { Id_ASC("`id` ASC"),Id_DESC("`id` DESC") @@ -395,6 +406,7 @@ public class WxCUser implements Serializable { ,Latitude_ASC("`latitude` ASC"),Latitude_DESC("`latitude` DESC") ,LoginCount_ASC("`login_count` ASC"),LoginCount_DESC("`login_count` DESC") ,ExtraInfo_ASC("`extra_info` ASC"),ExtraInfo_DESC("`extra_info` DESC") + ,IsSubscribe_ASC("`is_subscribe` ASC"),IsSubscribe_DESC("`is_subscribe` DESC") ; private String value; Field(String value){ diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxOrder.java b/mallinkService/src/main/java/com/iformall/domain/po/WxOrder.java index 7ecdeb86e..a6e3c2c59 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/WxOrder.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxOrder.java @@ -59,6 +59,9 @@ public class WxOrder implements Serializable { /*券ID-产品ID将来的产品都会放在coupon表里**/ @io.swagger.annotations.ApiModelProperty(value="券ID",name="couponId") private Long couponId; + /*类型0:券,1:刷卡支付金**/ + @io.swagger.annotations.ApiModelProperty(value="类型",name="type") + private Integer type; /*0: 付款 1: 退款**/ @io.swagger.annotations.ApiModelProperty(value="0: 付款 1: 退款",name="paymentType") private Integer paymentType; @@ -118,6 +121,14 @@ public class WxOrder implements Serializable { this.couponId = _couponId; } + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + public Integer getPaymentType() { return paymentType; } @@ -172,6 +183,7 @@ public class WxOrder implements Serializable { ,MerchantId_ASC("`merchant_id` ASC"),MerchantId_DESC("`merchant_id` DESC") ,BUserId_ASC("`b_user_id` ASC"),BUserId_DESC("`b_user_id` DESC") ,CouponId_ASC("`coupon_id` ASC"),CouponId_DESC("`coupon_id` DESC") + ,Type_ASC("`type` ASC"),Type_DESC("`type` DESC") ,PaymentType_ASC("`payment_type` ASC"),PaymentType_DESC("`payment_type` DESC") ,Payment_ASC("`payment` ASC"),Payment_DESC("`payment` DESC") ,PaymentTime_ASC("`payment_time` ASC"),PaymentTime_DESC("`payment_time` DESC") diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxPayOrder.java b/mallinkService/src/main/java/com/iformall/domain/po/WxPayOrder.java index 2efe3c68f..60b2f5594 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/WxPayOrder.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxPayOrder.java @@ -56,6 +56,12 @@ public class WxPayOrder implements Serializable { /**用户ID**/ @io.swagger.annotations.ApiModelProperty(value="用户ID",name="cUserId") private Long cUserId; + /**B端用户ID**/ + @io.swagger.annotations.ApiModelProperty(value="B端用户ID",name="bUserId") + private Long bUserId; + /**扫码授权编码**/ + @io.swagger.annotations.ApiModelProperty(value="扫码授权编码",name="authCode") + private String authCode; /**ip地址**/ @io.swagger.annotations.ApiModelProperty(value="ip地址",name="ip") private String ip; @@ -125,7 +131,23 @@ public class WxPayOrder implements Serializable { this.cUserId = cUserId; } - public String getIp() { + public Long getbUserId() { + return bUserId; + } + + public void setbUserId(Long bUserId) { + this.bUserId = bUserId; + } + + public String getAuthCode() { + return authCode; + } + + public void setAuthCode(String authCode) { + this.authCode = authCode; + } + + public String getIp() { return ip; } public void setIp(String _ip) { @@ -215,6 +237,8 @@ public class WxPayOrder implements Serializable { ,UpdateTime_ASC("`update_time` ASC"),UpdateTime_DESC("`update_time` DESC") ,OrderId_ASC("`order_id` ASC"),OrderId_DESC("`order_id` DESC") ,CUserId_ASC("`c_user_id` ASC"),CUserId_DESC("`c_user_id` DESC") + ,BUserId_ASC("`b_user_id` ASC"),BUserId_DESC("`b_user_id` DESC") + ,AuthCode_ASC("`auth_code` ASC"),AuthCode_DESC("`auth_code` 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") diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumCouponSendSendType.java b/mallinkService/src/main/java/com/iformall/enums/EnumCouponSendSendType.java index 0fa1a5032..c199bca93 100644 --- a/mallinkService/src/main/java/com/iformall/enums/EnumCouponSendSendType.java +++ b/mallinkService/src/main/java/com/iformall/enums/EnumCouponSendSendType.java @@ -5,13 +5,13 @@ package com.iformall.enums; */ public enum EnumCouponSendSendType { - // 2:停车发券 3:核销发券 + // 2:停车发券 3:核销发券 4: B端刷卡发券 UNKNOWN(-1, "未知"), INJECT(0, "精准发券"), ACTIVE(1, "主动(保留)"), CAR_STOP(2, "停车发券"), COUPON_VERIFY(3, "核销发券"), - + B_MICROPAY(4, "B端刷卡发券") ; public static EnumCouponSendSendType getEnum(Integer code) { diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumDateAmtType.java b/mallinkService/src/main/java/com/iformall/enums/EnumDateAmtType.java index ef97bb2ef..135a28920 100644 --- a/mallinkService/src/main/java/com/iformall/enums/EnumDateAmtType.java +++ b/mallinkService/src/main/java/com/iformall/enums/EnumDateAmtType.java @@ -5,9 +5,10 @@ package com.iformall.enums; */ public enum EnumDateAmtType { - // 0 交易记录 1.核销记录; + // 0 交易记录 1.核销记录 2:刷卡支付; PAY_RECORD(0, "交易记录"), VERIFY_RECORD(1, "核销记录"), + MICROPAY_RECORD(2, "刷卡支付"), ; public static EnumDateAmtType getEnum(Integer code) { diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumOrderType.java b/mallinkService/src/main/java/com/iformall/enums/EnumOrderType.java new file mode 100644 index 000000000..6ba90146f --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/enums/EnumOrderType.java @@ -0,0 +1,38 @@ +package com.iformall.enums; + + +/** + * @author gongbiao + */ + +public enum EnumOrderType { + + COUPON(0,"券"), + MICROPAY(1,"刷卡支付金") + ; + + public static EnumOrderType getEnum(Integer code) { + for (EnumOrderType value : values()) { + if (value.getCode().equals(code)) { + return value; + } + } + return null; + } + + private Integer code; + private String message; + + EnumOrderType(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumPayStatus.java b/mallinkService/src/main/java/com/iformall/enums/EnumPayStatus.java index bd49a112f..803dc295c 100644 --- a/mallinkService/src/main/java/com/iformall/enums/EnumPayStatus.java +++ b/mallinkService/src/main/java/com/iformall/enums/EnumPayStatus.java @@ -4,11 +4,18 @@ package com.iformall.enums; * Created by Stormeye on 2018/08/09. */ public enum EnumPayStatus { - PAY_WAY_UNKNOWN(-1, "未知"), - PAY_WAY_WAIT(0, "支付中"), - PAY_WAY_SUCCESS(1, "支付成功"), - PAY_WAY_FAIL(2, "支付失败"), - PAY_WAY_CANCEL(3, "取消支付") + PAY_STATUS_NOTPAY(-2, "未支付"), + PAY_STATUS_UNKNOWN(-1, "未知"), + PAY_STATUS_WAIT(0, "支付中"), + PAY_STATUS_SUCCESS(1, "支付成功"), + PAY_STATUS_FAIL(2, "支付错误"), + PAY_STATUS_CANCEL(3, "取消支付"), + PAY_STATUS_CANCEL_FAIL(4,"取消支付失败"), + PAY_STATUS_CLOSE(5, "关闭支付订单"), + PAY_STATUS_CLOSE_FAIL(6,"关闭支付订单失败"), + PAY_STATUS_REVERSE(7, "撤销支付订单"), + PAY_STATUS_REVERSE_FAIL(8,"撤销支付订单失败"), + PAY_STATUS_REFUND(9,"支付转退款") ; public static EnumPayStatus getEnum(Integer code) { diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumUserIsSubscribe.java b/mallinkService/src/main/java/com/iformall/enums/EnumUserIsSubscribe.java new file mode 100644 index 000000000..a843f85e2 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/enums/EnumUserIsSubscribe.java @@ -0,0 +1,38 @@ +package com.iformall.enums; + +/** + * Created by Stormeye on 2018/08/09. + */ +public enum EnumUserIsSubscribe { + + // 0-否 1-是 + + NO(0, "N"), + YES(1, "Y") + ; + + public static EnumUserIsSubscribe getEnum(Integer code) { + for (EnumUserIsSubscribe value : values()) { + if (value.getCode().equals(code)) { + return value; + } + } + return null; + } + + private Integer code; + private String message; + + EnumUserIsSubscribe(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/mallinkService/src/main/java/com/iformall/mapper/WxOrderMapper.java b/mallinkService/src/main/java/com/iformall/mapper/WxOrderMapper.java index 3285cb1ee..106fde6c1 100644 --- a/mallinkService/src/main/java/com/iformall/mapper/WxOrderMapper.java +++ b/mallinkService/src/main/java/com/iformall/mapper/WxOrderMapper.java @@ -18,4 +18,7 @@ public interface WxOrderMapper extends CommonMapper { List findListOfCUser(WxOrder wxOrder); WxOrderCVo selectDetailOfCUser(WxOrder wxOrder); + Map dayMicroPayAmountList(Map dateMap); + List findListOfMicroPayOrderByDate(Map dateMap); + } diff --git a/mallinkService/src/main/java/com/iformall/pay/WxMicroPayOrderP.java b/mallinkService/src/main/java/com/iformall/pay/WxMicroPayOrderP.java new file mode 100644 index 000000000..52c666ee7 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/pay/WxMicroPayOrderP.java @@ -0,0 +1,135 @@ +package com.iformall.pay; + +/** + * Created by Stormeye on 2018/11/7. + * 普通商户模式 + */ +public class WxMicroPayOrderP { + private String appid; // 小程序ID + private String mch_id; // 商户号 + private String device_info; // 终端设备号 门店编号 + private String nonce_str; // 随机字符串 + private String sign; // 签名 + private String body; // 商品简单描述 128 + private String out_trade_no; // 商户订单号 + private Integer total_fee; // 支付金额 + private String spbill_create_ip; // 支付IP + private String time_start; // 开始时间 + private String time_expire; // 失效时间 + private String auth_code; // 扫码支付授权码 + + public String getTime_start() { + return time_start; + } + + public void setTime_start(String time_start) { + this.time_start = time_start; + } + + public String getTime_expire() { + return time_expire; + } + + public void setTime_expire(String time_expire) { + this.time_expire = time_expire; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public Integer getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(Integer total_fee) { + this.total_fee = total_fee; + } + + public String getSpbill_create_ip() { + return spbill_create_ip; + } + + public void setSpbill_create_ip(String spbill_create_ip) { + this.spbill_create_ip = spbill_create_ip; + } + + public String getAuth_code() { + return auth_code; + } + + public void setAuth_code(String auth_code) { + this.auth_code = auth_code; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("WxPayOrderP{"); + sb.append("appid='").append(appid).append('\''); + sb.append(", mch_id='").append(mch_id).append('\''); + sb.append(", device_info='").append(device_info).append('\''); + sb.append(", nonce_str='").append(nonce_str).append('\''); + sb.append(", sign='").append(sign).append('\''); + sb.append(", body='").append(body).append('\''); + sb.append(", out_trade_no='").append(out_trade_no).append('\''); + sb.append(", total_fee=").append(total_fee); + sb.append(", spbill_create_ip='").append(spbill_create_ip).append('\''); + sb.append(", time_start='").append(time_start).append('\''); + sb.append(", time_expire='").append(time_expire).append('\''); + sb.append(", auth_code='").append(auth_code).append('\''); + sb.append('}'); + return sb.toString(); + } +} diff --git a/mallinkService/src/main/java/com/iformall/pay/WxMicroPayOrderSP.java b/mallinkService/src/main/java/com/iformall/pay/WxMicroPayOrderSP.java new file mode 100644 index 000000000..cdf617a56 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/pay/WxMicroPayOrderSP.java @@ -0,0 +1,174 @@ +package com.iformall.pay; + +/** + * Created by Stormeye on 2018/11/7. + * 服务商模式 + */ +public class WxMicroPayOrderSP { + private String appid; // 公众账号ID + private String sub_appid; // 小程序ID + private String mch_id; // 服务商号 + private String sub_mch_id; // 特约商户号 + private String device_info; // 终端设备号 - 门店编号 + private String nonce_str; // 随机字符串 + private String sign; // 签名 + private String sign_type; // 签名类型 + private String body; // 商品简单描述 128 + private String out_trade_no; // 商户订单号 + private Integer total_fee; // 支付金额 + private String spbill_create_ip; // 支付IP + private String time_start; // 开始时间 + private String time_expire; // 失效时间 + private String auth_code; // 扫码支付授权码 + private String profit_sharing; // 是否开启分账 + + public String getTime_start() { + return time_start; + } + + public void setTime_start(String time_start) { + this.time_start = time_start; + } + + public String getTime_expire() { + return time_expire; + } + + public void setTime_expire(String time_expire) { + this.time_expire = time_expire; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getSub_appid() { + return sub_appid; + } + + public void setSub_appid(String sub_appid) { + this.sub_appid = sub_appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getSub_mch_id() { + return sub_mch_id; + } + + public void setSub_mch_id(String sub_mch_id) { + this.sub_mch_id = sub_mch_id; + } + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getSign_type() { + return sign_type; + } + + public void setSign_type(String sign_type) { + this.sign_type = sign_type; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public Integer getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(Integer total_fee) { + this.total_fee = total_fee; + } + + public String getSpbill_create_ip() { + return spbill_create_ip; + } + + public void setSpbill_create_ip(String spbill_create_ip) { + this.spbill_create_ip = spbill_create_ip; + } + + public String getAuth_code() { + return auth_code; + } + + public void setAuth_code(String auth_code) { + this.auth_code = auth_code; + } + + public String getProfit_sharing() { + return profit_sharing; + } + + public void setProfit_sharing(String profit_sharing) { + this.profit_sharing = profit_sharing; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("WxPayOrderSP{"); + sb.append("appid='").append(appid).append('\''); + sb.append(", sub_appid='").append(sub_appid).append('\''); + sb.append(", mch_id='").append(mch_id).append('\''); + sb.append(", sub_mch_id='").append(sub_mch_id).append('\''); + sb.append(", device_info='").append(device_info).append('\''); + sb.append(", nonce_str='").append(nonce_str).append('\''); + sb.append(", sign='").append(sign).append('\''); + sb.append(", body='").append(body).append('\''); + sb.append(", out_trade_no='").append(out_trade_no).append('\''); + sb.append(", total_fee=").append(total_fee); + sb.append(", spbill_create_ip='").append(spbill_create_ip).append('\''); + sb.append(", time_start='").append(time_start).append('\''); + sb.append(", time_expire='").append(time_expire).append('\''); + sb.append(", auth_code='").append(auth_code).append('\''); + sb.append(", profit_sharing='").append(profit_sharing).append('\''); + sb.append('}'); + return sb.toString(); + } +} diff --git a/mallinkService/src/main/java/com/iformall/service/WxCouponOrderService.java b/mallinkService/src/main/java/com/iformall/service/WxCouponOrderService.java index db4c3787f..eab5697b0 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxCouponOrderService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxCouponOrderService.java @@ -4,6 +4,7 @@ import com.github.pagehelper.PageInfo; import com.iformall.common.ResultData; import com.iformall.domain.po.WxCouponOrder; import com.iformall.domain.po.WxMerchantBUser; +import com.iformall.domain.po.WxOrder; import com.iformall.domain.vo.CUserDateAmountVo; import java.util.Date; @@ -71,6 +72,13 @@ public interface WxCouponOrderService { */ boolean sendCouponAfterVerify(WxCouponOrder couponOrder, WxMerchantBUser bUser); + /** + * B端刷卡支付发券 + * @param order + * @param bUser + */ + boolean sendCouponAfterMicroPay(String tenantId, Long orderId, Long cUserId); + /** * 核销分账 * @param couponOrder diff --git a/mallinkService/src/main/java/com/iformall/service/WxOrderService.java b/mallinkService/src/main/java/com/iformall/service/WxOrderService.java index 86dc9525b..f1b0528db 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxOrderService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxOrderService.java @@ -6,6 +6,7 @@ import com.github.pagehelper.PageInfo; import com.iformall.common.ResultData; import com.iformall.domain.po.WxCUser; import com.iformall.domain.po.WxCouponOrder; +import com.iformall.domain.po.WxMerchantBUser; import com.iformall.domain.po.WxOrder; import com.iformall.domain.vo.WxOrderCVo; import com.iformall.enums.EnumOrderStatus; @@ -23,6 +24,15 @@ public interface WxOrderService { PageInfo listAsPage(WxOrder record, Integer pageIndex, Integer pageSize); + /** + * 根据日期 b用户查刷卡支付list + * + * @param bUserId B端用户) + */ + + ResultData microPayListOnDateAsPage(Long bUserId, Integer type, String date, Integer pageIndex, Integer pageSize); + + /** * 提交订单 * @param user @@ -31,6 +41,14 @@ public interface WxOrderService { */ WxOrder saveOrder(WxCUser user, Long couponChannelId, Long couponId); + /** + * 刷卡支付 + * @param user + * @param totalFeeStr + * @return 订单id + */ + WxOrder saveMicroOrder(WxMerchantBUser user, String totalFeeStr); + /** * 免费券订单接口 * @param userId @@ -54,6 +72,13 @@ public interface WxOrderService { */ int orderSuccess(WxOrder updateOrder); + /** + * microPayOrderSuccess 刷卡支付成功 + * @param updateOrder + * @return + */ + int microPayOrderSuccess(WxOrder updateOrder); + /** * updateOrderStatus 更新订单状态, 只针对已取消及已退款 * @param updateOrder @@ -103,4 +128,11 @@ public interface WxOrderService { void stockBack(WxOrder updateOrder); + /** + * microPay分账 + * @param orderId + * @param payOrderId + */ + void shareForMicroPay(String tenantId, Long orderId, Long payOrderId); + } diff --git a/mallinkService/src/main/java/com/iformall/service/WxPayOrderService.java b/mallinkService/src/main/java/com/iformall/service/WxPayOrderService.java index eed93b166..e25731ff9 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxPayOrderService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxPayOrderService.java @@ -6,6 +6,7 @@ import com.github.pagehelper.PageInfo; import com.iformall.common.ResultData; import com.iformall.domain.po.WxAppinfo; import com.iformall.domain.po.WxCUser; +import com.iformall.domain.po.WxMerchantBUser; import com.iformall.domain.po.WxPayOrder; import com.iformall.enums.EnumPayWay; @@ -20,12 +21,20 @@ public interface WxPayOrderService { */ ResultData createPayOrder(boolean isReal, WxAppinfo appInfo, WxCUser user, WxPayOrder record, EnumPayWay payWay); + /** + * 刷卡支付订单 + * + * @param record 支付订单请求 + * @param payWay + * @return + */ + ResultData createMicroPayOrder(boolean isReal, WxMerchantBUser user, WxPayOrder record, EnumPayWay payWay); + /** * 微信支付订单查询 - * @param appInfo 支付订单Appinfo * @param record 支付订单 */ - ResultData payOrderQuery(WxAppinfo appInfo, WxPayOrder record); + ResultData payOrderQuery(WxPayOrder record); /** * 微信支付关闭订单 @@ -34,6 +43,12 @@ public interface WxPayOrderService { */ ResultData payOrderClose(WxAppinfo appInfo, WxPayOrder record); + /** + * 微信支付刷卡支付撤销订单 + * @param record 支付订单 + */ + ResultData payOrderReverse(WxPayOrder record); + /** * 异步通知 * @@ -51,6 +66,14 @@ public interface WxPayOrderService { */ void handleOrderPaySuccess(WxPayOrder record, String transactionId); + /** + * 刷卡支付成功处理 + * + * @param record + * @param transactionId + */ + void handleMicroOrderPaySuccess(WxPayOrder record, String transactionId, String openId, String isSubscribe); + /** * 支付状态处理 * diff --git a/mallinkService/src/main/java/com/iformall/service/WxRefundOrderService.java b/mallinkService/src/main/java/com/iformall/service/WxRefundOrderService.java index 63dfb7839..5cbc50b96 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxRefundOrderService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxRefundOrderService.java @@ -21,6 +21,17 @@ public interface WxRefundOrderService { */ ResultData createRefundOrder(boolean isReal, WxAppinfo appInfo, Long couponOrderId, EnumRefundWay refundWay, Long bUserId); + /** + * 创建退款订单 + * @param isReal + * @param appInfo + * @param orderId 订单Id + * @param refundWay 退款来源 + * @param bUserId b端退款Id,auto,admin,self可为null + * @return + */ + ResultData createRefundOrderFromMicroPay(boolean isReal, WxAppinfo appInfo, Long orderId, EnumRefundWay refundWay, Long bUserId); + /** * 退款订单查询 * @param appInfo diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxCouponOrderServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxCouponOrderServiceImpl.java index 512158082..59bbc55c4 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxCouponOrderServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxCouponOrderServiceImpl.java @@ -5,7 +5,6 @@ import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; -import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.google.common.collect.Lists; @@ -368,8 +367,9 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { // 微信分账 try { WxPayOrder wxPayOrder = new WxPayOrder(); + wxPayOrder.setTenantId(couponOrder.getTenantId()); wxPayOrder.setOrderId(couponOrder.getOrderId()); - wxPayOrder.setPayOrderStatus(EnumPayStatus.PAY_WAY_SUCCESS.getCode()); + wxPayOrder.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); wxPayOrder = wxPayOrderMapper.selectOne(wxPayOrder); if (wxPayOrder != null && wxPayOrder.getShare().equals(EnumPayShare.YES.getCode())) wxProfitSharingOrderService.createSharingOrder(wxPayOrder); @@ -392,6 +392,20 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { return false; } + @Override + public boolean sendCouponAfterMicroPay(String tenantId, Long orderId, Long cUserId) { + // B端刷卡支付发券 + WxOrder wxOrder = wxOrderMapper.selectByPrimaryKey(orderId); + if (wxOrder != null) { + try { + return wxCouponSendService.sendCouponToUser(tenantId, cUserId, EnumCouponSendSendType.B_MICROPAY); + } catch (Exception e) { + logger.error("B端刷卡支付发券: " + e.getMessage()); + } + } + return false; + } + /** * 微信模板消息 * @@ -436,7 +450,7 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { WxPayOrder payOrderQ = new WxPayOrder(); payOrderQ.setTenantId(couponOrder.getTenantId()); payOrderQ.setOrderId(order.getId()); - payOrderQ.setPayOrderStatus(EnumPayStatus.PAY_WAY_SUCCESS.getCode()); + payOrderQ.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); List payList = wxPayOrderMapper.select(payOrderQ); if (payList.size() > 0) { payOrder = payList.get(0); diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxCouponSendServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxCouponSendServiceImpl.java index ac6eda5c2..7a2b8b236 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxCouponSendServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxCouponSendServiceImpl.java @@ -73,7 +73,7 @@ public class WxCouponSendServiceImpl implements WxCouponSendService { @Transactional public boolean sendCouponToUser(String tenantId, Long cUserId, EnumCouponSendSendType type) { //查询开关是否打开 - //查询停车或者核销的券 stopCarCouponSwitch verifyConponSwitch + //查询停车或者核销的券 stopCarCouponSwitch, verifyCouponSwitch, microPayCouponSwitch WxCouponSend wxCouponSendQuery = new WxCouponSend(); wxCouponSendQuery.setTenantId(tenantId); wxCouponSendQuery.setStatus(EnumCouponSendStatus.VALID.getCode()); @@ -84,13 +84,17 @@ public class WxCouponSendServiceImpl implements WxCouponSendService { actionType = EnumCouponSendSendType.CAR_STOP.getCode(); wxCouponSendQuery.setSendType(actionType); configKey = "stopCarCouponSwitch"; - } - else if (type == EnumCouponSendSendType.COUPON_VERIFY) { + } else if (type == EnumCouponSendSendType.COUPON_VERIFY) { //核销 actionType = EnumCouponSendSendType.COUPON_VERIFY.getCode(); wxCouponSendQuery.setSendType(actionType); - configKey = "verifyConponSwitch"; - } else { + configKey = "verifyCouponSwitch"; + } else if (type == EnumCouponSendSendType.B_MICROPAY) { + //B端刷卡发券 + actionType = EnumCouponSendSendType.B_MICROPAY.getCode(); + wxCouponSendQuery.setSendType(actionType); + configKey = "microPayCouponSwitch"; + }else { return false; } WxMallConfig wxMallConfigQuery = new WxMallConfig(); @@ -108,7 +112,7 @@ public class WxCouponSendServiceImpl implements WxCouponSendService { try { checkTime = pushLimitService.checkSendTime(tenantId); } catch (MallinkException e) { - logger.error(e.getMessage()); + logger.error("push limit check time :" + e.getMessage()); return false; } @@ -122,7 +126,7 @@ public class WxCouponSendServiceImpl implements WxCouponSendService { try { checkLimit = pushLimitService.checkCoupon(tenantId, cUserId, send.getCouponId()); } catch (MallinkException e) { - logger.error(e.getMessage()); + logger.error("券达到limit: " + e.getMessage()); } if (!checkLimit) { continue; diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java index ca3707376..8cabe7ea5 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java @@ -20,6 +20,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.*; @Service @@ -60,6 +63,9 @@ public class WxOrderServiceImpl implements WxOrderService { @Autowired WxPayOrderMapper wxPayOrderMapper; + @Autowired + WxMerchantBUserMapper wxMerchantBUserMapper; + @Autowired WxPayOrderService wxPayOrderService; @@ -72,11 +78,76 @@ public class WxOrderServiceImpl implements WxOrderService { @Autowired WxCouponActionLogService wxCouponActionLogService; + @Autowired + WxProfitSharingOrderService wxProfitSharingOrderService; + @Override public PageInfo listAsPage(WxOrder record, Integer pageIndex, Integer pageSize) { return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxOrderMapper.findList(record)); } + @Override + public ResultData microPayListOnDateAsPage(Long bUserId, Integer type, String date, Integer pageIndex, Integer pageSize) { + WxMerchantBUser wxMerchantBUser = wxMerchantBUserMapper.selectByPrimaryKey(bUserId.longValue()); + if (wxMerchantBUser == null) { + logger.error("B端用户不存在:" + bUserId); + throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_FOUND); + } + + WxMerchant wxMerchant = wxMerchantMapper.selectByPrimaryKey(wxMerchantBUser.getMerchantId()); + if (wxMerchant == null) { + logger.error("商户不存在:" + bUserId); + throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_FOUND); + } + + SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd"); + String dateString; + Date startDate; + Date endDate; + + if (date == null) { + endDate = new Date(); + dateString = fmt.format(new Date()); + try { + startDate = fmt.parse(dateString); + } catch (ParseException e) { + return new ResultData(ErrorCode.SYS_PARAMETER_CAST_ERROR); + } + } else { + try { + startDate = fmt.parse(date); + } catch (ParseException e) { + return new ResultData(ErrorCode.SYS_PARAMETER_CAST_ERROR); + } + Calendar cal = Calendar.getInstance(); + cal.setTime(startDate); + cal.add(Calendar.DATE, 1); + endDate = cal.getTime(); + } + + Map dateMap = new HashMap(); + dateMap.put("startDate", startDate); + dateMap.put("endDate", endDate); + dateMap.put("merchantID", wxMerchant.getId()); + dateMap.put("type", type); + + Map resultMap = new HashMap(); + + if (pageIndex == null || pageSize == null) { + List list; + list = wxOrderMapper.findListOfMicroPayOrderByDate(dateMap); + logger.info("find " + list.size() + " order from " + startDate + " to " + new Date()); + int total_price = 0; + for (WxOrder order : list) { + total_price = total_price + order.getPayment(); + } + resultMap.put("amount", total_price); + } else { + resultMap.put("list", PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxOrderMapper.findListOfMicroPayOrderByDate(dateMap))); + } + return new ResultData(resultMap); + } + private int getUserCouponOrderCount(WxCUser user, WxCoupon counpon) { // 用户购买的券包数量 @@ -86,6 +157,8 @@ public class WxOrderServiceImpl implements WxOrderService { WxOrder orderQ = new WxOrder(); orderQ.setTenantId(user.getTenantId()); orderQ.setCouponId(counpon.getId()); + orderQ.setType(EnumOrderType.COUPON.getCode()); + orderQ.setType(EnumOrderType.COUPON.getCode()); orderQ.setCUserId(user.getId()); orderQ.setOrderStatus(EnumOrderStatus.ORDER_STATUS_PENDING_PAYMENT.getCode()); try { @@ -267,6 +340,8 @@ public class WxOrderServiceImpl implements WxOrderService { record.setTenantId(user.getTenantId()); record.setOrderNumber(orderNumber); record.setCouponId(couponId); + record.setType(EnumOrderType.COUPON.getCode()); + record.setType(EnumOrderType.COUPON.getCode()); record.setCUserId(user.getId()); record.setMerchantId(coupon.getMerchantId()); record.setPaymentType(EnumPayType.PAY_PAYMENT.getCode()); @@ -298,6 +373,64 @@ public class WxOrderServiceImpl implements WxOrderService { return record; } + @Override + @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) + public WxOrder saveMicroOrder(WxMerchantBUser user, String totalFeeStr) { + // 检查用户 + if (user == null) { + logger.error("用户不存在"); + throw new MallinkException(ErrorCode.USER_IS_EMPTY); + } + + WxMerchant wxMerchant = wxMerchantMapper.selectByPrimaryKey(user.getMerchantId()); + if (wxMerchant == null) { + logger.error("商户不存在, merchantId: " + user.getMerchantId()); + throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_FOUND); + } + if (wxMerchant.getStatus() == EnumMerchantStatus.NOT_VALID.getCode()) { + logger.error("商户已禁用, merchantId: " + user.getMerchantId()); + throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_VALID); + } + + Date curr = new Date(); + + BigDecimal totalFee = new BigDecimal(totalFeeStr); + totalFee.setScale(2, BigDecimal.ROUND_HALF_UP); // 第一个变量是小数位数,第二个变量是取舍方法(四舍五入) + + int payment = totalFee.multiply(new BigDecimal(100)).intValue(); + + final IdWorker idWorker = IdWorker.get(); + Long orderNumber = idWorker.nextId(); + + // body + // tenant_id + merchant_id + title + subtitle + String bodyStr = "刷卡支付, 金额:" + totalFeeStr; + + + WxOrder record = new WxOrder(); + record.setId(orderNumber); + record.setTenantId(user.getTenantId()); + record.setOrderNumber(orderNumber); + record.setType(EnumOrderType.MICROPAY.getCode()); + record.setBUserId(user.getId()); + record.setMerchantId(user.getMerchantId()); + record.setPaymentType(EnumPayType.PAY_PAYMENT.getCode()); + record.setPayment(payment); + record.setOrderStatus(EnumOrderStatus.ORDER_STATUS_PENDING_PAYMENT.getCode()); + record.setDetail(bodyStr); + record.setCreateDate(curr); + record.setUpdateDate(curr); + + try { + // 保存订单 + wxOrderMapper.insertSelective(record); + } catch (RuntimeException e) { + logger.error("保存订单:" + e.getMessage()); + throw new MallinkException(ErrorCode.ORDER_SAVE_ERR); + } + return record; + } + /** * 创建 couponOrder * @@ -397,6 +530,7 @@ public class WxOrderServiceImpl implements WxOrderService { record.setTenantId(user.getTenantId()); record.setOrderNumber(orderNumber); record.setCouponId(couponId); + record.setType(EnumOrderType.COUPON.getCode()); record.setCUserId(user.getId()); record.setMerchantId(coupon.getMerchantId()); record.setPaymentType(EnumPayType.PAY_PAYMENT.getCode()); @@ -476,6 +610,7 @@ public class WxOrderServiceImpl implements WxOrderService { record.setTenantId(user.getTenantId()); record.setOrderNumber(orderNumber); record.setCouponId(couponId); + record.setType(EnumOrderType.COUPON.getCode()); record.setCUserId(user.getId()); record.setMerchantId(coupon.getMerchantId()); record.setPaymentType(EnumPayType.PAY_PAYMENT.getCode()); @@ -538,12 +673,42 @@ public class WxOrderServiceImpl implements WxOrderService { logger.error("订单更新失败:" + e.getMessage()); throw new MallinkException(ErrorCode.ORDER_UPDATE_ERR); } - // 创建couponOrder + // 创建couponOrder + try { + createCouponOrder(user, updateOrder, coupon); + } catch (Exception e) { + logger.error("保存订单:" + e.getMessage()); + throw new MallinkException(ErrorCode.COUPON_ORDER_SAVE_ERR); + } + + // 成长值 计算 try { - createCouponOrder(user, updateOrder, coupon); + wxScoreRulesService.addScore(EnumScoreType.CONSUMPTION,updateOrder); } catch (Exception e) { - logger.error("保存订单:" + e.getMessage()); - throw new MallinkException(ErrorCode.COUPON_ORDER_SAVE_ERR); + logger.error("成长值:" + e.getMessage()); + } + return ret; + } + + @Override + @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) + public int microPayOrderSuccess(WxOrder updateOrder) { + Date currentDate = new Date(); + WxCUser user = wxCUserMapper.selectByPrimaryKey(updateOrder.getCUserId()); + if (user == null) { + logger.error("用户不存在, userId: " + updateOrder.getCUserId()); + throw new MallinkException(ErrorCode.USER_IS_EMPTY); + } + // 已支付,更新支付时间 + updateOrder.setPaymentTime(currentDate); + updateOrder.setOrderStatus(EnumOrderStatus.ORDER_STATUS_PAYMENT_SUCCESS.getCode()); + updateOrder.setUpdateDate(currentDate); + int ret = 0; + try { + ret = wxOrderMapper.updateByPrimaryKey(updateOrder); + } catch (Exception e) { + logger.error("订单更新失败:" + e.getMessage()); + throw new MallinkException(ErrorCode.ORDER_UPDATE_ERR); } // 成长值 计算 @@ -552,6 +717,7 @@ public class WxOrderServiceImpl implements WxOrderService { } catch (Exception e) { logger.error("成长值:" + e.getMessage()); } + return ret; } @@ -600,7 +766,8 @@ public class WxOrderServiceImpl implements WxOrderService { // 2. get pay order WxPayOrder payOrderQ = new WxPayOrder(); payOrderQ.setTenantId(order.getTenantId()); - payOrderQ.setPayOrderStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); + payOrderQ.setOrderId(order.getId()); + payOrderQ.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode()); List payOrders = wxPayOrderMapper.select(payOrderQ); for(WxPayOrder payOrder: payOrders) { @@ -651,4 +818,24 @@ public class WxOrderServiceImpl implements WxOrderService { return wxOrderMapper.selectDetailOfCUser(record); } + @Override + @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) + public void shareForMicroPay(String tenantId, Long orderId, Long payOrderId) { + // 微信分账 + try { + WxPayOrder wxPayOrder = new WxPayOrder(); + wxPayOrder.setTenantId(tenantId); + wxPayOrder.setId(payOrderId); + wxPayOrder.setOrderId(orderId); + wxPayOrder.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); + wxPayOrder = wxPayOrderMapper.selectOne(wxPayOrder); + if (wxPayOrder != null && + wxPayOrder.getShare().equals(EnumPayShare.YES.getCode())) { + wxProfitSharingOrderService.createSharingOrder(wxPayOrder); + } + } catch (Exception e) { + logger.error("微信分账: " + e.getMessage()); + } + } + } diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxPayOrderServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxPayOrderServiceImpl.java index 28e8858c6..e7d4c3cc0 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxPayOrderServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxPayOrderServiceImpl.java @@ -13,6 +13,7 @@ import com.iformall.enums.*; import com.iformall.exception.MallinkException; import com.iformall.mapper.*; import com.iformall.pay.*; +import com.iformall.service.WxCouponOrderService; import com.iformall.service.WxOrderService; import com.iformall.service.WxPayOrderService; import com.iformall.utils.BeanUtils; @@ -26,7 +27,6 @@ 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.*; @@ -61,9 +61,15 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { @Autowired WxMerchantMapper wxMerchantMapper; + @Autowired + WxMerchantBUserMapper wxMerchantBUserMapper; + @Autowired WxProfitSharingReceiverMapper wxProfitSharingReceiverMapper; + @Autowired + WxCouponOrderService wxCouponOrderService; + JSONObject errorMap = JSON.parseObject("{" + "\"NOAUTH\":{\"detail\":\"商户无此接口权限\",\"reason\":\"商户未开通此接口权限\",\"resolution\":\"请商户前往申请此接口权限\"}," + "\"NOTENOUGH\":{\"detail\":\"余额不足\",\"reason\":\"用户帐号余额不足\",\"resolution\":\"用户帐号余额不足,请用户充值或更换支付卡后再支付\"}," + @@ -130,7 +136,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { } // 2. check 是否有支付订单 Date currentDate = new Date(); - record.setPayOrderStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode()); List list = wxPayOrderMapper.findList(record); String payOrderNo = ""; if (list.size() <= 0) { @@ -148,7 +154,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { record.setPayOrderNo(payOrderNo); record.setPayAmount(order.getPayment()); record.setPayVendor(EnumPayWay.PAY_WAY_WEAPP.getCode()); - record.setPayOrderStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode()); record.setShare(isShare.getCode()); if (isShare == EnumPayShare.YES) { // 分账金额 @@ -351,6 +357,252 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { } } + @Override + public ResultData createMicroPayOrder(boolean isReal, WxMerchantBUser user, WxPayOrder record, EnumPayWay payWay) { + final IdWorker idworker = IdWorker.get(); + + WxAppinfo appInfo = getWxAppinfo(EnumOrderType.MICROPAY.getCode(), user.getTenantId()); + + EnumPayShare isShare = EnumPayShare.NO; + + try { + // 1. check 订单 + WxOrder order = wxOrderMapper.selectByPrimaryKey(record.getOrderId()); + if (order == null) { + logger.error("pay order, order not allow, repaymentReq: " + record.toString() + ", payWay: " + payWay.toString()); + throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND); + } + if (order.getOrderStatus() != EnumOrderStatus.ORDER_STATUS_PENDING_PAYMENT.getCode()) { + logger.error("pay order, order status not allow, repaymentReq: " + order.toString() + " , payWay: " + payWay.toString()); + throw new MallinkException(ErrorCode.ORDER_IS_NOT_PAY); + } + if (order.getPaymentType() != EnumPayType.PAY_PAYMENT.getCode()) { + return new ResultData(ErrorCode.PAY_ORDER_IS_NOT_PAYMENT); + } + WxPayAccount payAccount = wxPayAccountMapper.selectByPrimaryKey(appInfo.getPayId()); + if (payAccount.getShare().intValue() > 0) { + isShare = EnumPayShare.YES; + } + // 1.5 check 分账 receive + if (isShare == EnumPayShare.YES) { + WxProfitSharingReceiver receiver = new WxProfitSharingReceiver(); + receiver.setMerchantId(order.getMerchantId()); + List merList = wxProfitSharingReceiverMapper.findList(receiver); + if (merList.size() > 0) { + isShare = EnumPayShare.YES; + } else { + isShare = EnumPayShare.NO; + } + } + // 2. check 是否有支付订单 + Date currentDate = new Date(); + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode()); + List list = wxPayOrderMapper.findList(record); + String payOrderNo = ""; + String orderNo = String.valueOf(order.getId()); + if (list.size() <= 0) { + // 3. 创建支付订单 + Long id = idworker.nextId(); + payOrderNo = String.valueOf(id); + record.setId(id); + record.setTenantId(user.getTenantId()); + record.setbUserId(user.getId()); + record.setCreateTime(currentDate); + record.setUpdateTime(currentDate); + record.setPayTimeStart(currentDate); + record.setPayTimeEnd(currentDate); + // 支付单号 + record.setPayOrderNo(payOrderNo); + record.setPayAmount(order.getPayment()); + record.setPayVendor(EnumPayWay.PAY_WAY_WEAPP.getCode()); + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode()); + record.setShare(isShare.getCode()); + if (isShare == EnumPayShare.YES) { + // 分账金额 + Double dChargeFee = Math.ceil(record.getPayAmount() * 1.0D * payAccount.getRate() / 1000); + Integer share_amount = record.getPayAmount() - dChargeFee.intValue(); + record.setShareAmount(share_amount); + if (share_amount <= 0) { + isShare = EnumPayShare.NO; + record.setShare(isShare.getCode()); + } + } + + int sqlRow = wxPayOrderMapper.insertSelective(record); + if (sqlRow != 1) { + logger.error("pay order insert error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + } else { + record = list.get(0); + record.setShare(isShare.getCode()); + payOrderNo = String.valueOf(record.getId()); + } + + + if (isReal) { + // 微信实际支付 + if (payAccount.getType() == EnumPayMode.MCH.getCode()) { + // 刷卡支付 普通商户模式 + String noncestr = Utility.generate32UUID(); + WxMicroPayOrderP wxPayOrderP = new WxMicroPayOrderP(); + wxPayOrderP.setAppid(user.getAppId()); + wxPayOrderP.setMch_id(payAccount.getMchId()); + wxPayOrderP.setDevice_info(user.getPhone()); + wxPayOrderP.setNonce_str(noncestr); + wxPayOrderP.setBody(order.getDetail()); + wxPayOrderP.setOut_trade_no(record.getPayOrderNo()); + wxPayOrderP.setTotal_fee(order.getPayment()); + wxPayOrderP.setSpbill_create_ip(record.getIp()); // 终端IP + wxPayOrderP.setAuth_code(record.getAuthCode()); + wxPayOrderP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate)); + Date futureDate = new Date(); + futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000); + wxPayOrderP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); // 15分钟后结束 + Map payOrderMap = BeanUtils.toStringMap(wxPayOrderP); + wxPayOrderP.setSign(WxPayment.createSign(payOrderMap, payAccount.getApiKey())); + String response = WxPay.micropay(BeanUtils.toStringMap(wxPayOrderP)); + logger.info("pay order, wechat micropay, " + wxPayOrderP.toString() + ", response: " + response.toString()); + Map returnMap = WxPayment.xmlToMap(response); + returnMap.put("payOrderId", payOrderNo); + returnMap.put("orderId", orderNo); + String return_code = returnMap.get("return_code"); + String result_code = returnMap.get("result_code"); + if ("SUCCESS".equalsIgnoreCase(return_code)) { + if ("SUCCESS".equals(result_code)) { + String openId = returnMap.get("openid"); + String isSubscribe = returnMap.get("is_subscribe"); + String transactionId = returnMap.get("transaction_id"); + record.setTransactionId(transactionId); + record.setUpdateTime(new Date()); + handleMicroOrderPaySuccess(record, transactionId, openId, isSubscribe); + return new ResultData(Result.SUCCESS, "刷卡支付成功", returnMap); + } else { + String err_code = returnMap.get("err_code"); + String errMsg = returnMap.get("err_code_des"); + if (errMsg.length() <= 0) { + errMsg = returnMap.get("return_msg"); + } + record.setFailReason(errMsg); + record.setUpdateTime(new Date()); + try { + wxPayOrderMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay order update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap); + } + } else { + String errMsg = returnMap.get("return_msg"); + record.setFailReason(errMsg); + record.setUpdateTime(new Date()); + try { + wxPayOrderMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay order update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap); + } + } else { + // 统一下单 // 服务商模式 + String noncestr = Utility.generate32UUID(); + WxMicroPayOrderSP wxPayOrderSP = new WxMicroPayOrderSP(); + wxPayOrderSP.setAppid(appInfo.getParentAppId()); + wxPayOrderSP.setMch_id(payAccount.getMchId()); + wxPayOrderSP.setSub_appid(appInfo.getAppId()); + wxPayOrderSP.setSub_mch_id(payAccount.getSubMchId()); + wxPayOrderSP.setDevice_info(user.getPhone()); + wxPayOrderSP.setNonce_str(noncestr); + wxPayOrderSP.setBody(order.getDetail()); + wxPayOrderSP.setOut_trade_no(record.getPayOrderNo()); + wxPayOrderSP.setTotal_fee(order.getPayment()); + wxPayOrderSP.setSpbill_create_ip(record.getIp()); + wxPayOrderSP.setAuth_code(record.getAuthCode()); + wxPayOrderSP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate)); + Date futureDate = new Date(); + futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000); + wxPayOrderSP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); // 15分钟后结束 + wxPayOrderSP.setSign_type("HMAC-SHA256"); + wxPayOrderSP.setProfit_sharing(null); + if (isShare == EnumPayShare.YES) { + wxPayOrderSP.setProfit_sharing("Y"); + } + Map payOrderMap = BeanUtils.toStringMap(wxPayOrderSP); + + wxPayOrderSP.setSign(WxPayment.createSignHMAC(payOrderMap, payAccount.getApiKey())); + String response = WxPay.micropay(BeanUtils.toStringMap(wxPayOrderSP)); + logger.info("pay order, wechat micropay, " + wxPayOrderSP.toString() + ", response: " + response.toString()); + Map returnMap = WxPayment.xmlToMap(response); + returnMap.put("payOrderId", payOrderNo); + returnMap.put("orderId", orderNo); + String return_code = returnMap.get("return_code"); + String result_code = returnMap.get("result_code"); + if ("SUCCESS".equalsIgnoreCase(return_code)) { + if ("SUCCESS".equals(result_code)) { + String openId = returnMap.get("sub_openid"); + String isSubscribe = returnMap.get("sub_is_subscribe"); + String transactionId = returnMap.get("transaction_id"); + record.setTransactionId(transactionId); + record.setUpdateTime(new Date()); + handleMicroOrderPaySuccess(record, transactionId, openId, isSubscribe); + return new ResultData(Result.SUCCESS, "刷卡支付成功", returnMap); + } else { + String err_code = returnMap.get("err_code"); + String errMsg = returnMap.get("err_code_des"); + if (errMsg.length() <= 0) { + errMsg = returnMap.get("return_msg"); + } + record.setFailReason(errMsg); + record.setUpdateTime(new Date()); + try { + wxPayOrderMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay order update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap); + } + } else { + String errMsg = returnMap.get("return_msg"); + record.setFailReason(errMsg); + record.setUpdateTime(new Date()); + try { + wxPayOrderMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay order update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap); + } + } + } else { + // 虚拟支付 + WxMicroPayOrderP wxPayOrderP = new WxMicroPayOrderP(); + wxPayOrderP.setAppid(user.getAppId()); + wxPayOrderP.setMch_id(payAccount.getMchId()); + wxPayOrderP.setBody(order.getDetail()); + wxPayOrderP.setOut_trade_no(record.getPayOrderNo()); + wxPayOrderP.setTotal_fee(order.getPayment()); + wxPayOrderP.setSpbill_create_ip(record.getIp()); // 终端IP + wxPayOrderP.setDevice_info(user.getPhone()); + wxPayOrderP.setAuth_code(record.getAuthCode()); + wxPayOrderP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate)); + Date futureDate = new Date(); + futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000); + wxPayOrderP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); // 15分钟后结束 + wxPayOrderP.setSign(WxPayment.createSign(BeanUtils.toStringMap(wxPayOrderP), payAccount.getApiKey())); + Map returnMap = BeanUtils.toStringMap(wxPayOrderP); + 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 String wechatPayOrderQuery(WxAppinfo appInfo, WxPayOrder record) { // get payAccount @@ -406,45 +658,100 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { * 微信订单查询 */ @Override - public ResultData payOrderQuery(WxAppinfo appInfo, WxPayOrder record) { + public ResultData payOrderQuery(WxPayOrder record) { + try { if (StringUtils.isBlank(record.getPayOrderNo())) record.setPayOrderNo(String.valueOf(record.getId())); + + WxPayOrder payOrder = wxPayOrderMapper.selectByPrimaryKey(record.getId()); + if (payOrder != null) { + record.setPayOrderStatus(payOrder.getPayOrderStatus()); + } else { + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), "payOrder not found"); + } + + WxOrder order = wxOrderMapper.selectByPrimaryKey(record.getOrderId()); + if (order == null) { + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), "Order not found"); + } + + WxAppinfo appInfo = getWxAppinfo(order.getType(), record.getTenantId()); + String response = wechatPayOrderQuery(appInfo, record); logger.info("pay order query, " + record.toString() + ", response: " + response); Map returnMap = WxPayment.xmlToMap(response); + String return_code = returnMap.get("return_code"); 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.setPayOrderStatus(EnumPayStatus.PAY_WAY_SUCCESS.getCode()); - handlePayOrderStatusUpdate(record); - } else if ("USERPAYING".equals(trade_state)) { - record.setPayOrderStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); - handlePayOrderStatusUpdate(record); + if ("SUCCESS".equalsIgnoreCase(return_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)) { + String openId = returnMap.get("sub_openid"); + String sub_is_subscribe = returnMap.get("sub_is_subscribe"); + String transactionId = returnMap.get("transaction_id"); + String tradeType = returnMap.get("trade_type"); + if ("MICROPAY".equals(tradeType)) { + handleMicroOrderPaySuccess(record, transactionId, openId, sub_is_subscribe); + } else { + handleOrderPaySuccess(record, transactionId); + } + return new ResultData(Result.SUCCESS, "订单支付成功", returnMap); + } else if ("REFUND".equals(trade_state)) { + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_REFUND.getCode()); + // handlePayOrderStatusUpdate(record); + return new ResultData(ErrorCode.PAY_ORDER_REFUND, returnMap); + } else if ("NOTPAY".equals(trade_state)) { + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_NOTPAY.getCode()); + //handlePayOrderStatusUpdate(record); + return new ResultData(ErrorCode.PAY_ORDER_NOT_PAY, returnMap); + } else if ("CLOSED".equals(trade_state)) { + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_CLOSE.getCode()); + ///handlePayOrderStatusUpdate(record); + return new ResultData(ErrorCode.PAY_ORDER_CLOSED, returnMap); + } else if ("REVOKED".equals(trade_state)) { + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_REVERSE.getCode()); + // handlePayOrderStatusUpdate(record); + return new ResultData(ErrorCode.PAY_ORDER_REVERSE, returnMap); + } else if ("USERPAYING".equals(trade_state)) { + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode()); + // handlePayOrderStatusUpdate(record); + return new ResultData(ErrorCode.PAY_ORDER_PAYING, returnMap); + } else { + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_FAIL.getCode()); + // handlePayOrderStatusUpdate(record); + return new ResultData(ErrorCode.PAY_ORDER_ERROR, returnMap); + } } else { - record.setPayOrderStatus(EnumPayStatus.PAY_WAY_FAIL.getCode()); - handlePayOrderStatusUpdate(record); + String errMsg = ""; + JSONObject errObj = errorMapQuery.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 { + wxPayOrderMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay order update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap); } - return new ResultData(Result.SUCCESS, "订单查询成功", returnMap); } else { - String errMsg = ""; - JSONObject errObj = errorMapQuery.getJSONObject(result_code); - if (errObj != null) { - errMsg = errObj.toJSONString(); - record.setFailReason(errMsg); - } else { - errMsg = returnMap.get("return_msg"); - record.setFailReason(errMsg); - } + String errMsg = returnMap.get("return_msg"); + record.setFailReason(errMsg); record.setUpdateTime(new Date()); try { wxPayOrderMapper.updateByPrimaryKeySelective(record); @@ -480,6 +787,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { payOrderC.setSign(WxPayment.createSign(map, payAccount.getApiKey())); map = BeanUtils.toStringMap(payOrderC); String response = WxPay.closeOrder(map); + logger.info("request:" + map.toString() + "\nresponse:" + response); return response; } catch (RuntimeException e) { throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); @@ -503,6 +811,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { payOrderSC.setSign(WxPayment.createSignHMAC(map, payAccount.getApiKey())); map = BeanUtils.toStringMap(payOrderSC); String response = WxPay.closeOrder(map); + logger.info("request:" + map.toString() + "\nresponse:" + response); return response; } catch (RuntimeException e) { throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); @@ -523,19 +832,158 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { logger.info("pay order close, " + record.toString() + ", response: " + response); Map returnMap = WxPayment.xmlToMap(response); + String return_code = returnMap.get("return_code"); String result_code = returnMap.get("result_code"); - if ("SUCCESS".equals(result_code)) { - record.setPayOrderStatus(EnumPayStatus.PAY_WAY_CANCEL.getCode()); - handlePayOrderStatusUpdate(record); - return new ResultData(Result.SUCCESS, "订单关闭成功", returnMap); + if ("SUCCESS".equalsIgnoreCase(return_code)) { + if ("SUCCESS".equals(result_code)) { + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_CANCEL.getCode()); + handlePayOrderStatusUpdate(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 { + wxPayOrderMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay order update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap); + } } else { - String errMsg = ""; - JSONObject errObj = errorMapClose.getJSONObject(result_code); - if (errObj != null) { - errMsg = errObj.toJSONString(); + String errMsg = returnMap.get("return_msg"); + record.setFailReason(errMsg); + record.setUpdateTime(new Date()); + try { + wxPayOrderMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay order 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()); + } + } + + private String wechatPayOrderReverse(WxAppinfo appInfo, WxPayOrder record) { + // get payAccount + WxPayAccount payAccount = wxPayAccountMapper.selectByPrimaryKey(appInfo.getPayId()); + if (payAccount.getType() == EnumPayMode.MCH.getCode()) { + // 普通商户号模式 + WxPayOrderQ payOrderC = new WxPayOrderQ(); + String noncestr = Utility.generate32UUID(); + payOrderC.setAppid(appInfo.getAppId()); + payOrderC.setMch_id(payAccount.getMchId()); + payOrderC.setNonce_str(noncestr); + payOrderC.setOut_trade_no(record.getPayOrderNo()); + + try { + Map map = BeanUtils.toStringMap(payOrderC); + payOrderC.setSign(WxPayment.createSign(map, payAccount.getApiKey())); + map = BeanUtils.toStringMap(payOrderC); + String response = WxPay.orderReverse(map, payAccount.getCertPath(), payAccount.getMchId()); + logger.info("request:" + map.toString() + "\nresponse:" + response); + 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 payOrderSC = new WxPayOrderSQ(); + String noncestr = Utility.generate32UUID(); + payOrderSC.setAppid(appInfo.getParentAppId()); + payOrderSC.setSub_appid(appInfo.getAppId()); + payOrderSC.setMch_id(payAccount.getMchId()); + payOrderSC.setSub_mch_id(payAccount.getSubMchId()); + payOrderSC.setNonce_str(noncestr); + payOrderSC.setOut_trade_no(record.getPayOrderNo()); + payOrderSC.setSign_type("HMAC-SHA256"); + + try { + Map map = BeanUtils.toStringMap(payOrderSC); + payOrderSC.setSign(WxPayment.createSignHMAC(map, payAccount.getApiKey())); + map = BeanUtils.toStringMap(payOrderSC); + String response = WxPay.orderReverse(map, payAccount.getCertPath(), payAccount.getMchId()); + logger.info("request:" + map.toString() + "\nresponse:" + response); + 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 payOrderReverse(WxPayOrder record) { + + WxAppinfo appInfo = getWxAppinfo(EnumOrderType.MICROPAY.getCode(), record.getTenantId()); + + try { + String response = wechatPayOrderReverse(appInfo, record); + + logger.info("pay order reverse, " + record.toString() + ", response: " + response); + Map returnMap = WxPayment.xmlToMap(response); + String return_code = returnMap.get("return_code"); + String result_code = returnMap.get("result_code"); + if ("SUCCESS".equalsIgnoreCase(return_code)) { + if ("SUCCESS".equals(result_code)) { + record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_REVERSE.getCode()); + record.setUpdateTime(new Date()); + try { + wxPayOrderMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay order update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + WxOrder order = new WxOrder(); + order.setId(record.getOrderId()); + order.setType(EnumOrderType.MICROPAY.getCode()); + order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_OVERTIME_CANCEL.getCode()); + order.setUpdateDate(new Date()); + try { + wxOrderMapper.updateByPrimaryKeySelective(order); + } catch (Exception e) { + logger.error("order update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return new ResultData(Result.SUCCESS, "订单撤销成功", returnMap); } else { - errMsg = returnMap.get("return_msg"); + 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 { + wxPayOrderMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("pay order update error: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap); } + } else { + String errMsg = returnMap.get("return_msg"); record.setFailReason(errMsg); record.setUpdateTime(new Date()); try { @@ -546,6 +994,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { } 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) { @@ -574,6 +1023,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { // 普通商户号 appinfo = wxAppinfoMapper.findByAppId(appId); if (appinfo == null) { + logger.error("appid not found: " + appId); throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); } isNormal = true; @@ -581,6 +1031,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { // 服务号 现在用hmac-sha256 appinfo = wxAppinfoMapper.findByAppId(subAppId); if (appinfo == null) { + logger.error("subappid not found: " + subAppId); throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); } isNormal = false; @@ -678,7 +1129,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { Date currentDate = new Date(); EnumPayStatus payStatus = EnumPayStatus.getEnum(record.getPayOrderStatus()); // 判断支付状态 - if (payStatus == EnumPayStatus.PAY_WAY_SUCCESS) { + if (payStatus == EnumPayStatus.PAY_STATUS_SUCCESS) { // 已经是成功状态,只更新transactionId try { record.setUpdateTime(currentDate); @@ -690,14 +1141,14 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { } return; } - if (payStatus != EnumPayStatus.PAY_WAY_WAIT) { - logger.error("pay success handle, payOrder " + record.getPayOrderNo() + + if (payStatus != EnumPayStatus.PAY_STATUS_WAIT) { + logger.info("pay success handle, payOrder " + record.getPayOrderNo() + "is paid success , orderId : " + record.getOrderId()); return; } WxOrder order = wxOrderMapper.selectByPrimaryKey(record.getOrderId()); if (order == null) { - logger.error("pay success handle, order " + record.getOrderId() + " not found , payOrderGid : " + record.getPayOrderNo()); + logger.error("pay success handle, order " + record.getOrderId() + " not found , payOrderid : " + record.getPayOrderNo()); throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND); } @@ -707,7 +1158,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { updateOrder.setId(record.getId()); updateOrder.setOrderId(record.getOrderId()); updateOrder.setUpdateTime(currentDate); - updateOrder.setPayOrderStatus(EnumPayStatus.PAY_WAY_SUCCESS.getCode()); + updateOrder.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); updateOrder.setTransactionId(transactionId); try { wxPayOrderMapper.updateByPrimaryKeySelective(updateOrder); @@ -742,30 +1193,153 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { */ } + @Override + @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) + public void handleMicroOrderPaySuccess(WxPayOrder record, String transactionId, String openId, String isSubscribe) { + Date currentDate = new Date(); + EnumPayStatus payStatus = EnumPayStatus.getEnum(record.getPayOrderStatus()); + // 判断支付状态 + if (payStatus == EnumPayStatus.PAY_STATUS_SUCCESS) { + // 已经是成功状态,只更新transactionId + try { + record.setUpdateTime(currentDate); + record.setTransactionId(transactionId); + record.setFailReason(""); + wxPayOrderMapper.updateByPrimaryKeySelective(record); + } catch (Exception e) { + logger.error("更新transactionId: " + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return; + } + if (payStatus != EnumPayStatus.PAY_STATUS_WAIT) { + logger.info("pay success handle, payOrder " + record.getPayOrderNo() + + "is paid success , orderId : " + record.getOrderId()); + return; + } + + WxOrder order = wxOrderMapper.selectByPrimaryKey(record.getOrderId()); + if (order == null) { + logger.error("pay success handle, order " + record.getOrderId() + " not found , payOrderid : " + record.getPayOrderNo()); + throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND); + } + + WxAppinfo appinfo = getWxAppinfo(EnumOrderType.MICROPAY.getCode(), order.getTenantId()); + + // add c_user + Date curDate = new Date(); + WxCUser userQ = new WxCUser(); + userQ.setOpenId(openId); + userQ.setAppId(appinfo.getAppId()); + WxCUser user1 = wxCUserMapper.findByOpenId(userQ); + if (user1 == null) { + final IdWorker idWorker = IdWorker.get(); + userQ.setId(idWorker.nextId()); + userQ.setCreateDate(curDate); + userQ.setUpdateDate(curDate); + if ("N".equalsIgnoreCase(isSubscribe)) { + userQ.setIsSubscribe(EnumUserIsSubscribe.NO.getCode()); + } else { + userQ.setIsSubscribe(EnumUserIsSubscribe.NO.getCode()); + } + wxCUserMapper.insertSelective(userQ); + } else { + userQ.setId(user1.getId()); + userQ.setUpdateDate(curDate); + if ("N".equalsIgnoreCase(isSubscribe)) { + userQ.setIsSubscribe(EnumUserIsSubscribe.NO.getCode()); + } else { + userQ.setIsSubscribe(EnumUserIsSubscribe.NO.getCode()); + } + wxCUserMapper.updateByPrimaryKeySelective(userQ); + } + record.setcUserId(userQ.getId()); + + // 修改支付订单状态 + WxPayOrder updateOrder = new WxPayOrder(); + updateOrder.setId(record.getId()); + updateOrder.setOrderId(record.getOrderId()); + updateOrder.setcUserId(userQ.getId()); + updateOrder.setUpdateTime(currentDate); + updateOrder.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); + updateOrder.setTransactionId(transactionId); + updateOrder.setFailReason(""); + try { + wxPayOrderMapper.updateByPrimaryKeySelective(updateOrder); + } catch (Exception e) { + logger.error("支付订单数据库更新失败: " + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "支付订单数据库更新失败: " + e.getMessage()); + } + + // 修改订单状态 + order.setCUserId(userQ.getId()); + try { + int _count = wxOrderService.microPayOrderSuccess(order); + if (_count > 1) { + logger.error("order micro pay count > 1"); + throw new MallinkException(ErrorCode.ORDER_IS_FAIL); + } + } catch (Exception e) { + logger.error("order status : " + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "订单更新"); + } + + // 延迟3秒后分账 + new Thread(() -> { + String tenantId = record.getTenantId(); + Long orderId = record.getOrderId(); + Long payOrderId = record.getId(); + try { + Thread.currentThread().sleep(3000); + } catch (Exception e) { + logger.error("sleep error: " + e.getMessage()); + } + + // 支付分账 + try { + wxOrderService.shareForMicroPay(tenantId, orderId, payOrderId); + logger.info("订单分账: orderId: {}, payOrderId: {}", orderId, payOrderId); + } catch (Exception e) { + logger.error("订单分账失败: orderId: {}, payOrderId: {}", orderId, payOrderId); + logger.error("订单分账失败: " +e.getMessage()); + } + }).start(); + + + // B端刷卡支付发券 + try { + wxCouponOrderService.sendCouponAfterMicroPay(record.getTenantId(), record.getOrderId(), record.getcUserId()); + } catch (Exception e) { + logger.error("订单刷卡失败: orderId: {}, payOrderId: {}", record.getOrderId(), record.getId()); + logger.error("订单刷卡失败: " +e.getMessage()); + } + } + @Override @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) public void handlePayOrderStatusUpdate(WxPayOrder record) { // 判断支付状态 - if (record.getPayOrderStatus() == EnumPayStatus.PAY_WAY_WAIT.getCode()) { + if (record.getPayOrderStatus() == EnumPayStatus.PAY_STATUS_WAIT.getCode()) { logger.error("pay handle, payOrder " + record.getPayOrderNo() + "is complete, orderId : " + record.getOrderId()); return; } WxOrder order = wxOrderMapper.selectByPrimaryKey(record.getOrderId()); if (order == null) { - logger.error("pay handle, order " + record.getOrderId() + " not found , payOrderGid : " + record.getPayOrderNo()); + logger.error("pay handle, order " + record.getOrderId() + " not found , payOrderid : " + record.getPayOrderNo()); throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND); } - WxCUser user = wxCUserMapper.selectByPrimaryKey(order.getCUserId()); - if (user == null) { - logger.error("pay handle, order " + record.getOrderId() + " not found , payOrderGid : " + record.getPayOrderNo()); - throw new MallinkException(ErrorCode.USER_IS_EMPTY); + if (order.getType().equals(EnumOrderType.COUPON.getCode())) { + WxCUser user = wxCUserMapper.selectByPrimaryKey(order.getCUserId()); + if (user == null) { + logger.error("pay handle, order " + record.getOrderId() + " not found , payOrderid : " + record.getPayOrderNo()); + throw new MallinkException(ErrorCode.USER_IS_EMPTY); + } } - if (order.getPayment() > 0) { // 订单金额不为0时, 支付订单未创建, 返回异常 - if (!(record.getId() >0)) { + if (!(record.getId() > 0)) { throw new MallinkException(ErrorCode.PAY_ORDER_NOT_FOUND); } } @@ -773,14 +1347,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { Date currentDate = new Date(); if (record.getId() > 0) { // 1. get appinfo - WxAppinfo appInfo = null; - WxAppinfo appinfoQ = new WxAppinfo(); - appinfoQ.setTenantId(order.getTenantId()); - appinfoQ.setType(EnumAppType.C.getCode()); - List appList = wxAppinfoMapper.select(appinfoQ); - if (appList.size() > 0) { - appInfo = appList.get(0); - } + WxAppinfo appInfo = getWxAppinfo(order.getType(), order.getTenantId()); WxPayOrder updateOrder = null; @@ -796,13 +1363,13 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { throw new MallinkException(ErrorCode.PAY_ORDER_NOT_FOUND); } - if (record.getPayOrderStatus() == EnumPayStatus.PAY_WAY_FAIL.getCode()) { - // 支付订单取消 + if (record.getPayOrderStatus() == EnumPayStatus.PAY_STATUS_FAIL.getCode()) { + // 支付订单失败,取消此订单 if (record.getPayAmount() > 0) { payOrderQ = new WxPayOrder(); payOrderQ.setTenantId(order.getTenantId()); payOrderQ.setOrderId(record.getOrderId()); - payOrderQ.setPayOrderStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); + payOrderQ.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode()); List payOrders = wxPayOrderMapper.select(payOrderQ); for (WxPayOrder payOrder : payOrders) { payOrderClose(appInfo, payOrder); @@ -810,15 +1377,15 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { } } else { // 支付订单成功? - if (updateOrder.getPayOrderStatus().equals(EnumPayStatus.PAY_WAY_SUCCESS.getCode())) { - if (StringUtils.isBlank(updateOrder.getTransactionId())) { + if (updateOrder.getPayOrderStatus().equals(EnumPayStatus.PAY_STATUS_SUCCESS.getCode())) { + if (StringUtils.isNotBlank(updateOrder.getTransactionId())) { // 回调已设置成功 // 继续修改订单状态 } else { // 回调异常 throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), "transactionId未获取"); } - } else if (updateOrder.getPayOrderStatus().equals(EnumPayStatus.PAY_WAY_WAIT.getCode())) { + } else if (updateOrder.getPayOrderStatus().equals(EnumPayStatus.PAY_STATUS_WAIT.getCode())) { // 回调未返回,主动检查支付订单状态 try { record.setPayOrderNo(String.valueOf(record.getId())); @@ -839,6 +1406,8 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { if ("SUCCESS".equals(trade_state)) { // 查询支付订单 -- 已支付 // 继续更改状态 + } else if ("USERPAYING".equals(trade_state)) { + // 继续检查状态 } else { // 支付订单未成功,返回异常 throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), "支付订单未成功"); @@ -856,7 +1425,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { } // 修改订单状态 - if (record.getPayOrderStatus() == EnumPayStatus.PAY_WAY_SUCCESS.getCode()) { + if (record.getPayOrderStatus() == EnumPayStatus.PAY_STATUS_SUCCESS.getCode()) { try { int _count = wxOrderService.orderSuccess(order); if (_count > 1) { @@ -866,7 +1435,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { logger.error(e.getMessage()); throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "订单更新"); } - } else if (record.getPayOrderStatus() == EnumPayStatus.PAY_WAY_FAIL.getCode()) { + } else if (record.getPayOrderStatus() == EnumPayStatus.PAY_STATUS_CANCEL.getCode()) { try { int _count = wxOrderService.updateOrderStatus(order, EnumOrderStatus.ORDER_STATUS_OVERTIME_CANCEL); if (_count > 1) { @@ -892,6 +1461,18 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { */ } + private WxAppinfo getWxAppinfo(Integer orderType, String tenentId) { + WxAppinfo appInfo = null; + WxAppinfo appinfoQ = new WxAppinfo(); + appinfoQ.setTenantId(tenentId); + appinfoQ.setType(EnumAppType.C.getCode()); + List appList = wxAppinfoMapper.select(appinfoQ); + if (appList.size() > 0) { + appInfo = appList.get(0); + } + return appInfo; + } + @Override public PageInfo listAsPage(WxPayOrder record, Integer pageIndex, Integer pageSize) { diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxRefundOrderServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxRefundOrderServiceImpl.java index fde2bac94..d9a1453fb 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxRefundOrderServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxRefundOrderServiceImpl.java @@ -291,6 +291,7 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService { rOrder.setTenantId(appInfo.getTenantId()); rOrder.setOrderNumber(wxOrder.getOrderNumber()); // 退款订单填写支付订单orderNumber rOrder.setCouponId(wxOrder.getCouponId()); + rOrder.setType(EnumOrderType.COUPON.getCode()); rOrder.setCUserId(wxOrder.getCUserId()); if (refundWay == EnumRefundWay.B) { rOrder.setBUserId(bUserId); @@ -338,7 +339,349 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService { payOrderQ.setTenantId(appInfo.getTenantId()); payOrderQ.setcUserId(wxOrder.getCUserId()); payOrderQ.setOrderId(wxOrder.getId()); - payOrderQ.setPayOrderStatus(EnumPayStatus.PAY_WAY_SUCCESS.getCode()); + payOrderQ.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); + + WxPayOrder payOrder = null; + List list = wxPayOrderMapper.findList(payOrderQ); + if (list.size() > 0) { + if (list.size() > 1) { + logger.error("TODO: payOrder成功记录应该只有一条????!!!"); + } + logger.warn(""); + payOrder = list.get(0); + } + if (payOrder == null) { + logger.error("支付订单不存在(payOrder不存在)"); + return new ResultData(ErrorCode.PAY_ORDER_NOT_FOUND); + } + + WxRefundOrder record = new WxRefundOrder(); + record.setPayOrderNo(String.valueOf(payOrder.getId())); + record.setOrderId(rOrder.getId()); + // 创建退款订单 + Long refundId = idWorker.nextId(); + String out_refund_id = String.valueOf(refundId); + + record.setId(refundId); + record.setTenantId(appInfo.getTenantId()); + record.setCreateTime(currentDate); + record.setUpdateTime(currentDate); + // 微信内部订单号 + record.setTransactionId(payOrder.getTransactionId()); + record.setCUserId(payOrder.getcUserId()); + record.setTotalFee(payOrder.getPayAmount()); + record.setRefundFee(payOrder.getPayAmount()); + record.setRefundTimeStart(currentDate); + record.setRefundOrderStatus(EnumRefundStatus.REFUND_WAIT.getCode()); + + // 退款订单 + try { + int sqlRow = wxRefundOrderMapper.insertSelective(record); + if (sqlRow != 1) { + logger.error("退款订单数据库插入出错: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + } catch (Exception e) { + logger.error("退款订单数据库插入出错: " + record.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + WxPayAccount payAccount = wxPayAccountMapper.selectByPrimaryKey(appInfo.getPayId()); + if (StringUtils.isBlank(payAccount.getApiKey())) { + logger.error("支付密钥为空"); + throw new MallinkException(ErrorCode.API_KEY_NOT_FOUND.getCode(), "支付密钥为空,请联系商城管理员"); + } + if (StringUtils.isBlank(payAccount.getCertPath())) { + logger.error("证书路径为空"); + throw new MallinkException(ErrorCode.CERT_PATH_NOT_FOUND.getCode(), "证书路径为空,请联系商城管理员"); + } + if (!Utility.isFileExist(payAccount.getCertPath())) { + logger.error("证书文件不存在"); + throw new MallinkException(ErrorCode.CERT_PATH_NOT_FOUND.getCode(), "证书文件不存在,请联系商城管理员"); + } + // check 是否有退款订单 + List refundList = wxRefundOrderMapper.findList(record); + if (refundList.size() > 0) { + logger.error("退款订单已存在, 无法再提交退款申请"); + throw new MallinkException(ErrorCode.REFUND_ORDER_EXIST.getCode(), "退款订单已存在, 无法再提交退款申请"); + } + + if (isReal) { + // 实际支付 + // 向微信提交退款申请 + if (payAccount.getType() == EnumPayMode.MCH.getCode()) { + // 普通商户模式 + String noncestr = Utility.generate32UUID(); + WxRefundOrderP wxRefundOrderP = new WxRefundOrderP(); + wxRefundOrderP.setAppid(appInfo.getAppId()); + wxRefundOrderP.setMch_id(payAccount.getMchId()); + wxRefundOrderP.setNonce_str(noncestr); + // 微信内部订单号 + if (record.getTransactionId() != null) + wxRefundOrderP.setTransaction_id(record.getTransactionId()); + // 支付订单号 + wxRefundOrderP.setOut_trade_no(payOrder.getPayOrderNo()); + // 退款支付订单号 + wxRefundOrderP.setOut_refund_no(out_refund_id); + wxRefundOrderP.setTotal_fee(record.getTotalFee()); + wxRefundOrderP.setRefund_fee(record.getRefundFee()); + if (refundWay == EnumRefundWay.B) { + wxRefundOrderP.setRefund_desc("B端商户退款"); + } else if (refundWay == EnumRefundWay.ADMIN) { + wxRefundOrderP.setRefund_desc("管理端商户退款"); + } else if (refundWay == EnumRefundWay.AUTO) { + wxRefundOrderP.setRefund_desc("超期自动退款"); + } else { + wxRefundOrderP.setRefund_desc("用户自己退款"); + } + wxRefundOrderP.setNotify_url(payAccount.getNotifyUrl() + "/refund"); + + Map signMap = null; + try { + signMap = BeanUtils.toStringMap(wxRefundOrderP); + } catch (Exception e) { + logger.error("退款命令生辰: " + e.getMessage()); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "退款签名异常"); + } + + String signAgent = WxPayment.createSign(signMap, payAccount.getApiKey()); + signMap.put("sign", signAgent); + String response = null; + try { + response = WxPay.orderRefund(signMap, payAccount.getCertPath(), payAccount.getMchId()); + } catch (Exception e) { + logger.error("退款异常: " + e.getMessage()); + throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "退款异常"); + } + logger.info("微信退款订单:" + wxRefundOrderP.toString() + ", response: " + response.toString()); + Map returnMap = WxPayment.xmlToMap(response); + String result_no = returnMap.get("result_code"); + String refund_id = returnMap.get("refund_id"); + // 设置 微信退款订单号 + record.setRefundId(refund_id); + record.setRefundVendor(EnumPayWay.PAY_WAY_WEAPP.getCode()); + if ("SUCCESS".equals(result_no)) { + logger.info("微信退款订单申请成功: " + returnMap.toString()); + try { + record.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_SUCCESS.getCode()); + wxRefundOrderMapper.updateByPrimaryKey(record); + return new ResultData(Result.SUCCESS, "退款订单申请成功", returnMap); + } catch (Exception e) { + logger.error("微信退款订单更新入库出错: " + e.getMessage() + ", record: " + record.toString()); + throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR); + } + } else { + logger.error("微信退款订单申请失败: " + response); + String errMsg = ""; + JSONObject errObj = errorRefundReqMap.getJSONObject(result_no); + if (errObj != null) { + errMsg = errObj.toJSONString(); + record.setFailReason(errMsg); + } else { + errMsg = returnMap.get("return_msg"); + record.setFailReason(errMsg); + } + record.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_FAIL.getCode()); + wxRefundOrderMapper.updateByPrimaryKey(record); + return new ResultData(ErrorCode.REFUND_ORDER_ERROR.getCode(), errMsg, returnMap); + } + } else { + // 服务商模式 + String noncestr = Utility.generate32UUID(); + WxRefundOrderSP wxRefundOrderSP = new WxRefundOrderSP(); + wxRefundOrderSP.setAppid(appInfo.getParentAppId()); + wxRefundOrderSP.setSub_appid(appInfo.getAppId()); + wxRefundOrderSP.setMch_id(payAccount.getMchId()); + wxRefundOrderSP.setSub_mch_id(payAccount.getSubMchId()); + wxRefundOrderSP.setNonce_str(noncestr); + // 微信内部订单号 + if (record.getTransactionId() != null) + wxRefundOrderSP.setTransaction_id(record.getTransactionId()); + // 支付订单号 + wxRefundOrderSP.setOut_trade_no(payOrder.getPayOrderNo()); + // 退款支付订单号 + wxRefundOrderSP.setOut_refund_no(out_refund_id); + wxRefundOrderSP.setTotal_fee(record.getTotalFee()); + wxRefundOrderSP.setRefund_fee(record.getRefundFee()); + if (refundWay == EnumRefundWay.B) { + wxRefundOrderSP.setRefund_desc("B端商户退款"); + } else if (refundWay == EnumRefundWay.ADMIN) { + wxRefundOrderSP.setRefund_desc("管理端商户退款"); + } else if (refundWay == EnumRefundWay.AUTO) { + wxRefundOrderSP.setRefund_desc("超期自动退款"); + } else { + wxRefundOrderSP.setRefund_desc("用户自己退款"); + } + wxRefundOrderSP.setNotify_url(payAccount.getNotifyUrl() + "/refund"); + wxRefundOrderSP.setSign_type("HMAC-SHA256"); + + Map signMap = null; + try { + signMap = BeanUtils.toStringMap(wxRefundOrderSP); + } catch (Exception e) { + logger.error("退款命令生辰: " + e.getMessage()); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "退款签名异常"); + } + + String signAgent = WxPayment.createSignHMAC(signMap, payAccount.getApiKey()); + signMap.put("sign", signAgent); + String response = null; + try { + response = WxPay.orderRefund(signMap, payAccount.getCertPath(), payAccount.getMchId()); + } catch (Exception e) { + logger.error("退款异常: " + e.getMessage()); + throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "退款异常"); + } + logger.info("微信退款订单:" + wxRefundOrderSP.toString() + ", response: " + response.toString()); + Map returnMap = WxPayment.xmlToMap(response); + String result_no = returnMap.get("result_code"); + String refund_id = returnMap.get("refund_id"); + // 设置 微信退款订单号 + record.setRefundId(refund_id); + record.setRefundVendor(EnumPayWay.PAY_WAY_WEAPP.getCode()); + if ("SUCCESS".equals(result_no)) { + logger.info("微信退款订单申请成功: " + returnMap.toString()); + try { + record.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_SUCCESS.getCode()); + wxRefundOrderMapper.updateByPrimaryKey(record); + return new ResultData(Result.SUCCESS, "退款订单申请成功", returnMap); + } catch (Exception e) { + logger.error("微信退款订单更新入库出错: " + e.getMessage() + ", record: " + record.toString()); + throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "订单状态更新失败"); + } + } else { + logger.error("微信退款订单申请失败: " + response); + String errMsg = ""; + JSONObject errObj = errorRefundReqMap.getJSONObject(result_no); + if (errObj != null) { + errMsg = errObj.toJSONString(); + record.setFailReason(errMsg); + } else { + errMsg = returnMap.get("return_msg"); + record.setFailReason(errMsg); + } + record.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_FAIL.getCode()); + wxRefundOrderMapper.updateByPrimaryKey(record); + throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), errMsg); + } + } + } else { + // 虚拟支付 + // 向微信提交退款申请 + String noncestr = Utility.generate32UUID(); + WxRefundOrderP wxRefundOrderP = new WxRefundOrderP(); + wxRefundOrderP.setAppid(appInfo.getAppId()); + wxRefundOrderP.setMch_id(payAccount.getMchId()); + wxRefundOrderP.setNonce_str(noncestr); + // 微信内部订单号 + if (record.getTransactionId() != null) + wxRefundOrderP.setTransaction_id(record.getTransactionId()); + // 支付订单号 + wxRefundOrderP.setOut_trade_no(payOrder.getPayOrderNo()); + // 退款支付订单号 + wxRefundOrderP.setOut_refund_no(out_refund_id); + wxRefundOrderP.setTotal_fee(record.getTotalFee()); + wxRefundOrderP.setRefund_fee(record.getRefundFee()); + if (refundWay == EnumRefundWay.B) { + wxRefundOrderP.setRefund_desc("B端商户退款"); + } else if (refundWay == EnumRefundWay.ADMIN) { + wxRefundOrderP.setRefund_desc("管理端商户退款"); + } else if (refundWay == EnumRefundWay.AUTO) { + wxRefundOrderP.setRefund_desc("超期自动退款"); + } else { + wxRefundOrderP.setRefund_desc("用户自己退款"); + } + wxRefundOrderP.setNotify_url(payAccount.getNotifyUrl() + "/refund"); + + Map returnMap = null; + try { + returnMap = BeanUtils.toStringMap(wxRefundOrderP); + } catch (Exception e) { + logger.error("退款签名异常"); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "退款签名异常"); + } + try { + record.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_SUCCESS.getCode()); + wxRefundOrderMapper.updateByPrimaryKey(record); + return new ResultData(Result.SUCCESS, "退款订单申请成功", returnMap); + } catch (Exception e) { + logger.error("微信退款订单更新入库出错: " + e.getMessage() + ", record: " + record.toString()); + throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR); + } + } + } + + @Override + @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) + public ResultData createRefundOrderFromMicroPay(boolean isReal, WxAppinfo appInfo, Long orderId, EnumRefundWay refundWay, Long bUserId) { + WxOrder wxOrder = wxOrderMapper.selectByPrimaryKey(orderId); + + if (refundWay == EnumRefundWay.B) { + logger.info("B端发起退款: bUserId-" + bUserId); + if (bUserId == null || bUserId == 0) { + logger.error("B端用户不存在:" + bUserId); + throw new MallinkException(ErrorCode.USER_IS_EMPTY); + } + // B端用户退款检查一下商户 + WxMerchantBUser wxMerchantBUser = wxMerchantBUserMapper.selectByPrimaryKey(bUserId); + if (wxMerchantBUser == null) { + logger.error("操作员ID不存在:" + bUserId); + throw new MallinkException(ErrorCode.COUPON_ORDER_BUSER_IS_NULL); + } + if (!wxOrder.getMerchantId().equals(wxMerchantBUser.getMerchantId())) { + logger.error("券: couponMerchantId-" + wxOrder.getMerchantId() + "核销: couponMerchantId-" + wxMerchantBUser.getMerchantId()); + throw new MallinkException(ErrorCode.COUPON_ORDER_BUSER_IS_NULL); + } + } else if (refundWay == EnumRefundWay.ADMIN) { + logger.info("ADMIN端发起退款: bUserId-" + bUserId); + } else if (refundWay == EnumRefundWay.AUTO) { + logger.info("auto端发起退款"); + } else { + logger.info("自己发起退款: cUserId-" + bUserId); + } + if (wxOrder.getPayment() <= 0) { + logger.error("订单支付金额小于等于0: " + wxOrder.toString()); + throw new MallinkException(ErrorCode.REFUND_PAY_ORDER_IS_ZERO); + } + final IdWorker idWorker = IdWorker.get(); + Long refundOrderId = idWorker.nextId(); + + Date currentDate = new Date(); + + // 创建 refund Order + WxOrder rOrder = new WxOrder(); + rOrder.setId(refundOrderId); + rOrder.setTenantId(appInfo.getTenantId()); + rOrder.setOrderNumber(wxOrder.getOrderNumber()); // 退款订单填写支付订单orderNumber + rOrder.setType(EnumOrderType.MICROPAY.getCode()); + rOrder.setCUserId(wxOrder.getCUserId()); + if (refundWay == EnumRefundWay.B) { + rOrder.setBUserId(bUserId); + } else if (refundWay == EnumRefundWay.AUTO) { + rOrder.setBUserId(0L); // 自动退款, 设置bUserId为0 + } else if (refundWay == EnumRefundWay.ADMIN) { + rOrder.setBUserId(1L); // ADMIN发起退款, 设置bUserId为1 + } else { + rOrder.setBUserId(2L); // 自己发起退款, 设置bUserId为2 + } + rOrder.setMerchantId(wxOrder.getMerchantId()); + rOrder.setPaymentType(EnumPayType.PAY_REFUND.getCode()); + rOrder.setPayment(wxOrder.getPayment()); + rOrder.setOrderStatus(EnumOrderStatus.ORDER_STATUS_PENDING_REFUND.getCode()); + rOrder.setCreateDate(currentDate); + rOrder.setUpdateDate(currentDate); + try { + wxOrderMapper.insertSelective(rOrder); + } catch (Exception e) { + logger.error("退款订单保存出错: " + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "退款订单保存出错"); + } + + // 查找支付订单 + WxPayOrder payOrderQ = new WxPayOrder(); + payOrderQ.setTenantId(appInfo.getTenantId()); + payOrderQ.setcUserId(wxOrder.getCUserId()); + payOrderQ.setOrderId(wxOrder.getId()); + payOrderQ.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); WxPayOrder payOrder = null; List list = wxPayOrderMapper.findList(payOrderQ); diff --git a/mallinkService/src/main/resources/mapper/WxCUserMapper.xml b/mallinkService/src/main/resources/mapper/WxCUserMapper.xml index 7ca2710a2..08026b173 100644 --- a/mallinkService/src/main/resources/mapper/WxCUserMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxCUserMapper.xml @@ -31,10 +31,15 @@ + - `id`,`tenant_id`,`open_id`,`union_id`,`nick_name`,`gender`,`avatar_url`,`phone`,`pure_phone`,`city`,`province`,`language`,`country_code`,`register_ip`,`verify_code_phone`,`qrcode_source`,`scene`,`scene_address`,`session_key`,`score`,`update_date`,`create_date`,`app_id`,`token`,`expire_time`,`latitude`, `longitude`, `login_count`, `extra_info` + `id`,`tenant_id`,`open_id`,`union_id`,`nick_name`,`gender`,`avatar_url`,`phone`,`pure_phone`, + `city`,`province`,`language`,`country_code`,`register_ip`,`verify_code_phone`, + `qrcode_source`,`scene`,`scene_address`,`session_key`,`score`, + `update_date`,`create_date`,`app_id`,`token`,`expire_time`,`latitude`, `longitude`, + `login_count`, `extra_info`, `is_subscribe` @@ -156,6 +161,10 @@ and `extra_info` = #{extraInfo} + + and `is_subscribe` = #{isSubscribe} + + and id in diff --git a/mallinkService/src/main/resources/mapper/WxOrderMapper.xml b/mallinkService/src/main/resources/mapper/WxOrderMapper.xml index e4824de3e..ba53e8f5e 100644 --- a/mallinkService/src/main/resources/mapper/WxOrderMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxOrderMapper.xml @@ -1,155 +1,150 @@ - - - - - - - - - - - - - - - - - - - `id`,`order_number`,`tenant_id`,`c_user_id`,`merchant_id`,`b_user_id`,`payment_type`,`payment`,`payment_time`,`order_status`,`create_date`,`update_date`,`detail` - + + + + + + + + + + + + + + + + + - - where 1 = 1 - - - and `id` = #{id} - - - - - and `order_number` = #{orderNumber} - - - - - and `tenant_id` = #{tenantId} - - - - - and `c_user_id` = #{cUserId} - - - - - and `merchant_id` = #{merchantId} - - - - - and `b_user_id` = #{bUserId} - - - - - and `coupon_id` = #{couponId} - - - - - and `payment_type` = #{paymentType} - - - - - and `payment` = #{payment} - - - - - and `payment_time` = #{paymentTime} - - - - - and `order_status` = #{orderStatus} - - - - - and `create_date` = #{createDate} - - - - - and `update_date` = #{updateDate} - - - - - and `detail` like concat('%', #{detail},'%') - - - - and id in - - #{idItem} - - - order by ${sortColumns} + + `id`,`order_number`,`tenant_id`,`c_user_id`,`merchant_id`,`coupon_id`,`type`,`b_user_id`,`payment_type`,`payment`,`payment_time`,`order_status`,`create_date`,`update_date`,`detail` - - - - - - - - - - - + + + where 1 = 1 + + + and `id` = #{id} + + + + and `order_number` = #{orderNumber} + + + + and `tenant_id` = #{tenantId} + + + + and `c_user_id` = #{cUserId} + + + + and `merchant_id` = #{merchantId} + + + + and `b_user_id` = #{bUserId} + + + + and `coupon_id` = #{couponId} + + + + and `type` = #{type} + + + + and `payment_type` = #{paymentType} + + + + and `payment` = #{payment} + + + + and `payment_time` = #{paymentTime} + + + + and `order_status` = #{orderStatus} + + + + and `create_date` = #{createDate} + + + + and `update_date` = #{updateDate} + + + + and `detail` like concat('%', #{detail},'%') + + + and id in + + #{idItem} + + + order by ${sortColumns} + + + + + + + + + + + + o.id,o.order_number,o.tenant_id,o.c_user_id,o.merchant_id,o.b_user_id,o.payment_type,o.payment,o.payment_time,o.order_status,o.create_date,o.update_date, co.cover_img,co.title,co.sub_title,co.sale_price,co.use_price,co.price, m.name - + o.id,o.order_number,o.tenant_id,o.c_user_id,o.merchant_id,o.b_user_id,o.payment_type,o.payment,o.payment_time,o.order_status,o.create_date,o.update_date, co.type,co.cover_img,co.title,co.sub_title,co.sale_price,co.use_price,co.price,co.detail,co.remark, m.img_url,m.name,m.link_phone,m.status, @@ -158,88 +153,141 @@ c.id as coupon_order_id,c.coupon_order_status - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + select + + from wx_order o,wx_coupon co,wx_merchant m + where o.coupon_id = co.id + and co.merchant_id = m.id + + and o.c_user_id = #{cUserId} + + + and o.tenant_id = #{tenantId} + + + AND o.order_status = #{orderStatus} + + order by ${sortColumns} + + + + left join wx_merchant_shop ms on ms.merchant_id = m.id and ms.is_del = 0 + left join wx_shop s on ms.shop_id = s.id + left join wx_mall_building mb on s.building = mb.id + left join wx_mall_floor mf on s.floor = mf.id + where o.coupon_id = co.id + and co.merchant_id = m.id + + and o.c_user_id = #{cUserId} + + + and o.tenant_id = #{tenantId} + + + and o.id = #{id} + + + + + + + diff --git a/mallinkService/src/main/resources/mapper/WxPayOrderMapper.xml b/mallinkService/src/main/resources/mapper/WxPayOrderMapper.xml index c6fff3b33..99e0530d1 100644 --- a/mallinkService/src/main/resources/mapper/WxPayOrderMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxPayOrderMapper.xml @@ -8,6 +8,8 @@ + + @@ -23,7 +25,10 @@ - `id`,`tenant_id`,`create_time`,`update_time`,`order_id`,`c_user_id`,`ip`,`pay_amount`,`pay_time_start`,`pay_time_end`,`prepay_id`,`transaction_id`,`pay_vendor`,`pay_order_no`,`pay_order_status`,`share`,`share_amount`,`fail_reason` + `id`,`tenant_id`,`create_time`,`update_time`,`order_id`,`c_user_id`,`b_user_id`, + `auth_code`,`ip`,`pay_amount`,`pay_time_start`,`pay_time_end`, + `prepay_id`,`transaction_id`,`pay_vendor`,`pay_order_no`, + `pay_order_status`,`share`,`share_amount`,`fail_reason` @@ -53,6 +58,14 @@ and `c_user_id` = #{cUserId} + + and `b_user_id` = #{bUserId} + + + + and `auth_code` = #{authCode} + + and `ip` like concat('%', #{ip},'%')