Commit 30a07ff1 by 程裕兵

feat:axf

parent a8bc1326
package com.jiejing.fitness.finance.api.axf;
import com.jiejing.common.model.JsonResult;
import com.jiejing.common.model.PageVO;
import com.jiejing.common.request.IdRequest;
import com.jiejing.fitness.finance.api.axf.request.*;
import com.jiejing.fitness.finance.api.axf.vo.*;
import com.jiejing.fitness.request.StudioIdRequest;
import com.jiejing.paycenter.common.model.vo.BindCardVO;
import io.swagger.annotations.ApiOperation;
import java.util.List;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
/**
* 安心付
*
* @author chengyubing
* @since 2024/9/7 11:00
*/
@FeignClient(name = "FINANCE", url = "${rpc.url.fit-finance:http://app-fit-finance:7008}", fallbackFactory = StudioAxfApiFallback.class)
public interface StudioAxfApi {
@ApiOperation(value = "authToken")
@PostMapping(value = "/private/axf/authToken")
JsonResult<StudioAuthTokenVO> authToken(AxfAuthTokenRequest request);
@ApiOperation(value = "getAuthToken")
@PostMapping(value = "/private/axf/getAuthToken")
JsonResult<StudioAuthTokenVO> getAuthToken(GetAxfAuthTokenRequest request);
@ApiOperation(value = "申请开通安心付")
@PostMapping(value = "/private/axf/apply")
JsonResult<Long> apply(StudioAxfApplyRequest request);
@ApiOperation(value = "查询可绑定的安心付结算账户")
@PostMapping(value = "/private/axf/listSettleAccount")
JsonResult<List<String>> listSettleAccount(ListAxfSettleAccountRequest request);
@ApiOperation(value = "绑定结算账户")
@PostMapping(value = "/private/axf/bindCard")
JsonResult<BindCardVO> bindCard(BindAxfSettleAccountRequest request);
@ApiOperation(value = "获取最新一条安心付申请记录")
@PostMapping(value = "/private/axf/getLatestApply")
JsonResult<StudioAxfApplyVO> getLatestApply(GetLatestAxfApplyRequest request);
@ApiOperation(value = "查询开通安心付申请结果")
@PostMapping(value = "/private/axf/getById")
JsonResult<StudioAxfApplyVO> getById(IdRequest request);
@ApiOperation(value = "获取当前绑定的商户信息(开通中、开通失败、未开通都返回null)")
@PostMapping(value = "/private/axf/getMerchant")
JsonResult<StudioAxfApplyVO> getMerchant(StudioIdRequest request);
@ApiOperation(value = "分页查询开通安心付申请记录")
@PostMapping(value = "/private/axf/page")
JsonResult<PageVO<StudioAxfApplyVO>> page(PageStudioAxfApplyRequest request);
@ApiOperation(value = "统计")
@PostMapping(value = "/private/axf/agg")
JsonResult<AggStudioAxfApplyVO> agg();
}
package com.jiejing.fitness.finance.api.axf;
import com.jiejing.common.model.JsonResult;
import com.jiejing.common.model.PageVO;
import com.jiejing.common.request.IdRequest;
import com.jiejing.fitness.finance.api.axf.request.AxfAuthTokenRequest;
import com.jiejing.fitness.finance.api.axf.request.BindAxfSettleAccountRequest;
import com.jiejing.fitness.finance.api.axf.request.GetAxfAuthTokenRequest;
import com.jiejing.fitness.finance.api.axf.request.GetLatestAxfApplyRequest;
import com.jiejing.fitness.finance.api.axf.request.StudioAxfApplyRequest;
import com.jiejing.fitness.finance.api.axf.request.ListAxfSettleAccountRequest;
import com.jiejing.fitness.finance.api.axf.request.PageStudioAxfApplyRequest;
import com.jiejing.fitness.finance.api.axf.vo.AggStudioAxfApplyVO;
import com.jiejing.fitness.finance.api.axf.vo.StudioAuthTokenVO;
import com.jiejing.fitness.finance.api.axf.vo.StudioAxfApplyVO;
import com.jiejing.fitness.request.StudioIdRequest;
import com.jiejing.paycenter.common.model.vo.BindCardVO;
import feign.hystrix.FallbackFactory;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 安心付
*
* @author chengyubing
* @since 2024/9/7 11:00
*/
@Slf4j
@Component
public class StudioAxfApiFallback implements FallbackFactory<StudioAxfApi> {
@Override
public StudioAxfApi create(Throwable throwable) {
return new StudioAxfApi() {
@Override
public JsonResult<StudioAuthTokenVO> authToken(AxfAuthTokenRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<StudioAuthTokenVO> getAuthToken(GetAxfAuthTokenRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<Long> apply(StudioAxfApplyRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<List<String>> listSettleAccount(ListAxfSettleAccountRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<BindCardVO> bindCard(BindAxfSettleAccountRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<StudioAxfApplyVO> getLatestApply(GetLatestAxfApplyRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<StudioAxfApplyVO> getById(IdRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<StudioAxfApplyVO> getMerchant(StudioIdRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<PageVO<StudioAxfApplyVO>> page(PageStudioAxfApplyRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<AggStudioAxfApplyVO> agg() {
return JsonResult.rpcError();
}
};
}
}
package com.jiejing.fitness.finance.api.axf;
import com.jiejing.common.model.JsonResult;
import com.jiejing.fitness.finance.api.axf.request.CreateStudioAxfCommodityRequest;
import com.jiejing.fitness.finance.api.axf.request.GetStudioAxfCommodityRequest;
import com.jiejing.paycenter.common.model.vo.CommodityVO;
import com.jiejing.paycenter.common.model.vo.CreateCommodityVO;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
/**
* 安心付
*
* @author chengyubing
* @since 2024/9/7 11:00
*/
@FeignClient(name = "FINANCE", url = "${rpc.url.fit-finance:http://app-fit-finance:7008}", fallbackFactory = StudioAxfCommodityApiFallback.class)
public interface StudioAxfCommodityApi {
@ApiOperation(value = "创建安心付一课一价商品")
@PostMapping(value = "/private/axfCommodity/create")
JsonResult<CreateCommodityVO> create(CreateStudioAxfCommodityRequest request);
@ApiOperation(value = "查询安心付一课一价商品")
@PostMapping(value = "/private/axfCommodity/get")
JsonResult<CommodityVO> get(GetStudioAxfCommodityRequest request);
}
package com.jiejing.fitness.finance.api.axf;
import com.jiejing.common.model.JsonResult;
import com.jiejing.fitness.finance.api.axf.request.CreateStudioAxfCommodityRequest;
import com.jiejing.fitness.finance.api.axf.request.GetStudioAxfCommodityRequest;
import com.jiejing.paycenter.common.model.vo.CommodityVO;
import com.jiejing.paycenter.common.model.vo.CreateCommodityVO;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* 安心付商品API
*
* @author chengyubing
* @since 2024/9/7 11:00
*/
@Component
public class StudioAxfCommodityApiFallback implements FallbackFactory<StudioAxfCommodityApi> {
@Override
public StudioAxfCommodityApi create(Throwable throwable) {
return new StudioAxfCommodityApi() {
@Override
public JsonResult<CreateCommodityVO> create(CreateStudioAxfCommodityRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<CommodityVO> get(GetStudioAxfCommodityRequest request) {
return JsonResult.rpcError();
}
};
}
}
package com.jiejing.fitness.finance.api.axf;
import com.jiejing.common.enums.ConfirmEnum;
import com.jiejing.common.model.JsonResult;
import com.jiejing.common.model.PageVO;
import com.jiejing.fitness.finance.api.axf.request.*;
import com.jiejing.fitness.finance.api.axf.vo.*;
import com.jiejing.paycenter.common.model.vo.*;
import io.swagger.annotations.ApiOperation;
import java.util.List;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
/**
* 安心付
*
* @author chengyubing
* @since 2024/9/7 11:00
*/
@FeignClient(name = "FINANCE", url = "${rpc.url.fit-finance:http://app-fit-finance:7008}", fallbackFactory = StudioAxfOrderApiFallback.class)
public interface StudioAxfOrderApi {
@ApiOperation(value = "取消订购单")
@PostMapping(value = "/private/axfOrder/cancel")
JsonResult<CancelCommodityOrderVO> cancel(CancelStudioAxfOrderRequest request);
@ApiOperation(value = "分页查询订购单")
@PostMapping(value = "/private/axfOrder/page")
JsonResult<PageVO<StudioAxfOrderVO>> page(PageStudioAxfOrderRequest request);
@ApiOperation(value = "统计订购单")
@PostMapping(value = "/private/axfOrder/agg")
JsonResult<AggStudioAxfOrderVO> agg(PageStudioAxfOrderRequest request);
@ApiOperation(value = "查询订购单详情")
@PostMapping(value = "/private/axfOrder/getById")
JsonResult<StudioAxfOrderVO> getById(GetStudioAxfOrderRequest request);
@ApiOperation(value = "根据订单查询安心付订购单")
@PostMapping(value = "/private/axfOrder/getByVoucherId")
JsonResult<StudioAxfOrderVO> getByVoucherId(GetStudioAxfOrderByVoucherIdRequest request);
@ApiOperation(value = "查询订购单扣款明细")
@PostMapping(value = "/private/axfOrder/listDeduction")
JsonResult<List<StudioAxfOrderDeductionVO>> listDeduction(ListStudioAxfOrderDeductionRequest request);
@ApiOperation(value = "校验是否存在失败的扣款")
@PostMapping(value = "/private/axfOrder/existFailDeduction")
JsonResult<ConfirmEnum> existFailDeduction(ListStudioAxfOrderDeductionRequest request);
@ApiOperation(value = "查询订购单追缴明细")
@PostMapping(value = "/private/axfOrder/listRecovery")
JsonResult<List<StudioAxfOrderRecoveryVO>> listRecovery(ListStudioAxfOrderRecoveryRequest request);
}
package com.jiejing.fitness.finance.api.axf;
import com.jiejing.common.enums.ConfirmEnum;
import com.jiejing.common.model.JsonResult;
import com.jiejing.common.model.PageVO;
import com.jiejing.fitness.finance.api.axf.request.CancelStudioAxfOrderRequest;
import com.jiejing.fitness.finance.api.axf.request.GetStudioAxfOrderByVoucherIdRequest;
import com.jiejing.fitness.finance.api.axf.request.GetStudioAxfOrderRequest;
import com.jiejing.fitness.finance.api.axf.request.ListStudioAxfOrderDeductionRequest;
import com.jiejing.fitness.finance.api.axf.request.ListStudioAxfOrderRecoveryRequest;
import com.jiejing.fitness.finance.api.axf.request.PageStudioAxfOrderRequest;
import com.jiejing.fitness.finance.api.axf.vo.AggStudioAxfOrderVO;
import com.jiejing.fitness.finance.api.axf.vo.StudioAxfOrderDeductionVO;
import com.jiejing.fitness.finance.api.axf.vo.StudioAxfOrderRecoveryVO;
import com.jiejing.fitness.finance.api.axf.vo.StudioAxfOrderVO;
import com.jiejing.paycenter.common.model.vo.CancelCommodityOrderVO;
import feign.hystrix.FallbackFactory;
import java.util.List;
import org.springframework.stereotype.Component;
/**
* 安心付订单API
*
* @author chengyubing
* @since 2024/9/7 11:00
*/
@Component
public class StudioAxfOrderApiFallback implements FallbackFactory<StudioAxfOrderApi> {
@Override
public StudioAxfOrderApi create(Throwable throwable) {
return new StudioAxfOrderApi() {
@Override
public JsonResult<CancelCommodityOrderVO> cancel(CancelStudioAxfOrderRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<PageVO<StudioAxfOrderVO>> page(PageStudioAxfOrderRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<AggStudioAxfOrderVO> agg(PageStudioAxfOrderRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<StudioAxfOrderVO> getById(GetStudioAxfOrderRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<StudioAxfOrderVO> getByVoucherId(GetStudioAxfOrderByVoucherIdRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<List<StudioAxfOrderDeductionVO>> listDeduction(
ListStudioAxfOrderDeductionRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<ConfirmEnum> existFailDeduction(ListStudioAxfOrderDeductionRequest request) {
return JsonResult.rpcError();
}
@Override
public JsonResult<List<StudioAxfOrderRecoveryVO>> listRecovery(ListStudioAxfOrderRecoveryRequest request) {
return JsonResult.rpcError();
}
};
}
}
package com.jiejing.fitness.finance.api.axf.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author chengyubing
* @since 2024/9/12 17:07
*/
@Getter
@AllArgsConstructor
public enum AxfOrderSignStateEnums {
/**
* 先学后付订购单状态
*/
SIGN("已签约"),
CANCEL_PROCESS("解约中"),
CANCEL("已解约"),
;
@EnumValue
private final String code = name();
private final String message;
}
package com.jiejing.fitness.finance.api.axf.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author chengyubing
* @since 2024/9/7 11:08
*/
@Getter
@AllArgsConstructor
public enum AxfStateEnums {
/**
* 先学后付状态
*/
INIT("初始"),
AXF_PROCESS("安心付开通中"),
AXF_SUCCESS("安心付开通成功"),
AXF_FAIL("安心付开通失败"),
SETTLE_SUCCESS("结算账户绑定成功"),
SETTLE_FAIL("结算账户绑定失败"),
STORE_PROCESS("门店开通中"),
STORE_SUCCESS("门店开通成功"),
STORE_FAIL("门店开通失败"),
;
@EnumValue
private final String code = name();
private final String message;
}
package com.jiejing.fitness.finance.api.axf.request;
import com.jiejing.paycenter.common.enums.merchant.GrantTypeEnums;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/5 15:17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "授权Token请求参数")
public class AxfAuthTokenRequest {
@ApiModelProperty(value = "code")
private String code;
@ApiModelProperty(value = "grantType")
private GrantTypeEnums grantType;
@ApiModelProperty(value = "refreshToken")
private String refreshToken;
@ApiModelProperty(value = "场馆ID", required = true)
@NotNull(message = "场馆ID不能为空")
private Long studioId;
}
package com.jiejing.fitness.finance.api.axf.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import lombok.Data;
/**
* @author chengyubing
* @since 2024/9/29 11:10
*/
@Data
@ApiModel(description = "绑定结算账户")
public class BindAxfSettleAccountRequest {
@ApiModelProperty(value = "申请记录ID", required = true)
@NotNull(message = "申请记录ID不能为空")
private Long id;
@ApiModelProperty(value = "结算账户", required = true)
@NotBlank(message = "结算账户不能为空")
private String cardNo;
}
package com.jiejing.fitness.finance.api.axf.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import lombok.Data;
/**
* @author chengyubing
* @since 2024/9/12 15:24
*/
@Data
@ApiModel(description = "取消订购单")
public class CancelStudioAxfOrderRequest {
@ApiModelProperty(value = "订购单ID", required = true)
@NotNull(message = "订购单ID不能为空")
private Long id;
@ApiModelProperty(value = "操作人", required = true)
@NotNull(message = "操作人不能为空")
private Long bizAccountId;
}
package com.jiejing.fitness.finance.api.axf.request;
import com.jiejing.paycenter.common.model.request.CycleCommodityAttr;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/11 16:55
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "创建一课一价商品请求")
public class CreateStudioAxfCommodityRequest {
@ApiModelProperty(value = "场馆ID", required = true)
@NotNull(message = "场馆ID不能为空")
private Long studioId;
@ApiModelProperty(value = "订单ID", required = true)
@NotNull(message = "订单ID不能为空")
private Long voucherId;
@ApiModelProperty(value = "原价(元)", required = true)
@NotNull(message = "原价不能为空")
private BigDecimal originalPrice;
@ApiModelProperty(value = "售价(元)", required = true)
@NotNull(message = "售价不能为空")
private BigDecimal salePrice;
@ApiModelProperty(value = "周期类商品属性")
private CycleCommodityAttr cycleCommodityAttr;
}
package com.jiejing.fitness.finance.api.axf.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/5 15:17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "查看授权Token请求参数")
public class GetAxfAuthTokenRequest {
@ApiModelProperty(value = "场馆ID", required = true)
@NotNull(message = "场馆ID不能为空")
private Long studioId;
}
package com.jiejing.fitness.finance.api.axf.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/5 15:17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "查看最新一条安心付申请记录请求参数")
public class GetLatestAxfApplyRequest {
@ApiModelProperty(value = "场馆ID", required = true)
@NotNull(message = "场馆ID不能为空")
private Long studioId;
@ApiModelProperty(value = "merchantNo")
private String merchantNo;
}
package com.jiejing.fitness.finance.api.axf.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/11 16:55
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "查询一课一价商品请求")
public class GetStudioAxfCommodityRequest {
@ApiModelProperty(value = "三方商品ID", required = true)
@NotBlank(message = "三方商品ID不能为空")
private String thirdCommodityId;
}
package com.jiejing.fitness.finance.api.axf.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/10 14:14
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "根据订单查询安心付订购单")
public class GetStudioAxfOrderByVoucherIdRequest {
@ApiModelProperty(value = "订单ID", required = true)
@NotNull(message = "订单ID不能为空")
private Long voucherId;
}
package com.jiejing.fitness.finance.api.axf.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/10 14:14
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "查询安心付订购单")
public class GetStudioAxfOrderRequest {
@ApiModelProperty(value = "订购单ID", required = true)
@NotNull(message = "订购单ID不能为空")
private Long id;
}
package com.jiejing.fitness.finance.api.axf.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/5 15:17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "查询安心付可配置的结算账户请求参数")
public class ListAxfSettleAccountRequest {
@ApiModelProperty(value = "场馆ID", required = true)
@NotNull(message = "场馆ID不能为空")
private Long studioId;
}
package com.jiejing.fitness.finance.api.axf.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/10 14:14
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "查询安心付订购单扣款明细")
public class ListStudioAxfOrderDeductionRequest {
@ApiModelProperty(value = "订购单ID")
private Long orderId;
}
package com.jiejing.fitness.finance.api.axf.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/10 14:14
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "查询安心付订购单追缴明细")
public class ListStudioAxfOrderRecoveryRequest {
@ApiModelProperty(value = "订购单扣款ID")
private Long deductionId;
}
package com.jiejing.fitness.finance.api.axf.request;
import com.jiejing.fitness.finance.api.axf.enums.AxfStateEnums;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/10 14:14
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "分页查询安心付申请记录")
public class PageStudioAxfApplyRequest {
@ApiModelProperty(value = "场馆ID")
private Long studioId;
@ApiModelProperty(value = "场馆名称")
private String studioName;
@ApiModelProperty(value = "商户简称")
private String shortName;
@ApiModelProperty(value = "申请开始时间")
private Date createTimeStart;
@ApiModelProperty(value = "申请结束时间")
private Date createTimeEnd;
@ApiModelProperty(value = "开通状态")
private List<AxfStateEnums> stateList;
@ApiModelProperty(value = "页码", notes = "1开始")
private Integer current;
@ApiModelProperty(value = "分页大小")
private Integer size = 10;
}
package com.jiejing.fitness.finance.api.axf.request;
import com.jiejing.fitness.finance.api.axf.enums.AxfOrderSignStateEnums;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/10 14:14
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "分页查询安心付订购单")
public class PageStudioAxfOrderRequest {
@ApiModelProperty(value = "场馆ID")
private Long studioId;
@ApiModelProperty(value = "场馆名称")
private String studioName;
@ApiModelProperty(value = "学员ID")
private Long studentId;
@ApiModelProperty(value = "学员名称")
private String studentName;
@ApiModelProperty(value = "订单号")
private String voucherBusinessNo;
@ApiModelProperty(value = "支付宝订购单号")
private String thirdOrderNo;
@ApiModelProperty(value = "签约开始时间")
private Date signTimeStart;
@ApiModelProperty(value = "签约结束时间")
private Date signTimeEnd;
@ApiModelProperty(value = "解约开始时间")
private Date cancelTimeStart;
@ApiModelProperty(value = "解约结束时间")
private Date cancelTimeEnd;
@ApiModelProperty(value = "订购单状态")
private AxfOrderSignStateEnums state;
@ApiModelProperty(value = "页码", notes = "1开始")
private Integer current;
@ApiModelProperty(value = "分页大小")
private Integer size = 10;
}
package com.jiejing.fitness.finance.api.axf.request;
import com.jiejing.paycenter.common.enums.merchant.CompanyTypeEnums;
import com.jiejing.paycenter.common.enums.merchant.ExpireTypeEnums;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import lombok.Data;
/**
* @author chengyubing
* @since 2024/9/7 11:11
*/
@Data
@ApiModel(description = "先学后付请求")
public class StudioAxfApplyRequest {
@ApiModelProperty(value = "支付宝商户号不能为空", required = true)
@NotBlank(message = "支付宝商户号不能为空")
private String merchantNo;
@ApiModelProperty(value = "场馆ID", required = true)
@NotNull(message = "场馆ID不能为空")
private Long studioId;
@ApiModelProperty(value = "商户名称")
private String merchantName;
@ApiModelProperty(value = "商户简称")
private String shortName;
@ApiModelProperty(value = "企业类型")
private CompanyTypeEnums companyType;
@ApiModelProperty(value = "营业执照编号")
private String licenseCode;
@ApiModelProperty(value = "营业执照名称")
private String licenseName;
@ApiModelProperty(value = "营业执照有效期类型")
private ExpireTypeEnums licenseExpireType;
@ApiModelProperty(value = "营业执照有效期开始时间")
private Date licenseStartTime;
@ApiModelProperty(value = "营业执照有效期结束时间")
private Date licenseEndTime;
@ApiModelProperty(value = "法人姓名")
private String legalName;
@ApiModelProperty(value = "法人证件号")
private String legalCertNo;
@ApiModelProperty(value = "联系人手机号")
private String phone;
@ApiModelProperty(value = "结算账户号")
private String cardNo;
@ApiModelProperty(value = "经营地址-省份code")
private String businessProvinceCode;
@ApiModelProperty(value = "经营地址-省份名称")
private String businessProvinceName;
@ApiModelProperty(value = "经营地址城市code")
private String businessCityCode;
@ApiModelProperty(value = "经营地址城市名称")
private String businessCityName;
@ApiModelProperty(value = "经营地址县区code")
private String businessDistrictCode;
@ApiModelProperty(value = "经营地址县区名称")
private String businessDistrictName;
@ApiModelProperty(value = "经营详细地址")
private String businessAddress;
@ApiModelProperty(value = "营业执照资源ID")
private Long licenseResourceId;
@ApiModelProperty(value = "门头照资源ID")
private Long storeHeadResourceId;
@ApiModelProperty(value = "员工ID", required = true)
@NotNull(message = "员工ID不能为空")
private Long bizAccountId;
}
package com.jiejing.fitness.finance.api.axf.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/11 14:42
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "先学后付申请统计数据VO")
public class AggStudioAxfApplyVO {
@ApiModelProperty(value = "申请成功的场馆数")
private Integer success;
@ApiModelProperty(value = "发起申请的场馆数")
private Integer total;
}
package com.jiejing.fitness.finance.api.axf.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/12 15:31
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "统计订购单VO")
public class AggStudioAxfOrderVO {
@ApiModelProperty(value = "场馆ID")
private Long studioId;
@ApiModelProperty(value = "已扣款金额")
private BigDecimal receivedAmount;
@ApiModelProperty(value = "已扣款实收金额")
private BigDecimal receivedActualAmount;
@ApiModelProperty(value = "费率")
private BigDecimal rate;
}
package com.jiejing.fitness.finance.api.axf.vo;
import com.jiejing.common.enums.ConfirmEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/5 15:16
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "场馆安心付授权VO")
public class StudioAuthTokenVO {
@ApiModelProperty("ID")
private Long id;
@ApiModelProperty("本次授权是否已经完成进件")
private ConfirmEnum used;
@ApiModelProperty("appAuthToken")
private String appAuthToken;
@ApiModelProperty("appRefreshToken")
private String appRefreshToken;
@ApiModelProperty("authAppId")
private String authAppId;
@ApiModelProperty("expiresIn")
private String expiresIn;
@ApiModelProperty("reExpiresIn")
private String reExpiresIn;
@ApiModelProperty("userId")
private String userId;
@ApiModelProperty("创建时间")
private Date createTime;
@ApiModelProperty("更新时间")
private Date updateTime;
}
package com.jiejing.fitness.finance.api.axf.vo;
import com.jiejing.fitness.finance.api.axf.enums.AxfStateEnums;
import com.jiejing.paycenter.common.enums.merchant.CompanyTypeEnums;
import com.jiejing.paycenter.common.enums.merchant.ExpireTypeEnums;
import com.jiejing.paycenter.common.enums.merchant.LicenseTypeEnums;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
import lombok.Data;
/**
* @author chengyubing
* @since 2024/9/7 11:11
*/
@Data
@ApiModel(description = "先学后付申请记录VO")
public class StudioAxfApplyVO {
@ApiModelProperty(value = "申请记录ID")
private Long id;
@ApiModelProperty(value = "渠道号")
private String channelNo;
@ApiModelProperty(value = "申请类型")
private String applyType;
@ApiModelProperty(value = "支付宝pid")
private String merchantNo;
@ApiModelProperty(value = "商户ID")
private Long merchantId;
@ApiModelProperty(value = "场馆ID")
private Long studioId;
@ApiModelProperty(value = "场馆名称")
private String studioName;
@ApiModelProperty(value = "商户简称")
private String shortName;
@ApiModelProperty(value = "企业类型")
private CompanyTypeEnums companyType;
@ApiModelProperty(value = "开通状态:+ INIT: 初始+ AXF_PROCESS: 安心付开通中+ AXF_SUCCESS: 安心付开通成功+ STORE_PROCESS: 门店开通中+ STORE_SUCCESS: 门店开通成功")
private AxfStateEnums state;
@ApiModelProperty(value = "结算账户号")
private String cardNo;
@ApiModelProperty(value = "营业执照编号")
private String licenseCode;
@ApiModelProperty(value = "营业执照名称")
private String licenseName;
@ApiModelProperty(value = "营业执照类型")
private LicenseTypeEnums licenseType;
@ApiModelProperty(value = "营业执照有效期类型")
private ExpireTypeEnums licenseExpireType;
@ApiModelProperty(value = "营业执照有效期开始时间")
private Date licenseStartTime;
@ApiModelProperty(value = "营业执照有效期结束时间")
private Date licenseEndTime;
@ApiModelProperty(value = "法人姓名")
private String legalName;
@ApiModelProperty(value = "法人证件号")
private String legalCertNo;
@ApiModelProperty(value = "联系人手机号")
private String phone;
@ApiModelProperty(value = "经营地址-省份code")
private String businessProvinceCode;
@ApiModelProperty(value = "经营地址-省份名称")
private String businessProvinceName;
@ApiModelProperty(value = "经营地址城市code")
private String businessCityCode;
@ApiModelProperty(value = "经营地址城市名称")
private String businessCityName;
@ApiModelProperty(value = "经营地址县区code")
private String businessDistrictCode;
@ApiModelProperty(value = "经营地址县区名称")
private String businessDistrictName;
@ApiModelProperty(value = "经营详细地址")
private String businessAddress;
@ApiModelProperty(value = "营业执照资源ID")
private Long licenseResourceId;
@ApiModelProperty(value = "门头照资源ID")
private Long storeHeadResourceId;
@ApiModelProperty(value = "营业执照资源Url")
private String licenseResourceUrl;
@ApiModelProperty(value = "门头照资源Url")
private String storeHeadResourceUrl;
@ApiModelProperty(value = "失败原因")
private String failMessage;
@ApiModelProperty(value = "操作人ID")
private Long opId;
@ApiModelProperty(value = "操作人姓名")
private String opName;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更细时间")
private Date updateTime;
}
package com.jiejing.fitness.finance.api.axf.vo;
import com.jiejing.paycenter.common.enums.common.OpenStateEnums;
import com.jiejing.paycenter.common.enums.merchant.CommodityTypeEnums;
import com.jiejing.paycenter.common.model.request.CycleCommodityAttr;
import com.jiejing.paycenter.common.model.vo.CommodityTemplateVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* <p>
* 商品
* </p>
*
* @author chengyubing, created on 2024-09-06
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "场馆安心付商品VO")
public class StudioAxfCommodityVO {
@ApiModelProperty(value = "商品ID")
private Long id;
@ApiModelProperty(value = "业务ID")
private Long bizId;
@ApiModelProperty(value = "商户ID")
private Long merchantId;
@ApiModelProperty(value = "门店ID")
private Long storeId;
@ApiModelProperty(value = "商品模板ID")
private Long templateId;
@ApiModelProperty(value = "三方商品模板ID")
private String thirdTemplateId;
@ApiModelProperty(value = "三方商品ID")
private String thirdCommodityId;
@ApiModelProperty(value = "商品类型")
private CommodityTypeEnums commodityType;
@ApiModelProperty(value = "商品名称")
private String commodityName;
@ApiModelProperty(value = "原价(元)")
private BigDecimal originalPrice;
@ApiModelProperty(value = "售价(元)")
private BigDecimal salePrice;
@ApiModelProperty(value = "商品状态")
private OpenStateEnums state;
@ApiModelProperty(value = "售卖开始时间")
private Date saleStartTime;
@ApiModelProperty(value = "售卖结束时间")
private Date saleEndTime;
@ApiModelProperty(value = "商品属性")
private String commodityAttr;
@ApiModelProperty(value = "周期类商品属性")
private CycleCommodityAttr cycleCommodityAttr;
@ApiModelProperty(value = "商品说明")
private String commodityNote;
@ApiModelProperty(value = "商品模板")
private CommodityTemplateVO template;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}
package com.jiejing.fitness.finance.api.axf.vo;
import com.jiejing.paycenter.common.enums.merchant.CommodityOrderDeductionStateEnums;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* <p>
* 场馆先学后付订购单扣款记录
* </p>
*
* @author raccoon
* @since 2024-09-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "场馆先学后付订购单扣款记录")
public class StudioAxfOrderDeductionVO {
@ApiModelProperty(value = "主键")
private Long id;
@ApiModelProperty(value = "订购单ID")
private Long orderId;
@ApiModelProperty(value = "扣款期数")
private Integer period;
@ApiModelProperty(value = "扣款金额:元")
private BigDecimal amount;
@ApiModelProperty(value = "实收金额:元")
private BigDecimal actualAmount;
@ApiModelProperty(value = "费率(%)")
private BigDecimal rate;
@ApiModelProperty(value = "手续费:元")
private BigDecimal fee;
@ApiModelProperty(value = "扣款状态")
private CommodityOrderDeductionStateEnums state;
@ApiModelProperty(value = "扣款失败原因")
private String failMessage;
@ApiModelProperty(value = "支付流水号")
private String transNo;
@ApiModelProperty(value = "支付宝订购单号")
private String thirdOrderNo;
@ApiModelProperty(value = "支付宝交易单号")
private String thirdTransNo;
@ApiModelProperty(value = "追缴次数")
private Integer recoveryTimes;
@ApiModelProperty(value = "扣款时间")
private Date deductionTime;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}
package com.jiejing.fitness.finance.api.axf.vo;
import com.jiejing.paycenter.common.enums.merchant.CommodityOrderDeductionStateEnums;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* <p>
* 场馆先学后付订购单追缴记录
* </p>
*
* @author raccoon
* @since 2024-09-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "场馆先学后付订购单追缴记录")
public class StudioAxfOrderRecoveryVO {
@ApiModelProperty(value = "主键")
private Long id;
@ApiModelProperty(value = "订购单ID")
private Long orderId;
@ApiModelProperty(value = "扣款记录ID")
private Long deductionId;
@ApiModelProperty(value = "扣款期数")
private Integer period;
@ApiModelProperty(value = "扣款金额:元")
private BigDecimal amount;
@ApiModelProperty(value = "实收金额:元")
private BigDecimal actualAmount;
@ApiModelProperty(value = "手续费:元")
private BigDecimal fee;
@ApiModelProperty(value = "费率(%)")
private BigDecimal rate;
@ApiModelProperty(value = "扣款状态")
private CommodityOrderDeductionStateEnums state;
@ApiModelProperty(value = "扣款失败原因")
private String failMessage;
@ApiModelProperty(value = "支付流水号")
private String transNo;
@ApiModelProperty(value = "支付宝订购单号:冗余字段")
private String thirdOrderNo;
@ApiModelProperty(value = "支付宝交易单号")
private String thirdTransNo;
@ApiModelProperty(value = "扣款时间")
private Date deductionTime;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}
package com.jiejing.fitness.finance.api.axf.vo;
import com.jiejing.fitness.finance.api.axf.enums.AxfOrderSignStateEnums;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chengyubing
* @since 2024/9/12 15:31
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "订购单VO")
public class StudioAxfOrderVO {
@ApiModelProperty(value = "主键")
private Long id;
@ApiModelProperty(value = "场馆ID")
private Long studioId;
@ApiModelProperty(value = "场馆名称")
private String studioName;
@ApiModelProperty(value = "渠道号")
private String channelNo;
@ApiModelProperty(value = "商户ID")
private Long merchantId;
@ApiModelProperty(value = "商品ID")
private Long commodityId;
@ApiModelProperty(value = "学员ID")
private Long studentId;
@ApiModelProperty(value = "学员姓名")
private String studentName;
@ApiModelProperty(value = "学员手机号")
private String studentPhone;
@ApiModelProperty(value = "签约状态")
private AxfOrderSignStateEnums signState;
@ApiModelProperty(value = "总期数")
private Integer totalPeriod;
@ApiModelProperty(value = "总原价(签约扣款金额):元")
private BigDecimal originalPrice;
@ApiModelProperty(value = "售价:元")
private BigDecimal salePrice;
@ApiModelProperty(value = "已扣款金额:元")
private BigDecimal receivedAmount;
@ApiModelProperty(value = "已扣款手续费:元")
private BigDecimal receivedFee;
@ApiModelProperty(value = "已扣款实收金额:元")
private BigDecimal receivedActualAmount;
@ApiModelProperty(value = "当前扣款期数")
private Integer receivedPeriod;
@ApiModelProperty(value = "手续费率:%")
private BigDecimal rate;
@ApiModelProperty(value = "订单ID")
private Long voucherId;
@ApiModelProperty(value = "订单号:冗余字段")
private String voucherBusinessNo;
@ApiModelProperty(value = "支付宝订购单号")
private String thirdOrderNo;
@ApiModelProperty(value = "解约人ID")
private Long cancelOpId;
@ApiModelProperty(value = "解约人姓名")
private String cancelOpName;
@ApiModelProperty(value = "解约失败信息")
private String cancelFailMessage;
@ApiModelProperty(value = "解约时间")
private Date cancelTime;
@ApiModelProperty(value = "签约时间")
private Date signTime;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
@ApiModelProperty(value = "商品")
private StudioAxfCommodityVO commodity;
}
......@@ -4,10 +4,13 @@ import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import com.jiejing.common.config.idgen.EnableLeaseIdWorker;
import com.jiejing.fitness.event.finance.CashierEvent;
import com.jiejing.fitness.finance.service.event.ListenerService;
import com.jiejing.paycenter.common.event.CommodityOrderEvent;
import com.jiejing.paycenter.common.event.MerchantEvent;
import com.jiejing.paycenter.common.event.MerchantSubChannelEvent;
import com.jiejing.paycenter.common.event.OrderDeductionEvent;
import com.jiejing.paycenter.common.event.PayEvent;
import com.jiejing.paycenter.common.event.RefundEvent;
import com.jiejing.paycenter.common.event.StoreEvent;
import com.jiejing.workflow.event.DelayTaskEvent;
import com.xiaomai.event.annotation.EnableEventBinding;
import com.xiaomai.event.annotation.EventConfig;
......@@ -36,6 +39,9 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@EventConfig(event = MerchantSubChannelEvent.class, binder = "biz-kafka"),
@EventConfig(event = DelayTaskEvent.class, binder = "biz-kafka"),
@EventConfig(event = CashierEvent.class, binder = "biz-kafka"),
@EventConfig(event = StoreEvent.class, binder = "biz-kafka"),
@EventConfig(event = OrderDeductionEvent.class, binder = "biz-kafka"),
@EventConfig(event = CommodityOrderEvent.class, binder = "biz-kafka"),
},
listenerClass = {ListenerService.class})
@EnableFeignClients(basePackages = {
......@@ -47,6 +53,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
"com.jiejing.permcenter.api",
"com.jiejing.configcenter.api",
"com.jiejing.workflow.api",
"com.jiejing.member.api"
})
@SpringBootApplication(scanBasePackages = "com.jiejing", exclude = {
DruidDataSourceAutoConfigure.class
......
package com.jiejing.fitness.finance.app.controller.axf;
import com.jiejing.common.model.JsonResult;
import com.jiejing.fitness.finance.api.axf.StudioAxfCommodityApi;
import com.jiejing.fitness.finance.api.axf.request.CreateStudioAxfCommodityRequest;
import com.jiejing.fitness.finance.api.axf.request.GetStudioAxfCommodityRequest;
import com.jiejing.fitness.finance.service.axf.AxfService;
import com.jiejing.paycenter.common.model.vo.CommodityVO;
import com.jiejing.paycenter.common.model.vo.CreateCommodityVO;
import io.swagger.annotations.ApiOperation;
import javax.annotation.Resource;
import javax.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author chengyubing
* @since 2024/9/7 11:30
*/
@RestController
public class StudioAxfCommodityController implements StudioAxfCommodityApi {
@Resource
private AxfService axfService;
@ApiOperation(value = "创建安心付一课一价商品")
@PostMapping(value = "/private/axfCommodity/create")
@Override
public JsonResult<CreateCommodityVO> create(@RequestBody @Valid CreateStudioAxfCommodityRequest request) {
return JsonResult.success(axfService.createCommodity(request));
}
@ApiOperation(value = "查询安心付一课一价商品")
@PostMapping(value = "/private/axfCommodity/get")
@Override
public JsonResult<CommodityVO> get(@RequestBody @Valid GetStudioAxfCommodityRequest request) {
return JsonResult.success(axfService.getCommodity(request.getThirdCommodityId()));
}
}
package com.jiejing.fitness.finance.app.controller.axf;
import com.jiejing.common.model.JsonResult;
import com.jiejing.common.model.PageVO;
import com.jiejing.common.request.IdRequest;
import com.jiejing.fitness.finance.api.axf.StudioAxfApi;
import com.jiejing.fitness.finance.api.axf.request.*;
import com.jiejing.fitness.finance.api.axf.vo.*;
import com.jiejing.fitness.finance.service.axf.AxfService;
import com.jiejing.fitness.request.StudioIdRequest;
import com.jiejing.paycenter.common.model.vo.BindCardVO;
import io.swagger.annotations.ApiOperation;
import java.util.List;
import javax.annotation.Resource;
import javax.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author chengyubing
* @since 2024/9/7 11:30
*/
@RestController
public class StudioAxfController implements StudioAxfApi {
@Resource
private AxfService axfService;
@ApiOperation(value = "authToken")
@PostMapping(value = "/private/axf/authToken")
@Override
public JsonResult<StudioAuthTokenVO> authToken(@RequestBody @Valid AxfAuthTokenRequest request) {
return JsonResult.success(
axfService.authToken(request.getStudioId(), request.getGrantType(), request.getCode(),
request.getRefreshToken()));
}
@ApiOperation(value = "getAuthToken")
@PostMapping(value = "/private/axf/getAuthToken")
@Override
public JsonResult<StudioAuthTokenVO> getAuthToken(@RequestBody @Valid GetAxfAuthTokenRequest request) {
return JsonResult.success(axfService.getAuthToken(request.getStudioId()));
}
@ApiOperation(value = "申请开通安心付")
@PostMapping(value = "/private/axf/apply")
@Override
public JsonResult<Long> apply(@RequestBody @Valid StudioAxfApplyRequest request) {
return JsonResult.success(axfService.apply(request));
}
@ApiOperation(value = "查询可绑定的安心付结算账户")
@PostMapping(value = "/private/axf/listSettleAccount")
@Override
public JsonResult<List<String>> listSettleAccount(@RequestBody @Valid ListAxfSettleAccountRequest request) {
return JsonResult.success(axfService.listSettleAccount(request.getStudioId()));
}
@ApiOperation(value = "绑定结算账户")
@PostMapping(value = "/private/axf/bindSettleAccount")
@Override
public JsonResult<BindCardVO> bindCard(@RequestBody @Valid BindAxfSettleAccountRequest request) {
return JsonResult.success(axfService.bindCard(request.getId(), request.getCardNo()));
}
@ApiOperation(value = "获取最新一条安心付申请记录")
@PostMapping(value = "/private/axf/getLatestApply")
@Override
public JsonResult<StudioAxfApplyVO> getLatestApply(@RequestBody @Valid GetLatestAxfApplyRequest request) {
return JsonResult.success(axfService.getLatestApply(request.getStudioId(), request.getMerchantNo()));
}
@ApiOperation(value = "查询开通安心付申请结果")
@PostMapping(value = "/private/axf/getById")
@Override
public JsonResult<StudioAxfApplyVO> getById(@RequestBody @Valid IdRequest request) {
return JsonResult.success(axfService.getById(request.getId()));
}
@ApiOperation(value = "获取当前绑定的商户信息(开通中、开通失败、未开通都返回null)")
@PostMapping(value = "/private/axf/getMerchant")
@Override
public JsonResult<StudioAxfApplyVO> getMerchant(@RequestBody @Valid StudioIdRequest request) {
return JsonResult.success(axfService.getMerchant(request.getStudioId()));
}
@ApiOperation(value = "分页查询开通安心付申请记录")
@PostMapping(value = "/private/axf/page")
@Override
public JsonResult<PageVO<StudioAxfApplyVO>> page(@RequestBody @Valid PageStudioAxfApplyRequest request) {
return JsonResult.success(axfService.page(request));
}
@ApiOperation(value = "统计")
@PostMapping(value = "/private/axf/agg")
@Override
public JsonResult<AggStudioAxfApplyVO> agg() {
return JsonResult.success(axfService.agg());
}
}
package com.jiejing.fitness.finance.app.controller.axf;
import com.jiejing.common.enums.ConfirmEnum;
import com.jiejing.common.model.JsonResult;
import com.jiejing.common.model.PageVO;
import com.jiejing.fitness.finance.api.axf.StudioAxfOrderApi;
import com.jiejing.fitness.finance.api.axf.request.*;
import com.jiejing.fitness.finance.api.axf.vo.*;
import com.jiejing.fitness.finance.service.axf.AxfService;
import com.jiejing.paycenter.common.model.vo.*;
import io.swagger.annotations.ApiOperation;
import java.util.List;
import javax.annotation.Resource;
import javax.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author chengyubing
* @since 2024/9/7 11:30
*/
@RestController
public class StudioAxfOrderController implements StudioAxfOrderApi {
@Resource
private AxfService axfService;
@ApiOperation(value = "取消订购单")
@PostMapping(value = "/private/axfOrder/cancel")
@Override
public JsonResult<CancelCommodityOrderVO> cancel(@RequestBody @Valid CancelStudioAxfOrderRequest request) {
return JsonResult.success(axfService.cancelOrder(request.getId(), request.getBizAccountId()));
}
@ApiOperation(value = "分页查询订购单")
@PostMapping(value = "/private/axfOrder/page")
@Override
public JsonResult<PageVO<StudioAxfOrderVO>> page(@RequestBody @Valid PageStudioAxfOrderRequest request) {
return JsonResult.success(axfService.pageOrder(request));
}
@ApiOperation(value = "统计订购单")
@PostMapping(value = "/private/axfOrder/agg")
@Override
public JsonResult<AggStudioAxfOrderVO> agg(@RequestBody @Valid PageStudioAxfOrderRequest request) {
return JsonResult.success(axfService.aggOrder(request));
}
@ApiOperation(value = "查询订购单详情")
@PostMapping(value = "/private/axfOrder/getById")
@Override
public JsonResult<StudioAxfOrderVO> getById(@RequestBody @Valid GetStudioAxfOrderRequest request) {
return JsonResult.success(axfService.getOrder(request.getId()));
}
@ApiOperation(value = "根据订单查询安心付订购单")
@PostMapping(value = "/private/axfOrder/getByVoucherId")
@Override
public JsonResult<StudioAxfOrderVO> getByVoucherId(
@RequestBody @Valid GetStudioAxfOrderByVoucherIdRequest request) {
return JsonResult.success(axfService.getByVoucherId(request.getVoucherId()));
}
@ApiOperation(value = "查询订购单扣款明细")
@PostMapping(value = "/private/axfOrder/listDeduction")
@Override
public JsonResult<List<StudioAxfOrderDeductionVO>> listDeduction(
@RequestBody @Valid ListStudioAxfOrderDeductionRequest request) {
return JsonResult.success(axfService.listDeduction(request.getOrderId()));
}
@ApiOperation(value = "校验是否存在失败的扣款")
@PostMapping(value = "/private/axfOrder/existFailDeduction")
@Override
public JsonResult<ConfirmEnum> existFailDeduction(
@RequestBody @Valid ListStudioAxfOrderDeductionRequest request) {
return JsonResult.success(axfService.existFailDeduction(request.getOrderId()));
}
@ApiOperation(value = "查询订购单追缴明细")
@PostMapping(value = "/private/axfOrder/listRecovery")
@Override
public JsonResult<List<StudioAxfOrderRecoveryVO>> listRecovery(
@RequestBody @Valid ListStudioAxfOrderRecoveryRequest request) {
return JsonResult.success(axfService.listRecovery(request.getDeductionId()));
}
}
......@@ -101,6 +101,16 @@
<artifactId>workflow-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.jiejing.app</groupId>
<artifactId>member-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.jiejing.fitness</groupId>
<artifactId>trade-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- ======================= jiejing api end ======================= -->
......
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* <p>
* 机构安心付申请记录
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class StudioAxfApply implements Serializable {
private static final long serialVersionUID = -166947593419927514L;
/**
* 备注: 主键 是否允许为null: NO
*/
@TableId(value = "id", type = IdType.ID_WORKER)
private Long id;
/**
* 备注: 渠道号 默认值: 001 是否允许为null: NO
*/
private String channelNo;
/**
* 备注: 支付宝pid/userid 是否允许为null: NO
*/
private String merchantNo;
/**
* 备注: 商户ID 是否允许为null: YES
*/
private Long merchantId;
/**
* 备注: 场馆ID 是否允许为null: NO
*/
private Long studioId;
/**
* 备注: 操作类型 默认值: OPEN 是否允许为null: YES
*/
private String applyType;
/**
* 备注: 场馆名称 是否允许为null: YES
*/
private String studioName;
/**
* 备注: 商户名称 是否允许为null: YES
*/
private String merchantName;
/**
* 备注: 商户简称 是否允许为null: NO
*/
private String shortName;
/**
* 备注: 企业类型:+ PRIVATE: 私营企业+ PERSONAL: 个体工商户 是否允许为null: YES
*/
private String companyType;
/**
* 备注: 开通状态:+ INIT: 初始+ AXF_PROCESS: 安心付开通中+ AXF_SUCCESS: 安心付开通成功+ STORE_PROCESS: 门店开通中+ STORE_SUCCESS:
* 门店开通成功 是否允许为null: NO
*/
private String state;
/**
* 备注: 结算账户号 是否允许为null: YES
*/
private String cardNo;
/**
* 备注: 营业执照编号 是否允许为null: NO
*/
private String licenseCode;
/**
* 备注: 营业执照名称 是否允许为null: NO
*/
private String licenseName;
/**
* 备注: 营业执照类型 是否允许为null: YES
*/
private String licenseType;
/**
* 备注: 营业执照有效期类型 是否允许为null: YES
*/
private String licenseExpireType;
/**
* 备注: 营业执照有效期开始时间 是否允许为null: YES
*/
private Date licenseStartTime;
/**
* 备注: 营业执照有效期结束时间 是否允许为null: YES
*/
private Date licenseEndTime;
/**
* 备注: 法人姓名 是否允许为null: YES
*/
private String legalName;
/**
* 备注: 法人证件号 是否允许为null: YES
*/
private String legalCertNo;
/**
* 备注: 联系人手机号 是否允许为null: YES
*/
private String phone;
/**
* 备注: 经营地址-省份code 是否允许为null: YES
*/
private String businessProvinceCode;
/**
* 备注: 经营地址-省份名称 是否允许为null: YES
*/
private String businessProvinceName;
/**
* 备注: 经营地址城市code 是否允许为null: YES
*/
private String businessCityCode;
/**
* 备注: 经营地址城市名称 是否允许为null: YES
*/
private String businessCityName;
/**
* 备注: 经营地址县区code 是否允许为null: YES
*/
private String businessDistrictCode;
/**
* 备注: 经营地址县区名称 是否允许为null: YES
*/
private String businessDistrictName;
/**
* 备注: 经营详细地址 是否允许为null: YES
*/
private String businessAddress;
/**
* 备注: 营业执照资源ID 是否允许为null: YES
*/
private Long licenseResourceId;
/**
* 备注: 门头照资源ID 是否允许为null: YES
*/
private Long storeHeadResourceId;
/**
* 备注: 失败原因 是否允许为null: YES
*/
private String failMessage;
/**
* 备注: 操作人ID 默认值: -1 是否允许为null: YES
*/
private Long opId;
/**
* 备注: 操作人姓名 是否允许为null: YES
*/
private String opName;
/**
* 备注: 盐 是否允许为null: YES
*/
private String salt;
/**
* 备注: 创建时间 是否允许为null: YES
*/
private Date createTime;
/**
* 备注: 更细时间 是否允许为null: YES
*/
private Date updateTime;
public static final String ID = "id";
public static final String CHANNEL_NO = "channel_no";
public static final String MERCHANT_NO = "merchant_no";
public static final String MERCHANT_ID = "merchant_id";
public static final String STUDIO_ID = "studio_id";
public static final String APPLY_TYPE = "apply_type";
public static final String STUDIO_NAME = "studio_name";
public static final String MERCHANT_NAME = "merchant_name";
public static final String SHORT_NAME = "short_name";
public static final String COMPANY_TYPE = "company_type";
public static final String STATE = "state";
public static final String CARD_NO = "card_no";
public static final String LICENSE_CODE = "license_code";
public static final String LICENSE_NAME = "license_name";
public static final String LICENSE_TYPE = "license_type";
public static final String LICENSE_EXPIRE_TYPE = "license_expire_type";
public static final String LICENSE_START_TIME = "license_start_time";
public static final String LICENSE_END_TIME = "license_end_time";
public static final String LEGAL_NAME = "legal_name";
public static final String LEGAL_CERT_NO = "legal_cert_no";
public static final String PHONE = "phone";
public static final String BUSINESS_PROVINCE_CODE = "business_province_code";
public static final String BUSINESS_PROVINCE_NAME = "business_province_name";
public static final String BUSINESS_CITY_CODE = "business_city_code";
public static final String BUSINESS_CITY_NAME = "business_city_name";
public static final String BUSINESS_DISTRICT_CODE = "business_district_code";
public static final String BUSINESS_DISTRICT_NAME = "business_district_name";
public static final String BUSINESS_ADDRESS = "business_address";
public static final String LICENSE_RESOURCE_ID = "license_resource_id";
public static final String STORE_HEAD_RESOURCE_ID = "store_head_resource_id";
public static final String FAIL_MESSAGE = "fail_message";
public static final String OP_ID = "op_id";
public static final String OP_NAME = "op_name";
public static final String SALT = "salt";
public static final String CREATE_TIME = "create_time";
public static final String UPDATE_TIME = "update_time";
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* <p>
* 场馆安心付授权记录
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class StudioAxfAuth implements Serializable {
private static final long serialVersionUID = -166947593419927514L;
/**
* 备注: 主键
* 是否允许为null: NO
*/
@TableId(value = "id", type = IdType.ID_WORKER)
private Long id;
/**
* 备注: 场馆id
* 是否允许为null: YES
*/
private Long studioId;
/**
* 备注: 支付宝用户id
* 是否允许为null: YES
*/
private String userId;
/**
* 备注: token
* 是否允许为null: YES
*/
private String appAuthToken;
/**
* 备注: 刷新token
* 是否允许为null: YES
*/
private String appRefreshToken;
/**
* 备注: 授权appid
* 是否允许为null: YES
*/
private String authAppId;
/**
* 备注: expiresIn
* 是否允许为null: YES
*/
private Long expiresIn;
/**
* 备注: re_expires_in
* 是否允许为null: YES
*/
private Integer reExpiresIn;
/**
* 备注: 本次授权是否已经完成进件
* 默认值: NO
* 是否允许为null: YES
*/
private String used;
/**
* 备注: 创建时间
* 是否允许为null: YES
*/
private Date createTime;
/**
* 备注: 更新时间
* 是否允许为null: YES
*/
private Date updateTime;
public static final String ID = "id";
public static final String STUDIO_ID = "studio_id";
public static final String USER_ID = "user_id";
public static final String APP_AUTH_TOKEN = "app_auth_token";
public static final String APP_REFRESH_TOKEN = "app_refresh_token";
public static final String AUTH_APP_ID = "auth_app_id";
public static final String EXPIRES_IN = "expires_in";
public static final String RE_EXPIRES_IN = "re_expires_in";
public static final String USED = "used";
public static final String CREATE_TIME = "create_time";
public static final String UPDATE_TIME = "update_time";
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* <p>
* 场馆安心付授权申请记录
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class StudioAxfAuthApply implements Serializable {
private static final long serialVersionUID = -166947593419927514L;
/**
* 备注: 主键
* 是否允许为null: NO
*/
@TableId(value = "id", type = IdType.ID_WORKER)
private Long id;
/**
* 备注: 场馆id
* 是否允许为null: YES
*/
private Long studioId;
/**
* 备注: 支付宝用户id
* 是否允许为null: YES
*/
private String userId;
/**
* 备注: token
* 是否允许为null: YES
*/
private String appAuthToken;
/**
* 备注: 刷新token
* 是否允许为null: YES
*/
private String appRefreshToken;
/**
* 备注: 授权appid
* 是否允许为null: YES
*/
private String authAppId;
/**
* 备注: expiresIn
* 是否允许为null: YES
*/
private Long expiresIn;
/**
* 备注: re_expires_in
* 是否允许为null: YES
*/
private Integer reExpiresIn;
/**
* 备注: 授权是否进件
* 默认值: NO
* 是否允许为null: YES
*/
private String used;
/**
* 备注: 创建时间
* 是否允许为null: YES
*/
private Date createTime;
/**
* 备注: 更新时间
* 是否允许为null: YES
*/
private Date updateTime;
public static final String ID = "id";
public static final String STUDIO_ID = "studio_id";
public static final String USER_ID = "user_id";
public static final String APP_AUTH_TOKEN = "app_auth_token";
public static final String APP_REFRESH_TOKEN = "app_refresh_token";
public static final String AUTH_APP_ID = "auth_app_id";
public static final String EXPIRES_IN = "expires_in";
public static final String RE_EXPIRES_IN = "re_expires_in";
public static final String USED = "used";
public static final String CREATE_TIME = "create_time";
public static final String UPDATE_TIME = "update_time";
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* <p>
* 场馆先享后付标品表
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class StudioAxfCommodityTemplate implements Serializable {
private static final long serialVersionUID = -166947593419927514L;
/**
* 备注: 主键ID
* 是否允许为null: NO
*/
@TableId(value = "id", type = IdType.ID_WORKER)
private Long id;
/**
* 备注: 场馆ID
* 是否允许为null: NO
*/
private Long studioId;
/**
* 备注: 商户ID
* 是否允许为null: YES
*/
private Long merchantId;
/**
* 备注: 商品模板ID
* 是否允许为null: YES
*/
private Long templateId;
/**
* 备注: 三方商品ID
* 是否允许为null: YES
*/
private String thirdTemplateId;
/**
* 备注: 商品模板名称
* 是否允许为null: YES
*/
private String templateName;
/**
* 备注: 申请状态
* 是否允许为null: YES
*/
private String state;
/**
* 备注: 是否立即扣首期款
* 默认值: 0
* 是否允许为null: YES
*/
private Boolean chargeNow;
/**
* 备注: 总期数
* 是否允许为null: YES
*/
private Integer totalPeriod;
/**
* 备注: 周期类型
* 是否允许为null: YES
*/
private String cycleType;
/**
* 备注: 周期计费类型
* 是否允许为null: YES
*/
private String cycleChargeType;
/**
* 备注: 周期计费参数
* 是否允许为null: YES
*/
private Integer cycleValue;
/**
* 备注: 售卖开始时间
* 是否允许为null: YES
*/
private Date saleStartTime;
/**
* 备注: 售卖结束时间
* 是否允许为null: YES
*/
private Date saleEndTime;
/**
* 备注: 其他属性
* 是否允许为null: YES
*/
private String attr;
/**
* 备注: 失败原因
* 是否允许为null: YES
*/
private String failMessage;
/**
* 备注: 创建时间
* 是否允许为null: YES
*/
private Date createTime;
/**
* 备注: 更新时间
* 是否允许为null: YES
*/
private Date updateTime;
public static final String ID = "id";
public static final String STUDIO_ID = "studio_id";
public static final String MERCHANT_ID = "merchant_id";
public static final String TEMPLATE_ID = "template_id";
public static final String THIRD_TEMPLATE_ID = "third_template_id";
public static final String TEMPLATE_NAME = "template_name";
public static final String STATE = "state";
public static final String CHARGE_NOW = "charge_now";
public static final String TOTAL_PERIOD = "total_period";
public static final String CYCLE_TYPE = "cycle_type";
public static final String CYCLE_CHARGE_TYPE = "cycle_charge_type";
public static final String CYCLE_VALUE = "cycle_value";
public static final String SALE_START_TIME = "sale_start_time";
public static final String SALE_END_TIME = "sale_end_time";
public static final String ATTR = "attr";
public static final String FAIL_MESSAGE = "fail_message";
public static final String CREATE_TIME = "create_time";
public static final String UPDATE_TIME = "update_time";
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* <p>
* 场馆商品标品申请表
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class StudioAxfCommodityTemplateApply implements Serializable {
private static final long serialVersionUID = -166947593419927514L;
/**
* 备注: 主键ID
* 是否允许为null: NO
*/
@TableId(value = "id", type = IdType.ID_WORKER)
private Long id;
/**
* 备注: 场馆ID
* 是否允许为null: NO
*/
private Long studioId;
/**
* 备注: 商户ID
* 是否允许为null: YES
*/
private Long merchantId;
/**
* 备注: 商品模板ID
* 是否允许为null: YES
*/
private Long templateId;
/**
* 备注: 三方商品ID
* 是否允许为null: YES
*/
private String thirdTemplateId;
/**
* 备注: 商品模板名称
* 是否允许为null: YES
*/
private String templateName;
/**
* 备注: 申请状态
* 是否允许为null: YES
*/
private String state;
/**
* 备注: 是否立即扣首期款
* 默认值: 0
* 是否允许为null: YES
*/
private Boolean chargeNow;
/**
* 备注: 总期数
* 是否允许为null: YES
*/
private Integer totalPeriod;
/**
* 备注: 周期类型
* 是否允许为null: YES
*/
private String cycleType;
/**
* 备注: 周期计费类型
* 是否允许为null: YES
*/
private String cycleChargeType;
/**
* 备注: 周期计费参数
* 是否允许为null: YES
*/
private Integer cycleValue;
/**
* 备注: 售卖开始时间
* 是否允许为null: YES
*/
private Date saleStartTime;
/**
* 备注: 售卖结束时间
* 是否允许为null: YES
*/
private Date saleEndTime;
/**
* 备注: 其他属性
* 是否允许为null: YES
*/
private String attr;
/**
* 备注: 失败原因
* 是否允许为null: YES
*/
private String failMessage;
/**
* 备注: 创建时间
* 是否允许为null: YES
*/
private Date createTime;
/**
* 备注: 更新时间
* 是否允许为null: YES
*/
private Date updateTime;
public static final String ID = "id";
public static final String STUDIO_ID = "studio_id";
public static final String MERCHANT_ID = "merchant_id";
public static final String TEMPLATE_ID = "template_id";
public static final String THIRD_TEMPLATE_ID = "third_template_id";
public static final String TEMPLATE_NAME = "template_name";
public static final String STATE = "state";
public static final String CHARGE_NOW = "charge_now";
public static final String TOTAL_PERIOD = "total_period";
public static final String CYCLE_TYPE = "cycle_type";
public static final String CYCLE_CHARGE_TYPE = "cycle_charge_type";
public static final String CYCLE_VALUE = "cycle_value";
public static final String SALE_START_TIME = "sale_start_time";
public static final String SALE_END_TIME = "sale_end_time";
public static final String ATTR = "attr";
public static final String FAIL_MESSAGE = "fail_message";
public static final String CREATE_TIME = "create_time";
public static final String UPDATE_TIME = "update_time";
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* <p>
* 先享后付订购单
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class StudioAxfOrder implements Serializable {
private static final long serialVersionUID = -166947593419927514L;
/**
* 备注: 主键
* 是否允许为null: NO
*/
@TableId(value = "id", type = IdType.ID_WORKER)
private Long id;
/**
* 备注: 场馆ID
* 是否允许为null: YES
*/
private Long studioId;
/**
* 备注: 渠道号
* 默认值: 001
* 是否允许为null: YES
*/
private String channelNo;
/**
* 备注: 商户ID
* 是否允许为null: YES
*/
private Long merchantId;
/**
* 备注: 商品ID
* 是否允许为null: YES
*/
private Long commodityId;
/**
* 备注: 学员ID
* 是否允许为null: YES
*/
private Long studentId;
/**
* 备注: 学员姓名
* 是否允许为null: YES
*/
private String studentName;
/**
* 备注: 签约状态
* 是否允许为null: YES
*/
private String signState;
/**
* 备注: 总期数
* 是否允许为null: YES
*/
private Integer totalPeriod;
/**
* 备注: 总原价(签约扣款金额):元
* 是否允许为null: YES
*/
private BigDecimal originalPrice;
/**
* 备注: 售价:元
* 是否允许为null: YES
*/
private BigDecimal salePrice;
/**
* 备注: 已扣款金额:元
* 是否允许为null: YES
*/
private BigDecimal receivedAmount;
/**
* 备注: 已扣款手续费:元
* 是否允许为null: YES
*/
private BigDecimal receivedFee;
/**
* 备注: 已扣款实收金额:元
* 是否允许为null: YES
*/
private BigDecimal receivedActualAmount;
/**
* 备注: 当前扣款期数
* 是否允许为null: YES
*/
private Integer receivedPeriod;
/**
* 备注: 手续费率:%
* 是否允许为null: YES
*/
private BigDecimal rate;
/**
* 备注: 订单ID
* 是否允许为null: YES
*/
private Long voucherId;
/**
* 备注: 订单号:冗余字段
* 是否允许为null: YES
*/
private String voucherBusinessNo;
/**
* 备注: 支付宝订购单号
* 是否允许为null: YES
*/
private String thirdOrderNo;
/**
* 备注: 解约人ID
* 是否允许为null: YES
*/
private Long cancelOpId;
/**
* 备注: 解约人姓名
* 是否允许为null: YES
*/
private String cancelOpName;
/**
* 备注: 解约失败
* 是否允许为null: YES
*/
private String cancelFailMessage;
/**
* 备注: 订单的其他属性
* 是否允许为null: YES
*/
private String attr;
/**
* 备注: 解约时间
* 是否允许为null: YES
*/
private Date cancelTime;
/**
* 备注: 签约时间
* 是否允许为null: YES
*/
private Date signTime;
/**
* 备注: 创建时间
* 是否允许为null: YES
*/
private Date createTime;
/**
* 备注: 更新时间
* 是否允许为null: YES
*/
private Date updateTime;
public static final String ID = "id";
public static final String STUDIO_ID = "studio_id";
public static final String CHANNEL_NO = "channel_no";
public static final String MERCHANT_ID = "merchant_id";
public static final String COMMODITY_ID = "commodity_id";
public static final String STUDENT_ID = "student_id";
public static final String STUDENT_NAME = "student_name";
public static final String SIGN_STATE = "sign_state";
public static final String TOTAL_PERIOD = "total_period";
public static final String ORIGINAL_PRICE = "original_price";
public static final String SALE_PRICE = "sale_price";
public static final String RECEIVED_AMOUNT = "received_amount";
public static final String RECEIVED_FEE = "received_fee";
public static final String RECEIVED_ACTUAL_AMOUNT = "received_actual_amount";
public static final String RECEIVED_PERIOD = "received_period";
public static final String RATE = "rate";
public static final String VOUCHER_ID = "voucher_id";
public static final String VOUCHER_BUSINESS_NO = "voucher_business_no";
public static final String THIRD_ORDER_NO = "third_order_no";
public static final String CANCEL_OP_ID = "cancel_op_id";
public static final String CANCEL_OP_NAME = "cancel_op_name";
public static final String CANCEL_FAIL_MESSAGE = "cancel_fail_message";
public static final String ATTR = "attr";
public static final String CANCEL_TIME = "cancel_time";
public static final String SIGN_TIME = "sign_time";
public static final String CREATE_TIME = "create_time";
public static final String UPDATE_TIME = "update_time";
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* <p>
* 场馆先享后付订购单扣款记录
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class StudioAxfOrderDeduction implements Serializable {
private static final long serialVersionUID = -166947593419927514L;
/**
* 备注: 主键 是否允许为null: NO
*/
@TableId(value = "id", type = IdType.ID_WORKER)
private Long id;
/**
* 备注: 订购单ID 是否允许为null: YES
*/
private Long orderId;
/**
* 备注: 扣款期数 是否允许为null: YES
*/
private Integer period;
/**
* 备注: 扣款金额:元 是否允许为null: YES
*/
private BigDecimal amount;
/**
* 备注: 实收金额(元) 是否允许为null: YES
*/
private BigDecimal actualAmount;
/**
* 备注: 手续费 默认值: 0.00 是否允许为null: YES
*/
private BigDecimal fee;
/**
* 备注: 费率(%) 是否允许为null: YES
*/
private BigDecimal rate;
/**
* 备注: 扣款状态 是否允许为null: YES
*/
private String state;
/**
* 备注: 扣款失败原因 是否允许为null: YES
*/
private String failMessage;
/**
* 备注: 支付流水号 是否允许为null: YES
*/
private String transNo;
/**
* 备注: 支付宝订购单号:冗余字段 是否允许为null: YES
*/
private String thirdOrderNo;
/**
* 备注: 支付宝交易单号 是否允许为null: YES
*/
private String thirdTransNo;
/**
* 备注: 追缴次数 默认值: 0 是否允许为null: YES
*/
private Integer recoveryTimes;
/**
* 备注: 扣款时间 是否允许为null: YES
*/
private Date deductionTime;
/**
* 备注: 创建时间 是否允许为null: YES
*/
private Date createTime;
/**
* 备注: 更新时间 是否允许为null: YES
*/
private Date updateTime;
public static final String ID = "id";
public static final String ORDER_ID = "order_id";
public static final String PERIOD = "period";
public static final String AMOUNT = "amount";
public static final String ACTUAL_AMOUNT = "actual_amount";
public static final String FEE = "fee";
public static final String RATE = "rate";
public static final String STATE = "state";
public static final String FAIL_MESSAGE = "fail_message";
public static final String TRANS_NO = "trans_no";
public static final String THIRD_ORDER_NO = "third_order_no";
public static final String THIRD_TRANS_NO = "third_trans_no";
public static final String RECOVERY_TIMES = "recovery_times";
public static final String DEDUCTION_TIME = "deduction_time";
public static final String CREATE_TIME = "create_time";
public static final String UPDATE_TIME = "update_time";
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* <p>
* 场馆先享后付订购单追缴记录
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class StudioAxfOrderRecovery implements Serializable {
private static final long serialVersionUID = -166947593419927514L;
/**
* 备注: 主键
* 是否允许为null: NO
*/
@TableId(value = "id", type = IdType.ID_WORKER)
private Long id;
/**
* 备注: 订购单ID
* 是否允许为null: YES
*/
private Long orderId;
/**
* 备注: 扣款记录ID
* 是否允许为null: YES
*/
private Long deductionId;
/**
* 备注: 扣款期数
* 是否允许为null: YES
*/
private Integer period;
/**
* 备注: 扣款金额:元
* 是否允许为null: YES
*/
private BigDecimal amount;
/**
* 备注: 实收金额(元)
* 是否允许为null: YES
*/
private BigDecimal actualAmount;
/**
* 备注: 手续费
* 默认值: 0.00
* 是否允许为null: YES
*/
private BigDecimal fee;
/**
* 备注: 费率(%)
* 是否允许为null: YES
*/
private BigDecimal rate;
/**
* 备注: 扣款状态
* 是否允许为null: YES
*/
private String state;
/**
* 备注: 扣款失败原因
* 是否允许为null: YES
*/
private String failMessage;
/**
* 备注: 支付流水号
* 是否允许为null: YES
*/
private String transNo;
/**
* 备注: 支付宝订购单号:冗余字段
* 是否允许为null: YES
*/
private String thirdOrderNo;
/**
* 备注: 支付宝交易单号
* 是否允许为null: YES
*/
private String thirdTransNo;
/**
* 备注: 扣款时间
* 是否允许为null: YES
*/
private Date deductionTime;
/**
* 备注: 创建时间
* 是否允许为null: YES
*/
private Date createTime;
/**
* 备注: 更新时间
* 是否允许为null: YES
*/
private Date updateTime;
public static final String ID = "id";
public static final String ORDER_ID = "order_id";
public static final String DEDUCTION_ID = "deduction_id";
public static final String PERIOD = "period";
public static final String AMOUNT = "amount";
public static final String ACTUAL_AMOUNT = "actual_amount";
public static final String FEE = "fee";
public static final String RATE = "rate";
public static final String STATE = "state";
public static final String FAIL_MESSAGE = "fail_message";
public static final String TRANS_NO = "trans_no";
public static final String THIRD_ORDER_NO = "third_order_no";
public static final String THIRD_TRANS_NO = "third_trans_no";
public static final String DEDUCTION_TIME = "deduction_time";
public static final String CREATE_TIME = "create_time";
public static final String UPDATE_TIME = "update_time";
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.mapper;
import com.jiejing.fitness.finance.repository.entity.StudioAxfApply;
import com.jiejing.mbp.inject.XBaseMapper;
/**
* <p>
* 机构安心付申请记录 Mapper 接口
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
public interface StudioAxfApplyMapper extends XBaseMapper<StudioAxfApply> {
int countDistinctStudioId();
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
~
~ The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
~ Official website: www.xiaomai5.com
~
~
~
~ Copyright © 2024 杭州杰竞科技有限公司 版权所有.
~
~ 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
~ 官网: www.xiaomai5.com
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiejing.fitness.finance.repository.mapper.StudioAxfApplyMapper">
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, channel_no, merchant_no, merchant_id, studio_id, apply_type, studio_name, merchant_name, short_name, company_type, state, card_no, license_code, license_name, license_type, license_expire_type, license_start_time, license_end_time, legal_name, legal_cert_no, phone, business_province_code, business_province_name, business_city_code, business_city_name, business_district_code, business_district_name, business_address, license_resource_id, store_head_resource_id, fail_message, op_id, op_name, salt, create_time, update_time
</sql>
<select id="countDistinctStudioId" resultType="java.lang.Integer">
select count(distinct studio_id)
from studio_axf_apply
</select>
</mapper>
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.mapper;
import com.jiejing.fitness.finance.repository.entity.StudioAxfAuthApply;
import com.jiejing.mbp.inject.XBaseMapper;
/**
* <p>
* 场馆安心付授权申请记录 Mapper 接口
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
public interface StudioAxfAuthApplyMapper extends XBaseMapper<StudioAxfAuthApply> {
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
~
~ The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
~ Official website: www.xiaomai5.com
~
~
~
~ Copyright © 2024 杭州杰竞科技有限公司 版权所有.
~
~ 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
~ 官网: www.xiaomai5.com
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiejing.fitness.finance.repository.mapper.StudioAxfAuthApplyMapper">
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, studio_id, user_id, app_auth_token, app_refresh_token, auth_app_id, expires_in, re_expires_in, used, create_time, update_time
</sql>
</mapper>
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.mapper;
import com.jiejing.fitness.finance.repository.entity.StudioAxfAuth;
import com.jiejing.mbp.inject.XBaseMapper;
/**
* <p>
* 场馆安心付授权记录 Mapper 接口
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
public interface StudioAxfAuthMapper extends XBaseMapper<StudioAxfAuth> {
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
~
~ The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
~ Official website: www.xiaomai5.com
~
~
~
~ Copyright © 2024 杭州杰竞科技有限公司 版权所有.
~
~ 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
~ 官网: www.xiaomai5.com
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiejing.fitness.finance.repository.mapper.StudioAxfAuthMapper">
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, studio_id, user_id, app_auth_token, app_refresh_token, auth_app_id, expires_in, re_expires_in, used, create_time, update_time
</sql>
</mapper>
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.mapper;
import com.jiejing.fitness.finance.repository.entity.StudioAxfCommodityTemplateApply;
import com.jiejing.mbp.inject.XBaseMapper;
/**
* <p>
* 场馆商品标品申请表 Mapper 接口
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
public interface StudioAxfCommodityTemplateApplyMapper extends XBaseMapper<StudioAxfCommodityTemplateApply> {
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
~
~ The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
~ Official website: www.xiaomai5.com
~
~
~
~ Copyright © 2024 杭州杰竞科技有限公司 版权所有.
~
~ 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
~ 官网: www.xiaomai5.com
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiejing.fitness.finance.repository.mapper.StudioAxfCommodityTemplateApplyMapper">
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, studio_id, merchant_id, template_id, third_template_id, template_name, state, charge_now, total_period, cycle_type, cycle_charge_type, cycle_value, sale_start_time, sale_end_time, attr, fail_message, create_time, update_time
</sql>
</mapper>
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.mapper;
import com.jiejing.fitness.finance.repository.entity.StudioAxfCommodityTemplate;
import com.jiejing.mbp.inject.XBaseMapper;
/**
* <p>
* 场馆先享后付标品表 Mapper 接口
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
public interface StudioAxfCommodityTemplateMapper extends XBaseMapper<StudioAxfCommodityTemplate> {
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
~
~ The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
~ Official website: www.xiaomai5.com
~
~
~
~ Copyright © 2024 杭州杰竞科技有限公司 版权所有.
~
~ 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
~ 官网: www.xiaomai5.com
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiejing.fitness.finance.repository.mapper.StudioAxfCommodityTemplateMapper">
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, studio_id, merchant_id, template_id, third_template_id, template_name, state, charge_now, total_period, cycle_type, cycle_charge_type, cycle_value, sale_start_time, sale_end_time, attr, fail_message, create_time, update_time
</sql>
</mapper>
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.mapper;
import com.jiejing.fitness.finance.repository.entity.StudioAxfOrderDeduction;
import com.jiejing.mbp.inject.XBaseMapper;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* 场馆先享后付订购单扣款记录 Mapper 接口
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
public interface StudioAxfOrderDeductionMapper extends XBaseMapper<StudioAxfOrderDeduction> {
void incRecoveryTimes(@Param("id") Long id);
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
~
~ The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
~ Official website: www.xiaomai5.com
~
~
~
~ Copyright © 2024 杭州杰竞科技有限公司 版权所有.
~
~ 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
~ 官网: www.xiaomai5.com
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiejing.fitness.finance.repository.mapper.StudioAxfOrderDeductionMapper">
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, order_id, period, amount, actual_amount, fee, rate, state, fail_message, trans_no, third_order_no, third_trans_no, recovery_times, deduction_time, create_time, update_time
</sql>
<update id="incRecoveryTimes">
update studio_axf_order_deduction
set recovery_times = recovery_times + 1
where id = #{id}
</update>
</mapper>
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.mapper;
import com.jiejing.fitness.finance.api.axf.enums.AxfOrderSignStateEnums;
import com.jiejing.fitness.finance.api.axf.vo.AggStudioAxfOrderVO;
import com.jiejing.fitness.finance.repository.entity.StudioAxfOrder;
import com.jiejing.mbp.inject.XBaseMapper;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* 先享后付订购单 Mapper 接口
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
public interface StudioAxfOrderMapper extends XBaseMapper<StudioAxfOrder> {
AggStudioAxfOrderVO agg(@Param("studioIds") List<Long> studioIds, @Param("studentId") Long studentId,
@Param("studentName") String studentName, @Param("voucherBusinessNo") String voucherBusinessNo,
@Param("thirdOrderNo") String thirdOrderNo, @Param("signTimeStart") Date signTimeStart,
@Param("signTimeEnd") Date signTimeEnd, @Param("cancelTimeStart") Date cancelTimeStart,
@Param("cancelTimeEnd") Date cancelTimeEnd, @Param("state") AxfOrderSignStateEnums state);
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
~
~ The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
~ Official website: www.xiaomai5.com
~
~
~
~ Copyright © 2024 杭州杰竞科技有限公司 版权所有.
~
~ 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
~ 官网: www.xiaomai5.com
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiejing.fitness.finance.repository.mapper.StudioAxfOrderMapper">
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, studio_id, channel_no, merchant_id, commodity_id, student_id, student_name, sign_state, total_period, original_price, sale_price, received_amount, received_fee, received_actual_amount, received_period, rate, voucher_id, voucher_business_no, third_order_no, cancel_op_id, cancel_op_name, cancel_fail_message, attr, cancel_time, sign_time, create_time, update_time
</sql>
<select id="agg" resultType="com.jiejing.fitness.finance.api.axf.vo.AggStudioAxfOrderVO">
select sum(received_amount) as receivedAmount, sum(received_actual_amount) as receivedActualAmount
from studio_axf_order
<where>
<if test="studioIds != null and studioIds.size > 0">
and studio_id in
<foreach close=")" collection="studioIds" index="index" item="item" open="(" separator=",">
#{item}
</foreach>
</if>
<if test="studentId != null">
and student_id = #{studentId}
</if>
<if test="studentName != null">
and student_name = #{studentName}
</if>
<if test="voucherBusinessNo != null">
and voucher_business_no = #{voucherBusinessNo}
</if>
<if test="thirdOrderNo != null">
and third_order_no = #{thirdOrderNo}
</if>
<if test="signTimeStart != null">
and sign_time >= #{signTimeStart}
</if>
<if test="signTimeEnd != null">
and sign_time &lt;= #{signTimeEnd}
</if>
<if test="cancelTimeStart != null">
and cancel_time >= #{cancelTimeStart}
</if>
<if test="cancelTimeEnd != null">
and cancel_time &lt;= #{cancelTimeEnd}
</if>
<if test="state != null">
and sign_state = #{state}
</if>
</where>
</select>
</mapper>
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.mapper;
import com.jiejing.fitness.finance.repository.entity.StudioAxfOrderRecovery;
import com.jiejing.mbp.inject.XBaseMapper;
/**
* <p>
* 场馆先享后付订购单追缴记录 Mapper 接口
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
public interface StudioAxfOrderRecoveryMapper extends XBaseMapper<StudioAxfOrderRecovery> {
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
~
~ The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
~ Official website: www.xiaomai5.com
~
~
~
~ Copyright © 2024 杭州杰竞科技有限公司 版权所有.
~
~ 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
~ 官网: www.xiaomai5.com
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiejing.fitness.finance.repository.mapper.StudioAxfOrderRecoveryMapper">
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, order_id, deduction_id, period, amount, actual_amount, fee, rate, state, fail_message, trans_no, third_order_no, third_trans_no, deduction_time, create_time, update_time
</sql>
</mapper>
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.jiejing.fitness.finance.api.axf.enums.AxfStateEnums;
import com.jiejing.fitness.finance.repository.entity.StudioAxfApply;
import com.jiejing.fitness.finance.repository.mapper.StudioAxfApplyMapper;
import com.jiejing.mbp.MapperRepoService;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
/**
* <p>
* 机构安心付申请记录 服务实现类
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Service
public class StudioAxfApplyRpService extends MapperRepoService<Long, StudioAxfApply, StudioAxfApplyMapper> {
public Integer countProcessByStudioId(Long studioId) {
QueryWrapper<StudioAxfApply> wrapper = new QueryWrapper<>();
wrapper.eq(StudioAxfApply.STUDIO_ID, studioId);
wrapper.in(StudioAxfApply.STATE,
Lists.newArrayList(AxfStateEnums.INIT, AxfStateEnums.AXF_PROCESS, AxfStateEnums.STORE_PROCESS));
Integer count = this.baseMapper.selectCount(wrapper);
return Optional.ofNullable(count).orElse(0);
}
public StudioAxfApply getLatestOneByMerchantId(Long merchantId, AxfStateEnums state) {
QueryWrapper<StudioAxfApply> wrapper = new QueryWrapper<>();
wrapper.eq(StudioAxfApply.MERCHANT_ID, merchantId);
wrapper.eq(StudioAxfApply.STATE, state);
wrapper.orderByDesc(StudioAxfApply.ID);
return this.baseMapper.selectPage(new Page<>(0, 1), wrapper).getRecords().stream().findFirst()
.orElse(null);
}
public org.springframework.data.domain.Page<StudioAxfApply> page(Long studioId, String instName,
String shortName, Date createTimeStart,
Date createTimeEnd, List<AxfStateEnums> stateList, Integer current, Integer size) {
QueryWrapper<StudioAxfApply> wrapper = new QueryWrapper<>();
if (null != studioId) {
wrapper.eq(StudioAxfApply.STUDIO_ID, studioId);
}
if (StringUtils.isNotBlank(instName)) {
wrapper.like(StudioAxfApply.STUDIO_NAME, instName);
}
if (StringUtils.isNotBlank(shortName)) {
wrapper.like(StudioAxfApply.SHORT_NAME, shortName);
}
if (CollectionUtils.isNotEmpty(stateList)) {
wrapper.in(StudioAxfApply.STATE, stateList);
}
if (null != createTimeStart) {
wrapper.ge(StudioAxfApply.CREATE_TIME, createTimeStart);
}
if (null != createTimeEnd) {
wrapper.le(StudioAxfApply.CREATE_TIME, createTimeEnd);
}
wrapper.orderByDesc(StudioAxfApply.ID);
return this.findByWrapperPage(wrapper, current, size);
}
public StudioAxfApply getLatestOneByMerchantNo(Long studioId, String merchantNo) {
QueryWrapper<StudioAxfApply> wrapper = new QueryWrapper<>();
wrapper.eq(StudioAxfApply.STUDIO_ID, studioId);
if (StringUtils.isNotBlank(merchantNo)) {
wrapper.eq(StudioAxfApply.MERCHANT_NO, merchantNo);
}
wrapper.orderByDesc(StudioAxfApply.ID);
return this.baseMapper.selectPage(new Page<>(0, 1), wrapper).getRecords().stream().findFirst()
.orElse(null);
}
public int countDistinctStudioId() {
return this.baseMapper.countDistinctStudioId();
}
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jiejing.fitness.finance.repository.entity.StudioAxfAuthApply;
import com.jiejing.fitness.finance.repository.mapper.StudioAxfAuthApplyMapper;
import com.jiejing.mbp.MapperRepoService;
import org.springframework.stereotype.Service;
/**
* <p>
* 场馆安心付授权申请记录 服务实现类
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Service
public class StudioAxfAuthApplyRpService extends
MapperRepoService<Long, StudioAxfAuthApply, StudioAxfAuthApplyMapper> {
public StudioAxfAuthApply getLatestByUserId(Long studioId, String userId) {
QueryWrapper<StudioAxfAuthApply> wrapper = new QueryWrapper<>();
wrapper.eq(StudioAxfAuthApply.STUDIO_ID, studioId);
wrapper.eq(StudioAxfAuthApply.USER_ID, userId);
wrapper.orderByDesc(StudioAxfAuthApply.ID);
return this.baseMapper.selectPage(new Page<>(0, 1), wrapper).getRecords().stream().findFirst()
.orElse(null);
}
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.service;
import com.jiejing.fitness.finance.repository.entity.StudioAxfAuth;
import com.jiejing.fitness.finance.repository.mapper.StudioAxfAuthMapper;
import com.jiejing.mbp.MapperRepoService;
import org.springframework.stereotype.Service;
/**
* <p>
* 场馆安心付授权记录 服务实现类
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Service
public class StudioAxfAuthRpService extends MapperRepoService<Long, StudioAxfAuth, StudioAxfAuthMapper> {
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.service;
import com.jiejing.fitness.finance.repository.entity.StudioAxfCommodityTemplateApply;
import com.jiejing.fitness.finance.repository.mapper.StudioAxfCommodityTemplateApplyMapper;
import com.jiejing.mbp.MapperRepoService;
import org.springframework.stereotype.Service;
/**
* <p>
* 场馆商品标品申请表 服务实现类
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Service
public class StudioAxfCommodityTemplateApplyRpService extends MapperRepoService<Long, StudioAxfCommodityTemplateApply, StudioAxfCommodityTemplateApplyMapper> {
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jiejing.fitness.finance.repository.entity.StudioAxfCommodityTemplate;
import com.jiejing.fitness.finance.repository.mapper.StudioAxfCommodityTemplateMapper;
import com.jiejing.mbp.MapperRepoService;
import com.jiejing.paycenter.common.enums.common.OpenStateEnums;
import java.util.List;
import org.springframework.stereotype.Service;
/**
* <p>
* 场馆先享后付标品表 服务实现类
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Service
public class StudioAxfCommodityTemplateRpService extends
MapperRepoService<Long, StudioAxfCommodityTemplate, StudioAxfCommodityTemplateMapper> {
public List<StudioAxfCommodityTemplate> listSuccessAll(Long merchantId) {
QueryWrapper<StudioAxfCommodityTemplate> wrapper = new QueryWrapper<>();
wrapper.eq(StudioAxfCommodityTemplate.MERCHANT_ID, merchantId);
wrapper.eq(StudioAxfCommodityTemplate.STATE, OpenStateEnums.SUCCESS.getCode());
return this.baseMapper.selectList(wrapper);
}
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jiejing.fitness.finance.repository.entity.StudioAxfOrderDeduction;
import com.jiejing.fitness.finance.repository.mapper.StudioAxfOrderDeductionMapper;
import com.jiejing.mbp.MapperRepoService;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Service;
/**
* <p>
* 场馆先享后付订购单扣款记录 服务实现类
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Service
public class StudioAxfOrderDeductionRpService extends
MapperRepoService<Long, StudioAxfOrderDeduction, StudioAxfOrderDeductionMapper> {
public List<StudioAxfOrderDeduction> listByOrderId(Long orderId) {
QueryWrapper<StudioAxfOrderDeduction> wrapper = new QueryWrapper<>();
wrapper.eq(StudioAxfOrderDeduction.ORDER_ID, orderId);
wrapper.orderByDesc(StudioAxfOrderDeduction.PERIOD);
return Optional.ofNullable(this.baseMapper.selectList(wrapper)).orElse(new ArrayList<>(1));
}
public Integer incRecoveryTimes(Long id) {
this.baseMapper.incRecoveryTimes(id);
return this.getById(id).orElse(new StudioAxfOrderDeduction()).getRecoveryTimes();
}
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jiejing.fitness.finance.repository.entity.StudioAxfOrderRecovery;
import com.jiejing.fitness.finance.repository.mapper.StudioAxfOrderRecoveryMapper;
import com.jiejing.mbp.MapperRepoService;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Service;
/**
* <p>
* 场馆先享后付订购单追缴记录 服务实现类
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Service
public class StudioAxfOrderRecoveryRpService extends
MapperRepoService<Long, StudioAxfOrderRecovery, StudioAxfOrderRecoveryMapper> {
public List<StudioAxfOrderRecovery> listByDeductionId(Long deductionId) {
QueryWrapper<StudioAxfOrderRecovery> wrapper = new QueryWrapper<>();
wrapper.eq(StudioAxfOrderRecovery.DEDUCTION_ID, deductionId);
wrapper.orderByDesc(StudioAxfOrderRecovery.ID);
return Optional.ofNullable(this.baseMapper.selectList(wrapper)).orElse(new ArrayList<>(1));
}
}
/*
* Copyright © 2024 Hangzhou Jiejing Technology Co., Ltd. All rights reserved.
*
* The copyright of the company's program code belongs to Hangzhou Jiejing Technology Co., Ltd. No one can illegally copy it without the explicit permission of this website.
* Official website: www.xiaomai5.com
*
*
*
* Copyright © 2024 杭州杰竞科技有限公司 版权所有.
*
* 本公司程序代码的版权归杭州杰竞科技有限公司所有,未经本网站的明确许可,任何人不得非法复制。
* 官网: www.xiaomai5.com
*/
package com.jiejing.fitness.finance.repository.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jiejing.fitness.finance.api.axf.enums.AxfOrderSignStateEnums;
import com.jiejing.fitness.finance.api.axf.vo.AggStudioAxfOrderVO;
import com.jiejing.fitness.finance.repository.entity.StudioAxfOrder;
import com.jiejing.fitness.finance.repository.mapper.StudioAxfOrderMapper;
import com.jiejing.mbp.MapperRepoService;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import org.springframework.stereotype.Service;
/**
* <p>
* 先享后付订购单 服务实现类
* </p>
*
* @author chengyubing, created on 2024-11-04
*/
@Service
public class StudioAxfOrderRpService extends MapperRepoService<Long, StudioAxfOrder, StudioAxfOrderMapper> {
public StudioAxfOrder getByVoucherId(Long voucherId) {
QueryWrapper<StudioAxfOrder> wrapper = new QueryWrapper<>();
wrapper.eq(StudioAxfOrder.VOUCHER_ID, voucherId);
wrapper.orderByAsc(StudioAxfOrder.ID);
return this.baseMapper.selectPage(new Page<>(0, 1), wrapper).getRecords().stream().findFirst()
.orElse(null);
}
public org.springframework.data.domain.Page<StudioAxfOrder> page(List<Long> studioIds, Long studentId,
String studentName,
String voucherBusinessNo, String thirdOrderNo, Date signTimeStart, Date signTimeEnd,
Date cancelTimeStart, Date cancelTimeEnd, AxfOrderSignStateEnums state, Integer current, Integer size) {
QueryWrapper<StudioAxfOrder> wrapper = new QueryWrapper<>();
if (CollectionUtils.isNotEmpty(studioIds)) {
wrapper.in(StudioAxfOrder.STUDIO_ID, studioIds);
}
if (null != studentId) {
wrapper.eq(StudioAxfOrder.STUDENT_ID, studentId);
}
if (StringUtils.isNotEmpty(studentName)) {
wrapper.eq(StudioAxfOrder.STUDENT_NAME, studentName);
}
if (StringUtils.isNotEmpty(voucherBusinessNo)) {
wrapper.eq(StudioAxfOrder.VOUCHER_BUSINESS_NO, voucherBusinessNo);
}
if (StringUtils.isNotEmpty(thirdOrderNo)) {
wrapper.eq(StudioAxfOrder.THIRD_ORDER_NO, thirdOrderNo);
}
if (null != state) {
wrapper.eq(StudioAxfOrder.SIGN_STATE, state);
}
if (null != signTimeStart) {
wrapper.ge(StudioAxfOrder.SIGN_TIME, signTimeStart);
}
if (null != signTimeEnd) {
wrapper.le(StudioAxfOrder.SIGN_TIME, signTimeEnd);
}
if (null != cancelTimeStart) {
wrapper.ge(StudioAxfOrder.CANCEL_TIME, cancelTimeStart);
}
if (null != cancelTimeEnd) {
wrapper.le(StudioAxfOrder.CANCEL_TIME, cancelTimeEnd);
}
wrapper.orderByDesc(StudioAxfOrder.ID);
return this.findByWrapperPage(wrapper, current, size);
}
public StudioAxfOrder getByThirdOrderNo(Long merchantId, String thirdOrderNo) {
QueryWrapper<StudioAxfOrder> wrapper = new QueryWrapper<>();
wrapper.eq(StudioAxfOrder.MERCHANT_ID, merchantId);
wrapper.eq(StudioAxfOrder.THIRD_ORDER_NO, thirdOrderNo);
return this.baseMapper.selectPage(new Page<>(0, 1), wrapper).getRecords().stream().findFirst()
.orElse(null);
}
public AggStudioAxfOrderVO agg(List<Long> studioIds, Long studentId, String studentName,
String voucherBusinessNo, String thirdOrderNo, Date signTimeStart, Date signTimeEnd,
Date cancelTimeStart, Date cancelTimeEnd, AxfOrderSignStateEnums state) {
AggStudioAxfOrderVO vo = this.baseMapper.agg(studioIds, studentId, studentName, voucherBusinessNo,
thirdOrderNo, signTimeStart, signTimeEnd, cancelTimeStart, cancelTimeEnd, state);
if (null == vo) {
return AggStudioAxfOrderVO.builder().receivedActualAmount(BigDecimal.ZERO)
.receivedAmount(BigDecimal.ZERO)
.build();
}
vo.setReceivedActualAmount(
vo.getReceivedActualAmount() == null ? BigDecimal.ZERO : vo.getReceivedActualAmount());
vo.setReceivedAmount(vo.getReceivedAmount() == null ? BigDecimal.ZERO : vo.getReceivedAmount());
return vo;
}
}
......@@ -60,7 +60,15 @@ public class GeneratorServiceEntity {
// "studio_settle_record",
// "studio_check_settle_record",
// "merchant_settle_record"
"studio_embedded_xcx_apply"
// "studio_embedded_xcx_apply",
"studio_axf_apply",
"studio_axf_auth",
"studio_axf_auth_apply",
"studio_axf_commodity_template",
"studio_axf_commodity_template_apply",
"studio_axf_order",
"studio_axf_order_deduction",
"studio_axf_order_recovery"
};
/**
......
......@@ -48,6 +48,14 @@
<artifactId>workflow-api</artifactId>
</dependency>
<dependency>
<groupId>com.jiejing.app</groupId>
<artifactId>member-api</artifactId>
</dependency>
<dependency>
<groupId>com.jiejing.fitness</groupId>
<artifactId>trade-api</artifactId>
</dependency>
<dependency>
<groupId>com.jiejing.event</groupId>
<artifactId>scs-event</artifactId>
</dependency>
......
package com.jiejing.fitness.finance.service.axf;
import com.jiejing.common.enums.ConfirmEnum;
import com.jiejing.common.model.PageVO;
import com.jiejing.fitness.finance.api.axf.request.StudioAxfApplyRequest;
import com.jiejing.fitness.finance.api.axf.request.*;
import com.jiejing.fitness.finance.api.axf.vo.*;
import com.jiejing.paycenter.common.enums.merchant.GrantTypeEnums;
import com.jiejing.paycenter.common.event.CommodityOrderEvent;
import com.jiejing.paycenter.common.event.MerchantEvent;
import com.jiejing.paycenter.common.event.OrderDeductionEvent;
import com.jiejing.paycenter.common.event.StoreEvent;
import com.jiejing.paycenter.common.model.vo.BindCardVO;
import com.jiejing.paycenter.common.model.vo.CancelCommodityOrderVO;
import com.jiejing.paycenter.common.model.vo.CommodityVO;
import com.jiejing.paycenter.common.model.vo.CreateCommodityVO;
import java.util.Date;
import java.util.List;
/**
* @author chengyubing
* @since 2024/9/7 11:35
*/
public interface AxfService {
/**
* 获取当前绑定的商户信息(开通中、开通失败、未开通都返回null)
*/
StudioAxfApplyVO getMerchant(Long instId);
/**
* 授权
*/
StudioAuthTokenVO authToken(Long instId, GrantTypeEnums grantType, String code, String refreshToken);
/**
* 获取授权信息
*/
StudioAuthTokenVO getAuthToken(Long instId);
/**
* 获取可配置的结算账号
*/
List<String> listSettleAccount(Long instId);
/**
* 进件
*/
Long apply(StudioAxfApplyRequest params);
/**
* 绑定结算账户
*/
BindCardVO bindCard(Long id, String cardNo);
/**
* 解约订购单
*/
CancelCommodityOrderVO cancelOrder(Long id, Long opId);
/**
* 商户回调
*/
void callback(MerchantEvent event);
/**
* 门店回调
*/
void storeCallback(StoreEvent event);
/**
* 订购单回调
*/
void orderCallback(CommodityOrderEvent event);
/**
* 订购单扣款回调
*/
void orderDeductionCallback(OrderDeductionEvent event);
/**
* 查询申请记录
*/
StudioAxfApplyVO getById(Long id);
/**
* 查询最近的申请记录
*/
StudioAxfApplyVO getLatestApply(Long instId, String merchantNo);
/**
* 分页查询申请记录
*/
PageVO<StudioAxfApplyVO> page(PageStudioAxfApplyRequest request);
/**
* 统计申请记录
*/
AggStudioAxfApplyVO agg();
/**
* 分页查询订购单
*/
PageVO<StudioAxfOrderVO> pageOrder(PageStudioAxfOrderRequest request);
/**
* 统计订购单
*/
AggStudioAxfOrderVO aggOrder(PageStudioAxfOrderRequest request);
/**
* 查询订购单详情
*/
StudioAxfOrderVO getOrder(Long id);
/**
* 创建商品
*/
CreateCommodityVO createCommodity(CreateStudioAxfCommodityRequest request);
/**
* 查询安心付一课一价商品
*/
CommodityVO getCommodity(String thirdCommodityId);
/**
* 查询订购单扣款明细
*/
List<StudioAxfOrderDeductionVO> listDeduction(Long orderId);
/**
* 校验是否存在失败的扣款
*/
ConfirmEnum existFailDeduction(Long orderId);
/**
* 查询订购单追缴明细
*/
List<StudioAxfOrderRecoveryVO> listRecovery(Long deductionId);
/**
* 解约失败
*/
void cancelFail(Long id, Long opId, Date date);
/**
* 根据订单查询订购单
*/
StudioAxfOrderVO getByVoucherId(Long voucherId);
}
package com.jiejing.fitness.finance.service.axf.constans;
import java.math.BigDecimal;
/**
* @author chengyubing
* @since 2024/9/7 11:34
*/
public interface AxfConst {
String CHANNEL_NO = "004";
BigDecimal RATE = new BigDecimal("0.6");
String OPEN = "OPEN";
}
package com.jiejing.fitness.finance.service.axf.convert;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.collect.Lists;
import com.jiejing.common.enums.ConfirmEnum;
import com.jiejing.common.model.JsonResult;
import com.jiejing.common.utils.convert.BeanUtil;
import com.jiejing.common.utils.crypt.AesUtil;
import com.jiejing.fitness.enums.trade.VoucherStateEnum;
import com.jiejing.fitness.finance.api.axf.enums.AxfOrderSignStateEnums;
import com.jiejing.fitness.finance.api.axf.enums.AxfStateEnums;
import com.jiejing.fitness.finance.api.axf.request.*;
import com.jiejing.fitness.finance.api.axf.vo.StudioAuthTokenVO;
import com.jiejing.fitness.finance.api.axf.vo.StudioAxfApplyVO;
import com.jiejing.fitness.finance.api.axf.vo.StudioAxfCommodityVO;
import com.jiejing.fitness.finance.api.axf.vo.StudioAxfOrderDeductionVO;
import com.jiejing.fitness.finance.api.axf.vo.StudioAxfOrderRecoveryVO;
import com.jiejing.fitness.finance.api.axf.vo.StudioAxfOrderVO;
import com.jiejing.fitness.finance.repository.entity.*;
import com.jiejing.fitness.finance.service.axf.constans.AxfConst;
import com.jiejing.fitness.finance.service.axf.impl.AxfServiceImpl;
import com.jiejing.fitness.finance.service.axf.model.AlipayCommerceMerchantcardDeductionOrderNotifyModel;
import com.jiejing.fitness.finance.service.axf.model.AlipayCommerceMerchantcardOrderNotifyModel;
import com.jiejing.fitness.finance.service.utils.MoneyUtil;
import com.jiejing.member.api.member.vo.MemberDetailVO;
import com.jiejing.paycenter.api.merchant.request.ApplyMerchantRequest;
import com.jiejing.paycenter.api.merchant.request.CreateCommodityRequest;
import com.jiejing.paycenter.api.merchant.request.CreateCommodityTemplateRequest;
import com.jiejing.paycenter.api.merchant.request.OpenStoreRequest;
import com.jiejing.paycenter.common.enums.common.OpenStateEnums;
import com.jiejing.paycenter.common.enums.merchant.CertTypeEnums;
import com.jiejing.paycenter.common.enums.merchant.CommodityOrderDeductionStateEnums;
import com.jiejing.paycenter.common.enums.merchant.CommodityTypeEnums;
import com.jiejing.paycenter.common.enums.merchant.CompanyTypeEnums;
import com.jiejing.paycenter.common.enums.merchant.CycleChargeTypeEnums;
import com.jiejing.paycenter.common.enums.merchant.CycleTypeEnums;
import com.jiejing.paycenter.common.enums.merchant.ExpireTypeEnums;
import com.jiejing.paycenter.common.enums.merchant.LicenseTypeEnums;
import com.jiejing.paycenter.common.enums.merchant.ResourceTypeEnums;
import com.jiejing.paycenter.common.enums.merchant.SubChannelEnums;
import com.jiejing.paycenter.common.enums.merchant.SubChannelOpenTypeEnums;
import com.jiejing.paycenter.common.event.CommodityOrderEvent;
import com.jiejing.paycenter.common.event.OrderDeductionEvent;
import com.jiejing.paycenter.common.event.StoreEvent;
import com.jiejing.paycenter.common.model.request.Address;
import com.jiejing.paycenter.common.model.request.BusinessInfo;
import com.jiejing.paycenter.common.model.request.Contact;
import com.jiejing.paycenter.common.model.request.CycleCommodityAttr;
import com.jiejing.paycenter.common.model.request.CycleCommodityAttr.PeriodPrice;
import com.jiejing.paycenter.common.model.request.Legal;
import com.jiejing.paycenter.common.model.request.License;
import com.jiejing.paycenter.common.model.request.ResourceInfo;
import com.jiejing.paycenter.common.model.request.SubChannelInfo;
import com.jiejing.paycenter.common.model.vo.AuthTokenVO;
import com.jiejing.paycenter.common.model.vo.CommodityVO;
import com.jiejing.paycenter.common.model.vo.CreateCommodityTemplateVO;
import com.jiejing.trade.api.voucher.vo.VoucherVO;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.lang3.time.DateUtils;
/**
* @author chengyubing
* @since 2024/9/7 11:58
*/
public class AxfConvert {
public static StudioAxfApply toEntity(StudioAxfApplyRequest request, Function<Long, String> studioFunc,
Function<Long, String> adminFunc) {
String salt = AesUtil.getSalt(8);
StudioAxfApply apply = BeanUtil.map(request, StudioAxfApply.class);
apply.setId(IdWorker.getId());
apply.setLicenseType(LicenseTypeEnums.NATIONAL_LEGAL_MERGE.getCode());
apply.setState(AxfStateEnums.INIT.getCode());
apply.setChannelNo(AxfConst.CHANNEL_NO);
apply.setApplyType(AxfConst.OPEN);
apply.setOpId(request.getBizAccountId());
apply.setOpName(adminFunc.apply(request.getBizAccountId()));
apply.setStudioName(studioFunc.apply(request.getStudioId()));
apply.setSalt(salt);
apply.setCreateTime(new Date());
apply.setUpdateTime(new Date());
return encrypt(apply);
}
public static StudioAxfApply encrypt(StudioAxfApply apply) {
StudioAxfApply encrypt = BeanUtil.map(apply, StudioAxfApply.class);
encrypt.setLegalCertNo(AesUtil.encrypt(apply.getSalt(), apply.getLegalCertNo()));
encrypt.setLicenseCode(AesUtil.encrypt(apply.getSalt(), apply.getLicenseCode()));
encrypt.setCardNo(AesUtil.encrypt(apply.getSalt(), apply.getCardNo()));
return encrypt;
}
public static void main(String[] args) {
System.out.println(AesUtil.encrypt("J7t5sz4Z", "397176538@qq.com"));
}
public static StudioAxfApply decrypt(StudioAxfApply apply) {
StudioAxfApply decrypt = BeanUtil.map(apply, StudioAxfApply.class);
decrypt.setLegalCertNo(AesUtil.decrypt(apply.getSalt(), apply.getLegalCertNo()));
decrypt.setLicenseCode(AesUtil.decrypt(apply.getSalt(), apply.getLicenseCode()));
decrypt.setCardNo(AesUtil.decrypt(apply.getSalt(), apply.getCardNo()));
return decrypt;
}
public static Map<ResourceTypeEnums, ResourceInfo> toResourceMap(StudioAxfApplyRequest request,
Function<List<Long>, Map<Long, String>> fileFunc) {
Map<ResourceTypeEnums, ResourceInfo> map = new HashMap<>(2);
Map<Long, String> fileMap = fileFunc.apply(Lists.newArrayList(
request.getLicenseResourceId(), request.getStoreHeadResourceId()
));
map.put(ResourceTypeEnums.LICENSE,
ResourceInfo.builder()
.resourceId(request.getLicenseResourceId())
.thirdId(fileMap.get(request.getLicenseResourceId()))
.type(ResourceTypeEnums.LICENSE)
.build());
map.put(ResourceTypeEnums.STORE_HEADER_PIC,
ResourceInfo.builder()
.resourceId(request.getStoreHeadResourceId())
.thirdId(fileMap.get(request.getStoreHeadResourceId()))
.type(ResourceTypeEnums.STORE_HEADER_PIC)
.build());
return map;
}
public static ApplyMerchantRequest toRequest(StudioAxfApply apply,
Map<ResourceTypeEnums, ResourceInfo> resourceMap) {
return ApplyMerchantRequest.builder()
.bizCode("AXF")
.merchantNo(apply.getMerchantNo())
.applyNo(apply.getId().toString())
.channelNo(AxfConst.CHANNEL_NO)
.companyType(CompanyTypeEnums.getByCode(apply.getCompanyType()))
.merchantName(apply.getMerchantName())
.shortName(apply.getShortName())
.legal(convertLegal(apply))
.license(convertLicense(apply))
.business(convertBusiness(apply))
.contact(convertContact(apply))
.resourceMap(resourceMap)
.subChannels(Lists.newArrayList(
SubChannelInfo.builder()
.subChannel(SubChannelEnums.ALI)
.openType(SubChannelOpenTypeEnums.AXF_MERCHANT_PERIOD_PAY)
.feeRate(AxfConst.RATE)
.build()
))
.build();
}
private static Contact convertContact(StudioAxfApply apply) {
return Contact.builder().contactPhone(apply.getPhone()).build();
}
private static Legal convertLegal(StudioAxfApply params) {
return Legal.builder()
.legalName(params.getLegalName())
.legalCertNo(params.getLegalCertNo())
.legalCertType(CertTypeEnums.ID_CARD)
.build();
}
private static License convertLicense(StudioAxfApply params) {
return License.builder()
.licenseCode(params.getLicenseCode())
.licenseType(LicenseTypeEnums.valueOf(params.getLicenseType()))
.licenseExpireType(ExpireTypeEnums.valueOf(params.getLicenseExpireType()))
.licenseStartDate(params.getLicenseStartTime())
.licenseEndDate(params.getLicenseEndTime())
.build();
}
private static BusinessInfo convertBusiness(StudioAxfApply params) {
return BusinessInfo.builder()
.businessAddress(Address.builder()
.province(params.getBusinessProvinceCode())
.city(params.getBusinessCityCode())
.district(params.getBusinessDistrictCode())
.address(params.getBusinessAddress())
.build())
.build();
}
public static OpenStoreRequest toStoreRequest(Long merchantId, SubChannelOpenTypeEnums openType) {
return OpenStoreRequest.builder().merchantId(merchantId).openType(openType).build();
}
public static CreateCommodityTemplateRequest toCommodityRequest(StudioAxfApply apply, StoreEvent event,
String commodityName, Boolean chargeNow, CycleTypeEnums cycleType, Integer cycleValue) {
int totalPeriod = 10;
BigDecimal eachOriginalPrice = new BigDecimal("600");
BigDecimal eachSalePrice = new BigDecimal("500");
BigDecimal totalOriginalPrice = eachOriginalPrice.multiply(new BigDecimal(totalPeriod));
BigDecimal totalSalePrice = eachSalePrice.multiply(new BigDecimal(totalPeriod));
List<PeriodPrice> periodPriceList = new ArrayList<>(totalPeriod);
for (int i = 0; i < totalPeriod; i++) {
periodPriceList.add(
PeriodPrice.builder().period(i + 1).originalPrice(eachOriginalPrice).salePrice(eachSalePrice)
.build());
}
return CreateCommodityTemplateRequest.builder()
.merchantId(event.getMerchantId())
.storeId(event.getId())
.commodityType(CommodityTypeEnums.AXF_MERCHANT_PERIOD_PAY)
.commodityName(commodityName)
.commodityNote(commodityName)
.originalPrice(totalOriginalPrice)
.salePrice(totalSalePrice)
.saleStartTime(apply.getCreateTime())
.saleEndTime(DateUtils.addDays(apply.getCreateTime(), 365))
.cycleCommodityAttr(CycleCommodityAttr.builder()
.totalPeriod(totalPeriod)
.cycleType(cycleType)
.cycleChargeType(CycleChargeTypeEnums.FIXED_DATE)
.cycleValue(cycleValue)
.chargeNow(chargeNow)
.periodPriceList(periodPriceList)
.build())
.build();
}
public static StudioAxfCommodityTemplate toTemplate(StudioAxfApply apply,
JsonResult<CreateCommodityTemplateVO> result, CreateCommodityTemplateRequest request) {
OpenStateEnums state = result.getSuccess() ? result.getResult().getState() : OpenStateEnums.FAIL;
String failMessage = result.getSuccess() ? result.getResult().getFailMessage() : "网络异常";
return StudioAxfCommodityTemplate.builder()
.id(IdWorker.getId())
.studioId(apply.getStudioId())
.merchantId(apply.getMerchantId())
.templateName(request.getCommodityName())
.state(state.getCode())
.templateId(state == OpenStateEnums.SUCCESS ? result.getResult().getTemplateId() : null)
.thirdTemplateId(state == OpenStateEnums.SUCCESS ? result.getResult().getThirdTemplateId() : null)
.totalPeriod(request.getCycleCommodityAttr().getTotalPeriod())
.chargeNow(request.getCycleCommodityAttr().getChargeNow())
.cycleType(request.getCycleCommodityAttr().getCycleType().getCode())
.cycleValue(request.getCycleCommodityAttr().getCycleValue())
.saleStartTime(request.getSaleStartTime())
.saleEndTime(request.getSaleEndTime())
.cycleChargeType(request.getCycleCommodityAttr().getCycleChargeType().getCode())
.attr(JSON.toJSONString(request))
.failMessage(failMessage)
.createTime(new Date())
.updateTime(new Date())
.build();
}
public static StudioAxfCommodityTemplateApply toTemplateApply(StudioAxfApply apply,
JsonResult<CreateCommodityTemplateVO> result, CreateCommodityTemplateRequest request) {
OpenStateEnums state = result.getSuccess() ? result.getResult().getState() : OpenStateEnums.FAIL;
String failMessage = result.getSuccess() ? result.getResult().getFailMessage() : "网络异常";
return StudioAxfCommodityTemplateApply.builder()
.id(IdWorker.getId())
.studioId(apply.getStudioId())
.merchantId(apply.getMerchantId())
.templateName(request.getCommodityName())
.state(state.getCode())
.templateId(state == OpenStateEnums.SUCCESS ? result.getResult().getTemplateId() : null)
.thirdTemplateId(state == OpenStateEnums.SUCCESS ? result.getResult().getThirdTemplateId() : null)
.totalPeriod(request.getCycleCommodityAttr().getTotalPeriod())
.chargeNow(request.getCycleCommodityAttr().getChargeNow())
.cycleType(request.getCycleCommodityAttr().getCycleType().getCode())
.cycleValue(request.getCycleCommodityAttr().getCycleValue())
.saleStartTime(request.getSaleStartTime())
.saleEndTime(request.getSaleEndTime())
.cycleChargeType(request.getCycleCommodityAttr().getCycleChargeType().getCode())
.attr(JSON.toJSONString(request))
.failMessage(failMessage)
.createTime(new Date())
.updateTime(new Date())
.build();
}
public static List<StudioAxfApplyVO> toList(List<StudioAxfApply> records) {
if (null == records) {
return Lists.newArrayList();
}
return records.stream().map(e -> toVO(e, vo -> {
})).collect(Collectors.toList());
}
public static StudioAxfApplyVO toVO(StudioAxfApply apply, Consumer<StudioAxfApplyVO> consumer) {
if (null == apply) {
return null;
}
StudioAxfApply decrypt = AxfConvert.decrypt(apply);
StudioAxfApplyVO vo = BeanUtil.map(decrypt, StudioAxfApplyVO.class);
vo.setFailMessage(AxfServiceImpl.replaceFailMessage(vo.getFailMessage()));
consumer.accept(vo);
return vo;
}
public static CreateCommodityRequest toRequest(CreateStudioAxfCommodityRequest request,
StudioAxfCommodityTemplate template) {
CreateCommodityTemplateRequest attr = JSON.parseObject(template.getAttr(),
CreateCommodityTemplateRequest.class);
return CreateCommodityRequest.builder()
.merchantId(template.getMerchantId())
.bizId(request.getVoucherId())
.templateId(template.getTemplateId())
.commodityName(template.getTemplateName())
.originalPrice(request.getOriginalPrice())
.salePrice(request.getSalePrice())
.saleStartTime(attr.getSaleStartTime())
.saleEndTime(attr.getSaleEndTime())
.cycleCommodityAttr(request.getCycleCommodityAttr())
.build();
}
public static StudioAxfOrder toEntity(CommodityOrderEvent event, CommodityVO commodity,
VoucherVO voucher, MemberDetailVO student) {
AlipayCommerceMerchantcardOrderNotifyModel model = JSON.parseObject(event.getAttr(),
AlipayCommerceMerchantcardOrderNotifyModel.class);
return StudioAxfOrder.builder()
.id(IdWorker.getId())
.channelNo(event.getChannelNo())
.studioId(voucher.getSupplierId())
.merchantId(event.getMerchantId())
.commodityId(commodity.getId())
.studentId(student.getId())
.studentName(student.getName())
.originalPrice(MoneyUtil.divide(new BigDecimal(model.getOriginPriceTotal()), new BigDecimal("100")))
.salePrice(MoneyUtil.divide(new BigDecimal(model.getSalePriceTotal()), new BigDecimal("100")))
.totalPeriod(Integer.parseInt(model.getTotalCount()))
.signState(AxfOrderSignStateEnums.SIGN.getCode())
.receivedAmount(BigDecimal.ZERO)
.receivedFee(BigDecimal.ZERO)
.receivedActualAmount(BigDecimal.ZERO)
.receivedPeriod(0)
.rate(AxfConst.RATE)
.voucherId(commodity.getBizId())
.voucherBusinessNo(
VoucherStateEnum.CANCEL.name().equals(voucher.getState()) ? null : voucher.getBusinessNo())
.thirdOrderNo(event.getThirdOrderNo())
.attr(JSON.toJSONString(commodity))
.signTime(event.getCreateTime())
.createTime(new Date())
.updateTime(new Date())
.build();
}
public static StudioAxfOrderVO toVO(StudioAxfOrder order) {
StudioAxfOrderVO vo = BeanUtil.map(order, StudioAxfOrderVO.class);
if (null != order.getAttr()) {
StudioAxfCommodityVO commodity = JSON.parseObject(order.getAttr(), StudioAxfCommodityVO.class);
vo.setCommodity(commodity);
}
return vo;
}
public static StudioAxfOrderDeduction toDeduction(OrderDeductionEvent event, StudioAxfOrderVO order,
AlipayCommerceMerchantcardDeductionOrderNotifyModel model, Integer recoveryTimes) {
CycleCommodityAttr commodityAttr = order.getCommodity().getCycleCommodityAttr();
Integer period = Integer.parseInt(model.getPeriod());
PeriodPrice periodPrice = commodityAttr.getPeriodPriceList().stream()
.filter(e -> e.getPeriod().equals(period))
.findFirst().orElse(new PeriodPrice());
BigDecimal fee = MoneyUtil.divide(MoneyUtil.multiply(periodPrice.getSalePrice(), AxfConst.RATE),
new BigDecimal("100"));
return StudioAxfOrderDeduction.builder()
.id(event.getId())
.orderId(order.getId())
.period(period)
.amount(periodPrice.getSalePrice())
.fee(fee)
.actualAmount(MoneyUtil.subtract(periodPrice.getSalePrice(), fee))
.rate(AxfConst.RATE)
.state(event.getState().getCode())
.failMessage(event.getFailMessage())
.transNo(event.getId().toString())
.thirdOrderNo(event.getThirdOrderNo())
.thirdTransNo(model.getTradeNo())
.recoveryTimes(recoveryTimes)
.deductionTime(CommodityOrderDeductionStateEnums.SUCCESS == event.getState() ? new Date() : null)
.createTime(new Date())
.updateTime(new Date())
.build();
}
public static StudioAxfOrderRecovery toRecovery(OrderDeductionEvent event, StudioAxfOrderVO order,
StudioAxfOrderDeduction deduction, AlipayCommerceMerchantcardDeductionOrderNotifyModel model) {
return StudioAxfOrderRecovery.builder()
.id(IdWorker.getId())
.deductionId(deduction.getId())
.orderId(order.getId())
.period(Integer.parseInt(model.getPeriod()))
.amount(deduction.getAmount())
.actualAmount(deduction.getActualAmount())
.fee(deduction.getFee())
.rate(deduction.getRate())
.state(event.getState().getCode())
.failMessage(event.getFailMessage())
.transNo(event.getId().toString())
.thirdOrderNo(event.getThirdOrderNo())
.thirdTransNo(model.getTradeNo())
.deductionTime(event.getState() == CommodityOrderDeductionStateEnums.SUCCESS ? new Date() : null)
.createTime(new Date())
.updateTime(new Date())
.build();
}
public static List<StudioAxfOrderDeductionVO> toDeductionVO(List<StudioAxfOrderDeduction> deductions) {
return deductions.stream().map(AxfConvert::toDeductionVO).collect(Collectors.toList());
}
public static StudioAxfOrderDeductionVO toDeductionVO(StudioAxfOrderDeduction deduction) {
StudioAxfOrderDeductionVO vo = BeanUtil.map(deduction, StudioAxfOrderDeductionVO.class);
vo.setActualAmount(
CommodityOrderDeductionStateEnums.SUCCESS == vo.getState() ? vo.getActualAmount() : null);
return vo;
}
public static List<StudioAxfOrderRecoveryVO> toRecoveryVO(List<StudioAxfOrderRecovery> recoveries) {
return recoveries.stream().map(AxfConvert::toDeductionVO).collect(Collectors.toList());
}
public static StudioAxfOrderRecoveryVO toDeductionVO(StudioAxfOrderRecovery recovery) {
return BeanUtil.map(recovery, StudioAxfOrderRecoveryVO.class);
}
public static StudioAuthTokenVO toAuth(Long id, AuthTokenVO result, ConfirmEnum used) {
StudioAuthTokenVO vo = BeanUtil.map(result, StudioAuthTokenVO.class);
vo.setUsed(used);
vo.setId(id);
return vo;
}
public static StudioAuthTokenVO toAuth(StudioAxfAuth exist) {
StudioAuthTokenVO vo = BeanUtil.map(exist, StudioAuthTokenVO.class);
vo.setUsed(ConfirmEnum.valueOf(exist.getUsed()));
return vo;
}
}
package com.jiejing.fitness.finance.service.axf.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jiejing.common.enums.ConfirmEnum;
import com.jiejing.common.exception.BizException;
import com.jiejing.common.model.JsonResult;
import com.jiejing.common.model.PageVO;
import com.jiejing.common.request.IdRequest;
import com.jiejing.common.utils.convert.BeanUtil;
import com.jiejing.common.utils.crypt.AesUtil;
import com.jiejing.filecenter.api.resource.vo.ResourceInfoVO;
import com.jiejing.fitness.enums.delay.DelayTaskCodeEnum;
import com.jiejing.fitness.enums.finance.PartyTypeEnum;
import com.jiejing.fitness.finance.api.axf.enums.*;
import com.jiejing.fitness.finance.api.axf.request.*;
import com.jiejing.fitness.finance.api.axf.vo.*;
import com.jiejing.fitness.finance.repository.entity.*;
import com.jiejing.fitness.finance.repository.service.PartyToMerchantRpService;
import com.jiejing.fitness.finance.repository.service.StudioAxfApplyRpService;
import com.jiejing.fitness.finance.repository.service.StudioAxfAuthApplyRpService;
import com.jiejing.fitness.finance.repository.service.StudioAxfAuthRpService;
import com.jiejing.fitness.finance.repository.service.StudioAxfCommodityTemplateApplyRpService;
import com.jiejing.fitness.finance.repository.service.StudioAxfCommodityTemplateRpService;
import com.jiejing.fitness.finance.repository.service.StudioAxfOrderDeductionRpService;
import com.jiejing.fitness.finance.repository.service.StudioAxfOrderRecoveryRpService;
import com.jiejing.fitness.finance.repository.service.StudioAxfOrderRpService;
import com.jiejing.fitness.finance.service.axf.AxfService;
import com.jiejing.fitness.finance.service.axf.constans.AxfConst;
import com.jiejing.fitness.finance.service.axf.convert.AxfConvert;
import com.jiejing.fitness.finance.service.axf.model.AlipayCommerceMerchantcardDeductionOrderNotifyModel;
import com.jiejing.fitness.finance.service.enums.FinanceErrorEnums;
import com.jiejing.fitness.finance.service.rpc.ResourceRpcService;
import com.jiejing.fitness.finance.service.rpc.StudioRpcService;
import com.jiejing.fitness.finance.service.utils.DingUtil;
import com.jiejing.fitness.finance.service.utils.MoneyUtil;
import com.jiejing.fitness.request.MemberIdRequest;
import com.jiejing.member.api.member.MemberApi;
import com.jiejing.member.api.member.request.ListByIdOffsetRequest;
import com.jiejing.member.api.member.request.ListStudioMemberInfoRequest;
import com.jiejing.member.api.member.vo.MemberDetailVO;
import com.jiejing.message.enums.MsgChannelEnum;
import com.jiejing.message.event.SendCommonMsgEvent;
import com.jiejing.paycenter.api.merchant.MerchantApi;
import com.jiejing.paycenter.api.merchant.MerchantQueryApi;
import com.jiejing.paycenter.api.merchant.StoreApi;
import com.jiejing.paycenter.api.merchant.StoreQueryApi;
import com.jiejing.paycenter.api.merchant.request.*;
import com.jiejing.paycenter.common.enums.common.OpenStateEnums;
import com.jiejing.paycenter.common.enums.merchant.*;
import com.jiejing.paycenter.common.event.CommodityOrderEvent;
import com.jiejing.paycenter.common.event.MerchantEvent;
import com.jiejing.paycenter.common.event.OrderDeductionEvent;
import com.jiejing.paycenter.common.event.StoreEvent;
import com.jiejing.paycenter.common.model.request.*;
import com.jiejing.paycenter.common.model.request.CycleCommodityAttr.PeriodPrice;
import com.jiejing.paycenter.common.model.vo.*;
import com.jiejing.paycenter.common.model.vo.AuthTokenVO;
import com.jiejing.paycenter.common.model.vo.BankCardVO;
import com.jiejing.paycenter.common.model.vo.BindCardVO;
import com.jiejing.paycenter.common.model.vo.OpenStoreVO;
import com.jiejing.studio.api.admin.vo.AdminVO;
import com.jiejing.studio.api.admin.vo.BaseAdminVO;
import com.jiejing.studio.api.studio.vo.StudioVO;
import com.jiejing.trade.api.voucher.VoucherApi;
import com.jiejing.trade.api.voucher.vo.VoucherVO;
import com.jiejing.workflow.api.DelayQueueApi;
import com.jiejing.workflow.api.request.RemoveDelayTaskRequest;
import com.jiejing.workflow.api.request.SaveDelayTaskRequest;
import com.jiejing.workflow.common.enums.DelayTopicEnum;
import com.xiaomai.event.EventAgent;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* @author chengyubing
* @since 2024/11/4 16:31
*/
@Slf4j
@Service
public class AxfServiceImpl implements AxfService {
@Resource
private MerchantApi merchantApi;
@Resource
private StudioAxfApplyRpService studioAxfApplyRpService;
@Resource
private StudioAxfCommodityTemplateRpService studioAxfCommodityTemplateRpService;
@Resource
private StudioAxfCommodityTemplateApplyRpService studioAxfCommodityTemplateApplyRpService;
@Resource(name = "financeThreadPool")
private Executor executor;
@Resource
private StoreApi storeApi;
@Resource
private StoreQueryApi storeQueryApi;
@Resource
private MerchantQueryApi merchantQueryApi;
@Resource
private StudioAxfAuthRpService studioAxfAuthRpService;
@Resource
private StudioAxfAuthApplyRpService studioAxfAuthApplyRpService;
@Resource
private PartyToMerchantRpService partyToMerchantRpService;
@Resource
private StudioAxfOrderRpService studioAxfOrderRpService;
@Resource
private StudioAxfOrderDeductionRpService studioAxfOrderDeductionRpService;
@Resource
private StudioAxfOrderRecoveryRpService studioAxfOrderRecoveryRpService;
@Resource
private DelayQueueApi delayQueueApi;
@Resource
private StudioRpcService studioRpcService;
@Resource
private MemberApi memberApi;
@Value("${spring.profiles.active}")
private String env;
@Value("${message.axf.app}")
private String pushUrl;
@Override
public StudioAxfApplyVO getMerchant(Long studioId) {
PartyToMerchant merchant = partyToMerchantRpService.getByStudioId(studioId, AxfConst.CHANNEL_NO);
if (null == merchant) {
return null;
}
StudioAxfApply apply = studioAxfApplyRpService.getLatestOneByMerchantId(merchant.getMerchantId(),
AxfStateEnums.SETTLE_SUCCESS);
return this.toVO(apply);
}
@DS("finance")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@Override
public StudioAuthTokenVO authToken(Long studioId, GrantTypeEnums grantType, String code,
String refreshToken) {
AuthTokenRequest req = AuthTokenRequest.builder().grantType(grantType).code(code)
.refreshToken(refreshToken).channelNo(AxfConst.CHANNEL_NO).build();
JsonResult<AuthTokenVO> result = merchantApi.authToken(req);
result.assertSuccess();
// 存在,则表示曾经授权过,本次为重新授权
StudioAxfAuthApply existApply = studioAxfAuthApplyRpService.getLatestByUserId(studioId,
result.getResult().getUserId());
StudioAxfAuthApply toSave = BeanUtil.map(result.getResult(), StudioAxfAuthApply.class);
toSave.setId(IdWorker.getId());
toSave.setStudioId(studioId);
toSave.setCreateTime(new Date());
toSave.setUpdateTime(new Date());
toSave.setUsed(null == existApply ? ConfirmEnum.NO.name() : existApply.getUsed());
studioAxfAuthApplyRpService.insert(toSave);
StudioAxfAuth exist = studioAxfAuthRpService.getById(studioId).orElse(null);
if (null != exist) {
StudioAxfAuth auth = BeanUtil.map(result.getResult(), StudioAxfAuth.class);
auth.setId(exist.getId());
auth.setUpdateTime(new Date());
auth.setUsed(toSave.getUsed());
studioAxfAuthRpService.updateById(auth);
return AxfConvert.toAuth(exist.getId(), result.getResult(), ConfirmEnum.valueOf(toSave.getUsed()));
}
StudioAxfAuth auth = BeanUtil.map(result.getResult(), StudioAxfAuth.class);
auth.setId(studioId);
auth.setStudioId(studioId);
auth.setUsed(toSave.getUsed());
auth.setCreateTime(new Date());
auth.setUpdateTime(new Date());
studioAxfAuthRpService.insert(auth);
return AxfConvert.toAuth(auth.getId(), result.getResult(), ConfirmEnum.valueOf(toSave.getUsed()));
}
@Override
public StudioAuthTokenVO getAuthToken(Long studioId) {
StudioAxfAuth exist = studioAxfAuthRpService.getById(studioId).orElse(null);
if (null != exist) {
return AxfConvert.toAuth(exist);
}
return null;
}
@Override
public List<String> listSettleAccount(Long studioId) {
StudioAuthTokenVO auth = this.getAuthToken(studioId);
ListBankCardRequest request = new ListBankCardRequest();
request.setMerchantNo(auth.getUserId());
request.setChannelNo(AxfConst.CHANNEL_NO);
JsonResult<List<BankCardVO>> result = merchantApi.listBankCard(request);
result.assertSuccess();
return result.getResult().stream().map(BankCardVO::getCardNo).collect(Collectors.toList());
}
@Override
public Long apply(StudioAxfApplyRequest params) {
this.checkBeforeApply(params);
StudioAxfApply apply = AxfConvert.toEntity(params, studioId -> {
StudioVO studio = studioRpcService.getStudio(params.getStudioId());
return null == studio ? "" : studio.getName();
}, adminId -> {
AdminVO admin = studioRpcService.getAdmin(params.getBizAccountId());
return null == admin ? "" : admin.getName();
});
studioAxfApplyRpService.insert(apply);
executor.execute(() -> {
try {
Map<ResourceTypeEnums, ResourceInfo> resourceMap = this.upload(params, apply);
ApplyMerchantRequest request = AxfConvert.toRequest(AxfConvert.decrypt(apply), resourceMap);
JsonResult<ApplyMerchantResultVO> result = merchantApi.apply(request);
result.assertSuccess();
} catch (Exception e) {
log.error("apply axf merchant fail {}, studio id = {}", apply.getId(), params.getStudioId(), e);
String failMessage =
e instanceof BizException ? ((BizException) e).getDefaultErrorMessage() : e.getMessage();
this.doOpenAxfFail(apply.getId(), failMessage);
return;
}
this.doOpenAxfProcess(apply.getId());
});
return apply.getId();
}
@Override
public BindCardVO bindCard(Long id, String cardNo) {
StudioAxfApply apply = studioAxfApplyRpService.getById(id)
.orElseThrow(() -> new BizException(FinanceErrorEnums.NOT_EXIST));
StudioAxfApply toModify = StudioAxfApply.builder().id(apply.getId())
.cardNo(AesUtil.encrypt(apply.getSalt(), cardNo)).build();
studioAxfApplyRpService.updateById(toModify);
// 绑定结算账户
BindCardVO vo = this.bindSettleAccount(id, apply.getMerchantId());
StudioAxfApply newApply = studioAxfApplyRpService.getById(id)
.orElseThrow(() -> new BizException(FinanceErrorEnums.NOT_EXIST));
if (AxfStateEnums.SETTLE_SUCCESS.getCode().equals(newApply.getState())) {
// 结算账户绑定完成,安心付可用
this.openAxfAllSuccess(apply);
} else if (AxfStateEnums.SETTLE_FAIL.getCode().equals(newApply.getState())) {
executor.execute(() -> this.sendAxfFailMessage(id, replaceFailMessage(vo.getFailMessage())));
}
return vo;
}
private void openAxfAllSuccess(StudioAxfApply apply) {
PartyToMerchant exist = partyToMerchantRpService.getByStudioId(apply.getStudioId(), AxfConst.CHANNEL_NO);
if (null != exist) {
exist.setMerchantId(apply.getMerchantId());
exist.setMerchantNo(apply.getMerchantNo());
partyToMerchantRpService.updateById(exist);
} else {
partyToMerchantRpService.insert(
PartyToMerchant.builder().id(IdWorker.getId()).partyId(apply.getStudioId())
.partyType(PartyTypeEnum.STUDIO.getCode()).merchantId(apply.getMerchantId())
.merchantNo(apply.getMerchantNo()).channelNo(AxfConst.CHANNEL_NO).createTime(new Date())
.updateTime(new Date()).build());
}
this.setAuthUsed(apply.getStudioId(), apply.getMerchantNo());
// 开通标品
executor.execute(() -> {
JsonResult<StoreVO> result = storeQueryApi.getStoreByMerchantId(
GetByMerchantIdRequest.builder().merchantId(apply.getMerchantId()).build());
result.assertSuccess();
StoreEvent event = StoreEvent.builder().merchantId(apply.getMerchantId()).id(result.getResult().getId())
.build();
this.createCommodityTemplate(apply, event, "立即扣款周期付周1", true, CycleTypeEnums.WEEK, 1);
this.createCommodityTemplate(apply, event, "立即扣款周期付周3", true, CycleTypeEnums.WEEK, 3);
this.createCommodityTemplate(apply, event, "立即扣款周期付月1", true, CycleTypeEnums.MONTH, 1);
this.createCommodityTemplate(apply, event, "立即扣款周期付月15", true, CycleTypeEnums.MONTH, 15);
this.createCommodityTemplate(apply, event, "立即扣款周期付月28", true, CycleTypeEnums.MONTH, 28);
this.createCommodityTemplate(apply, event, "周期付周1", false, CycleTypeEnums.WEEK, 1);
this.createCommodityTemplate(apply, event, "周期付周3", false, CycleTypeEnums.WEEK, 3);
this.createCommodityTemplate(apply, event, "周期付月1", false, CycleTypeEnums.MONTH, 1);
this.createCommodityTemplate(apply, event, "周期付月15", false, CycleTypeEnums.MONTH, 15);
this.createCommodityTemplate(apply, event, "周期付月28", false, CycleTypeEnums.MONTH, 28);
this.sendAxfSuccessMessage(apply);
});
}
@Override
public CancelCommodityOrderVO cancelOrder(Long id, Long opId) {
StudioAxfOrder order = studioAxfOrderRpService.getById(id)
.orElseThrow(() -> new BizException(FinanceErrorEnums.NOT_EXIST));
StudioAxfOrderVO orderVO = AxfConvert.toVO(order);
if (AxfOrderSignStateEnums.CANCEL.getCode().equals(order.getSignState())
|| AxfOrderSignStateEnums.CANCEL_PROCESS.getCode().equals(order.getSignState())) {
throw new BizException("", "请勿重复解约");
}
if (AxfOrderSignStateEnums.SIGN.getCode().equals(order.getSignState())) {
if (orderVO.getCommodity().getCycleCommodityAttr().getTotalPeriod().equals(order.getReceivedPeriod())) {
// 全部扣款完成
throw new BizException("", "已全部扣款完成,无需解约");
}
}
List<StudioAxfOrderDeductionVO> deductions = this.listDeduction(id);
if (deductions.stream().anyMatch(e -> CommodityOrderDeductionStateEnums.FAIL == e.getState())) {
throw new BizException("", "订购单存在扣款失败,请确保扣款成功后再发起解约");
}
AdminVO admin = studioRpcService.getAdmin(opId);
CancelCommodityOrderVO vo;
try {
JsonResult<CancelCommodityOrderVO> result = storeApi.cancelCommodityOrder(
CancelCommodityOrderRequest.builder().merchantId(order.getMerchantId())
.thirdOrderNo(order.getThirdOrderNo()).build());
result.assertSuccess();
vo = result.getResult();
} catch (Exception e) {
log.error("cancel order fail {}", id, e);
vo = CancelCommodityOrderVO.builder().state(OpenStateEnums.FAIL)
.failMessage(e instanceof BizException ? ((BizException) e).getDefaultErrorMessage() : "网络异常")
.build();
}
if (OpenStateEnums.FAIL == vo.getState()) {
this.cancelFailNoCheck(id, opId, new Date());
return vo;
}
StudioAxfOrder toModify = StudioAxfOrder.builder().id(id).cancelOpId(opId)
.signState(AxfOrderSignStateEnums.CANCEL_PROCESS.getCode()).cancelOpName(admin.getName())
.cancelFailMessage("").updateTime(new Date()).build();
studioAxfOrderRpService.updateById(toModify);
delayQueueApi.save(
SaveDelayTaskRequest.builder().bizCode(DelayTaskCodeEnum.CANCEL_AXF_ORDER_FAIL.getCode()).bizId(id)
.executionTime(DateUtils.addDays(toModify.getUpdateTime(), 1)).taskBody(
new JSONObject().fluentPut("opId", opId).fluentPut("cancelTime", toModify.getUpdateTime()))
.tenantId(order.getStudioId()).topic(DelayTopicEnum.COMMON_DELAY_TASK).build());
return vo;
}
@Override
public void callback(MerchantEvent event) {
if (CollectionUtils.isEmpty(event.getSubChannels())) {
return;
}
SubChannelVO subChannel = event.getSubChannels().stream()
.filter(e -> SubChannelOpenTypeEnums.AXF_MERCHANT_PERIOD_PAY.getCode().equals(e.getOpenType()))
.findFirst().orElse(null);
if (null == subChannel) {
return;
}
Long id = Long.parseLong(event.getApplyNo());
switch (OpenStateEnums.getByCode(subChannel.getState())) {
case FAIL:
this.doOpenAxfFail(id, subChannel.getFailMessage());
break;
case SUCCESS:
this.doOpenAxfSuccess(id, event.getMerchantId());
break;
default:
break;
}
}
@Override
public void storeCallback(StoreEvent event) {
OpenStateEnums state = OpenStateEnums.getByCode(event.getState());
if (OpenStateEnums.SUCCESS != state && OpenStateEnums.FAIL != state) {
return;
}
StudioAxfApply apply = studioAxfApplyRpService.getLatestOneByMerchantId(event.getMerchantId(),
AxfStateEnums.STORE_PROCESS);
if (null == apply) {
return;
}
if (OpenStateEnums.SUCCESS == state) {
this.doOpenAxfStoreSuccess(apply, event);
} else {
this.doOpenAxfStoreFail(apply.getId(), event.getFailMessage());
}
}
@Override
public void orderCallback(CommodityOrderEvent event) {
switch (event.getState()) {
case AVAILABLE:
// 签约,生成订购单
this.createOrderCallback(event);
break;
case CLOSED:
// 解约,更新订购单状态
this.cancelOrderCallback(event);
break;
default:
break;
}
}
@DS("finance")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@Override
public void orderDeductionCallback(OrderDeductionEvent event) {
if (CommodityOrderDeductionStateEnums.INIT == event.getState()
|| CommodityOrderDeductionStateEnums.REFUND == event.getState()) {
return;
}
AlipayCommerceMerchantcardDeductionOrderNotifyModel model = JSON.parseObject(event.getAttr(),
AlipayCommerceMerchantcardDeductionOrderNotifyModel.class);
StudioAxfOrderVO order = this.getByThirdOrderNo(event.getMerchantId(), event.getThirdOrderNo());
List<StudioAxfOrderDeduction> deductions = studioAxfOrderDeductionRpService.listByOrderId(order.getId());
StudioAxfOrderDeduction exist = deductions.stream()
.filter(e -> e.getPeriod().equals(Integer.parseInt(model.getPeriod()))).findFirst().orElse(null);
if (null == exist) {
// 生成扣款记录
StudioAxfOrderDeduction deduction = AxfConvert.toDeduction(event, order, model, 0);
studioAxfOrderDeductionRpService.insert(deduction);
} else if (!CommodityOrderDeductionStateEnums.SUCCESS.getCode().equals(exist.getState())) {
// 生成补缴记录
StudioAxfOrderRecovery recovery = AxfConvert.toRecovery(event, order, exist, model);
studioAxfOrderRecoveryRpService.insert(recovery);
if (CommodityOrderDeductionStateEnums.SUCCESS == event.getState()) {
studioAxfOrderDeductionRpService.deleteById(exist.getId());
StudioAxfOrderDeduction deduction = AxfConvert.toDeduction(event, order, model,
exist.getRecoveryTimes() + 1);
studioAxfOrderDeductionRpService.insert(deduction);
List<StudioAxfOrderRecovery> recoveries = studioAxfOrderRecoveryRpService.listByDeductionId(
exist.getId());
studioAxfOrderRecoveryRpService.updateBatchById(recoveries.stream()
.map(e -> StudioAxfOrderRecovery.builder().id(e.getId()).deductionId(deduction.getId()).build())
.collect(Collectors.toSet()));
} else {
studioAxfOrderDeductionRpService.incRecoveryTimes(exist.getId());
}
}
if (CommodityOrderDeductionStateEnums.SUCCESS == event.getState()) {
this.syncOrder(order);
}
}
@Override
public StudioAxfApplyVO getById(Long id) {
StudioAxfApply apply = studioAxfApplyRpService.getById(id).orElse(null);
if (apply == null) {
return null;
}
return toVO(apply);
}
@Override
public PageVO<StudioAxfApplyVO> page(PageStudioAxfApplyRequest request) {
org.springframework.data.domain.Page<StudioAxfApply> page = studioAxfApplyRpService.page(
request.getStudioId(), request.getStudioName(),
request.getShortName(), request.getCreateTimeStart(), request.getCreateTimeEnd(),
request.getStateList(), request.getCurrent(), request.getSize());
return PageVO.convert(page, AxfConvert.toList(page.getContent()));
}
@Override
public StudioAxfApplyVO getLatestApply(Long studioId, String merchantNo) {
StudioAxfApply apply = studioAxfApplyRpService.getLatestOneByMerchantNo(studioId, merchantNo);
if (null == apply) {
return null;
}
return toVO(apply);
}
@Override
public AggStudioAxfApplyVO agg() {
Future<Integer> total = ((ThreadPoolTaskExecutor) executor).submit(
() -> studioAxfApplyRpService.countDistinctStudioId());
Future<Integer> success = ((ThreadPoolTaskExecutor) executor).submit(
() -> ((Long) partyToMerchantRpService.countAll()).intValue());
try {
return AggStudioAxfApplyVO.builder().total(total.get(5, TimeUnit.SECONDS))
.success(success.get(5, TimeUnit.SECONDS)).build();
} catch (Exception e) {
log.error("agg studio axf apply fail", e);
throw new BizException(FinanceErrorEnums.AGG_TIME_OUT);
}
}
@Override
public PageVO<StudioAxfOrderVO> pageOrder(PageStudioAxfOrderRequest request) {
Set<Long> studioIds = new HashSet<>(1);
if (null != request.getStudioId()) {
if (CollectionUtils.isNotEmpty(studioIds)) {
if (!studioIds.contains(request.getStudioId())) {
return PageVO.empty(request.getCurrent(), request.getCurrent());
}
}
studioIds.add(request.getStudioId());
}
Page<StudioAxfOrder> page = studioAxfOrderRpService.page(Lists.newArrayList(studioIds),
request.getStudentId(), request.getStudentName(), request.getVoucherBusinessNo(),
request.getThirdOrderNo(), request.getSignTimeStart(), request.getSignTimeEnd(),
request.getCancelTimeStart(), request.getCancelTimeEnd(), request.getState(), request.getCurrent(),
request.getSize());
if (CollectionUtils.isEmpty(page.getContent())) {
return PageVO.empty(request.getCurrent(), request.getCurrent());
}
// 补充学员姓名+校区名称
List<StudioAxfOrderVO> vos = toVOList(page.getContent());
this.appendStudioName(vos);
return PageVO.convert(page, vos);
}
@Override
public AggStudioAxfOrderVO aggOrder(PageStudioAxfOrderRequest request) {
AggStudioAxfOrderVO vo = studioAxfOrderRpService.agg(
Optional.ofNullable(request.getStudioId()).map(Lists::newArrayList).orElse(null),
request.getStudentId(), request.getStudentName(), request.getVoucherBusinessNo(),
request.getThirdOrderNo(), request.getSignTimeStart(), request.getSignTimeEnd(),
request.getCancelTimeStart(), request.getCancelTimeEnd(), request.getState());
vo.setRate(AxfConst.RATE);
return vo;
}
private void appendStudioName(List<StudioAxfOrderVO> vos) {
Set<Long> studioIds = vos.stream().map(StudioAxfOrderVO::getStudioId).collect(Collectors.toSet());
Map<Long, StudioVO> studioMap = studioRpcService.mapStudio(Lists.newArrayList(studioIds));
vos.forEach(
e -> e.setStudioName(studioMap.getOrDefault(e.getStudioId(), new StudioVO()).getName()));
}
private List<StudioAxfOrderVO> toVOList(List<StudioAxfOrder> orders) {
return orders.stream().map(e -> BeanUtil.map(e, StudioAxfOrderVO.class)).collect(Collectors.toList());
}
@Override
public StudioAxfOrderVO getOrder(Long id) {
StudioAxfOrder order = studioAxfOrderRpService.getById(id).orElse(null);
if (null == order) {
return null;
}
return AxfConvert.toVO(order);
}
private void doOpenAxfStoreProcess(Long id) {
studioAxfApplyRpService.updateById(
StudioAxfApply.builder().id(id).state(AxfStateEnums.STORE_PROCESS.getCode()).updateTime(new Date())
.build());
}
private void doOpenAxfStoreFail(Long id, String failMessage) {
studioAxfApplyRpService.updateById(
StudioAxfApply.builder().id(id).state(AxfStateEnums.STORE_FAIL.getCode())
.failMessage(replaceFailMessage(failMessage)).updateTime(new Date()).build());
executor.execute(() -> this.sendAxfFailMessage(id, replaceFailMessage(failMessage)));
}
private void doOpenAxfSuccess(Long id, Long merchantId) {
studioAxfApplyRpService.updateById(
StudioAxfApply.builder().id(id).state(AxfStateEnums.AXF_SUCCESS.getCode()).merchantId(merchantId)
.updateTime(new Date()).build());
// 开通门店
this.openStore(id, merchantId, SubChannelOpenTypeEnums.AXF_MERCHANT_PERIOD_PAY);
}
private BindCardVO bindSettleAccount(Long id, Long merchantId) {
StudioAxfApply apply = studioAxfApplyRpService.getById(id)
.orElseThrow(() -> new BizException(FinanceErrorEnums.NOT_EXIST));
String cardNo = AxfConvert.decrypt(apply).getCardNo();
MerchantBindCardRequest request = new MerchantBindCardRequest();
request.setApplyNo(IdWorker.getIdStr());
request.setMerchantId(merchantId);
request.setChannelNo(AxfConst.CHANNEL_NO);
request.setBankCard(BankCard.builder().cardNo(cardNo).cardType(CardTypeEnums.ALI_SETTLE_ACCOUNT).build());
BindCardVO vo;
try {
JsonResult<BindCardVO> result = merchantApi.bindCard(request);
result.assertSuccess();
vo = result.getResult();
} catch (Exception e) {
log.error("bind settle account fail {}", merchantId, e);
vo = BindCardVO.builder().state(OpenStateEnums.FAIL)
.failMessage(e instanceof BizException ? ((BizException) e).getDefaultErrorMessage() : "系统异常")
.build();
}
apply.setState(vo.getState() == OpenStateEnums.SUCCESS ? AxfStateEnums.SETTLE_SUCCESS.getCode()
: AxfStateEnums.SETTLE_FAIL.getCode());
apply.setFailMessage(replaceFailMessage(vo.getFailMessage()));
studioAxfApplyRpService.updateById(apply);
return vo;
}
private void openStore(Long id, Long merchantId, SubChannelOpenTypeEnums openType) {
OpenStoreVO vo;
try {
JsonResult<OpenStoreVO> result = storeApi.openStore(AxfConvert.toStoreRequest(merchantId, openType));
result.assertSuccess();
vo = result.getResult();
} catch (Exception e) {
log.error("open store fail {}, {}", id, merchantId, e);
String failMessage =
e instanceof BizException ? ((BizException) e).getDefaultErrorMessage() : "网络异常";
vo = OpenStoreVO.builder().state(OpenStateEnums.FAIL).failMessage(failMessage).build();
}
switch (vo.getState()) {
case INIT:
case PROCESS:
this.doOpenAxfStoreProcess(id);
break;
case FAIL:
this.doOpenAxfStoreFail(id, vo.getFailMessage());
break;
case SUCCESS:
this.doOpenAxfStoreSuccess(studioAxfApplyRpService.getById(id)
.orElseThrow(() -> new BizException(FinanceErrorEnums.NOT_EXIST)),
StoreEvent.builder().id(vo.getStoreId()).merchantId(merchantId).build());
break;
default:
break;
}
}
public void createCommodityTemplateTest(Long applyId, Long storeId) {
StudioAxfApply apply = studioAxfApplyRpService.getById(applyId)
.orElseThrow(() -> new BizException(FinanceErrorEnums.NOT_EXIST));
StoreEvent event = StoreEvent.builder().id(storeId).merchantId(apply.getMerchantId()).build();
this.createCommodityTemplate(apply, event, "立即扣款周期付周1", true, CycleTypeEnums.WEEK, 1);
this.createCommodityTemplate(apply, event, "立即扣款周期付周3", true, CycleTypeEnums.WEEK, 3);
this.createCommodityTemplate(apply, event, "立即扣款周期付月1", true, CycleTypeEnums.MONTH, 1);
this.createCommodityTemplate(apply, event, "立即扣款周期付月15", true, CycleTypeEnums.MONTH, 15);
this.createCommodityTemplate(apply, event, "立即扣款周期付月28", true, CycleTypeEnums.MONTH, 28);
this.createCommodityTemplate(apply, event, "周期付周1", false, CycleTypeEnums.WEEK, 1);
this.createCommodityTemplate(apply, event, "周期付周3", false, CycleTypeEnums.WEEK, 3);
this.createCommodityTemplate(apply, event, "周期付月1", false, CycleTypeEnums.MONTH, 1);
this.createCommodityTemplate(apply, event, "周期付月15", false, CycleTypeEnums.MONTH, 15);
this.createCommodityTemplate(apply, event, "周期付月28", false, CycleTypeEnums.MONTH, 28);
}
private void doOpenAxfStoreSuccess(StudioAxfApply apply, StoreEvent event) {
studioAxfApplyRpService.updateById(
StudioAxfApply.builder().id(apply.getId()).state(AxfStateEnums.STORE_SUCCESS.getCode())
.updateTime(new Date()).build());
}
private void createCommodityTemplate(StudioAxfApply apply, StoreEvent event, String commodityName,
boolean chargeNow, CycleTypeEnums cycleType, Integer cycleValue) {
CreateCommodityTemplateRequest request = AxfConvert.toCommodityRequest(apply, event, commodityName,
chargeNow, cycleType, cycleValue);
JsonResult<CreateCommodityTemplateVO> result = storeApi.createCommodityTemplate(request);
StudioAxfCommodityTemplateApply templateApply = AxfConvert.toTemplateApply(apply, result, request);
studioAxfCommodityTemplateApplyRpService.insert(templateApply);
if (OpenStateEnums.SUCCESS == OpenStateEnums.getByCode(templateApply.getState())) {
StudioAxfCommodityTemplate exist = this.hitTemplate(templateApply.getMerchantId(),
request.getCycleCommodityAttr());
if (null == exist) {
StudioAxfCommodityTemplate template = AxfConvert.toTemplate(apply, result, request);
studioAxfCommodityTemplateRpService.insert(template);
} else {
StudioAxfCommodityTemplate template = AxfConvert.toTemplate(apply, result, request);
template.setId(exist.getId());
studioAxfCommodityTemplateRpService.updateById(template);
}
}
if (OpenStateEnums.FAIL == OpenStateEnums.getByCode(templateApply.getState())) {
// 钉钉告警
DingUtil.sendCreateCommodityTemplateFail(env, apply.getStudioId(), templateApply.getId());
}
}
@Override
public CreateCommodityVO createCommodity(CreateStudioAxfCommodityRequest request) {
// 校验
this.check(request);
StudioAxfCommodityTemplate template = this.hitTemplate(request);
if (null == template) {
return CreateCommodityVO.builder().state(OpenStateEnums.FAIL).failMessage("未找到相应标品").build();
}
return this.createCommodity(AxfConvert.toRequest(request, template));
}
private void check(CreateStudioAxfCommodityRequest request) {
BigDecimal sumOriginalPrice = request.getCycleCommodityAttr().getPeriodPriceList().stream()
.map(PeriodPrice::getOriginalPrice).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
BigDecimal sumSalePrice = request.getCycleCommodityAttr().getPeriodPriceList().stream()
.map(PeriodPrice::getSalePrice).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
if (sumSalePrice.compareTo(request.getSalePrice()) != 0) {
throw new BizException(FinanceErrorEnums.AXF_PERIOD_SALE_PRICE_ERROR);
}
if (sumOriginalPrice.compareTo(request.getOriginalPrice()) != 0) {
throw new BizException(FinanceErrorEnums.AXF_PERIOD_SALE_PRICE_ERROR);
}
}
@Override
public CommodityVO getCommodity(String thirdCommodityId) {
JsonResult<CommodityVO> result = storeQueryApi.getCommodityByThirdCommodityId(
GetCommodityByThirdCommodityIdRequest.builder().channelNo(AxfConst.CHANNEL_NO)
.thirdCommodityId(thirdCommodityId).build());
result.assertSuccess();
return result.getResult();
}
private CreateCommodityVO createCommodity(CreateCommodityRequest req) {
try {
JsonResult<CreateCommodityVO> result = storeApi.createCommodity(req);
result.assertSuccess();
return result.getResult();
} catch (Exception e) {
log.error("create commodity fail {}, {}", req.getMerchantId(), req.getTemplateId(), e);
return CreateCommodityVO.builder().state(OpenStateEnums.FAIL).failMessage("网络异常").build();
}
}
@Override
public List<StudioAxfOrderDeductionVO> listDeduction(Long orderId) {
List<StudioAxfOrderDeduction> deductions = studioAxfOrderDeductionRpService.listByOrderId(orderId);
return AxfConvert.toDeductionVO(deductions);
}
@Override
public ConfirmEnum existFailDeduction(Long orderId) {
List<StudioAxfOrderDeduction> deductions = studioAxfOrderDeductionRpService.listByOrderId(orderId);
return Optional.ofNullable(deductions).orElse(new ArrayList<>(1)).stream()
.anyMatch(e -> CommodityOrderDeductionStateEnums.FAIL.getCode().equals(e.getState()))
? ConfirmEnum.YES
: ConfirmEnum.NO;
}
@Override
public List<StudioAxfOrderRecoveryVO> listRecovery(Long deductionId) {
List<StudioAxfOrderRecovery> recoveries = studioAxfOrderRecoveryRpService.listByDeductionId(deductionId);
return AxfConvert.toRecoveryVO(recoveries);
}
private StudioAxfCommodityTemplate hitTemplate(CreateStudioAxfCommodityRequest request) {
PartyToMerchant merchant = partyToMerchantRpService.getByStudioId(request.getStudioId(),
AxfConst.CHANNEL_NO);
if (null == merchant) {
throw new BizException(FinanceErrorEnums.NOT_OPEN_AXF);
}
return hitTemplate(merchant.getMerchantId(), request.getCycleCommodityAttr());
}
private StudioAxfCommodityTemplate hitTemplate(Long merchantId, CycleCommodityAttr attr) {
List<StudioAxfCommodityTemplate> list = studioAxfCommodityTemplateRpService.listSuccessAll(merchantId);
return Optional.ofNullable(list).orElse(new ArrayList<>(1)).stream()
.filter(e -> e.getChargeNow().equals(attr.getChargeNow()))
.filter(e -> attr.getCycleType().getCode().equals(e.getCycleType()))
.filter(e -> attr.getCycleValue().equals(e.getCycleValue()))
.filter(e -> attr.getCycleChargeType().getCode().equals(e.getCycleChargeType())).findFirst()
.orElse(null);
}
private void doOpenAxfProcess(Long id) {
studioAxfApplyRpService.updateById(
StudioAxfApply.builder().id(id).state(AxfStateEnums.AXF_PROCESS.getCode()).updateTime(new Date())
.build());
}
private static final List<Pair<String, String>> AXF_FAIL_REPLACE = new ArrayList<>(1);
static {
AXF_FAIL_REPLACE.add(Pair.of("商户名称与传参不匹配",
"F_90001|TIHUAN|授权支付宝商户名称与上传资料的营业执照主体名称不一致"));
AXF_FAIL_REPLACE.add(Pair.of("该账号不是个体户或者企业支付宝账号,请升级后再开通",
"F_90001|TIHUAN|授权支付宝商户名称与上传资料的营业执照主体名称不一致"));
AXF_FAIL_REPLACE.add(Pair.of("该商户存在特殊资质但未上传特殊资质图片",
"F_90002|TIHUAN|商户营业执照对应的经营类目不在支付宝准许开通安心付的范围内,请通过下方办法修改经营类目后重新开通使用。"));
AXF_FAIL_REPLACE.add(Pair.of("该账号未上传营业执照,请上传后再开通。",
"F_90002|TIHUAN|商户营业执照对应的经营类目不在支付宝准许开通安心付的范围内,请通过下方办法修改经营类目后重新开通使用。"));
AXF_FAIL_REPLACE.add(
Pair.of("当前经营类目不支持开通此服务,请重新选择。;mcc不在准入白名单内;该经营类目不允许开周期卡;",
"F_90003|TIHUAN|商户营业执照对应的经营类目不在支付宝准许开通安心付的范围内,请通过下方办法修改经营类目后重新开通使用。"));
AXF_FAIL_REPLACE.add(
Pair.of("门店地址信息与高德等地图反馈的地址信息(含经纬度)偏差较大,建议填写精确到xxx路xx号的详细地址",
"F_90004|TIHUAN|地址识别有误,请前往支付宝修改蚂蚁门店地址,门店审核成功后,功能即可开通成功。"));
AXF_FAIL_REPLACE.add(Pair.of("商户未授权当前接口",
"F_90005|TIHUAN|在支付宝授权时未勾选全部权限请重新授权,勾选“全权委托开发授权”"));
}
private void doOpenAxfFail(Long id, String failMessage) {
studioAxfApplyRpService.updateById(StudioAxfApply.builder().id(id).state(AxfStateEnums.AXF_FAIL.getCode())
.failMessage(replaceFailMessage(failMessage)).updateTime(new Date()).build());
executor.execute(() -> this.sendAxfFailMessage(id, replaceFailMessage(failMessage)));
}
public static String replaceFailMessage(String failMessage) {
if (null == failMessage) {
return null;
}
return AXF_FAIL_REPLACE.stream().filter(e -> failMessage.contains(e.getLeft())).findFirst()
.map(Pair::getRight).orElse(failMessage);
}
public static void main(String[] args) {
System.out.println(replaceFailMessage("商户名称与传参不匹配"));
System.out.println(replaceFailMessage(null));
}
private void sendAxfSuccessMessage(StudioAxfApply apply) {
AdminVO admin = studioRpcService.getAdmin(apply.getOpId());
BaseAdminVO parentAdmin = studioRpcService.getBossAdmin(apply.getStudioId());
EventAgent.of(SendCommonMsgEvent.class).triggerEvent(
SendCommonMsgEvent.builder().sourceId(apply.getStudioId()).eventId(IdWorker.getId())
.covertTarget(false).channelEnums(Lists.newArrayList(MsgChannelEnum.SMS)).bizType("AXF_SUCCESS")
.params(buildMessageMap(admin, MsgChannelEnum.SMS)).build());
EventAgent.of(SendCommonMsgEvent.class).triggerEvent(
SendCommonMsgEvent.builder().sourceId(apply.getStudioId()).eventId(IdWorker.getId())
.covertTarget(true).channelEnums(Lists.newArrayList(MsgChannelEnum.APP_PUSH))
.bizType("AXF_SUCCESS_SYSTEM").params(buildMessageMap(admin, MsgChannelEnum.APP_PUSH)).build());
if (!admin.getId().equals(parentAdmin.getId())) {
EventAgent.of(SendCommonMsgEvent.class).triggerEvent(
SendCommonMsgEvent.builder().sourceId(apply.getStudioId()).eventId(IdWorker.getId())
.covertTarget(false).channelEnums(Lists.newArrayList(MsgChannelEnum.SMS)).bizType("AXF_SUCCESS")
.params(buildMessageMap(BeanUtil.map(parentAdmin, AdminVO.class), MsgChannelEnum.SMS)).build());
EventAgent.of(SendCommonMsgEvent.class).triggerEvent(
SendCommonMsgEvent.builder().sourceId(apply.getStudioId()).eventId(IdWorker.getId())
.covertTarget(true).channelEnums(Lists.newArrayList(MsgChannelEnum.APP_PUSH))
.bizType("AXF_SUCCESS_SYSTEM")
.params(buildMessageMap(BeanUtil.map(parentAdmin, AdminVO.class), MsgChannelEnum.APP_PUSH))
.build());
}
}
private final static String SYMBOL = "|TIHUAN|";
private String resetFailMessage(String failMessage) {
if (null != failMessage && failMessage.contains(SYMBOL)) {
String[] strings = failMessage.split(SYMBOL);
if (strings.length > 1) {
failMessage = strings[1];
}
}
return failMessage;
}
private void sendAxfFailMessage(Long id, String failMessage) {
failMessage = this.resetFailMessage(failMessage);
StudioAxfApply apply = studioAxfApplyRpService.getById(id).orElse(null);
AdminVO admin = studioRpcService.getAdmin(apply.getOpId());
BaseAdminVO parentAdmin = studioRpcService.getBossAdmin(apply.getStudioId());
String finalFailMessage = failMessage;
EventAgent.of(SendCommonMsgEvent.class).triggerEvent(
SendCommonMsgEvent.builder().sourceId(apply.getStudioId()).eventId(IdWorker.getId())
.covertTarget(false).channelEnums(Lists.newArrayList(MsgChannelEnum.SMS)).bizType("AXF_FAIL")
.params(buildMessageMap(admin, MsgChannelEnum.SMS).stream()
.peek(e -> e.put("failMessage", finalFailMessage)).collect(Collectors.toList())).build());
EventAgent.of(SendCommonMsgEvent.class).triggerEvent(
SendCommonMsgEvent.builder().sourceId(apply.getStudioId()).eventId(IdWorker.getId())
.covertTarget(true).channelEnums(Lists.newArrayList(MsgChannelEnum.APP_PUSH))
.bizType("AXF_FAIL_SYSTEM").params(buildMessageMap(admin, MsgChannelEnum.APP_PUSH)).build());
if (!admin.getId().equals(parentAdmin.getId())) {
EventAgent.of(SendCommonMsgEvent.class).triggerEvent(
SendCommonMsgEvent.builder().sourceId(apply.getStudioId()).eventId(IdWorker.getId())
.covertTarget(false).channelEnums(Lists.newArrayList(MsgChannelEnum.SMS)).bizType("AXF_FAIL")
.params(buildMessageMap(BeanUtil.map(parentAdmin, AdminVO.class), MsgChannelEnum.SMS).stream()
.peek(e -> e.put("failMessage", finalFailMessage)).collect(Collectors.toList())).build());
EventAgent.of(SendCommonMsgEvent.class).triggerEvent(
SendCommonMsgEvent.builder().sourceId(apply.getStudioId()).eventId(IdWorker.getId())
.covertTarget(true).channelEnums(Lists.newArrayList(MsgChannelEnum.APP_PUSH))
.bizType("AXF_FAIL_SYSTEM")
.params(buildMessageMap(BeanUtil.map(parentAdmin, AdminVO.class), MsgChannelEnum.APP_PUSH))
.build());
}
}
private List<Map<String, Object>> buildMessageMap(AdminVO admin, MsgChannelEnum channel) {
List<Map<String, Object>> param = Lists.newArrayList();
Map<String, Object> map = Maps.newHashMap();
switch (channel) {
case SMS:
map.put("targetId", admin.getPhone());
break;
case APP_PUSH:
map.put("targetId", admin.getId());
map.put("appUrl", pushUrl);
break;
default:
break;
}
param.add(map);
return param;
}
@Resource
private ResourceRpcService resourceRpcService;
private Map<ResourceTypeEnums, ResourceInfo> upload(StudioAxfApplyRequest request, StudioAxfApply apply) {
return AxfConvert.toResourceMap(request, resourceIds -> {
Map<Long, com.jiejing.filecenter.api.resource.vo.ResourceInfoVO> urlMap = resourceRpcService.getResourceMap(
request.getStudioId(), resourceIds);
Map<Long, String> thirdMap = new HashMap<>(2);
urlMap.keySet().forEach(resourceId -> {
com.jiejing.filecenter.api.resource.vo.ResourceInfoVO info = urlMap.get(resourceId);
JsonResult<UploadVO> result = merchantApi.upload(
UploadRequest.builder().channelNo(AxfConst.CHANNEL_NO).url(info.getUrl())
.resourceType(ResourceTypeEnums.LICENSE).suffix(info.getSuffix())
.fileSize(info.getFileSize()).build());
result.assertSuccess();
thirdMap.put(resourceId, result.getResult().getThirdId());
});
return thirdMap;
});
}
private void checkBeforeApply(StudioAxfApplyRequest request) {
Integer count = studioAxfApplyRpService.countProcessByStudioId(request.getStudioId());
if (count.compareTo(0) > 0) {
throw new BizException(FinanceErrorEnums.EXIST_PROCESS_APPLY);
}
}
private void cancelOrderCallback(CommodityOrderEvent event) {
Long voucherId = Long.parseLong(event.getOrderNo());
StudioAxfOrder order = studioAxfOrderRpService.getByVoucherId(voucherId);
if (null == order) {
return;
}
order.setSignState(AxfOrderSignStateEnums.CANCEL.getCode());
order.setCancelFailMessage("");
order.setCancelTime(new Date());
order.setUpdateTime(new Date());
studioAxfOrderRpService.updateById(order);
delayQueueApi.remove(RemoveDelayTaskRequest.builder().bizId(order.getId()).build());
}
@Resource
private VoucherApi voucherApi;
private void createOrderCallback(CommodityOrderEvent event) {
Long voucherId = Long.parseLong(event.getOrderNo());
StudioAxfOrder exist = studioAxfOrderRpService.getByVoucherId(voucherId);
if (null != exist) {
return;
}
GetCommodityByBizIdRequest request = GetCommodityByBizIdRequest.builder()
.merchantId(event.getMerchantId()).bizId(voucherId).build();
JsonResult<CommodityVO> result = storeQueryApi.getCommodityByBizId(request);
result.assertSuccess();
CommodityVO commodity = result.getResult();
VoucherVO voucher = this.getVoucher(commodity.getBizId());
MemberDetailVO student = this.getStudent(voucher.getReceiver().getId());
StudioAxfOrder order = AxfConvert.toEntity(event, commodity, voucher, student);
studioAxfOrderRpService.insert(order);
}
private MemberDetailVO getStudent(Long memberId) {
MemberIdRequest request = new MemberIdRequest();
request.setMemberId(memberId);
JsonResult<MemberDetailVO> result = memberApi.findDetailById(request);
return result.assertAndReturn().getResult();
}
private VoucherVO getVoucher(Long voucherId) {
JsonResult<VoucherVO> result = voucherApi.getVoucher(IdRequest.builder().id(voucherId).build());
return result.assertAndReturn().getResult();
}
private StudioAxfApplyVO toVO(StudioAxfApply apply) {
return AxfConvert.toVO(apply, vo -> {
Map<Long, ResourceInfoVO> map = resourceRpcService.getResourceMap(vo.getStudioId(),
Lists.newArrayList(vo.getLicenseResourceId(), vo.getStoreHeadResourceId()));
vo.setLicenseResourceUrl(map.get(vo.getLicenseResourceId()).getUrl());
vo.setStoreHeadResourceUrl(map.get(vo.getStoreHeadResourceId()).getUrl());
});
}
private void syncOrder(StudioAxfOrderVO order) {
List<StudioAxfOrderDeduction> deductions = studioAxfOrderDeductionRpService.listByOrderId(order.getId())
.stream().filter(e -> CommodityOrderDeductionStateEnums.SUCCESS.getCode().equals(e.getState()))
.collect(Collectors.toList());
BigDecimal amount = deductions.stream().map(StudioAxfOrderDeduction::getAmount).reduce(BigDecimal::add)
.orElse(BigDecimal.ZERO);
BigDecimal actualAmount = deductions.stream().map(StudioAxfOrderDeduction::getActualAmount)
.reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
Integer receivedPeriod = deductions.stream().map(StudioAxfOrderDeduction::getPeriod).max(Integer::compare)
.orElse(0);
StudioAxfOrder toModify = StudioAxfOrder.builder().id(order.getId()).rate(AxfConst.RATE)
.receivedAmount(amount).receivedActualAmount(actualAmount)
.receivedFee(MoneyUtil.subtract(amount, actualAmount)).receivedPeriod(receivedPeriod)
.updateTime(new Date()).build();
studioAxfOrderRpService.updateById(toModify);
}
private StudioAxfOrderVO getByThirdOrderNo(Long merchantId, String thirdOrderNo) {
StudioAxfOrder order = studioAxfOrderRpService.getByThirdOrderNo(merchantId, thirdOrderNo);
return AxfConvert.toVO(order);
}
@Override
public void cancelFail(Long id, Long opId, Date date) {
StudioAxfOrder order = studioAxfOrderRpService.getById(id)
.orElseThrow(() -> new BizException(FinanceErrorEnums.NOT_EXIST));
if (!AxfOrderSignStateEnums.CANCEL_PROCESS.getCode().equals(order.getSignState())) {
return;
}
this.cancelFailNoCheck(id, opId, date);
}
@Override
public StudioAxfOrderVO getByVoucherId(Long voucherId) {
StudioAxfOrder order = studioAxfOrderRpService.getByVoucherId(voucherId);
return AxfConvert.toVO(order);
}
private void cancelFailNoCheck(Long id, Long opId, Date date) {
AdminVO admin = studioRpcService.getAdmin(opId);
studioAxfOrderRpService.updateById(
StudioAxfOrder.builder().id(id).signState(AxfOrderSignStateEnums.SIGN.getCode()).cancelOpId(-1L)
.cancelOpName("").cancelFailMessage(
DateFormatUtils.format(date, "yyyy-MM-dd HH:mm:ss") + " " + admin.getName()
+ "发起解约,解约失败,如需解约请重新操作").build());
}
private void setAuthUsed(Long studioId, String merchantNo) {
StudioAxfAuthApply apply = studioAxfAuthApplyRpService.getLatestByUserId(studioId, merchantNo);
if (null != apply) {
apply.setUsed(ConfirmEnum.YES.name());
apply.setUpdateTime(new Date());
studioAxfAuthApplyRpService.updateById(apply);
}
StudioAxfAuth auth = studioAxfAuthRpService.getById(studioId).orElse(null);
if (null != auth && auth.getUserId().equals(merchantNo)) {
auth.setUsed(ConfirmEnum.YES.name());
auth.setUpdateTime(new Date());
studioAxfAuthRpService.updateById(auth);
}
}
}
package com.jiejing.fitness.finance.service.axf.model;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
/**
* 核销订单变更通知
*
* @author chengyubing
* @since 2024/9/7 17:15
*/
@Data
public class AlipayCommerceMerchantcardDeductionOrderNotifyModel {
/**
* 【描述】核销订单id 【示例值】1000100202405300000000100003
*/
@JSONField(name = "deduction_order_id")
private String deductionOrderId;
/**
* 核销订单状态 待支付: UNPAID 支付成功: PAYMENT_SUCCESS 支付失败: PAYMENT_FAILED 已退款: REFUND
*/
@JSONField(name = "deduction_order_status")
private String deductionOrderStatus;
/**
* 售卖订单id
*/
@JSONField(name = "card_id")
private String cardId;
/**
* 售卖订单对应的期数
*/
@JSONField(name = "period")
private String period;
/**
* 支付宝交易号
*/
@JSONField(name = "trade_no")
private String tradeNo;
/**
* 用户id
* <p>
* 新商户建议使用open_id替代该字段。对于新商户,user_id字段未来计划逐步回收,存量商户可继续使用。如使用open_id,请确认 应用-开发配置-openid配置管理
* 已启用。无该配置项,可查看openid配置申请。
*/
@JSONField(name = "user_id")
private String userId;
/**
* 用于标记支付宝用户在应用下的唯一标识 详情可查看 openid简介
*/
@JSONField(name = "open_id")
private String openId;
/**
* 【描述】商品小程序appid
*/
@JSONField(name = "card_template_app_id")
private String cardTemplateAppId;
/**
* 卡ID
*/
@JSONField(name = "card_template_id")
private String cardTemplateId;
}
package com.jiejing.fitness.finance.service.axf.model;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
/**
* 售卖订单变更消息通知
*
* @author chengyubing
* @since 2024/9/6 17:36
*/
@Data
public class AlipayCommerceMerchantcardOrderNotifyModel {
/**
* 【描述】售卖订单ID(订购单ID)
* 【示例值】202306240000000001
*/
@JSONField(name = "card_id")
private String cardId;
/**
* 【描述】业务单id,也是交易组件订单编号
* 【示例值】202306270007300200080GVS95IS
*/
@JSONField(name = "order_id")
private String orderId;
/**
* 【描述】创建时间
* 【示例值】yyyy-MM-dd HH:mm:ss
*/
@JSONField(name = "create_time")
private String createTime;
/**
* 【描述】卡ID(商品模板ID)
* 【示例值】2024070422000727041794
*/
@JSONField(name = "card_template_id")
private String cardTemplateId;
/**
* 【描述】售卖订单状态 订购中: init 可使用: available 已用完: used_up 关闭中: closing 已关闭: closed 已失效: invalid 已支付: paid 已退款:
* refund 超时关闭: timeout_closed 暂停: pause
*/
@JSONField(name = "card_status")
private String cardStatus;
/**
* 【描述】卡名称
* 【示例值】次卡1
*/
@JSONField(name = "card_name")
private String cardName;
/**
* 卡类型
* 次卡: TIMES_CARD
* 周期付: PERIOD_PAY
* 标准版周期付: AXF_MERCHANT_PERIOD_PAY
* 周期卡间连版: AXF_PERIOD_PAY_INDIRECT
* 标准版金额卡: AXF_MONEY_CARD
*/
@JSONField(name = "card_type")
private String cardType;
/**
* 【描述】支付宝用户的userId。新商户建议使用open_id替代该字段。对于新商户,user_id字段未来计划逐步回收,存量商户可继续使用。如使用open_id,请确认 应用-开发配置-openid配置管理 已启用。无该配置项,可查看openid配置申请。
* 【示例值】2088741116398093
*/
@JSONField(name = "user_id")
private String userId;
/**
* 【描述】用于标记支付宝用户在应用下的唯一标识 详情可查看 openid简介
* 【示例值】074a1CcTG1LelxKe4xQC0zgNdId0nxi95b5lsNpazWYoCo5
*/
@JSONField(name = "open_id")
private String openId;
/**
* 【描述】总期数,单位:期
* 【必选条件】当card_type=AXF_MONEY_CARD时,该字段没有值
*/
@JSONField(name = "total_count")
private String totalCount;
/**
* 【描述】剩余可用期数,单位:期
* 【必选条件】当card_type=AXF_MONEY_CARD时,该字段没有值
*/
@JSONField(name = "remain_count")
private String remainCount;
/**
* 【描述】支付宝交易号
* 【必选条件】当商品的card_type=AXF_MONEY_CARD时有值
*/
@JSONField(name = "trade_no")
private String tradeNo;
/**
* 【描述】金额卡余额现金价值,单位分
* 【必选条件】当card_type=AXF_MONEY_CARD时,该字段有值
*/
@JSONField(name = "usable_cash")
private String usableCash;
/**
* 【描述】金额卡余额面值,单位分
* 【必选条件】当card_type=AXF_MONEY_CARD时,该字段有值
*/
@JSONField(name = "available_amount")
private String availableAmount;
/**
* 【描述】小程序id
* 【示例值】2021004176600010
*/
@JSONField(name = "merchant_app_id")
private String merchantAppId;
/**
* 【描述】用于区分订购单的取消类型
* 【枚举值】
* 用户取消: USER_CANCEL
* 商户取消: MERCHANT_CANCEL
* 过期取消: EXPIRED_CANCEL
* 系统取消: SYSTEM_CANCEL
*/
@JSONField(name = "cancel_type")
private String cancelType;
/**
* 外部单号
* 【描述】商户在接入插件时自定义的外部单号
* 【示例值】123
*/
@JSONField(name = "out_order_no")
private String outOrderNo;
/**
* 【描述】卡售价,单位分
*/
@JSONField(name = "sale_price_total")
private String salePriceTotal;
/**
* 【描述】卡原价,单位分
*/
@JSONField(name = "origin_price_total")
private String originPriceTotal;
/**
* 【描述】售卖订单有效期开始时间
* 【示例值】yyyy-MM-dd HH:mm:ss
*/
@JSONField(name = "gmt_active")
private String gmtActive;
/**
* 【描述】售卖订单有效期结束时间
* 【示例值】yyyy-MM-dd HH:mm:ss
*/
@JSONField(name = "gmt_expired")
private String gmtExpired;
}
......@@ -28,6 +28,11 @@ public enum FinanceErrorEnums implements BaseBizError {
PAY_FAIL_AMOUNT_MIN("金额必须大于0元"),
PAY_FAIL_AMOUNT_MAX("金额必须小于10000000元"),
PAY_FAIL_NOT_OPEN("未开通线上支付,请联系场馆工作人员处理"),
TOKEN_INVALID("token失效,请重新授权"),
AGG_TIME_OUT("统计超时"),
NOT_OPEN_AXF("未开通先学后付"),
AXF_PERIOD_SALE_PRICE_ERROR("分期实扣金额计算错误"),
AXF_PERIOD_ORIGINAL_PRICE_ERROR("分期原价金额计算错误"),
;
......
package com.jiejing.fitness.finance.service.enums;
import com.jiejing.fitness.enums.finance.PartyTypeEnum;
import java.util.Arrays;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author chengyubing
* @since 2024/9/7 14:23
*/
@Getter
@AllArgsConstructor
public enum MerchantBizCodeEnums {
/**
* bizcode
*/
AXF("先学后付"),
STUDIO("场馆"),
BRAND("品牌"),
UNKNOWN("未知"),
;
private final String code = name();
private final String message;
public static MerchantBizCodeEnums getByCode(String code) {
return Arrays.stream(MerchantBizCodeEnums.values()).filter(e -> e.getCode().equals(code)).findFirst()
.orElse(UNKNOWN);
}
}
......@@ -3,14 +3,21 @@ package com.jiejing.fitness.finance.service.event;
import static org.springframework.integration.IntegrationMessageHeaderAccessor.DELIVERY_ATTEMPT;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jiejing.fitness.enums.delay.DelayTaskCodeEnum;
import com.jiejing.fitness.enums.finance.PartyTypeEnum;
import com.jiejing.fitness.finance.service.axf.AxfService;
import com.jiejing.fitness.finance.service.enums.MerchantBizCodeEnums;
import com.jiejing.fitness.finance.service.merchant.StudioMerchantService;
import com.jiejing.fitness.finance.service.pay.PayService;
import com.jiejing.fitness.finance.service.pay.RefundService;
import com.jiejing.paycenter.common.event.CommodityOrderEvent;
import com.jiejing.paycenter.common.event.MerchantEvent;
import com.jiejing.paycenter.common.event.MerchantSubChannelEvent;
import com.jiejing.paycenter.common.event.OrderDeductionEvent;
import com.jiejing.paycenter.common.event.PayEvent;
import com.jiejing.paycenter.common.event.RefundEvent;
import com.jiejing.paycenter.common.event.StoreEvent;
import com.jiejing.workflow.event.DelayTaskEvent;
import com.xiaomai.event.annotation.EventHandler;
import java.util.ArrayList;
......@@ -39,6 +46,9 @@ public class ListenerService {
@Resource
private RefundService refundService;
@Resource
private AxfService axfService;
@EventHandler(value = MerchantEvent.class, binder = "biz-kafka", maxAttempts = MAX_RETRY)
public void handleMerchantEvent(MerchantEvent event, @Header(DELIVERY_ATTEMPT) int retryNum) {
try {
......@@ -46,11 +56,14 @@ public class ListenerService {
event.setSubChannels(Optional.ofNullable(event.getSubChannels()).orElse(new ArrayList<>(1)));
event.setSubChannelAuths(Optional.ofNullable(event.getSubChannelAuths()).orElse(new ArrayList<>(1)));
PartyTypeEnum type = PartyTypeEnum.getByCode(event.getBizCode());
MerchantBizCodeEnums type = MerchantBizCodeEnums.getByCode(event.getBizCode());
switch (type) {
case STUDIO:
studioMerchantService.callback(event);
break;
case AXF:
axfService.callback(event);
break;
default:
break;
}
......@@ -95,10 +108,57 @@ public class ListenerService {
public void delayTaskEventCallback(DelayTaskEvent event, @Header(DELIVERY_ATTEMPT) int retryNum) {
try {
log.info("start process delayTaskEventCallback {}", JSON.toJSONString(event));
switch (DelayTaskCodeEnum.getByCode(event.getBizCode())) {
case EMBEDDED_XCX:
studioMerchantService.syncEmbeddedXcx(event.getId());
break;
case CANCEL_AXF_ORDER_FAIL:
this.processCancelAxfOrderFail(event);
break;
default:
return;
}
} catch (Exception e) {
log.info("process delayTaskEventCallback fail {}", event, e);
}
}
private void processCancelAxfOrderFail(DelayTaskEvent event) {
Long id = event.getBizId();
JSONObject body = JSON.parseObject(event.getTaskBody());
axfService.cancelFail(id, body.getLong("opId"), body.getDate("cancelTime"));
}
@EventHandler(value = StoreEvent.class, binder = "biz-kafka", maxAttempts = 5)
public void storeEvent(StoreEvent event, @Header(DELIVERY_ATTEMPT) int retryNum) {
try {
log.info("start process store event {}", JSON.toJSONString(event));
axfService.storeCallback(event);
} catch (Exception e) {
log.error("store event callback process fail {}", JSON.toJSONString(event), e);
}
}
@EventHandler(value = CommodityOrderEvent.class, binder = "biz-kafka", maxAttempts = 5)
public void commodityOrderEvent(CommodityOrderEvent event) {
try {
log.info("start process CommodityOrderEvent {}", JSON.toJSONString(event));
axfService.orderCallback(event);
} catch (Exception e) {
log.info("process CommodityOrderEvent fail {}", event.getOrderNo(), e);
}
}
@EventHandler(value = OrderDeductionEvent.class, binder = "biz-kafka", maxAttempts = 5)
public void orderDeductionEvent(OrderDeductionEvent event) {
try {
log.info("start process OrderDeductionEvent {}", JSON.toJSONString(event));
axfService.orderDeductionCallback(event);
} catch (Exception e) {
log.info("process OrderDeductionEvent fail {}, {}", event.getOrderNo(), event.getThirdTransNo(), e);
}
}
}
package com.jiejing.fitness.finance.service.rpc;
import com.google.common.collect.Lists;
import com.jiejing.common.model.JsonResult;
import com.jiejing.common.request.IdRequest;
import com.jiejing.common.request.IdsRequest;
import com.jiejing.fitness.enums.studio.AdminStudioStatusEnum;
import com.jiejing.studio.api.admin.AdminApi;
import com.jiejing.studio.api.admin.vo.AdminVO;
import com.jiejing.studio.api.admin.vo.BaseAdminVO;
import com.jiejing.studio.api.studio.StudioApi;
import com.jiejing.studio.api.studio.request.GetStudioAdminRequest;
import com.jiejing.studio.api.studio.vo.StudioVO;
......@@ -31,6 +34,16 @@ public class StudioRpcService {
@Resource
private AdminApi adminApi;
public AdminVO getAdmin(Long id) {
return adminApi.getAdmin(IdRequest.builder().id(id).build()).assertAndReturn().getResult();
}
public BaseAdminVO getBossAdmin(Long id) {
JsonResult<Map<Long, BaseAdminVO>> result = adminApi.listStudioBoss(IdsRequest.builder().ids(Lists.newArrayList(id)).build());
result.assertSuccess();
return result.getResult().get(id);
}
public List<Long> listAdminIdsByUserIds(Long studioId, List<Long> userIds) {
GetStudioAdminRequest request = new GetStudioAdminRequest();
request.setStudioId(studioId);
......
......@@ -18,6 +18,7 @@ public class DingUtil {
private static final String CHECK_SETTLE_SUCCESS = "%s【告警】【乐动收银自动结算记录对账】全部对账成功";
private static final String CHECK_SETTLE_FAIL = "%s【告警】【乐动收银自动结算记录对账】有%s家对账失败,请人工跟进";
private static final String CREATE_COMMODITY_TEMPLATE_FAIL = "【%s】场馆id%s,先享后付商品创建失败,商品id为%s,请立即处理";
public static void sendCheckSettleFail(String env, Integer total) {
Message message = new TextMessage(String.format(CHECK_SETTLE_FAIL, env, total));
......@@ -37,4 +38,13 @@ public class DingUtil {
}
}
public static void sendCreateCommodityTemplateFail(String env, Long studioId, Long id) {
try {
String text = String.format(CREATE_COMMODITY_TEMPLATE_FAIL, env, studioId, id);
TextMessage textMessage = new TextMessage(text);
DingtalkChatbotClient.send(URL, textMessage);
} catch (IOException e) {
log.error("sendCreateCommodityTemplateFail {}, {}", studioId, id, e);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment