Authored by LUOXC

重构人工打款

Showing 18 changed files with 441 additions and 105 deletions
@@ -3,6 +3,9 @@ package com.yohoufo.dal.order.model; @@ -3,6 +3,9 @@ package com.yohoufo.dal.order.model;
3 import java.math.BigDecimal; 3 import java.math.BigDecimal;
4 4
5 public class OrdersPayTransfer { 5 public class OrdersPayTransfer {
  6 +
  7 + public static final Integer INTERFACE_TYPE_TRANSFER_WHEN_EXCEED_MILLION = 2;
  8 +
6 private Integer id; 9 private Integer id;
7 10
8 private Long buyerOrderCode; 11 private Long buyerOrderCode;
@@ -40,13 +40,16 @@ import com.yohoufo.order.service.handler.BuyerCancelCompensateComputeHandler; @@ -40,13 +40,16 @@ import com.yohoufo.order.service.handler.BuyerCancelCompensateComputeHandler;
40 import com.yohoufo.order.service.handler.BuyerOrderPayDiffTimeHandler; 40 import com.yohoufo.order.service.handler.BuyerOrderPayDiffTimeHandler;
41 import com.yohoufo.order.service.pay.AbstractPayService; 41 import com.yohoufo.order.service.pay.AbstractPayService;
42 import com.yohoufo.order.service.pay.alipay.AlipayOuyinService; 42 import com.yohoufo.order.service.pay.alipay.AlipayOuyinService;
  43 +import com.yohoufo.order.service.pay.alipay.AlipayServiceAbstract;
43 import com.yohoufo.order.service.pay.wallet.WalletPayService; 44 import com.yohoufo.order.service.pay.wallet.WalletPayService;
44 import com.yohoufo.order.service.pay.weixin.WeixinMiniappPayService; 45 import com.yohoufo.order.service.pay.weixin.WeixinMiniappPayService;
45 import com.yohoufo.order.service.pay.weixin.WeixinPayUFORealAppService; 46 import com.yohoufo.order.service.pay.weixin.WeixinPayUFORealAppService;
46 import com.yohoufo.order.service.support.codegenerator.OrderCodeGenerator; 47 import com.yohoufo.order.service.support.codegenerator.OrderCodeGenerator;
47 import com.yohoufo.order.service.support.codegenerator.bean.CodeMeta; 48 import com.yohoufo.order.service.support.codegenerator.bean.CodeMeta;
  49 +import com.yohoufo.order.service.transfer.TransferResult;
48 import com.yohoufo.order.utils.LoggerUtils; 50 import com.yohoufo.order.utils.LoggerUtils;
49 import com.yohoufo.order.utils.PaymentHelper; 51 import com.yohoufo.order.utils.PaymentHelper;
  52 +import com.yohoufo.order.utils.ServiceExceptions;
50 import lombok.val; 53 import lombok.val;
51 import org.apache.commons.collections.CollectionUtils; 54 import org.apache.commons.collections.CollectionUtils;
52 import org.apache.commons.lang3.StringUtils; 55 import org.apache.commons.lang3.StringUtils;
@@ -1001,6 +1004,8 @@ public class PaymentServiceImpl implements IPaymentService { @@ -1001,6 +1004,8 @@ public class PaymentServiceImpl implements IPaymentService {
1001 if (tradeBillsMapper.selectByDealRelateId(tradeBillsId) != null) { 1004 if (tradeBillsMapper.selectByDealRelateId(tradeBillsId) != null) {
1002 throw new ServiceException(400, "manualDeal:该流水已经处理过"); 1005 throw new ServiceException(400, "manualDeal:该流水已经处理过");
1003 } 1006 }
  1007 + long orderCode = tradeBills.getOrderCode();
  1008 + String logTag = "manualDeal orderCode is " + orderCode + "tradeBillId is " + tradeBillsId;
1004 AuthorizeResultRespVO account = getAlipayAccount(tradeBills.getUid()); 1009 AuthorizeResultRespVO account = getAlipayAccount(tradeBills.getUid());
1005 if (account == null || 1010 if (account == null ||
1006 (StringUtils.isBlank(account.getAlipayAccount()) && StringUtils.isBlank(account.getAlipayId()))) { 1011 (StringUtils.isBlank(account.getAlipayAccount()) && StringUtils.isBlank(account.getAlipayId()))) {
@@ -1015,7 +1020,7 @@ public class PaymentServiceImpl implements IPaymentService { @@ -1015,7 +1020,7 @@ public class PaymentServiceImpl implements IPaymentService {
1015 logger.info("manualDeal uid {} 支付宝账号uid无值使用账号{}", tradeBills.getUid(), account.getAlipayAccount()); 1020 logger.info("manualDeal uid {} 支付宝账号uid无值使用账号{}", tradeBills.getUid(), account.getAlipayAccount());
1016 alipayAccount = account.getAlipayAccount(); 1021 alipayAccount = account.getAlipayAccount();
1017 } 1022 }
1018 - long orderCode = tradeBills.getOrderCode(); 1023 +
1019 1024
1020 BigDecimal amount = null; 1025 BigDecimal amount = null;
1021 try { 1026 try {
@@ -1098,104 +1103,112 @@ public class PaymentServiceImpl implements IPaymentService { @@ -1098,104 +1103,112 @@ public class PaymentServiceImpl implements IPaymentService {
1098 throw new ServiceException(500, "退款失败id=" + tradeBillsId); 1103 throw new ServiceException(500, "退款失败id=" + tradeBillsId);
1099 } 1104 }
1100 } 1105 }
1101 - JSONObject jsonObject = null;  
1102 - Integer interfaceType = null;  
1103 - try {  
1104 - OrdersPayTransfer transfer = ordersPayTransferMapper.selectByBuyerOrderCode(orderCode);  
1105 - if (transfer == null) {  
1106 - throw new ServiceException(400, "转账记录不存在,流水id=" + tradeBillsId);  
1107 - }  
1108 - if (transfer == null || transfer.getStatus() == 1) {  
1109 - throw new ServiceException(400, "转账记录已成功转账,流水id=" + tradeBillsId);  
1110 - }  
1111 - interfaceType = transfer.getInterfaceType();  
1112 -  
1113 - logger.info("manualDeal orderCode={}, tradeBillId={}, 转账接口类型为 {}", orderCode, tradeBillsId, interfaceType);  
1114 - if (interfaceType != null && interfaceType == 2) {  
1115 - logger.info("manualDeal orderCode={}, tradeBillId={}, 转账接口类型为 超过100万的接口", orderCode, tradeBillsId);  
1116 - Map<String, String> mapResult = transferWhenExceedMillion(transfer.getId(), preSuccess, orderCode, account, amount, now);  
1117 - String resultStr = JSON.toJSONString(mapResult);  
1118 - jsonObject = JSON.parseObject(resultStr);  
1119 - if(!StringUtils.equals("T", mapResult.get("is_success"))) {  
1120 - throw new ServiceException(500, "转账失败:返回={}" + resultStr);  
1121 - } else {  
1122 - return;  
1123 - }  
1124 - }  
1125 -  
1126 - logger.info("manualDeal orderCode={}, tradeBillId={}, 转账接口类型为 小于100万的接口", orderCode, tradeBillsId);  
1127 - jsonObject = alipayService.transferMoney(Long.toString(orderCode), account.getAlipayId(), account.getAlipayAccount(), amount);  
1128 - if (jsonObject == null) {  
1129 - logger.warn("manualDeal 转账失败 , req is {}", req);  
1130 - throw new ServiceException(500, "转账失败:阿里接口返回null");  
1131 - }  
1132 - logger.info("manualDeal 转账阿里接口返回 {}", jsonObject.toJSONString());  
1133 - // 成功  
1134 - Integer code = null;  
1135 - String orderId = null;  
1136 - if (jsonObject.containsKey("code")  
1137 - && (code = jsonObject.getInteger("code")) == 10000  
1138 - && jsonObject.containsKey("order_id")  
1139 - && StringUtils.isNotBlank(orderId = jsonObject.getString("order_id"))) {  
1140 - logger.info("manualDeal转账成功,targeAccount is {}, amount is {}", alipayAccount, amount);  
1141 - // 加新流水  
1142 - tradeBills.setDealRelateId(tradeBills.getId());  
1143 - tradeBills.setId(null);  
1144 - tradeBills.setTradeStatus(100);  
1145 - tradeBills.setCreateTime(now);  
1146 - addTradeBills(tradeBills);  
1147 -  
1148 - OrdersPayTransfer transferSuccess = new OrdersPayTransfer();  
1149 - transferSuccess.setId(transfer.getId());  
1150 - transferSuccess.setAlipayTradeId(orderId);  
1151 - transferSuccess.setStatus(1);  
1152 - transferSuccess.setUpdateTime(now);  
1153 - ordersPayTransferMapper.updateByPrimaryKeySelective(transferSuccess);  
1154 - } else {  
1155 - logger.warn("manualDealErr 返回code或者order_id不是成功状态,code={}, orderId={}", code, orderId);  
1156 - // 上报  
1157 - throw new ServiceException(500, "转账失败:返回code="+code+",order_id="+orderId);  
1158 - }  
1159 - } catch (Exception e) {  
1160 - /*if (interfaceType != null && interfaceType == 2) {  
1161 - return;  
1162 - }*/  
1163 - logger.warn("manualDealErr 转账失败 , orderCode is {}, msg is {}", orderCode, e.getMessage());  
1164 - String alarmMsg = "订单号:" + orderCode + ",操作类型(转账),流水id=" + tradeBillsId + ",msg=" + e.getMessage();  
1165 - if (jsonObject != null) {  
1166 - alarmMsg += ",阿里返回DETAIL=" + jsonObject.toJSONString();  
1167 - }  
1168 - logger.info("manualDealErr 转账失败 , alarmMsg is {}", alarmMsg);  
1169 - alarm("人工处理转账失败", "ufo.order.manualDeal", alarmMsg);  
1170 - preSuccess.setDealStatus(0);  
1171 - tradeBillsMapper.updateToFailByPrimaryKey(preSuccess);  
1172 - if (e instanceof ServiceException) {  
1173 - throw new ServiceException(((ServiceException) e).getCode(), "转账失败id=" + tradeBillsId + "," + e.getMessage());  
1174 - } else {  
1175 - throw new ServiceException(500, "转账失败id=" + tradeBillsId);  
1176 - }  
1177 - } finally {  
1178 - logger.info("manualDeal转账结束, tradeBillsId is {}!", tradeBillsId);  
1179 - } 1106 + try {
  1107 + OrdersPayTransfer transfer = ordersPayTransferMapper.selectByBuyerOrderCode(orderCode);
  1108 + ServiceExceptions.throwServiceExceptionIf(() -> Objects.isNull(transfer),
  1109 + 400, "转账记录不存在[" + tradeBillsId + "]");
  1110 + ServiceExceptions.throwServiceExceptionIf(() -> transfer.getStatus() == 1,
  1111 + 400, "转账记录已成功转账,请不要重复操作。");
  1112 + Integer interfaceType = transfer.getInterfaceType();
  1113 + logger.info("{}, transfer channel router {}", logTag, interfaceType);
  1114 + if (OrdersPayTransfer.INTERFACE_TYPE_TRANSFER_WHEN_EXCEED_MILLION.equals(interfaceType)) {
  1115 + transferWithAlipayExceedMillionTransfer(tradeBills, orderCode, logTag, account, amount, transfer);
  1116 + } else {
  1117 + transferWithAlipayTransfer(logTag, tradeBills, orderCode, account, amount, now, transfer);
  1118 + }
  1119 + } catch (Exception e) {
  1120 + logger.warn("{}, transfer fail", logTag, e);
  1121 + alarm("人工处理转账失败",
  1122 + "ufo.order.manualDeal",
  1123 + "订单号:" + orderCode + ",操作类型(转账),流水id=" + tradeBillsId + ",msg=" + e.getMessage());
  1124 + logger.info("{}, rollback lock", logTag);
  1125 + preSuccess.setDealStatus(0);
  1126 + tradeBillsMapper.updateToFailByPrimaryKey(preSuccess);
  1127 + logger.info("{}, rollback lock success", logTag);
  1128 + if (e instanceof ServiceException) {
  1129 + throw e;
  1130 + } else {
  1131 + ServiceExceptions.throwServiceException(500, "转账失败id=" + tradeBillsId);
  1132 + }
  1133 + } finally {
  1134 + logger.info("{}, complete", logTag);
  1135 + }
1180 } 1136 }
1181 1137
  1138 + private void transferWithAlipayTransfer(String logTag, TradeBills tradeBills, long orderCode, AuthorizeResultRespVO account, BigDecimal amount, int now, OrdersPayTransfer transfer) {
  1139 + TransferResult transferResult = alipayService.newAlipayTransfer()
  1140 + .transferOrderCode(Long.toString(orderCode))
  1141 + .alipayUid(account.getAlipayId())
  1142 + .alipayAccount(account.getAlipayAccount())
  1143 + .transferAmount(amount)
  1144 + .transfer();
  1145 + if (transferResult.getCode() == 200) {
  1146 + logger.info("{}, transfer success and out trade no is {}", logTag, orderCode);
  1147 + // 加新流水
  1148 + tradeBills.setDealRelateId(tradeBills.getId());
  1149 + tradeBills.setId(null);
  1150 + tradeBills.setTradeStatus(100);
  1151 + tradeBills.setCreateTime(now);
  1152 + addTradeBills(tradeBills);
  1153 + // ?
  1154 + OrdersPayTransfer transferSuccess = new OrdersPayTransfer();
  1155 + transferSuccess.setId(transfer.getId());
  1156 + transferSuccess.setAlipayTradeId(transferResult.getTradeNo());
  1157 + transferSuccess.setStatus(1);
  1158 + transferSuccess.setUpdateTime(now);
  1159 + ordersPayTransferMapper.updateByPrimaryKeySelective(transferSuccess);
  1160 + }else {
  1161 + logger.warn("{}, transfer fail {}", logTag,transferResult);
  1162 + throw new ServiceException(transferResult.getCode(), transferResult.getMsg());
  1163 + }
  1164 +
  1165 + }
  1166 +
  1167 + private void transferWithAlipayExceedMillionTransfer(TradeBills tradeBills, long orderCode, String logTag, AuthorizeResultRespVO account, BigDecimal amount, OrdersPayTransfer transfer) {
  1168 + String businessId = transfer.getId() + "_" + tradeBills.getId();
  1169 + TransferResult transferResult = alipayService.newAlipayExceedMillionTransfer()
  1170 + .transferOrderCode( Long.toString(orderCode))
  1171 + .alipayUid(account.getAlipayId())
  1172 + .alipayAccount(account.getAlipayAccount())
  1173 + .transferAmount(amount)
  1174 + .businessId(businessId)
  1175 + .userName(account.getCertName())
  1176 + .transfer();
  1177 + // success to wait
  1178 + if (transferResult.getCode() == 200) {
  1179 + logger.info("{}, transfer success and out trade no is {}", logTag, businessId);
  1180 + // 更新流水状态为转账中
  1181 + tradeBills.setDealStatus(0);
  1182 + tradeBills.setTradeStatus(TradeBills.Status.TRANSFER_WAITING.getCode());
  1183 + tradeBillsMapper.updateSelectiveByPrimaryKeyNoCondition(tradeBills);
  1184 + logger.info("{}, the trade bill has updated to transfer waiting", logTag);
  1185 + } else {
  1186 + logger.warn("{}, transfer fail {}", logTag,transferResult);
  1187 + throw new ServiceException(transferResult.getCode(), transferResult.getMsg());
  1188 + }
  1189 + }
  1190 +
1182 1191
1183 - private Map<String, String> transferWhenExceedMillion(Integer transferId, TradeBills tradeBills, long orderCode, AuthorizeResultRespVO account,  
1184 - BigDecimal amount, int now) throws Exception {  
1185 - Map<String, String> mapResult = alipayService.transferMoneyWhenExceedMillion(Long.toString(orderCode),  
1186 - transferId + "_" + tradeBills.getId(), account.getAlipayId(), account.getAlipayAccount(),  
1187 - account.getCertName(), amount); 1192 + private Map<String, String> transferWhenExceedMillion(Integer transferId, TradeBills tradeBills, long orderCode, AuthorizeResultRespVO account,
  1193 + BigDecimal amount, int now) throws Exception {
  1194 + Map<String, String> mapResult = alipayService.transferMoneyWhenExceedMillion(
  1195 + Long.toString(orderCode),
  1196 + transferId + "_" + tradeBills.getId(),
  1197 + account.getAlipayId(),
  1198 + account.getAlipayAccount(),
  1199 + account.getCertName(),
  1200 + amount);
1188 logger.info("transferWhenExceedMillion 转账阿里接口(总金额超过100万)返回 {}, orderCode is {}, transferId is {}, tradeBillsId is {}, alibillId is {}", mapResult, orderCode, transferId, tradeBills.getId(), transferId + "_" + tradeBills.getId()); 1201 logger.info("transferWhenExceedMillion 转账阿里接口(总金额超过100万)返回 {}, orderCode is {}, transferId is {}, tradeBillsId is {}, alibillId is {}", mapResult, orderCode, transferId, tradeBills.getId(), transferId + "_" + tradeBills.getId());
1189 // success to wait 1202 // success to wait
1190 - if (StringUtils.equals("T", mapResult.get("is_success"))) {  
1191 - tradeBills.setDealStatus(0);  
1192 - tradeBills.setTradeStatus(TradeBills.Status.TRANSFER_WAITING.getCode());  
1193 - // wait  
1194 - tradeBillsMapper.updateSelectiveByPrimaryKeyNoCondition(tradeBills); 1203 + if (StringUtils.equals("T", mapResult.get("is_success"))) {
  1204 + tradeBills.setDealStatus(0);
  1205 + tradeBills.setTradeStatus(TradeBills.Status.TRANSFER_WAITING.getCode());
  1206 + // wait
  1207 + tradeBillsMapper.updateSelectiveByPrimaryKeyNoCondition(tradeBills);
1195 logger.info("transferWhenExceedMillion 转账阿里接口(总金额超过100万)更新之后的tradeBill: {}", tradeBillsMapper.selectByPrimaryKey(tradeBills.getId())); 1208 logger.info("transferWhenExceedMillion 转账阿里接口(总金额超过100万)更新之后的tradeBill: {}", tradeBillsMapper.selectByPrimaryKey(tradeBills.getId()));
1196 } 1209 }
1197 - return mapResult;  
1198 - } 1210 + return mapResult;
  1211 + }
1199 1212
1200 private boolean exceedMillion(JSONObject jsonObject) { 1213 private boolean exceedMillion(JSONObject jsonObject) {
1201 // {"msg":"Business Failed","code":"40004","sub_msg":"单日最多可转100万元","sub_code":"EXCEED_LIMIT_DM_MAX_AMOUNT"} 1214 // {"msg":"Business Failed","code":"40004","sub_msg":"单日最多可转100万元","sub_code":"EXCEED_LIMIT_DM_MAX_AMOUNT"}
@@ -14,11 +14,16 @@ import com.yohoufo.common.utils.RSAUtils; @@ -14,11 +14,16 @@ import com.yohoufo.common.utils.RSAUtils;
14 import com.yohoufo.common.utils.WXUtil; 14 import com.yohoufo.common.utils.WXUtil;
15 import com.yohoufo.dal.order.OrdersPayHbfqMapper; 15 import com.yohoufo.dal.order.OrdersPayHbfqMapper;
16 import com.yohoufo.dal.order.model.OrdersPayHbfq; 16 import com.yohoufo.dal.order.model.OrdersPayHbfq;
  17 +import com.yohoufo.dal.order.model.TradeBills;
17 import com.yohoufo.order.common.HbfqEnum; 18 import com.yohoufo.order.common.HbfqEnum;
18 import com.yohoufo.order.config.AlipayConfig; 19 import com.yohoufo.order.config.AlipayConfig;
19 import com.yohoufo.order.constants.RefundContant; 20 import com.yohoufo.order.constants.RefundContant;
20 import com.yohoufo.order.model.*; 21 import com.yohoufo.order.model.*;
21 import com.yohoufo.order.service.pay.AbstractPayService; 22 import com.yohoufo.order.service.pay.AbstractPayService;
  23 +import com.yohoufo.order.service.transfer.TransferChannel;
  24 +import com.yohoufo.order.service.transfer.TransferResult;
  25 +import lombok.Builder;
  26 +import lombok.Data;
22 import org.apache.commons.lang3.StringUtils; 27 import org.apache.commons.lang3.StringUtils;
23 import org.slf4j.Logger; 28 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory; 29 import org.slf4j.LoggerFactory;
@@ -49,7 +54,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService { @@ -49,7 +54,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService {
49 protected abstract String getAppId(); 54 protected abstract String getAppId();
50 55
51 protected abstract String getPartnerId(); 56 protected abstract String getPartnerId();
52 - 57 +
53 protected String getAccountUserName() { 58 protected String getAccountUserName() {
54 return ""; 59 return "";
55 } 60 }
@@ -57,7 +62,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService { @@ -57,7 +62,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService {
57 protected String getAccountEmail() { 62 protected String getAccountEmail() {
58 return ""; 63 return "";
59 } 64 }
60 - 65 +
61 protected String getRsaAliMApipubKey() { 66 protected String getRsaAliMApipubKey() {
62 return ""; 67 return "";
63 } 68 }
@@ -70,7 +75,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService { @@ -70,7 +75,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService {
70 75
71 @Value("${alipay.notifyurl}") 76 @Value("${alipay.notifyurl}")
72 private String notifyURL; 77 private String notifyURL;
73 - 78 +
74 @Value("${alipay.transfer.notifyurl}") 79 @Value("${alipay.transfer.notifyurl}")
75 private String transferNotifyURL; 80 private String transferNotifyURL;
76 81
@@ -168,7 +173,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService { @@ -168,7 +173,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService {
168 * @param alipayAccount 173 * @param alipayAccount
169 * @param transferAmount 174 * @param transferAmount
170 * @return 175 * @return
171 - * @throws Exception 176 + * @throws Exception
172 */ 177 */
173 public JSONObject transferMoney(String transferOrderCode, String alipayUid, String alipayAccount, BigDecimal transferAmount) throws Exception{ 178 public JSONObject transferMoney(String transferOrderCode, String alipayUid, String alipayAccount, BigDecimal transferAmount) throws Exception{
174 179
@@ -184,14 +189,192 @@ public abstract class AlipayServiceAbstract extends AbstractPayService { @@ -184,14 +189,192 @@ public abstract class AlipayServiceAbstract extends AbstractPayService {
184 } 189 }
185 return result; 190 return result;
186 } 191 }
187 - 192 +
  193 + public class AlipayTransfer implements TransferChannel {
  194 +
  195 + String transferOrderCode;
  196 + String alipayUid;
  197 + String alipayAccount;
  198 + BigDecimal transferAmount;
  199 +
  200 + private AlipayTransfer(){
  201 +
  202 + }
  203 +
  204 + public AlipayTransfer transferOrderCode(String transferOrderCode){
  205 + this.transferOrderCode = transferOrderCode;
  206 + return this;
  207 + }
  208 +
  209 + public AlipayTransfer alipayUid(String alipayUid){
  210 + this.alipayUid = alipayUid;
  211 + return this;
  212 + }
  213 +
  214 + public AlipayTransfer alipayAccount(String alipayAccount){
  215 + this.alipayAccount = alipayAccount;
  216 + return this;
  217 + }
  218 +
  219 + public AlipayTransfer transferAmount(BigDecimal transferAmount){
  220 + this.transferAmount = transferAmount;
  221 + return this;
  222 + }
  223 +
  224 + @Override
  225 + public TransferResult transfer() {
  226 + Map<String, String> queryParams = buildTransferParams(transferOrderCode, alipayUid, alipayAccount, transferAmount);
  227 + String respTxt;
  228 + try {
  229 + respTxt = sendOpenApiRequestWithException(transferOrderCode, queryParams);
  230 + } catch (Exception e) {
  231 + logger.warn("transfer fail transferOrderCode is {} alipayUid is {} alipayAccount is {} transferAmount is {}",
  232 + transferOrderCode, alipayUid, alipayAccount, transferAmount, e);
  233 + return TransferResult.builder()
  234 + .code(599)
  235 + .msg("未知异常:" + e.getMessage())
  236 + .build();
  237 + }
  238 + if (StringUtils.isNotBlank(respTxt)){
  239 + JSONObject json = JSON.parseObject(respTxt);
  240 + JSONObject result = json.getJSONObject("alipay_fund_trans_toaccount_transfer_response");
  241 + String code = result.getString("code");
  242 + String msg = result.getString("msg");
  243 + String out_biz_no = result.getString("out_biz_no");
  244 + String order_id = result.getString("order_id");
  245 + String pay_date = result.getString("pay_date");
  246 + if (StringUtils.equals("10000", code)) {
  247 + if(StringUtils.isNoneBlank(order_id)){
  248 + return TransferResult.builder()
  249 + .code(200)
  250 + .msg(msg)
  251 + .transferOrderCode(out_biz_no)
  252 + .tradeNo(order_id)
  253 + .payDate(pay_date)
  254 + .build();
  255 + }else {
  256 + return TransferResult.builder()
  257 + .code(599)
  258 + .msg("未知异常:code is 10000 but order_id is blank")
  259 + .build();
  260 + }
  261 +
  262 + } else {
  263 + return transformError(result.getString("sub_code"), result.getString("sub_msg"));
  264 + }
  265 + } else {
  266 + return TransferResult.builder()
  267 + .code(500)
  268 + .msg("Response data is blank")
  269 + .build();
  270 + }
  271 + }
  272 + }
  273 +
  274 + public AlipayTransfer newAlipayTransfer(){
  275 + return new AlipayTransfer();
  276 + }
  277 +
  278 + public AlipayExceedMillionTransferChannel newAlipayExceedMillionTransfer(){
  279 + return new AlipayExceedMillionTransferChannel();
  280 + }
  281 +
  282 + private TransferResult transformError(String sub_code, String sub_msg) {
  283 + /*
  284 + * 错误描述:系统繁忙
  285 + * 解决方案:可能发生了网络或者系统异常,导致无法判定准确的转账结果。
  286 + * 此时,商户不能直接当做转账成功或者失败处理,可以考虑采用相同的out_biz_no重发请求,
  287 + * 或者通过调用“(alipay.fund.trans.order.query)”来查询该笔转账订单的最终状态。
  288 + */
  289 + if (StringUtils.equals("SYSTEM_ERROR", sub_code)) {
  290 + return TransferResult.builder()
  291 + .code(501)
  292 + .msg("可能发生了网络或者系统异常,请重试。")
  293 + .build();
  294 + } else if (StringUtils.equals("EXCEED_LIMIT_PERSONAL_SM_AMOUNT", sub_code)) {
  295 + return TransferResult.builder()
  296 + .code(502)
  297 + .msg("转账给个人支付宝账户单笔最多5万元。")
  298 + .build();
  299 + } else if (StringUtils.equals("EXCEED_LIMIT_ENT_SM_AMOUNT", sub_code)) {
  300 + return TransferResult.builder()
  301 + .code(503)
  302 + .msg("转账给企业支付宝账户单笔最多10万元。")
  303 + .build();
  304 + } else if (StringUtils.equals("EXCEED_LIMIT_SM_MIN_AMOUNT", sub_code)) {
  305 + return TransferResult.builder()
  306 + .code(504)
  307 + .msg("单笔最低转账金额0.1元。")
  308 + .build();
  309 + } else if (StringUtils.equals("EXCEED_LIMIT_DM_MAX_AMOUNT", sub_code)) {
  310 + return TransferResult.builder()
  311 + .code(505)
  312 + .msg("单日最多可转100万元,请明天重试。")
  313 + .build();
  314 + } else if (StringUtils.equals("EXCEED_LIMIT_UNRN_DM_AMOUNT", sub_code)) {
  315 + return TransferResult.builder()
  316 + .code(506)
  317 + .msg("收款账户未实名,单日最多可收款1000元,请明天重试。")
  318 + .build();
  319 + } else if (StringUtils.equals("PAYER_PAYEE_CANNOT_SAME", sub_code)) {
  320 + return TransferResult.builder()
  321 + .code(507)
  322 + .msg("请检查一下收款方信息填写是否为付款方本人。")
  323 + .build();
  324 + }
  325 + /*
  326 + 错误描述:根据监管部门的要求,对方未完善身份信息或未开立余额账户,无法收款
  327 + 解决方案:可能发生了网络或者系统异常,导致无法判定准确的转账结果。
  328 + */
  329 + else if (StringUtils.equals("PERMIT_NON_BANK_LIMIT_PAYEE", sub_code)) {
  330 + return TransferResult.builder()
  331 + .code(508)
  332 + .msg("请联系收款方登录支付宝站内或手机客户端更新身份信息后重试。")
  333 + .build();
  334 + }
  335 + /*
  336 + 错误描述:根据监管部门的要求,需要付款用户更新身份信息才能继续操作
  337 + 解决方案:根据监管部门的要求,需要付款用户登录支付宝站内或手机客户端更新身份信息才能继续操作。
  338 + */
  339 + else if (StringUtils.equals("PAYER_CERT_EXPIRED", sub_code)) {
  340 + return TransferResult.builder()
  341 + .code(509)
  342 + .msg("请联系收款方登录支付宝站内或手机客户端完善身份信息后重试。")
  343 + .build();
  344 + }/*
  345 + 错误描述:根据监管部门的要求,需要付款用户更新身份信息才能继续操作
  346 + 解决方案:根据监管部门的要求,需要付款用户登录支付宝站内或手机客户端更新身份信息才能继续操作。
  347 + */ else if (StringUtils.equals("PAYER_CERT_EXPIRED", sub_code)) {
  348 + return TransferResult.builder()
  349 + .code(510)
  350 + .msg("请联系收款方登录支付宝站内或手机客户端补全身份信息后重试。")
  351 + .build();
  352 + } else if (StringUtils.equals("REMARK_HAS_SENSITIVE_WORD", sub_code)) {
  353 + return TransferResult.builder()
  354 + .code(511)
  355 + .msg("转账备注包含敏感词,请修改备注文案后重试。")
  356 + .build();
  357 + } else if (StringUtils.equals("PAYER_BALANCE_NOT_ENOUGH", sub_code)) {
  358 + return TransferResult.builder()
  359 + .code(512)
  360 + .msg("付款账户余额不足,请联系财务保持付款账户余额充足。")
  361 + .build();
  362 + } else {
  363 + return TransferResult.builder()
  364 + .code(599)
  365 + .msg("未知异常:sub_code is " + sub_code + ",sub_msg is " + sub_msg)
  366 + .build();
  367 + }
  368 + }
  369 +
  370 +
188 /** 371 /**
189 * 转账功能 372 * 转账功能
190 * @param transferOrderCode 373 * @param transferOrderCode
191 * @param alipayAccount 374 * @param alipayAccount
192 * @param transferAmount 375 * @param transferAmount
193 * @return 376 * @return
194 - * @throws Exception 377 + * @throws Exception
195 */ 378 */
196 public Map<String, String> transferMoneyWhenExceedMillion(String transferOrderCode, String businessId, String alipayUid, String alipayAccount, String userName, BigDecimal transferAmount) throws Exception{ 379 public Map<String, String> transferMoneyWhenExceedMillion(String transferOrderCode, String businessId, String alipayUid, String alipayAccount, String userName, BigDecimal transferAmount) throws Exception{
197 380
@@ -207,7 +390,90 @@ public abstract class AlipayServiceAbstract extends AbstractPayService { @@ -207,7 +390,90 @@ public abstract class AlipayServiceAbstract extends AbstractPayService {
207 } 390 }
208 return result; 391 return result;
209 } 392 }
210 - 393 +
  394 + public class AlipayExceedMillionTransferChannel implements TransferChannel{
  395 +
  396 + String transferOrderCode;
  397 + String alipayUid;
  398 + String alipayAccount;
  399 + BigDecimal transferAmount;
  400 + String businessId;
  401 + String userName;
  402 +
  403 + private AlipayExceedMillionTransferChannel(){
  404 +
  405 + }
  406 +
  407 + public AlipayExceedMillionTransferChannel transferOrderCode(String transferOrderCode){
  408 + this.transferOrderCode = transferOrderCode;
  409 + return this;
  410 + }
  411 +
  412 + public AlipayExceedMillionTransferChannel alipayUid(String alipayUid){
  413 + this.alipayUid = alipayUid;
  414 + return this;
  415 + }
  416 +
  417 + public AlipayExceedMillionTransferChannel alipayAccount(String alipayAccount){
  418 + this.alipayAccount = alipayAccount;
  419 + return this;
  420 + }
  421 +
  422 + public AlipayExceedMillionTransferChannel transferAmount(BigDecimal transferAmount){
  423 + this.transferAmount = transferAmount;
  424 + return this;
  425 + }
  426 +
  427 + public AlipayExceedMillionTransferChannel businessId(String businessId){
  428 + this.businessId = businessId;
  429 + return this;
  430 + }
  431 +
  432 + public AlipayExceedMillionTransferChannel userName(String userName){
  433 + this.userName = userName;
  434 + return this;
  435 + }
  436 +
  437 + @Override
  438 + public TransferResult transfer() {
  439 + Map<String, String> queryParams = buildTransferParamsWhenExceedMillion(transferOrderCode, businessId, alipayUid, alipayAccount, userName, transferAmount);
  440 + String respTxt;
  441 + try {
  442 + respTxt = sendMApiRequestWithException(transferOrderCode, queryParams);
  443 + } catch (Exception e) {
  444 + logger.warn("transfer fail transferOrderCode is {} alipayUid is {} alipayAccount is {} transferAmount is {}",
  445 + transferOrderCode, alipayUid, alipayAccount, transferAmount, e);
  446 + return TransferResult.builder()
  447 + .code(599)
  448 + .msg("未知异常:" + e.getMessage())
  449 + .build();
  450 + }
  451 +
  452 + Map<String, String> result;
  453 + if (StringUtils.isNotBlank(respTxt)){
  454 + result = WXUtil.parseWXPayXml(respTxt);
  455 + if (StringUtils.equals("T", result.get("is_success"))) {
  456 + return TransferResult.builder()
  457 + .code(200)
  458 + .msg("ok")
  459 + .build();
  460 + } else {
  461 + String error = result.get("error");
  462 + return TransferResult.builder()
  463 + .code(599)
  464 + .msg("未知异常:error is " + error)
  465 + .build();
  466 + }
  467 + } else {
  468 + return TransferResult.builder()
  469 + .code(500)
  470 + .msg("Response data is blank")
  471 + .build();
  472 + }
  473 + }
  474 +
  475 + }
  476 +
211 public PayQueryBo transferQuery(String buyerOrderCode) { 477 public PayQueryBo transferQuery(String buyerOrderCode) {
212 String tradeNo = buyerOrderCode; 478 String tradeNo = buyerOrderCode;
213 Map<String, String> queryParams = buildAlipayTransferQueryParams(tradeNo); 479 Map<String, String> queryParams = buildAlipayTransferQueryParams(tradeNo);
@@ -245,14 +511,14 @@ public abstract class AlipayServiceAbstract extends AbstractPayService { @@ -245,14 +511,14 @@ public abstract class AlipayServiceAbstract extends AbstractPayService {
245 logger.info("[{}] trade openapi resp: {}", orderCode, response); 511 logger.info("[{}] trade openapi resp: {}", orderCode, response);
246 return response; 512 return response;
247 } 513 }
248 - 514 +
249 private String sendOpenApiRequestWithException(String orderCode, Map<String, String> paramMap) throws Exception { 515 private String sendOpenApiRequestWithException(String orderCode, Map<String, String> paramMap) throws Exception {
250 logger.info("[{}] send openapi request: {}", orderCode, paramMap); 516 logger.info("[{}] send openapi request: {}", orderCode, paramMap);
251 String response = httpClient.postFormData(AlipayConfig.OPENAPI_URL, paramMap); 517 String response = httpClient.postFormData(AlipayConfig.OPENAPI_URL, paramMap);
252 logger.info("[{}] trade openapi resp: {}", orderCode, response); 518 logger.info("[{}] trade openapi resp: {}", orderCode, response);
253 return response; 519 return response;
254 } 520 }
255 - 521 +
256 private String sendMApiRequestWithException(String orderCode, Map<String, String> paramMap) throws Exception { 522 private String sendMApiRequestWithException(String orderCode, Map<String, String> paramMap) throws Exception {
257 logger.info("[{}] send openapi request: {}", orderCode, paramMap); 523 logger.info("[{}] send openapi request: {}", orderCode, paramMap);
258 StringBuilder paramStr = new StringBuilder(); 524 StringBuilder paramStr = new StringBuilder();
@@ -291,7 +557,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService { @@ -291,7 +557,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService {
291 params.put("sign", RSAUtils.sign(preSignStr, getRsaPrivateKey(), AlipayConfig.input_charset)); 557 params.put("sign", RSAUtils.sign(preSignStr, getRsaPrivateKey(), AlipayConfig.input_charset));
292 return params; 558 return params;
293 } 559 }
294 - 560 +
295 /** 561 /**
296 * openapi支付查询 562 * openapi支付查询
297 * @param orderData 563 * @param orderData
@@ -349,7 +615,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService { @@ -349,7 +615,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService {
349 params.put("sign", RSAUtils.sign(preSignStr, getRsaPrivateKey(), AlipayConfig.input_charset)); 615 params.put("sign", RSAUtils.sign(preSignStr, getRsaPrivateKey(), AlipayConfig.input_charset));
350 return params; 616 return params;
351 } 617 }
352 - 618 +
353 /** 619 /**
354 * 单笔转账 620 * 单笔转账
355 * @param orderData 621 * @param orderData
@@ -367,7 +633,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService { @@ -367,7 +633,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService {
367 params.put("batch_num", "1"); 633 params.put("batch_num", "1");
368 params.put("batch_fee", transferAmount.toString()); 634 params.put("batch_fee", transferAmount.toString());
369 params.put("email", getAccountEmail()); 635 params.put("email", getAccountEmail());
370 - 636 +
371 StringBuilder detailAppender = new StringBuilder(); 637 StringBuilder detailAppender = new StringBuilder();
372 detailAppender.append(businessId).append("^"); 638 detailAppender.append(businessId).append("^");
373 if (StringUtils.isNotBlank(alipayUid)) { 639 if (StringUtils.isNotBlank(alipayUid)) {
@@ -536,7 +802,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService { @@ -536,7 +802,7 @@ public abstract class AlipayServiceAbstract extends AbstractPayService {
536 } 802 }
537 return payData; 803 return payData;
538 } 804 }
539 - 805 +
540 public TransferData getTransferData(String data) { 806 public TransferData getTransferData(String data) {
541 if (StringUtils.isBlank(data)) { 807 if (StringUtils.isBlank(data)) {
542 return null; 808 return null;
  1 +package com.yohoufo.order.service.transfer;
  2 +
  3 +public interface TransferChannel {
  4 +
  5 + TransferResult transfer();
  6 +
  7 +}
  1 +package com.yohoufo.order.service.transfer;
  2 +
  3 +import com.yohoufo.order.service.pay.alipay.AlipayOuyinService;
  4 +import org.springframework.beans.factory.annotation.Autowired;
  5 +import org.springframework.stereotype.Service;
  6 +
  7 +public interface TransferChannelRouter {
  8 +
  9 +
  10 +}
  1 +package com.yohoufo.order.service.transfer;
  2 +
  3 +import lombok.Builder;
  4 +
  5 +@Builder
  6 +@lombok.Value
  7 +public class TransferResult {
  8 +
  9 + private int code;
  10 +
  11 + private String msg;
  12 +
  13 + private String transferOrderCode;
  14 +
  15 + private String tradeNo;
  16 +
  17 + private String payDate;
  18 +
  19 +}
@@ -3,18 +3,36 @@ package com.yohoufo.order.utils; @@ -3,18 +3,36 @@ package com.yohoufo.order.utils;
3 import com.yoho.error.ServiceError; 3 import com.yoho.error.ServiceError;
4 import com.yoho.error.exception.ServiceException; 4 import com.yoho.error.exception.ServiceException;
5 5
  6 +import java.util.function.Function;
  7 +import java.util.function.Predicate;
  8 +
6 /** 9 /**
7 * @author LUOXC 10 * @author LUOXC
8 * @date 2019/1/9 11:14 11 * @date 2019/1/9 11:14
9 */ 12 */
10 public class ServiceExceptions { 13 public class ServiceExceptions {
11 14
  15 + @FunctionalInterface
  16 + public interface Condition {
  17 + boolean test();
  18 + }
  19 +
12 public static void throwServiceException(String message) { 20 public static void throwServiceException(String message) {
13 ServiceException serviceException = new ServiceException(ServiceError.ORDER_SERVICE_ERROR); 21 ServiceException serviceException = new ServiceException(ServiceError.ORDER_SERVICE_ERROR);
14 serviceException.setParams(message); 22 serviceException.setParams(message);
15 throw serviceException; 23 throw serviceException;
16 } 24 }
17 25
  26 + public static void throwServiceExceptionIf(Condition condition, int code, String message) {
  27 + if (condition.test()) {
  28 + throw new ServiceException(code, message);
  29 + }
  30 + }
  31 +
  32 + public static void throwServiceException(int code, String message) {
  33 + throw new ServiceException(code, message);
  34 + }
  35 +
18 public static void throwServiceException(ServiceError serviceError) { 36 public static void throwServiceException(ServiceError serviceError) {
19 throw new ServiceException(serviceError); 37 throw new ServiceException(serviceError);
20 } 38 }