From 41552bbf6c74853bb7eeff19c7730eadf68611bb Mon Sep 17 00:00:00 2001 From: xhxu Date: Sat, 27 Nov 2021 11:39:52 +0800 Subject: [PATCH] update --- .../service/pay/PayServiceFactory.java | 5 + .../share/douyin/TtPayShareService.java | 356 ++++++++++++++++++ 2 files changed, 361 insertions(+) create mode 100644 mallinkService/src/main/java/com/iformall/service/pay/service/share/douyin/TtPayShareService.java diff --git a/mallinkService/src/main/java/com/iformall/service/pay/PayServiceFactory.java b/mallinkService/src/main/java/com/iformall/service/pay/PayServiceFactory.java index 11c8b5ea8..62a32c339 100644 --- a/mallinkService/src/main/java/com/iformall/service/pay/PayServiceFactory.java +++ b/mallinkService/src/main/java/com/iformall/service/pay/PayServiceFactory.java @@ -4,6 +4,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import com.iformall.service.pay.service.pay.douyin.miniApp.TtMiniAppPayAdapterService; +import com.iformall.service.pay.service.share.douyin.TtPayShareService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.iformall.common.ErrorCode; @@ -46,6 +47,9 @@ public class PayServiceFactory { @Autowired WxPayShareService wxShareService; + + @Autowired + TtPayShareService ttShareService; @Autowired @@ -72,6 +76,7 @@ public class PayServiceFactory { shareMap = new ConcurrentHashMap(); shareMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode(), wxShareService); shareMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxShareService); + shareMap.put(EnumPayWay.PAY_WAY_TT.getCode(), ttShareService); shareMap.put(EnumPayWay.PAY_WAY_POS_NEU.getCode(), wxShareService); shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_MERCHANT.getCode(), wxShareService); shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_VERRIFY.getCode(), wxShareService); diff --git a/mallinkService/src/main/java/com/iformall/service/pay/service/share/douyin/TtPayShareService.java b/mallinkService/src/main/java/com/iformall/service/pay/service/share/douyin/TtPayShareService.java new file mode 100644 index 000000000..6e4d6d718 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/pay/service/share/douyin/TtPayShareService.java @@ -0,0 +1,356 @@ +package com.iformall.service.pay.service.share.douyin; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.iformall.common.ErrorCode; +import com.iformall.domain.po.*; +import com.iformall.douyin.pay.DouYinPayHelper; +import com.iformall.douyin.pay.orderQuery.QuerySettleResult; +import com.iformall.douyin.pay.preOrder.Settle; +import com.iformall.douyin.pay.preOrder.SettleResult; +import com.iformall.enums.*; +import com.iformall.exception.MallinkException; +import com.iformall.mapper.WxAppinfoMapper; +import com.iformall.mapper.WxPayAccountMapper; +import com.iformall.mapper.WxPayOrderMapper; +import com.iformall.mapper.WxProfitSharingReceiverMapper; +import com.iformall.pay.*; +import com.iformall.service.pay.service.share.PayShareBaseAdapterService; +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.ShareAccountResult; +import com.iformall.service.pay.service.share.entity.ShareNotifyAdapterResult; +import com.iformall.utils.BeanUtils; +import com.iformall.utils.Utility; +import com.iformall.utils.XmlUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.text.ParseException; +import java.util.Date; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +@Slf4j +@Service +public class TtPayShareService extends PayShareBaseAdapterService{ + + final JSONObject statusMap = JSON.parseObject( + "{\"ACCEPTED\":3," + + "\"PROCESSING\": 4," + + "\"FINISHED\": 5," + + "\"CLOSED\": 6}"); + + + @Override + public Integer getSubsidyType() { + return EnumMerchantSubsidyType.MANUAL.getCode(); + } + + @Override + public Integer getProfitSharingType() { + return null; + } + + @Override + public PayShareResult noReciverShare(WxAppinfo appInfo,WxPayAccount payAccount,WxProfitSharingOrder record,String transcationId,Integer amount) { + Settle settle = new Settle(); + settle.setAppId(appInfo.getAppId()); + settle.setSalt(payAccount.getApiKey()); + settle.setOutSettleNo(record.getId().toString()); + settle.setOutOrderNo(transcationId); + settle.setSettleDesc("自主完结分账"); +// if(order.getSettlementAmount() != null && order.getSettlementAmount().intValue() > 0){ +// List list = new ArrayList<>(); +// Map settleParams = new HashMap<>(); +// settleParams.put("merchant_uid",merchantUid); +// settleParams.put("amount",order.getPayment()-order.getSettlementAmount()); +// list.add(settleParams); +// settle.setSettleParams(JSON.toJSONString(list)); +// } + SettleResult settleResult = DouYinPayHelper.settle(settle); + + if (settleResult.isSuccess()) { + return new PayShareResult(true, null,"success", settleResult,settleResult.getSettleNo()); + }else{ + return new PayShareResult(false, EnumProfitSharingOrderStatus.PROFIT_SHARING_REQ_FAILED.getCode(),settleResult.getMsg(), null,null); + } + } + + @Override + public PayShareResult haveReciversShare(WxAppinfo appInfo,WxPayAccount payAccount,WxProfitSharingOrder record,String transcationId,JSONArray receivers,EnumProfitSharingOrderType shareType ) throws MallinkException { + // TODO: 2021/11/27抖音分账暂时不支持 需要处理添加分账帐号和分账方式 + + throw new MallinkException(ErrorCode.PROFIT_SHARING_REQUEST_FAILED); + +// Settle settle = new Settle(); +// settle.setAppId(appInfo.getAppId()); +// settle.setSalt(payAccount.getApiKey()); +// settle.setOutSettleNo(record.getId().toString()); +// settle.setOutOrderNo(transcationId); +// settle.setSettleDesc("自主完结分账"); +//// if(order.getSettlementAmount() != null && order.getSettlementAmount().intValue() > 0){ +//// List list = new ArrayList<>(); +//// Map settleParams = new HashMap<>(); +//// settleParams.put("merchant_uid",merchantUid); +//// settleParams.put("amount",order.getPayment()-order.getSettlementAmount()); +//// list.add(settleParams); +//// settle.setSettleParams(JSON.toJSONString(list)); +//// } +// +// settle.setSettleParams(receivers.toJSONString()); +// SettleResult settleResult = DouYinPayHelper.settle(settle); +// +// if (settleResult.isSuccess()) { +// return new PayShareResult(true, null,"success", settleResult,settleResult.getSettleNo()); +// }else{ +// return new PayShareResult(false, EnumProfitSharingOrderStatus.PROFIT_SHARING_REQ_FAILED.getCode(),settleResult.getMsg(), null,null); +// } + + } + + @Override + public PayShareQueryResult shareQuery(WxAppinfo appInfo, WxPayAccount payAccount, WxProfitSharingOrder record) throws MallinkException { + + QuerySettleResult querySettleResult = DouYinPayHelper.settleQuery(appInfo.getAppId(), payAccount.getApiKey(), record.getId().toString(), null); + if(querySettleResult != null){ + if(querySettleResult.getSettleStatus().equals("SUCCESS")){ + return new PayShareQueryResult(true, 5, "success",querySettleResult, null); + }else if(querySettleResult.getSettleStatus().equals("FAIL")){ + return new PayShareQueryResult(true, 6, "fail",querySettleResult, null); + } + } + throw new MallinkException(ErrorCode.PROFIT_SHARING_QUERY_REQUEST_FAILED.getCode(), querySettleResult.getMsg()); + } + + + @Autowired + WxAppinfoMapper wxAppinfoMapper; + @Autowired + WxPayAccountMapper wxPayAccountMapper; + @Autowired + WxPayOrderMapper wxPayOrderMapper; + + private ShareNotifyAdapterResult getErrorResult(String msg) { + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "FAIL"); + resultMap.put("return_msg", msg); + return new ShareNotifyAdapterResult(false,ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR.getCode(),msg,XmlUtil.getRequestXml(resultMap)); + } + + private ShareNotifyAdapterResult getSuccessResult(WxPayOrder payOrder, String transcationId){ + SortedMap resultMap = new TreeMap(); + resultMap.put("return_code", "SUCCESS"); + resultMap.put("return_msg", "OK"); + return new ShareNotifyAdapterResult(transcationId, payOrder, XmlUtil.getRequestXml(resultMap)); + } + + @Override + public ShareNotifyAdapterResult notify(Map paramMap,EnumPayWay payWay) { + // how to get wechatAppId, wechatMchId, partnerKey + String appId = paramMap.get("appid"); + String subAppId = paramMap.get("sub_appid"); + String mchId = paramMap.get("mch_id"); + String subMchId = paramMap.get("sub_mch_id"); + WxAppinfo appinfo = null; + boolean isNormal = true; + if (StringUtils.isBlank(subAppId) && StringUtils.isBlank(subMchId)) { + // 普通商户号 + appinfo = wxAppinfoMapper.findByAppId(appId); + if (appinfo == null) { + log.error("appid not found: " + appId); + throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); + } + isNormal = true; + } else { + // 服务号 现在用hmac-sha256 + appinfo = wxAppinfoMapper.findByAppId(subAppId); + if (appinfo == null) { + log.error("subappid not found: " + subAppId); + throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); + } + isNormal = false; + } + + WxPayAccount payAccount = wxPayAccountMapper.selectById(appinfo.getPayId()); + if (payAccount == null) { + throw new MallinkException(ErrorCode.MCH_INFO_NOT_FOUND); + } + String partnerKey = payAccount.getApiKey(); + try { + if (payWay == EnumPayWay.PAY_WAY_WECHAT) { + boolean signVerified = false; + if (isNormal) { + // 普通商户号支付 + signVerified = WxPayment.verifyNotify(paramMap, partnerKey); + if (!signVerified) { + log.warn("notify order, wxpay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR); + } + } else { + // 服务号 现在用hmac-sha256 + signVerified = WxPayment.verifyNotifyHMAC(paramMap, partnerKey); + if (!signVerified) { + log.warn("notify order, wxpay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR); + } + } + + if (!"SUCCESS".equals(paramMap.get("return_code"))) { + log.warn("notify order, wxpay status not success, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + return getErrorResult("订单状态码非SUCCESS"); + } + + String payOrderNo = paramMap.get("out_trade_no"); + String timEndStr = paramMap.get("time_end"); + Long payOrderId = Long.valueOf(payOrderNo); + WxPayOrder payOrder = wxPayOrderMapper.selectById(payOrderId,payAccount.getTenantId()); + if (payOrder == null) { + log.warn("notify order, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + return getErrorResult("订单不存在"); + } + // 验证支付金额 + if (!paramMap.get("total_fee").equals(payOrder.getPayAmount().toString())) { + log.warn("notify order, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + return getErrorResult("订单总金额不一致"); + } + + Date timeEnd = null; + + try { + timeEnd = Utility.getDateFromString(timEndStr); + } catch (ParseException e) { + log.error("解析timeEnd失败"); + timeEnd = new Date(); + } + payOrder.setPayTimeEnd(timeEnd); + + log.info("notify order, wxpay checksign success, paramMap:{}, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); + return getSuccessResult(payOrder, paramMap.get("transaction_id")); + } + } catch (RuntimeException e) { + log.warn("notify order, checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage()); + throw new MallinkException(ErrorCode.PAY_ORDER_ERROR); + } + + return getErrorResult("FAILED"); + } + + @Override + public ShareAccountResult createShareAccount(WxAppinfo appInfo,WxPayAccount payAccount,WxProfitSharingReceiver receiver) { + WxProfitSharingReceiverP wxProfitSharingReceiverP = new WxProfitSharingReceiverP(); + if (StringUtils.isNotBlank(appInfo.getParentAppId())) { + wxProfitSharingReceiverP.setAppid(appInfo.getParentAppId()); + wxProfitSharingReceiverP.setMch_id(payAccount.getMchId()); + wxProfitSharingReceiverP.setSub_appid(appInfo.getAppId()); + wxProfitSharingReceiverP.setSub_mch_id(payAccount.getSubMchId()); + } else { + wxProfitSharingReceiverP.setAppid(appInfo.getAppId()); + wxProfitSharingReceiverP.setMch_id(payAccount.getMchId()); + } + wxProfitSharingReceiverP.setNonce_str(Utility.generate32UUID()); + wxProfitSharingReceiverP.setSign_type("HMAC-SHA256"); + + + JSONObject receiverJSON = new JSONObject(); + receiverJSON.put("type", EnumProfitSharingReceiverType.getEnum(receiver.getReceiverType()).getMessage()); + receiverJSON.put("account", receiver.getReceiverAccount()); + receiverJSON.put("name", receiver.getTrueName()); + + wxProfitSharingReceiverP.setReceiver(receiverJSON.toJSONString()); + String response; + try { + wxProfitSharingReceiverP.setSign(WxPayment.createSignHMAC(BeanUtils.toStringMap(wxProfitSharingReceiverP), payAccount.getApiKey())); + response = WxProfitSharing.addReceiver(BeanUtils.toStringMap(wxProfitSharingReceiverP)); + log.info(response); + } catch (Exception e) { + log.error(ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getMessage() + e.getMessage()); + return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getCode(), e.getMessage(), null); + } + Map returnMap = WxPayment.xmlToMap(response); + String return_code = returnMap.get("return_code"); + if (!"SUCCESS".equals(return_code)) { + log.error(ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getMessage() + returnMap.get("return_msg")+":"+JSON.toJSONString(returnMap)); + return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getCode(), returnMap.get("return_msg"), null); + } + + String result_code = returnMap.get("result_code"); + if (!"SUCCESS".equals(result_code)) { + log.error(ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getMessage() + returnMap.get("err_code_des")+":"+JSON.toJSONString(returnMap)); + return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getCode(), returnMap.get("err_code_des"), null); + } + + if (!WxPayment.verifyNotifyHMAC(returnMap, payAccount.getApiKey())) { + log.error(ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getMessage() + "verifyNotifyHMAC"+":"+JSON.toJSONString(returnMap)); + return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getCode(), ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getMessage(), null); + } + + return new ShareAccountResult(true, null, "success", returnMap); + } + + @Autowired + WxProfitSharingReceiverMapper wxProfitSharingReceiverMapper; + + @Override + public ShareAccountResult deleteShareAccount(WxAppinfo appInfo, WxPayAccount payAccount, + WxProfitSharingReceiver receiver) { + //删除分账账户从微信服务器 + WxProfitSharingReceiverP wxProfitSharingReceiverP = new WxProfitSharingReceiverP(); + if (StringUtils.isNotBlank(appInfo.getParentAppId())) { + wxProfitSharingReceiverP.setAppid(appInfo.getParentAppId()); + wxProfitSharingReceiverP.setMch_id(payAccount.getMchId()); + wxProfitSharingReceiverP.setSub_appid(appInfo.getAppId()); + wxProfitSharingReceiverP.setSub_mch_id(payAccount.getSubMchId()); + } else { + wxProfitSharingReceiverP.setAppid(appInfo.getAppId()); + wxProfitSharingReceiverP.setMch_id(payAccount.getMchId()); + } + wxProfitSharingReceiverP.setNonce_str(Utility.generate32UUID()); + wxProfitSharingReceiverP.setSign_type("HMAC-SHA256"); + + JSONObject receiverJSON = new JSONObject(); + receiverJSON.put("type", EnumProfitSharingReceiverType.getEnum(receiver.getReceiverType()).getMessage()); + receiverJSON.put("account", receiver.getReceiverAccount()); + + wxProfitSharingReceiverP.setReceiver(receiverJSON.toJSONString()); + String response; + try { + wxProfitSharingReceiverP.setSign(WxPayment.createSignHMAC(BeanUtils.toStringMap(wxProfitSharingReceiverP), payAccount.getApiKey())); + response = WxProfitSharing.delReceiver(BeanUtils.toStringMap(wxProfitSharingReceiverP)); + } catch (Exception e) { + log.error(ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getMessage() + e.getMessage()); + return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getCode(), e.getMessage(), null); + } + Map returnMap = WxPayment.xmlToMap(response); + String return_code = returnMap.get("return_code"); + if (!"SUCCESS".equals(return_code)) { + log.error(ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getMessage() + returnMap.get("return_msg")+":"+JSON.toJSONString(returnMap)); + return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getCode(), returnMap.get("return_msg"), null); + } + + String result_code = returnMap.get("result_code"); + if (!"SUCCESS".equals(result_code)) { + + if (returnMap.get("err_code").contains("USER_NOT_EXIST")) { + receiver.setStatus(EnumProfitSharingReceiverStatus.PROFIT_SHARING_RECEIVER_STATUS_INVALID.getCode()); + receiver.setUpdateTime(new Date()); + wxProfitSharingReceiverMapper.updateById(receiver); + } + log.error(ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getMessage() + returnMap.get("err_code_des")+":"+JSON.toJSONString(returnMap)); + return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getCode(), returnMap.get("err_code_des"), null); + } + + if (!WxPayment.verifyNotifyHMAC(returnMap, payAccount.getApiKey())) { + log.error(ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getMessage()+":"+JSON.toJSONString(returnMap)); + return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getCode(), "verifyNotifyHMAC", null); + } + + return new ShareAccountResult(true, null, "success", returnMap); + } + + +}