| @@ -0,0 +1,34 @@ | |||||
| ALTER TABLE `wx_mall` | |||||
| ADD COLUMN `cash_out_support` INT(1) COMMENT '是否支持商户提现(不开启分账才有效) 0-不支持 1-支持' AFTER `live_support`; | |||||
| UPDATE wx_mall SET cash_out_support = 0 ; | |||||
| ALTER TABLE wx_merchant ADD COLUMN `cash_out_number` INT(11) COMMENT '商户待提现金额(分)' ; | |||||
| ###页面添加工作流,提现审批,22, 初始化里面也加上 | |||||
| CREATE TABLE `wx_cash_out` ( | |||||
| `id` bigint(20) NOT NULL, | |||||
| `total_fee` int(11) NOT NULL COMMENT '总金额(分)', | |||||
| `status` tinyint(1) NOT NULL COMMENT '状态 0-提现中,1-提现成功,2-提现失败,3-提现拒绝', | |||||
| `create_date` datetime DEFAULT NULL COMMENT '创建时间', | |||||
| `update_date` datetime DEFAULT NULL COMMENT '更新时间', | |||||
| `audio_remark` varchar(1000) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '审核备注', | |||||
| `tenant_id` varchar(5) COLLATE utf8mb4_unicode_ci NOT NULL, | |||||
| `parent_tenant_id` varchar(5) COLLATE utf8mb4_unicode_ci DEFAULT NULL, | |||||
| `b_user_id` bigint(20) NOT NULL COMMENT 'merchant_b_user编号', | |||||
| `wx_b_open_id` varchar(60) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'b端微信openId', | |||||
| `audio_date` datetime DEFAULT NULL COMMENT '审批时间', | |||||
| `merchant_id` bigint(20) NOT NULL COMMENT '提现商户', | |||||
| `merchant_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '商户名称', | |||||
| `recive_open_id` varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '接收的openId', | |||||
| `recive_nick_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '昵称', | |||||
| `wx_pay_no` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '支付渠道支付编号', | |||||
| `wx_pay_time` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '支付渠道支付时间', | |||||
| `fail_remark` varchar(1000) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '失败原因', | |||||
| PRIMARY KEY (`id`) | |||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; | |||||
| @@ -0,0 +1,62 @@ | |||||
| package com.iformall.controller; | |||||
| import com.github.pagehelper.PageInfo; | |||||
| import com.iformall.common.Result; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.enums.EnumPayWay; | |||||
| import com.iformall.service.*; | |||||
| import io.swagger.annotations.Api; | |||||
| import io.swagger.annotations.ApiImplicitParam; | |||||
| import io.swagger.annotations.ApiImplicitParams; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| @RestController | |||||
| @RequestMapping("/api/cashout") | |||||
| @Api(description = "提现相关接口") | |||||
| public class WxCashOutController extends BaseController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private WxCashOutService wxCashOutService; | |||||
| @Autowired | |||||
| WxCUserService wxCUserService; | |||||
| @ApiOperation("分页列表接口") | |||||
| @GetMapping("list") | |||||
| @ApiImplicitParams({ | |||||
| @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), | |||||
| @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) | |||||
| public ResultData list(@ModelAttribute WxCashOut wxCashOut, Integer pageNum, Integer pageSize) { | |||||
| if (null == wxCashOut) wxCashOut = new WxCashOut(); | |||||
| final PageInfo<WxCashOut> page = wxCashOutService.listAsPage(wxCashOut, pageNum, pageSize); | |||||
| return new ResultData(page); | |||||
| } | |||||
| @ApiOperation("微信B端提现") | |||||
| @PostMapping("cashout") | |||||
| public ResultData cashout(@RequestBody WxCashOut wxCashOut) { | |||||
| WxMerchantBUser buser = getLoginBUser(); | |||||
| //当前管理员的账户必须在c端授权了 | |||||
| WxCUser cuUser = new WxCUser(); | |||||
| cuUser.updateTenantInfo(buser); | |||||
| cuUser.setPhone(buser.getPhone()); | |||||
| try { | |||||
| WxCUser mUser = wxCUserService.getByObject(cuUser); | |||||
| if (mUser == null) { | |||||
| return new ResultData(Result.ERROR,"请用绑定["+buser.getPhone()+"]的微信在C端完成授权手机号操作。"); | |||||
| } | |||||
| wxCashOut.setReciveOpenId(mUser.getOpenId()); | |||||
| wxCashOut.setReciveNickName(mUser.getNickName()); | |||||
| }catch(Exception e) { | |||||
| return new ResultData(Result.ERROR,buser.getPhone()+"匹配C端用户失败,该情况可能是存在多个微信对应统一手机号,请联系管理员处理, 。"); | |||||
| } | |||||
| return wxCashOutService.applyCashout(buser, wxCashOut,EnumPayWay.PAY_WAY_WECHAT); | |||||
| } | |||||
| } | |||||
| @@ -46,6 +46,9 @@ public class MqBaseConsumer { | |||||
| //@Autowired | //@Autowired | ||||
| //UpdateCouponStockMsgServiceImpl updateCouponStockMsgService; | //UpdateCouponStockMsgServiceImpl updateCouponStockMsgService; | ||||
| @Autowired | |||||
| private FmInsideCashOutMsgServiceImpl fmInsideCashOutMsgService; | |||||
| public void doMessage(String message) { | public void doMessage(String message) { | ||||
| @@ -103,6 +106,11 @@ public class MqBaseConsumer { | |||||
| FmInsideNotifyRefundSuccessMsg msg = (FmInsideNotifyRefundSuccessMsg)JsonUtil.readValue(message,FmInsideNotifyRefundSuccessMsg.class); | FmInsideNotifyRefundSuccessMsg msg = (FmInsideNotifyRefundSuccessMsg)JsonUtil.readValue(message,FmInsideNotifyRefundSuccessMsg.class); | ||||
| fmInsideNotifyRefundSuccessMsgService.send(msg); | fmInsideNotifyRefundSuccessMsgService.send(msg); | ||||
| } | } | ||||
| else if(EnumMsgRecordType.CASH_OUT.getCode().equals(baseMsg.getMsgType())) { | |||||
| // 内部消息 - 商户提现通知 | |||||
| FmInsideCashOutMsg msg = (FmInsideCashOutMsg)JsonUtil.readValue(message,FmInsideCashOutMsg.class); | |||||
| fmInsideCashOutMsgService.send(msg); | |||||
| } | |||||
| //else if (EnumMsgRecordType.COUPON_STOCK.getCode().equals(baseMsg.getMsgType())) { | //else if (EnumMsgRecordType.COUPON_STOCK.getCode().equals(baseMsg.getMsgType())) { | ||||
| // UpdateCouponStockMsg msg = (UpdateCouponStockMsg)JsonUtil.readValue(message,UpdateCouponStockMsg.class); | // UpdateCouponStockMsg msg = (UpdateCouponStockMsg)JsonUtil.readValue(message,UpdateCouponStockMsg.class); | ||||
| // updateCouponStockMsgService.send(msg); | // updateCouponStockMsgService.send(msg); | ||||
| @@ -212,7 +212,12 @@ public class BaseMyBatisConfiguration { | |||||
| wxCarJSOrderSharding.setRule(EnumShardingRule.HASH.getCode()); | wxCarJSOrderSharding.setRule(EnumShardingRule.HASH.getCode()); | ||||
| shardingList.add(wxCarJSOrderSharding); | shardingList.add(wxCarJSOrderSharding); | ||||
| ShardingSphere wxCashOutSharding = new ShardingSphere(); | |||||
| wxCashOutSharding.setColumn("tenant_id"); | |||||
| wxCashOutSharding.setTableName("wx_cash_out"); | |||||
| wxCashOutSharding.setCount(100); | |||||
| wxCashOutSharding.setRule(EnumShardingRule.HASH.getCode()); | |||||
| shardingList.add(wxCashOutSharding); | |||||
| //初始化 | //初始化 | ||||
| shardingSpherePlugin.setShardingSpheres(shardingList); | shardingSpherePlugin.setShardingSpheres(shardingList); | ||||
| @@ -0,0 +1,51 @@ | |||||
| package com.iformall.domain.po; | |||||
| import com.baomidou.mybatisplus.annotation.TableName; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import lombok.ToString; | |||||
| import java.util.Date; | |||||
| @TableName(value = "wx_cash_out") | |||||
| @Data | |||||
| @ToString(callSuper = true) | |||||
| @EqualsAndHashCode(callSuper = true) | |||||
| public class WxCashOut extends TenantEntity { | |||||
| protected Long id; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "总金额(分)", name = "totalFee") | |||||
| private Integer totalFee; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "状态 0-提现中,1-提现成功,2-提现失败,3-提现拒绝", name = "status") | |||||
| private Integer status; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "创建时间", name = "createDate") | |||||
| private Date createDate; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "更新时间", name = "updateDate") | |||||
| private Date updateDate; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "审核备注", name = "audioRemark") | |||||
| private String audioRemark; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "merchant_b_user编号", name = "bUserId") | |||||
| private Long bUserId; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "b端微信用户Id", name = "wxBOpenId") | |||||
| private String wxBOpenId; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "审批时间", name = "audioDate") | |||||
| private Date audioDate; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "提现商户", name = "merchantId") | |||||
| private Long merchantId; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "商户名称", name = "merchantName") | |||||
| private String merchantName; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "接收的openId", name = "reciveOpenId") | |||||
| private String reciveOpenId; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "昵称", name = "reciveNickName") | |||||
| private String reciveNickName; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "支付渠道支付编号", name = "wxPayNo") | |||||
| private String wxPayNo; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "支付渠道支付时间", name = "wxPayTime") | |||||
| private String wxPayTime; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "失败原因", name = "failRemark") | |||||
| private String failRemark; | |||||
| } | |||||
| @@ -86,6 +86,9 @@ public class WxMall extends TenantEntity { | |||||
| private BigDecimal latitude; | private BigDecimal latitude; | ||||
| @io.swagger.annotations.ApiModelProperty(value="直播支持(0:不支持,1支持)",name="liveSupport") | @io.swagger.annotations.ApiModelProperty(value="直播支持(0:不支持,1支持)",name="liveSupport") | ||||
| private Integer liveSupport; | private Integer liveSupport; | ||||
| @io.swagger.annotations.ApiModelProperty(value="是否支持商户提现(不开启分账才有效) 0-不支持 1-支持",name="cashOutSupport") | |||||
| private Integer cashOutSupport; | |||||
| @TableField(exist = false) | @TableField(exist = false) | ||||
| protected List<WxMallBuilding> buildings; | protected List<WxMallBuilding> buildings; | ||||
| @@ -262,6 +262,9 @@ public class WxMerchant extends TenantEntity { | |||||
| @io.swagger.annotations.ApiModelProperty(value = "积分锁定0正常1锁定", name = "creditLocked") | @io.swagger.annotations.ApiModelProperty(value = "积分锁定0正常1锁定", name = "creditLocked") | ||||
| private Integer creditLocked; | private Integer creditLocked; | ||||
| @io.swagger.annotations.ApiModelProperty(value = "商户待提现金额(分)", name = "cashOutNumber") | |||||
| private Integer cashOutNumber; | |||||
| @TableField(exist = false) | @TableField(exist = false) | ||||
| @SortColumn(column = "couponSale") | @SortColumn(column = "couponSale") | ||||
| @@ -0,0 +1,23 @@ | |||||
| package com.iformall.domain.po.msg; | |||||
| import com.iformall.enums.EnumPayWay; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import lombok.ToString; | |||||
| @Data | |||||
| @ToString(callSuper = true) | |||||
| @EqualsAndHashCode(callSuper = true) | |||||
| public class FmInsideCashOutMsg extends BaseMsg{ | |||||
| private static final long serialVersionUID = 1L; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "租户ID", name = "tenantId") | |||||
| private String tenantId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="父租户id",name="parentTenantId") | |||||
| private String parentTenantId; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "提现ID", name = "cashOutId") | |||||
| private Long cashOutId; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "支付方式", name = "payWay") | |||||
| private EnumPayWay payWay; | |||||
| } | |||||
| @@ -0,0 +1,36 @@ | |||||
| package com.iformall.enums; | |||||
| /** | |||||
| * Created by Stormeye on 2018/08/09. | |||||
| */ | |||||
| public enum EnumCashOut { | |||||
| NO(0, "不持支商户提现"), | |||||
| YES(1, "支持商户提现") | |||||
| ; | |||||
| public static EnumCashOut getEnum(Integer code) { | |||||
| for (EnumCashOut value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String message; | |||||
| EnumCashOut(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,40 @@ | |||||
| package com.iformall.enums; | |||||
| /** | |||||
| * Created by Stormeye on 2018/08/09. | |||||
| */ | |||||
| public enum EnumCashOutStatus { | |||||
| //状态 0-提现中,1-提现成功,2-提现失败,3-提现拒绝 | |||||
| DOING(0, "提现中"), | |||||
| SUCCESS(1, "提现成功"), | |||||
| FAIL(2, "提现失败"), | |||||
| REJECT(3, "提现拒绝"), | |||||
| AUDIOING(4, "审批中"), | |||||
| WAITING(5, "待到账") | |||||
| ; | |||||
| public static EnumCashOutStatus getEnum(Integer code) { | |||||
| for (EnumCashOutStatus value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String message; | |||||
| EnumCashOutStatus(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -34,6 +34,8 @@ public enum EnumFlowKey { | |||||
| NEW_RENT_POINT_CONTRACT_END(20, "多经点位商铺租金+物业合同终止"), | NEW_RENT_POINT_CONTRACT_END(20, "多经点位商铺租金+物业合同终止"), | ||||
| SETTLE(21,"结算单审批"), | SETTLE(21,"结算单审批"), | ||||
| CASH_OUT(23,"商户提现审批") | |||||
| ; | ; | ||||
| public static EnumFlowKey getEnum(Integer code) { | public static EnumFlowKey getEnum(Integer code) { | ||||
| @@ -19,6 +19,7 @@ public enum EnumMsgRecordType { | |||||
| //INSIDE_NOTIFY_PAY_SUCCESS(103, "微信支付回调"), | //INSIDE_NOTIFY_PAY_SUCCESS(103, "微信支付回调"), | ||||
| INSIDE_NOTIFY_REFUND_SUCCESS(104, "微信退款回调"), | INSIDE_NOTIFY_REFUND_SUCCESS(104, "微信退款回调"), | ||||
| COUPON_STOCK(105, "券库存更新"), | COUPON_STOCK(105, "券库存更新"), | ||||
| CASH_OUT(106,"商户提现") | |||||
| ; | ; | ||||
| public static EnumMsgRecordType getEnum(Integer code) { | public static EnumMsgRecordType getEnum(Integer code) { | ||||
| @@ -0,0 +1,18 @@ | |||||
| package com.iformall.mapper; | |||||
| import com.iformall.common.CommonMapper; | |||||
| import com.iformall.domain.po.WxCashOut; | |||||
| import java.util.List; | |||||
| import org.apache.ibatis.annotations.Param; | |||||
| public interface WxCashOutMapper extends CommonMapper<WxCashOut, Long> { | |||||
| WxCashOut selectById(@Param("id")Long id,@Param("tenantId")String tenantId); | |||||
| List<WxCashOut> findList(WxCashOut wxCashOut); | |||||
| int updateStatus(WxCashOut wxCashOut); | |||||
| } | |||||
| @@ -41,4 +41,8 @@ public interface WxMerchantMapper extends CommonMapper<WxMerchant, Long> { | |||||
| List<WxMerchant> findListVo2(WxMerchant record); | List<WxMerchant> findListVo2(WxMerchant record); | ||||
| List<WxMerchant> getMerchantList(WxMerchant wxMerchant); | List<WxMerchant> getMerchantList(WxMerchant wxMerchant); | ||||
| void increaseCash(WxMerchant record); | |||||
| void reduceCash(WxMerchant record); | |||||
| } | } | ||||
| @@ -0,0 +1,37 @@ | |||||
| package com.iformall.pay; | |||||
| import lombok.Data; | |||||
| /** | |||||
| * Created by Stormeye on 2018/8/10. | |||||
| */ | |||||
| @Data | |||||
| public class WxCashOutP { | |||||
| private String mch_appid; // 申请商户号的appid或商户号绑定的appid | |||||
| private String mchid; // 商户号 | |||||
| private String nonce_str; // 随机字符串 | |||||
| private String sign; // 签名 | |||||
| private String partner_trade_no; // 商户订单号,需保持唯一性 (只能是字母或者数字,不能包含有其它字符) | |||||
| private String openid; // 商户appid下,某用户的openid | |||||
| private String check_name; // NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名 | |||||
| private String re_user_name; // 收款用户真实姓名。 如果check_name设置为FORCE_CHECK,则必填用户真实姓名 如需电子回单,需要传入收款用户姓名 | |||||
| private Integer amount; // 企业付款金额,单位为分 | |||||
| private String desc; // 企业付款备注,必填 | |||||
| @Override | |||||
| public String toString() { | |||||
| final StringBuilder sb = new StringBuilder("WxCashOutP{"); | |||||
| sb.append("mch_appid='").append(mch_appid).append('\''); | |||||
| sb.append(", mch_id='").append(mchid).append('\''); | |||||
| sb.append(", nonce_str='").append(nonce_str).append('\''); | |||||
| sb.append(", sign='").append(sign).append('\''); | |||||
| sb.append(", partner_trade_no='").append(partner_trade_no).append('\''); | |||||
| sb.append(", openid='").append(openid).append('\''); | |||||
| sb.append(", check_name=").append(check_name).append('\''); | |||||
| sb.append(", re_user_name=").append(re_user_name).append('\''); | |||||
| sb.append(", amount=").append(amount).append('\''); | |||||
| sb.append(", desc=").append(desc).append('\''); | |||||
| sb.append('}'); | |||||
| return sb.toString(); | |||||
| } | |||||
| } | |||||
| @@ -212,7 +212,7 @@ public class WxPay { | |||||
| /** | /** | ||||
| * 企业付款 | * 企业付款 | ||||
| * | |||||
| * https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2 | |||||
| * @param params | * @param params | ||||
| * 请求参数 | * 请求参数 | ||||
| * @param certPath | * @param certPath | ||||
| @@ -227,7 +227,7 @@ public class WxPay { | |||||
| /** | /** | ||||
| * 查询企业付款 | * 查询企业付款 | ||||
| * | |||||
| * https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3 | |||||
| * @param params | * @param params | ||||
| * 请求参数 | * 请求参数 | ||||
| * @param certPath | * @param certPath | ||||
| @@ -0,0 +1,45 @@ | |||||
| package com.iformall.service; | |||||
| import com.github.pagehelper.PageInfo; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import com.iformall.enums.EnumPayWay; | |||||
| public interface WxCashOutService { | |||||
| /** | |||||
| * 根据实体查询分页列表 | |||||
| * | |||||
| * @param record | |||||
| * @param pageIndex | |||||
| * @param pageSize | |||||
| * @return | |||||
| */ | |||||
| PageInfo<WxCashOut> listAsPage(WxCashOut record, Integer pageIndex, Integer pageSize); | |||||
| /** | |||||
| * 根据Id获得实体 | |||||
| * | |||||
| * @param id | |||||
| * @return | |||||
| */ | |||||
| WxCashOut getById(Long id,String tenantId); | |||||
| /** | |||||
| *更新状态 | |||||
| * | |||||
| * @param record | |||||
| */ | |||||
| void updateStatus(WxCashOut record); | |||||
| void createCashOut(WxCashOut record); | |||||
| ResultData applyCashout(WxMerchantBUser buser,WxCashOut record,EnumPayWay payWay); | |||||
| public void sendCashOutMsg(TenantEntity tenantEntity, Long cashOutId,EnumPayWay payWay); | |||||
| void rejectCashOut(WxCashOut record); | |||||
| void cashOutToWx(EnumPayWay payWay,TenantEntity tenantEntity, Long cashOutId); | |||||
| } | |||||
| @@ -0,0 +1,243 @@ | |||||
| package com.iformall.service.impl; | |||||
| import com.github.pagehelper.PageHelper; | |||||
| import com.github.pagehelper.PageInfo; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.IdWorker; | |||||
| import com.iformall.common.Result; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import com.iformall.domain.po.msg.FmInsideCashOutMsg; | |||||
| import com.iformall.domain.po.msg.FmInsideCouponVerifyMsg; | |||||
| import com.iformall.enums.EnumCashOut; | |||||
| import com.iformall.enums.EnumCashOutStatus; | |||||
| import com.iformall.enums.EnumFlowKey; | |||||
| import com.iformall.enums.EnumMsgMqKey; | |||||
| import com.iformall.enums.EnumMsgMqTag; | |||||
| import com.iformall.enums.EnumMsgMqTopic; | |||||
| import com.iformall.enums.EnumMsgRecordType; | |||||
| import com.iformall.enums.EnumPayWay; | |||||
| import com.iformall.mapper.*; | |||||
| import com.iformall.mq.MqBaseProducer; | |||||
| import com.iformall.service.*; | |||||
| import com.iformall.service.pay.PayServiceFactory; | |||||
| import com.iformall.service.pay.service.cashout.entity.CashOutAdapterResult; | |||||
| import com.iformall.utils.RedisLock; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Date; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import org.springframework.transaction.annotation.Propagation; | |||||
| import org.springframework.transaction.annotation.Transactional; | |||||
| @Service | |||||
| public class WxCashOutServiceImpl implements WxCashOutService { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| WxCashOutMapper wxCashOutMapper; | |||||
| @Autowired | |||||
| WxMerchantMapper wxMerchantMapper; | |||||
| @Autowired | |||||
| WxMallMapper wxMallMapper; | |||||
| @Autowired | |||||
| RedisLock redisLock; | |||||
| @Autowired | |||||
| MqBaseProducer mqBaseProducer; | |||||
| @Autowired | |||||
| private WxFlowService wxFlowService; | |||||
| @Autowired | |||||
| PayServiceFactory payServiceFactory; | |||||
| @Autowired | |||||
| WxAppinfoService wxAppinfoService; | |||||
| @Autowired | |||||
| WxPayAccountService wxPayAccountService; | |||||
| @Override | |||||
| public PageInfo<WxCashOut> listAsPage(WxCashOut record, Integer pageIndex, Integer pageSize) { | |||||
| return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCashOutMapper.findList(record)); | |||||
| } | |||||
| @Override | |||||
| public WxCashOut getById(Long id,String tenantId) { | |||||
| return wxCashOutMapper.selectById(id,tenantId); | |||||
| } | |||||
| @Override | |||||
| public void updateStatus(WxCashOut record) { | |||||
| wxCashOutMapper.updateStatus(record); | |||||
| } | |||||
| @Override | |||||
| public void createCashOut(WxCashOut record) { | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| record.setId(idWorker.nextId()); | |||||
| wxCashOutMapper.insert(record); | |||||
| } | |||||
| @Override | |||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | |||||
| public ResultData applyCashout(WxMerchantBUser buser, WxCashOut record,EnumPayWay payWay) { | |||||
| WxMall mall = wxMallMapper.getByTenantId(buser.getTenantId()); | |||||
| if (EnumCashOut.NO.getCode().intValue() == mall.getCashOutSupport().intValue()) { | |||||
| return new ResultData(Result.ERROR,"当前租户不支持商户提现。"); | |||||
| } | |||||
| //只有商户管理员才能进行此操作 | |||||
| WxMerchant merchant = wxMerchantMapper.selectById(buser.getMerchantId()); | |||||
| if (!(buser.getPhone().equals(merchant.getLinkPhone()))) { | |||||
| return new ResultData(Result.ERROR,"当前账号非商户管理员,不能进行此操作。"); | |||||
| } | |||||
| if (record.getTotalFee().intValue()<=0) { | |||||
| return new ResultData(Result.ERROR,"提现金额非法。"); | |||||
| } | |||||
| if (record.getTotalFee().intValue()> merchant.getCashOutNumber().intValue()) { | |||||
| return new ResultData(Result.ERROR,"提现金额超出商户余额。"); | |||||
| } | |||||
| if (StringUtils.isBlank(record.getReciveOpenId())) { | |||||
| return new ResultData(Result.ERROR,"收取人第三方openId不能为空。"); | |||||
| } | |||||
| //扣掉账户金额 | |||||
| //此处需要加锁,防止并发设置 | |||||
| long time = System.currentTimeMillis() + RedisLock.TIMEOUT; | |||||
| String timeStr = String.valueOf(time); | |||||
| boolean cashsetlock = redisLock.lock("merchantLockReduceCashSet_"+merchant.getId(), timeStr); | |||||
| if (cashsetlock) { | |||||
| try { | |||||
| merchant.setCashOutNumber(record.getTotalFee()); | |||||
| wxMerchantMapper.reduceCash(merchant); | |||||
| redisLock.unlock("merchantLockReduceCashSet_"+merchant.getId(), timeStr); | |||||
| }catch(Exception e) { | |||||
| redisLock.unlock("merchantLockReduceCashSet_"+merchant.getId(), timeStr); | |||||
| logger.error("update cashout fail.",e); | |||||
| }finally { | |||||
| redisLock.unlock("merchantLockReduceCashSet_"+merchant.getId(), timeStr); | |||||
| } | |||||
| } | |||||
| //记录提现记录 | |||||
| WxCashOut cashout = new WxCashOut(); | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| cashout.setId(idWorker.nextId()); | |||||
| cashout.setTotalFee(record.getTotalFee()); | |||||
| cashout.setStatus(EnumCashOutStatus.DOING.getCode()); | |||||
| cashout.setCreateDate(new Date()); | |||||
| cashout.setBUserId(buser.getId()); | |||||
| cashout.setWxBOpenId(String.valueOf(buser.getBuserId())); | |||||
| cashout.setMerchantId(merchant.getId()); | |||||
| cashout.setMerchantName(merchant.getName()); | |||||
| cashout.setReciveOpenId(record.getReciveOpenId()); | |||||
| cashout.setReciveNickName(record.getReciveNickName()); | |||||
| cashout.updateTenantInfo(buser); | |||||
| wxCashOutMapper.insert(cashout); | |||||
| //TODO有没有审批 | |||||
| boolean hasAudit = hasWorkFlow(buser); | |||||
| if (hasAudit) { | |||||
| //提交审批 | |||||
| Map<String, Object> map = new HashMap<String, Object>(); | |||||
| map.put("businessId", String.valueOf(cashout.getId())); | |||||
| map.put("businessType", EnumFlowKey.CASH_OUT.getCode()); | |||||
| map.put("phone", buser.getPhone()); | |||||
| List<Map> variablesList = new ArrayList<Map>(); | |||||
| Map tenantIdMap = new HashMap<String,Object>(); | |||||
| tenantIdMap.put("key","cashTenantId"); | |||||
| tenantIdMap.put("value",String.valueOf(buser.getTenantId())); | |||||
| variablesList.add(tenantIdMap); | |||||
| Map payWayMap = new HashMap<String,Object>(); | |||||
| payWayMap.put("key","cashPayWay"); | |||||
| payWayMap.put("value",String.valueOf(payWay.getCode())); | |||||
| variablesList.add(payWayMap); | |||||
| map.put("variables", variablesList); | |||||
| wxFlowService.start(map, buser.getId(), buser.getName(), buser); | |||||
| return new ResultData(Result.SUCCESS,"提现提交审批成功"); | |||||
| }else { | |||||
| //没有审批则发送消息 | |||||
| sendCashOutMsg(merchant, cashout.getId(),payWay); | |||||
| } | |||||
| return new ResultData("提现提交成功。"); | |||||
| } | |||||
| protected boolean hasWorkFlow(TenantEntity tenantEntity) { | |||||
| WxFlowModel wxFlowModel = new WxFlowModel(); | |||||
| wxFlowModel.setFlowType(EnumFlowKey.CASH_OUT.getCode()); | |||||
| wxFlowModel.updateTenantInfo(tenantEntity); | |||||
| List<WxFlowModel> flows = wxFlowService.getModelBybusiness(wxFlowModel); | |||||
| if (null != flows && flows.size() > 0) { | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| @Override | |||||
| public void sendCashOutMsg(TenantEntity tenantEntity, Long cashOutId,EnumPayWay payWay) { | |||||
| FmInsideCashOutMsg verifyMsg = new FmInsideCashOutMsg(); | |||||
| verifyMsg.setMsgType(EnumMsgRecordType.CASH_OUT.getCode()); | |||||
| verifyMsg.updateTenantInfo(tenantEntity); | |||||
| verifyMsg.setCashOutId(cashOutId); | |||||
| verifyMsg.setPayWay(payWay); | |||||
| mqBaseProducer.sendMessage(verifyMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| } | |||||
| @Override | |||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | |||||
| public void rejectCashOut(WxCashOut record) { | |||||
| //更新状态,并且把钱数退回账户 | |||||
| wxCashOutMapper.updateStatus(record); | |||||
| WxMerchant merchant = wxMerchantMapper.selectById(record.getMerchantId()); | |||||
| //增加账户金额 | |||||
| //此处需要加锁,防止并发设置 | |||||
| long time = System.currentTimeMillis() + RedisLock.TIMEOUT; | |||||
| String timeStr = String.valueOf(time); | |||||
| boolean cashsetlock = redisLock.lock("merchantLockRejectCashSet_"+merchant.getId(), timeStr); | |||||
| if (cashsetlock) { | |||||
| try { | |||||
| merchant.setCashOutNumber(record.getTotalFee()); | |||||
| wxMerchantMapper.increaseCash(merchant); | |||||
| redisLock.unlock("merchantLockRejectCashSet_"+merchant.getId(), timeStr); | |||||
| }catch(Exception e) { | |||||
| redisLock.unlock("merchantLockRejectCashSet_"+merchant.getId(), timeStr); | |||||
| logger.error("update cashout fail.",e); | |||||
| }finally { | |||||
| redisLock.unlock("merchantLockRejectCashSet_"+merchant.getId(), timeStr); | |||||
| } | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public void cashOutToWx(EnumPayWay payWay,TenantEntity tenantEntity, Long cashOutId) { | |||||
| WxCashOut cashout = this.getById(cashOutId, tenantEntity.getTenantId()); | |||||
| if (null == cashout ) { | |||||
| return; | |||||
| } | |||||
| WxAppinfo appInfo = wxAppinfoService.getCAppInfo(tenantEntity, payWay); | |||||
| if (null == appInfo) { | |||||
| return; | |||||
| } | |||||
| WxPayAccount payAccount = wxPayAccountService.getByTenantId(tenantEntity.getTenantId()); | |||||
| if (null == payAccount) { | |||||
| return; | |||||
| } | |||||
| CashOutAdapterResult result = payServiceFactory.getCashOutAdapterService(payWay.getCode()).cashOut(appInfo, payAccount, cashout); | |||||
| cashout.setUpdateDate(new Date()); | |||||
| if (result.isSuccess()) { | |||||
| cashout.setStatus(EnumCashOutStatus.SUCCESS.getCode()); | |||||
| }else { | |||||
| cashout.setStatus(EnumCashOutStatus.FAIL.getCode()); | |||||
| cashout.setFailRemark(result.getMsg()); | |||||
| } | |||||
| wxCashOutMapper.updateById(cashout); | |||||
| } | |||||
| } | |||||
| @@ -29,6 +29,8 @@ import com.iformall.service.pay.PayServiceFactory; | |||||
| import com.iformall.utils.Constant; | import com.iformall.utils.Constant; | ||||
| import com.iformall.utils.DateUtils; | import com.iformall.utils.DateUtils; | ||||
| import com.iformall.utils.PayUtils; | import com.iformall.utils.PayUtils; | ||||
| import com.iformall.utils.RedisLock; | |||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| @@ -144,6 +146,9 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| @Autowired | @Autowired | ||||
| @Qualifier("couponDetailRedisTemplate") | @Qualifier("couponDetailRedisTemplate") | ||||
| RedisTemplate<String, WxCouponCVo> cdRedisTemplate; | RedisTemplate<String, WxCouponCVo> cdRedisTemplate; | ||||
| @Autowired | |||||
| RedisLock redisLock; | |||||
| private final SimpleDateFormat mydateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | private final SimpleDateFormat mydateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | ||||
| @@ -524,18 +529,42 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| try { | try { | ||||
| // 核销记账 | // 核销记账 | ||||
| if (couponOrder.getCouponPrice() > 0) { | if (couponOrder.getCouponPrice() > 0) { | ||||
| recordAfterVerified(couponOrder, bUser.getMerchantId()); | |||||
| WxMerchantSubsidy subsidy = recordAfterVerified(couponOrder, bUser.getMerchantId()); | |||||
| //是否开通了商户提现,开通了商户提现往商户账户里面加金额 | |||||
| WxMall mall = wxMallMapper.getByTenantId(couponOrder.getTenantId()); | |||||
| if (null != mall && mall.getCashOutSupport().intValue() == EnumCashOut.YES.getCode().intValue()) { | |||||
| WxMerchant merchant = wxMerchantMapper.selectById(bUser.getMerchantId()); | |||||
| if (null != merchant) { | |||||
| //此处需要加锁,防止并发设置 | |||||
| long time = System.currentTimeMillis() + RedisLock.TIMEOUT; | |||||
| String timeStr = String.valueOf(time); | |||||
| boolean cashsetlock = redisLock.lock("merchantLockCashSet_"+merchant.getId(), timeStr); | |||||
| if (cashsetlock) { | |||||
| try { | |||||
| merchant.setCashOutNumber(couponOrder.getCouponPrice()); | |||||
| wxMerchantMapper.increaseCash(merchant); | |||||
| logger.info("wxcoupon update cashout success.wxCouponOrderId:["+couponOrder.getId()+"] subsidyId:["+subsidy.getId()+"]."); | |||||
| redisLock.unlock("merchantLockCashSet_"+merchant.getId(), timeStr); | |||||
| }catch(Exception e) { | |||||
| redisLock.unlock("merchantLockCashSet_"+merchant.getId(), timeStr); | |||||
| logger.error("update cashout fail.wxCouponOrderId:["+couponOrder.getId()+"] subsidyId:["+subsidy.getId()+"].",e); | |||||
| }finally { | |||||
| redisLock.unlock("merchantLockCashSet_"+merchant.getId(), timeStr); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| logger.info("核销记账失败"); | |||||
| logger.error(e.getMessage()); | |||||
| logger.error("核销记账失败"+e.getMessage(),e); | |||||
| } | } | ||||
| } else { | } else { | ||||
| try { | try { | ||||
| // 核销分账 | // 核销分账 | ||||
| shareAfterVerify(couponOrder, bUser.getMerchantId(),couponOrder.getPayVendor()); | shareAfterVerify(couponOrder, bUser.getMerchantId(),couponOrder.getPayVendor()); | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| logger.error(e.getMessage()); | |||||
| logger.error("核销记账失败"+e.getMessage(),e); | |||||
| } | } | ||||
| } | } | ||||
| @@ -543,7 +572,7 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| // 核销补贴 | // 核销补贴 | ||||
| subsidyAfterVerify(couponOrder, bUser.getMerchantId()); | subsidyAfterVerify(couponOrder, bUser.getMerchantId()); | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| logger.error(e.getMessage()); | |||||
| logger.error("核销记账失败"+e.getMessage(),e); | |||||
| } | } | ||||
| boolean bSentCoupon = false; | boolean bSentCoupon = false; | ||||
| @@ -552,18 +581,18 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| try { | try { | ||||
| bSentCoupon = sendCouponAfterVerify(couponOrder, bUser); | bSentCoupon = sendCouponAfterVerify(couponOrder, bUser); | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| logger.error(e.getMessage()); | |||||
| logger.error("核销记账失败"+e.getMessage(),e); | |||||
| } | } | ||||
| // 核销发模板消息 | // 核销发模板消息 | ||||
| try { | try { | ||||
| sendVerifyMsg(couponOrder, bUser, bSentCoupon); | sendVerifyMsg(couponOrder, bUser, bSentCoupon); | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| logger.error("核销发送消息发生错误:" + e.getMessage()); | |||||
| logger.error("核销发送消息发生错误:" + e.getMessage(),e); | |||||
| } | } | ||||
| } | } | ||||
| public void recordAfterVerified(WxCouponOrder couponOrder, Long merchantId) { | |||||
| public WxMerchantSubsidy recordAfterVerified(WxCouponOrder couponOrder, Long merchantId) { | |||||
| WxCoupon wxCoupon = wxCouponMapper.selectById(couponOrder.getCouponId(),couponOrder.getTenantId()); | WxCoupon wxCoupon = wxCouponMapper.selectById(couponOrder.getCouponId(),couponOrder.getTenantId()); | ||||
| WxMerchantSubsidy merchantSubsidy = new WxMerchantSubsidy(); | WxMerchantSubsidy merchantSubsidy = new WxMerchantSubsidy(); | ||||
| if (couponOrder.getCouponType().equals(EnumCouponType.COUPON_PRESS.getCode()) | if (couponOrder.getCouponType().equals(EnumCouponType.COUPON_PRESS.getCode()) | ||||
| @@ -597,6 +626,7 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| merchantSubsidy.setUpdateDate(curDate); | merchantSubsidy.setUpdateDate(curDate); | ||||
| merchantSubsidy.setStatus(EnumMerchantSubsidyStatus.NOT_SUBSIDY.getCode()); | merchantSubsidy.setStatus(EnumMerchantSubsidyStatus.NOT_SUBSIDY.getCode()); | ||||
| wxMerchantSubsidyMapper.insert(merchantSubsidy); | wxMerchantSubsidyMapper.insert(merchantSubsidy); | ||||
| return merchantSubsidy; | |||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -99,6 +99,8 @@ public class WxFlowServiceImpl implements WxFlowService { | |||||
| @Autowired | @Autowired | ||||
| @Qualifier("couponChannelRedisTemplate") | @Qualifier("couponChannelRedisTemplate") | ||||
| RedisTemplate<String, PageInfo<WxCouponChannelVo>> cdRedisTemplate; | RedisTemplate<String, PageInfo<WxCouponChannelVo>> cdRedisTemplate; | ||||
| @Autowired | |||||
| private WxCashOutService wxCashOutService; | |||||
| @Override | @Override | ||||
| public void wxFlowConfigInit(String tenantId) { | public void wxFlowConfigInit(String tenantId) { | ||||
| @@ -434,6 +436,34 @@ public class WxFlowServiceImpl implements WxFlowService { | |||||
| wxBillSettleService.updateFreezeOrStatus(settle.getPayBillIds(),EnumFreezeType.DEF.getCode(),null); | wxBillSettleService.updateFreezeOrStatus(settle.getPayBillIds(),EnumFreezeType.DEF.getCode(),null); | ||||
| } | } | ||||
| wxBillSettleMapper.updateById(wxBillSettle); | wxBillSettleMapper.updateById(wxBillSettle); | ||||
| }else if (EnumFlowKey.CASH_OUT.getCode().equals(flowType)) { | |||||
| String tenantId = (String)getVariableByKey(variables,"cashTenantId"); | |||||
| WxCashOut cashout = wxCashOutService.getById(Long.parseLong(businessId), tenantId); | |||||
| //如果是提交审批 | |||||
| if (EnumRentContractAppStatus.APPLYING.getCode().intValue() == applyStatus.intValue()) { | |||||
| cashout.setStatus(EnumCashOutStatus.AUDIOING.getCode()); | |||||
| cashout.setUpdateDate(new Date()); | |||||
| wxCashOutService.updateStatus(cashout); | |||||
| // 审批完成 | |||||
| }else if (EnumRentContractAppStatus.FINISH.getCode().intValue() == applyStatus.intValue()) { | |||||
| cashout.setStatus(EnumCashOutStatus.WAITING.getCode()); | |||||
| cashout.setUpdateDate(new Date()); | |||||
| wxCashOutService.updateStatus(cashout); | |||||
| //发送零钱提现通知 | |||||
| String cashPayWay = (String)getVariableByKey(variables,"cashPayWay"); | |||||
| wxCashOutService.sendCashOutMsg(cashout, cashout.getId(),EnumPayWay.getEnum(Integer.parseInt(cashPayWay))); | |||||
| logger.info("cashout msg:"+cashout.getId()); | |||||
| //如果是审批撤回,或者驳回,改回草稿状态 | |||||
| }else if (EnumRentContractAppStatus.SETBACK.getCode().intValue() == applyStatus.intValue() | |||||
| || EnumRentContractAppStatus.REJECT.getCode().intValue() == applyStatus.intValue()) { | |||||
| cashout.setStatus(EnumCashOutStatus.REJECT.getCode()); | |||||
| String remark = (String)mapInfo.get("remark"); | |||||
| cashout.setAudioRemark(remark); | |||||
| cashout.setAudioDate(new Date()); | |||||
| cashout.setUpdateDate(new Date()); | |||||
| wxCashOutService.rejectCashOut(cashout); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,29 @@ | |||||
| package com.iformall.service.msg.impl; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import com.iformall.domain.po.msg.BaseMsg; | |||||
| import com.iformall.domain.po.msg.FmInsideCashOutMsg; | |||||
| import com.iformall.service.WxCashOutService; | |||||
| import com.iformall.service.msg.MsgSendService; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| @Service | |||||
| public class FmInsideCashOutMsgServiceImpl implements MsgSendService { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private WxCashOutService wxCashOutService; | |||||
| @Override | |||||
| public void send(BaseMsg baseMsg) throws Exception { | |||||
| FmInsideCashOutMsg msg = (FmInsideCashOutMsg)baseMsg; | |||||
| TenantEntity tenantEntity = new TenantEntity(); | |||||
| tenantEntity.setTenantId(msg.getTenantId()); | |||||
| tenantEntity.setParentTenantId(msg.getParentTenantId()); | |||||
| wxCashOutService.cashOutToWx(msg.getPayWay(),tenantEntity, msg.getCashOutId()); | |||||
| } | |||||
| } | |||||
| @@ -134,7 +134,7 @@ public class CYFParkService extends BaseParkService implements ParkAdapterServic | |||||
| Integer endTime = retObj.getInteger("endTime");//离场时间 | Integer endTime = retObj.getInteger("endTime");//离场时间 | ||||
| String msg = retObj.getString("warmPrompt"); | String msg = retObj.getString("warmPrompt"); | ||||
| String appId = ""; | String appId = ""; | ||||
| String payPath = ""; | |||||
| String payPath = "http://wechat.cheyifu2016.com/fm-pay/#/transit?encodeURIComponent('orderNo=123&couponFee=2&actualFee=20')"; | |||||
| return new ResultData(new ParkStopFee(retObj.getString("orderId"), cyf.utcToLocal(String.valueOf(createTime)), | return new ResultData(new ParkStopFee(retObj.getString("orderId"), cyf.utcToLocal(String.valueOf(createTime)), | ||||
| cyf.utcToLocal(String.valueOf(endTime)), String.valueOf(retObj.getDouble("fee")),appId,payPath,null,msg)); | cyf.utcToLocal(String.valueOf(endTime)), String.valueOf(retObj.getDouble("fee")),appId,payPath,null,msg)); | ||||
| }else { | }else { | ||||
| @@ -8,6 +8,8 @@ import org.springframework.stereotype.Service; | |||||
| import com.iformall.common.ErrorCode; | import com.iformall.common.ErrorCode; | ||||
| import com.iformall.enums.EnumPayWay; | import com.iformall.enums.EnumPayWay; | ||||
| import com.iformall.exception.MallinkException; | import com.iformall.exception.MallinkException; | ||||
| import com.iformall.service.pay.service.cashout.CashOutAdapterService; | |||||
| import com.iformall.service.pay.service.cashout.wx.WxCashOutAdapterService; | |||||
| import com.iformall.service.pay.service.pay.CDrivingPayService; | import com.iformall.service.pay.service.pay.CDrivingPayService; | ||||
| import com.iformall.service.pay.service.pay.CPassivePayService; | import com.iformall.service.pay.service.pay.CPassivePayService; | ||||
| import com.iformall.service.pay.service.pay.PayAdapterService; | import com.iformall.service.pay.service.pay.PayAdapterService; | ||||
| @@ -29,6 +31,7 @@ public class PayServiceFactory { | |||||
| private Map<Integer,PayAdapterService> serviceMap = null; | private Map<Integer,PayAdapterService> serviceMap = null; | ||||
| private Map<Integer,PayShareAdapterService> shareMap = null; | private Map<Integer,PayShareAdapterService> shareMap = null; | ||||
| private Map<Integer,RefundPayAdapterService> refundMap = null; | private Map<Integer,RefundPayAdapterService> refundMap = null; | ||||
| private Map<Integer,CashOutAdapterService> cashoutMap = null; | |||||
| @Autowired | @Autowired | ||||
| WxMiniAppPayAdapterService wxMiniAppPayService; | WxMiniAppPayAdapterService wxMiniAppPayService; | ||||
| @@ -45,6 +48,9 @@ public class PayServiceFactory { | |||||
| @Autowired | @Autowired | ||||
| WxRefundAdapterService wxRefundService; | WxRefundAdapterService wxRefundService; | ||||
| @Autowired | |||||
| WxCashOutAdapterService WxCashOutService; | |||||
| private Map<Integer,PayAdapterService> getServiceMap() { | private Map<Integer,PayAdapterService> getServiceMap() { | ||||
| @@ -83,7 +89,16 @@ public class PayServiceFactory { | |||||
| refundMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxRefundService); | refundMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxRefundService); | ||||
| } | } | ||||
| return refundMap; | return refundMap; | ||||
| } | |||||
| } | |||||
| private Map<Integer,CashOutAdapterService> getCashOutMap() { | |||||
| if (null == cashoutMap ) { | |||||
| cashoutMap = new ConcurrentHashMap<Integer, CashOutAdapterService>(); | |||||
| cashoutMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode(), WxCashOutService); | |||||
| cashoutMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), WxCashOutService); | |||||
| } | |||||
| return cashoutMap; | |||||
| } | |||||
| public PayAdapterService getPayAdapterService(Integer type) throws MallinkException{ | public PayAdapterService getPayAdapterService(Integer type) throws MallinkException{ | ||||
| PayAdapterService service = getServiceMap().get(type); | PayAdapterService service = getServiceMap().get(type); | ||||
| @@ -132,4 +147,12 @@ public class PayServiceFactory { | |||||
| } | } | ||||
| return refundService; | return refundService; | ||||
| } | } | ||||
| public CashOutAdapterService getCashOutAdapterService(Integer type)throws MallinkException { | |||||
| CashOutAdapterService cashOutService = getCashOutMap().get(type); | |||||
| if (null == cashOutService) { | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 零钱service未找到"); | |||||
| } | |||||
| return cashOutService; | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,37 @@ | |||||
| package com.iformall.service.pay.service.cashout; | |||||
| import java.util.Map; | |||||
| import com.alibaba.fastjson.JSONArray; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.domain.po.WxCashOut; | |||||
| import com.iformall.domain.po.WxPayAccount; | |||||
| import com.iformall.domain.po.WxProfitSharingOrder; | |||||
| import com.iformall.domain.po.WxProfitSharingReceiver; | |||||
| import com.iformall.enums.EnumPayWay; | |||||
| import com.iformall.enums.EnumProfitSharingOrderType; | |||||
| import com.iformall.enums.EnumProfitSharingReceiverType; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.service.pay.service.share.entity.ShareAccountResult; | |||||
| import com.iformall.service.pay.service.cashout.entity.CashOutAdapterResult; | |||||
| import com.iformall.service.pay.service.share.entity.PayShareQueryResult; | |||||
| import com.iformall.service.pay.service.share.entity.PayShareResult; | |||||
| import com.iformall.service.pay.service.share.entity.ShareNotifyAdapterResult; | |||||
| /** | |||||
| * 零钱接口 | |||||
| * @author alascor | |||||
| */ | |||||
| public interface CashOutAdapterService { | |||||
| /** | |||||
| * 付款到零钱 | |||||
| * @param appInfo | |||||
| * @param payAccount | |||||
| * @param record | |||||
| * @param transcationId | |||||
| * @param amount 分账金额 | |||||
| * @return | |||||
| */ | |||||
| public CashOutAdapterResult cashOut(WxAppinfo appInfo,WxPayAccount payAccount,WxCashOut cashOut); | |||||
| } | |||||
| @@ -0,0 +1,51 @@ | |||||
| package com.iformall.service.pay.service.cashout.entity; | |||||
| import java.io.Serializable; | |||||
| public class CashOutAdapterResult implements Serializable{ | |||||
| private static final long serialVersionUID = -6647306162758854293L; | |||||
| private boolean isSuccess; | |||||
| private Integer code; | |||||
| private String msg; | |||||
| private Object data; | |||||
| public CashOutAdapterResult() { | |||||
| } | |||||
| public CashOutAdapterResult(boolean isSuccess,Integer code,String msg,Object data) { | |||||
| this.isSuccess = isSuccess; | |||||
| this.code = code; | |||||
| this.msg = msg; | |||||
| this.data = data; | |||||
| } | |||||
| public boolean isSuccess() { | |||||
| return isSuccess; | |||||
| } | |||||
| public void setSuccess(boolean isSuccess) { | |||||
| this.isSuccess = isSuccess; | |||||
| } | |||||
| public String getMsg() { | |||||
| return msg; | |||||
| } | |||||
| public void setMsg(String msg) { | |||||
| this.msg = msg; | |||||
| } | |||||
| public Object getData() { | |||||
| return data; | |||||
| } | |||||
| public void setData(Object data) { | |||||
| this.data = data; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public void setCode(Integer code) { | |||||
| this.code = code; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,216 @@ | |||||
| package com.iformall.service.pay.service.cashout.wx; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import java.util.SortedMap; | |||||
| import java.util.TreeMap; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.Result; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.domain.po.WxCashOut; | |||||
| import com.iformall.domain.po.WxPayAccount; | |||||
| import com.iformall.domain.po.WxPayOrder; | |||||
| import com.iformall.domain.po.WxRefundOrder; | |||||
| import com.iformall.enums.EnumCashOutStatus; | |||||
| import com.iformall.enums.EnumPayMode; | |||||
| import com.iformall.enums.EnumPayType; | |||||
| import com.iformall.enums.EnumPayWay; | |||||
| import com.iformall.enums.EnumRefundStatus; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.mapper.WxAppinfoMapper; | |||||
| import com.iformall.mapper.WxPayAccountMapper; | |||||
| import com.iformall.mapper.WxPayOrderMapper; | |||||
| import com.iformall.mapper.WxRefundOrderMapper; | |||||
| import com.iformall.pay.WxCashOutP; | |||||
| import com.iformall.pay.WxPay; | |||||
| import com.iformall.pay.WxPayment; | |||||
| import com.iformall.pay.WxRefundOrderP; | |||||
| import com.iformall.pay.WxRefundOrderSP; | |||||
| import com.iformall.service.pay.service.cashout.CashOutAdapterService; | |||||
| import com.iformall.service.pay.service.cashout.entity.CashOutAdapterResult; | |||||
| import com.iformall.service.pay.service.refund.RefundPayAdapterService; | |||||
| import com.iformall.service.pay.service.refund.entity.RefundAdapterResult; | |||||
| import com.iformall.service.pay.service.refund.entity.RefundNotifyAdapterResult; | |||||
| import com.iformall.utils.BeanUtils; | |||||
| import com.iformall.utils.CipherUtil; | |||||
| import com.iformall.utils.Utility; | |||||
| import com.iformall.utils.XmlUtil; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| @Slf4j | |||||
| @Service | |||||
| public class WxCashOutAdapterService implements CashOutAdapterService{ | |||||
| JSONObject errorRefundReqMap = JSON.parseObject("{\n" + | |||||
| " \"NO_AUTH\": {\n" + | |||||
| " \"detail\": \"没有该接口权限\",\n" + | |||||
| " \"reason\": \"1. 用户账号被冻结,无法付款;2. 产品权限没有开通或者被风控冻结;3. 此IP地址不允许调用接口,如有需要请登录微信支付商户平台更改配置\",\n" + | |||||
| " \"resolution\": \"请根据具体的错误返回描述做对应处理,如返回描述不够明确,请参考此处的错误原因做排查。\"\n" + | |||||
| " },\n" + | |||||
| " \"AMOUNT_LIMIT\": {\n" + | |||||
| " \"detail\": \"金额超限\",\n" + | |||||
| " \"reason\": \"1. 被微信风控拦截,最低单笔付款限额调整为5元。2. 低于最低单笔付款限额或者高于最高单笔付款限额\",\n" + | |||||
| " \"resolution\": \"目前最低付款金额为1元,最高10万元,请确认是否付款金额超限。\"\n" + | |||||
| " },\n" + | |||||
| " \"PARAM_ERROR\": {\n" + | |||||
| " \"detail\": \"参数错误\",\n" + | |||||
| " \"reason\": \"1. 请求参数校验错误 2. 字符中包含非utf8字符 3. 商户号和appid没有绑定关系\\t\",\n" + | |||||
| " \"resolution\": \"请参照原因检查您的请求参数是否正确\"\n" + | |||||
| " },\n" + | |||||
| " \"OPENID_ERROR\": {\n" + | |||||
| " \"detail\": \"Openid错误\",\n" + | |||||
| " \"reason\": \"Openid格式错误或者不属于商家公众账号\",\n" + | |||||
| " \"resolution\": \"Openid与appid是有一一映射关系的,请确保正确使用。\"\n" + | |||||
| " },\n" + | |||||
| " \"SEND_FAILED\": {\n" + | |||||
| " \"detail\": \"付款错误\",\n" + | |||||
| " \"reason\": \"付款错误,请查单确认付款结果\",\n" + | |||||
| " \"resolution\": \"请查单确认付款结果,以查单结果为准。\"\n" + | |||||
| " },\n" + | |||||
| " \"NOTENOUGH\": {\n" + | |||||
| " \"detail\": \"余额不足\",\n" + | |||||
| " \"reason\": \"您的付款帐号余额不足或资金未到账\\t\",\n" + | |||||
| " \"resolution\": \"如果要继续付款必须使用原商户订单号重试\"\n" + | |||||
| " },\n" + | |||||
| " \"SYSTEMERROR\": {\n" + | |||||
| " \"detail\": \"系统繁忙,请稍后再试\",\n" + | |||||
| " \"reason\": \"微信内部接口调用发生错误\",\n" + | |||||
| " \"resolution\": \"请先调用查询接口,查看此次付款结果,如结果为不明确状态(如订单号不存在),请务必使用原商户订单号进行重试。\"\n" + | |||||
| " },\n" + | |||||
| " \"NAME_MISMATCH\": {\n" + | |||||
| " \"detail\": \"姓名校验出错\",\n" + | |||||
| " \"reason\": \"收款人身份校验不通过\",\n" + | |||||
| " \"resolution\": \"如果要继续付款必须使用原商户订单号重试\"\n" + | |||||
| " },\n" + | |||||
| " \"SIGN_ERROR\": {\n" + | |||||
| " \"detail\": \"签名错误\",\n" + | |||||
| " \"reason\": \"校验签名错误\",\n" + | |||||
| " \"resolution\": \"请检查您的请求参数和签名密钥KEY是否正确,如果要继续付款必须使用原商户订单号重试\"\n" + | |||||
| " },\n" + | |||||
| " \"XML_ERROR\": {\n" + | |||||
| " \"detail\": \"Post内容出错\",\n" + | |||||
| " \"reason\": \"Post请求数据不是合法的xml格式内容\",\n" + | |||||
| " \"resolution\": \"格式问题,请检查请求格式是否正确。\"\n" + | |||||
| " },\n" + | |||||
| " \"FATAL_ERROR\": {\n" + | |||||
| " \"detail\": \"两次请求参数不一致\",\n" + | |||||
| " \"reason\": \"两次请求商户单号一样,但是参数不一致\",\n" + | |||||
| " \"resolution\": \"重入必须保证所有参数值都不变\"\n" + | |||||
| " },\n" + | |||||
| " \"FREQ_LIMIT\": {\n" + | |||||
| " \"detail\": \"超过频率限制,请稍后再试\",\n" + | |||||
| " \"reason\": \"接口请求频率超时接口限制\",\n" + | |||||
| " \"resolution\": \"调用接口过于频繁,请稍后再试,如果要继续付款必须使用原商户订单号重试\"\n" + | |||||
| " },\n" + | |||||
| " \"MONEY_LIMIT\": {\n" + | |||||
| " \"detail\": \"已经达到今日付款总额上限/已达到付款给此用户额度上限\",\n" + | |||||
| " \"reason\": \"请关注接口的付款限额条件\",\n" + | |||||
| " \"resolution\": \"付款额度已经超限,请参考接口使用条件,如果要继续付款必须使用原商户订单号重试\"\n" + | |||||
| " },\n" + | |||||
| " \"CA_ERROR\": {\n" + | |||||
| " \"detail\": \"商户API证书校验出错\",\n" + | |||||
| " \"reason\": \"请求没带商户API证书或者带上了错误的商户API证书\",\n" + | |||||
| " \"resolution\": \"您使用的调用证书有误,请确认是否使用了正确的证书,可以前往商户平台重新下载,证书需与商户号对应,如果要继续付款必须使用原商户订单号重试\"\n" + | |||||
| " },\n" + | |||||
| " \"V2_ACCOUNT_SIMPLE_BAN\": {\n" + | |||||
| " \"detail\": \"无法给未实名用户付款\",\n" + | |||||
| " \"reason\": \"用户微信支付账户未实名,无法付款\",\n" + | |||||
| " \"resolution\": \"不支持给未实名用户付款,如果要继续付款必须使用原商户订单号重试\"\n" + | |||||
| " },\n" + | |||||
| " \"PARAM_IS_NOT_UTF8\": {\n" + | |||||
| " \"detail\": \"请求参数中包含非utf8编码字符\",\n" + | |||||
| " \"reason\": \"接口规范要求所有请求参数都必须为utf8编码\",\n" + | |||||
| " \"resolution\": \"微信接口使用编码是UTF-8,请确认,如果要继续付款必须使用原商户订单号重试\"\n" + | |||||
| " },\n" + | |||||
| " \"SENDNUM_LIMIT\": {\n" + | |||||
| " \"detail\": \"该用户今日付款次数超过限制,如有需要请进入【微信支付商户平台-产品中心-企业付款到零钱-产品设置】进行修改\",\n" + | |||||
| " \"reason\": \"该用户今日付款次数超过限制,如有需要请进入【微信支付商户平台-产品中心-企业付款到零钱-产品设置】进行修改\",\n" + | |||||
| " \"resolution\": \"向用户付款的次数超限了,请参考接口使用条件,如果要继续付款必须使用原商户订单号重试\"\n" + | |||||
| " },\n" + | |||||
| " \"RECV_ACCOUNT_NOT_ALLOWED\": {\n" + | |||||
| " \"detail\": \"收款账户不在收款账户列表\",\n" + | |||||
| " \"reason\": \"收款账户不在收款账户列表\",\n" + | |||||
| " \"resolution\": \"请登陆商户平台,查看产品中心企业付款到零钱的产品配置\"\n" + | |||||
| " },\n" + | |||||
| " \"PAY_CHANNEL_NOT_ALLOWED\": {\n" + | |||||
| " \"detail\": \"本商户号未配置API发起能力\",\n" + | |||||
| " \"reason\": \"本商户号未配置API发起能力\",\n" + | |||||
| " \"resolution\": \"请登陆商户平台,查看产品中心企业付款到零钱的产品配置\"\n" + | |||||
| " }\n" + | |||||
| "}"); | |||||
| @Override | |||||
| public CashOutAdapterResult cashOut(WxAppinfo appInfo, WxPayAccount payAccount, WxCashOut cashOut) { | |||||
| WxCashOutP wxCashOutP = generateWxCashOutP(payAccount, appInfo, cashOut); | |||||
| Map signMap = null; | |||||
| try { | |||||
| signMap = BeanUtils.toStringMap(wxCashOutP); | |||||
| } catch (Exception e) { | |||||
| log.error("零钱支付命令生辰: " + e.getMessage(),e); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "零钱支付签名异常"); | |||||
| } | |||||
| String signAgent = WxPayment.createSign(signMap, payAccount.getApiKey()); | |||||
| signMap.put("sign", signAgent); | |||||
| String response = null; | |||||
| try { | |||||
| response = WxPay.transfers(signMap, payAccount.getCertPath(), payAccount.getMchId()); | |||||
| } catch (Exception e) { | |||||
| log.error("零钱支付异常: " + e.getMessage(),e); | |||||
| throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "零钱支付异常"); | |||||
| } | |||||
| log.info("微信零钱支付:" + wxCashOutP.toString() + ", response: " + response.toString()); | |||||
| return getReusltFromp(response,cashOut); | |||||
| // if (payAccount.getType() == EnumPayMode.MCH.getCode()) { | |||||
| // 普通商户模式 | |||||
| // } | |||||
| } | |||||
| private WxCashOutP generateWxCashOutP(WxPayAccount payAccount,WxAppinfo appInfo,WxCashOut cashOut) { | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| WxCashOutP wxCashOutP = new WxCashOutP(); | |||||
| wxCashOutP.setMch_appid(appInfo.getAppId()); | |||||
| wxCashOutP.setMchid(payAccount.getSubMchId()); | |||||
| wxCashOutP.setNonce_str(noncestr); | |||||
| wxCashOutP.setAmount(cashOut.getTotalFee()); | |||||
| wxCashOutP.setCheck_name("NO_CHECK"); | |||||
| wxCashOutP.setDesc("客户结算"); | |||||
| wxCashOutP.setOpenid(cashOut.getReciveOpenId()); | |||||
| wxCashOutP.setPartner_trade_no(String.valueOf(cashOut.getId())); | |||||
| return wxCashOutP; | |||||
| } | |||||
| private CashOutAdapterResult getReusltFromp(String response,WxCashOut cashOut) throws MallinkException{ | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| String result_no = returnMap.get("result_code"); | |||||
| if ("SUCCESS".equals(result_no)) { | |||||
| log.info("微信零钱支付申请成功: " + returnMap.toString()); | |||||
| String wxPayNo = returnMap.get("payment_no"); | |||||
| String payTime = returnMap.get("payment_time"); | |||||
| cashOut.setWxPayNo(wxPayNo); | |||||
| cashOut.setWxPayTime(payTime); | |||||
| return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"微信零钱支付申请成功",returnMap); | |||||
| } else { | |||||
| log.error("微信零钱支付申请失败: " + response); | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorRefundReqMap.getJSONObject(result_no); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| } else { | |||||
| errMsg = returnMap.get("err_code_des"); | |||||
| } | |||||
| return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), errMsg, returnMap); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,79 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||||
| <mapper namespace="com.iformall.mapper.WxCashOutMapper"> | |||||
| <resultMap id="BaseResultMap" type="com.iformall.domain.po.WxCashOut"> | |||||
| <id column="id" jdbcType="BIGINT" property="id" /> | |||||
| <result column="tenant_id" jdbcType="VARCHAR" property="tenantId" /> | |||||
| <result column="parent_tenant_id" jdbcType="VARCHAR" property="parentTenantId" /> | |||||
| <result column="total_fee" jdbcType="INTEGER" property="totalFee" /> | |||||
| <result column="status" jdbcType="INTEGER" property="status" /> | |||||
| <result column="audio_remark" jdbcType="VARCHAR" property="audioRemark" /> | |||||
| <result column="create_date" jdbcType="TIMESTAMP" property="createDate" /> | |||||
| <result column="update_date" jdbcType="TIMESTAMP" property="updateDate" /> | |||||
| <result column="b_user_id" jdbcType="BIGINT" property="updateDate" /> | |||||
| <result column="wx_b_open_id" jdbcType="VARCHAR" property="updateDate" /> | |||||
| <result column="audio_date" jdbcType="TIMESTAMP" property="updateDate" /> | |||||
| <result column="merchant_id" jdbcType="VARCHAR" property="merchantId" /> | |||||
| <result column="merchant_name" jdbcType="VARCHAR" property="merchantName" /> | |||||
| <result column="recive_open_id" jdbcType="VARCHAR" property="reciveOpenId" /> | |||||
| <result column="recive_nick_name" jdbcType="VARCHAR" property="reciveNickName" /> | |||||
| <result column="wx_pay_no" jdbcType="VARCHAR" property="wxPayNo" /> | |||||
| <result column="wx_pay_time" jdbcType="VARCHAR" property="wxPayTime" /> | |||||
| <result column="fail_remark" jdbcType="VARCHAR" property="failRemark" /> | |||||
| </resultMap> | |||||
| <sql id="allColumns"> | |||||
| `id`,`tenant_id`,`parent_tenant_id`,`total_fee`,`status`,`audio_remark`,`create_date`,`update_date`,`b_user_id`,`wx_b_open_id`,`audio_date`, | |||||
| `merchant_id`,`merchant_name`,`recive_open_id`,`reciveNickName`,`wx_pay_no`,`wx_pay_time`,`fail_remark` | |||||
| </sql> | |||||
| <sql id="dynamicWhereConditions"> | |||||
| where 1 = 1 | |||||
| <if test=" null != id "> | |||||
| and `id` = #{id} | |||||
| </if> | |||||
| <if test=" null != tenantId and '' != tenantId"> | |||||
| and `tenant_id` = #{tenantId} | |||||
| </if> | |||||
| <if test=" null != parentTenantId and '' != parentTenantId"> | |||||
| and `parent_tenant_id` = #{parentTenantId} | |||||
| </if> | |||||
| <if test=" null != status "> | |||||
| and `status` = #{status} | |||||
| </if> | |||||
| <if test=" null != ids "> | |||||
| and id in | |||||
| <foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")"> | |||||
| #{idItem} | |||||
| </foreach> | |||||
| </if> | |||||
| <if test=" null != sortColumns"> order by ${sortColumns} </if> | |||||
| </sql> | |||||
| <select id="selectById" parameterType="java.util.HashMap" resultMap="BaseResultMap"> | |||||
| select <include refid="allColumns" /> from wx_cash_out where id = #{id} and tenant_id=#{tenantId} | |||||
| </select> | |||||
| <select id="findList" parameterType="com.iformall.domain.po.WxCashOut" resultMap="BaseResultMap"> | |||||
| select <include refid="allColumns" /> from wx_cash_out | |||||
| <include refid="dynamicWhereConditions" /> | |||||
| </select> | |||||
| <update id="updateStatus" parameterType="com.iformall.domain.po.WxCashOut"> | |||||
| update wx_cash_out | |||||
| set `status` = #{status}, | |||||
| `update_date` = #{updateDate} | |||||
| where id=#{id} | |||||
| <if test=" null != tenantId and '' != tenantId"> | |||||
| and `tenant_id` = #{tenantId} | |||||
| </if> | |||||
| <if test=" null != parentTenantId and '' != parentTenantId"> | |||||
| and `parent_tenant_id` = #{parentTenantId} | |||||
| </if> | |||||
| </update> | |||||
| </mapper> | |||||
| @@ -3,7 +3,7 @@ | |||||
| <mapper namespace="com.iformall.mapper.WxCouponOrderMapper"> | <mapper namespace="com.iformall.mapper.WxCouponOrderMapper"> | ||||
| <resultMap id="BaseResultMap" type="com.iformall.domain.po.WxCouponOrder"> | <resultMap id="BaseResultMap" type="com.iformall.domain.po.WxCouponOrder"> | ||||
| <id column="id" jdbcType="BIGINT" property="id" /> | <id column="id" jdbcType="BIGINT" property="id" /> | ||||
| <result column="tenant_id" jdbcType="BIGINT" property="tenantId" /> | |||||
| <result column="tenant_id" jdbcType="VARCHAR" property="tenantId" /> | |||||
| <result column="parent_tenant_id" jdbcType="VARCHAR" property="parentTenantId" /> | <result column="parent_tenant_id" jdbcType="VARCHAR" property="parentTenantId" /> | ||||
| <result column="coupon_id" jdbcType="BIGINT" property="couponId" /> | <result column="coupon_id" jdbcType="BIGINT" property="couponId" /> | ||||
| <result column="coupon_type" jdbcType="INTEGER" property="couponType" /> | <result column="coupon_type" jdbcType="INTEGER" property="couponType" /> | ||||
| @@ -36,7 +36,7 @@ | |||||
| <result column="latitude" jdbcType="DECIMAL" property="latitude"/> | <result column="latitude" jdbcType="DECIMAL" property="latitude"/> | ||||
| <result column="longitude" jdbcType="DECIMAL" property="longitude"/> | <result column="longitude" jdbcType="DECIMAL" property="longitude"/> | ||||
| <result column="live_support" jdbcType="INTEGER" property="liveSupport"/> | <result column="live_support" jdbcType="INTEGER" property="liveSupport"/> | ||||
| <result column="cash_out_support" jdbcType="INTEGER" property="cashOutSupport"/> | |||||
| </resultMap> | </resultMap> | ||||
| <sql id="allColumns"> | <sql id="allColumns"> | ||||
| @@ -45,7 +45,7 @@ | |||||
| `img_url`,`img_url_h`, `weap_note`, `img_qrcode_weapp`, `img_qrcode_wemp`, | `img_url`,`img_url_h`, `weap_note`, `img_qrcode_weapp`, `img_qrcode_wemp`, | ||||
| `weapp_share_title`,`weapp_share_cover_img`, `pos_qrcode_rule`, | `weapp_share_title`,`weapp_share_cover_img`, `pos_qrcode_rule`, | ||||
| `sale_type`, `valid_start`, `valid_end`,`business_hours`,`introduction`,`img`, | `sale_type`, `valid_start`, `valid_end`,`business_hours`,`introduction`,`img`, | ||||
| `group_support`,`latitude`,`longitude`,`live_support` | |||||
| `group_support`,`latitude`,`longitude`,`live_support`,`cash_out_support` | |||||
| </sql> | </sql> | ||||
| <sql id="dynamicWhereConditions"> | <sql id="dynamicWhereConditions"> | ||||
| @@ -35,19 +35,19 @@ | |||||
| <result column="rental_start_date" property="rentalStartDate"/> | <result column="rental_start_date" property="rentalStartDate"/> | ||||
| <result column="rental_end_date" property="rentalEndDate"/> | <result column="rental_end_date" property="rentalEndDate"/> | ||||
| <result column="credit_locked" property="creditLocked"/> | <result column="credit_locked" property="creditLocked"/> | ||||
| <result column="cash_out_number" jdbcType="INTEGER" property="cashOutNumber"/> | |||||
| </resultMap> | </resultMap> | ||||
| <sql id="allColumns"> | <sql id="allColumns"> | ||||
| `id`,`tenant_id`,`parent_tenant_id`,`img_url`,`name`,`link_phone`,`create_date`,`update_date`,`car_vendor_type`,`car_params`,`status`,`link_person`, | `id`,`tenant_id`,`parent_tenant_id`,`img_url`,`name`,`link_phone`,`create_date`,`update_date`,`car_vendor_type`,`car_params`,`status`,`link_person`, | ||||
| `business_id`,`sub_business_id`,`shop_type`,`brand`,`type`,`is_public`,email,`title`,`cover_picture`,`is_admin`,`bill_setting`,`qr_code`, | `business_id`,`sub_business_id`,`shop_type`,`brand`,`type`,`is_public`,email,`title`,`cover_picture`,`is_admin`,`bill_setting`,`qr_code`, | ||||
| `introduction`,`action_desc`,`is_del`,`talk_user_main`,`talk_user_aux`,link_line_phone,credit_locked | |||||
| `introduction`,`action_desc`,`is_del`,`talk_user_main`,`talk_user_aux`,link_line_phone,credit_locked,cash_out_number | |||||
| </sql> | </sql> | ||||
| <sql id="allColumnsVo"> | <sql id="allColumnsVo"> | ||||
| m.`id`,m.`tenant_id`,m.`parent_tenant_id`,m.`img_url`,m.`name`,m.`link_phone`,m.`create_date`,m.`update_date`,m.`car_vendor_type`,m.`car_params`,m.`status`,m.`link_person`, | m.`id`,m.`tenant_id`,m.`parent_tenant_id`,m.`img_url`,m.`name`,m.`link_phone`,m.`create_date`,m.`update_date`,m.`car_vendor_type`,m.`car_params`,m.`status`,m.`link_person`, | ||||
| m.`business_id`,m.`sub_business_id`,m.`shop_type`,m.`brand`,m.`type`,m.`is_public`,m.email,m.`title`,m.`cover_picture`,m.`is_admin`,m.`bill_setting`,m.`qr_code`, | m.`business_id`,m.`sub_business_id`,m.`shop_type`,m.`brand`,m.`type`,m.`is_public`,m.email,m.`title`,m.`cover_picture`,m.`is_admin`,m.`bill_setting`,m.`qr_code`, | ||||
| m.`introduction`,m.`action_desc`,m.`is_del`,m.`talk_user_main`,m.`talk_user_aux`,m.link_line_phone,r.rental_start_date,r.rental_end_date | |||||
| m.`introduction`,m.`action_desc`,m.`is_del`,m.`talk_user_main`,m.`talk_user_aux`,m.link_line_phone,r.rental_start_date,r.rental_end_date,cash_out_number | |||||
| </sql> | </sql> | ||||
| <sql id="dynamicWhereConditions"> | <sql id="dynamicWhereConditions"> | ||||
| @@ -610,5 +610,12 @@ | |||||
| order by create_date desc | order by create_date desc | ||||
| </select> | </select> | ||||
| <update id="updateCash" parameterType="com.iformall.domain.po.WxMerchant"> | |||||
| update wx_merchant set cash_out_number = cash_out_number+#{cashOutNumber} where id = #{id} | |||||
| </update> | |||||
| <update id="reduceCash" parameterType="com.iformall.domain.po.WxMerchant"> | |||||
| update wx_merchant set cash_out_number = cash_out_number-#{cashOutNumber} where id = #{id} | |||||
| </update> | |||||
| </mapper> | </mapper> | ||||