|
|
@@ -0,0 +1,461 @@
|
|
|
+package com.sckw.freight.service;
|
|
|
+
|
|
|
+import com.alibaba.fastjson2.JSONArray;
|
|
|
+import com.alibaba.fastjson2.JSONObject;
|
|
|
+import com.alibaba.fastjson2.TypeReference;
|
|
|
+
|
|
|
+import com.sckw.freight.exception.BusinessException;
|
|
|
+import com.sckw.freight.model.dto.*;
|
|
|
+import com.sckw.freight.model.enums.ChannelEnum;
|
|
|
+import com.sckw.freight.model.enums.PayCenterEnum;
|
|
|
+import com.sckw.freight.util.OkHttpUtils;
|
|
|
+import com.sckw.freight.util.R;
|
|
|
+import jakarta.validation.constraints.NotBlank;
|
|
|
+import jakarta.validation.constraints.NotNull;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 转发中台接口
|
|
|
+ *
|
|
|
+ * @author xucaiqin
|
|
|
+ * @date 2023-07-21 17:45:51
|
|
|
+ */
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class PayCenterService {
|
|
|
+ @Value("${payCenter.address}")
|
|
|
+ private String payCenterAddr;
|
|
|
+
|
|
|
+ private <T> R<List<T>> parseArray(String in, Class<T> t) {
|
|
|
+ R<String> res = JSONObject.parseObject(in, new TypeReference<R<String>>() {
|
|
|
+ });
|
|
|
+ String data = res.getData();
|
|
|
+ List<T> ts = JSONArray.parseArray(data, t);
|
|
|
+ R<List<T>> ok = R.ok(ts);
|
|
|
+ ok.setStatus(res.getStatus());
|
|
|
+ ok.setMsg(res.getMsg());
|
|
|
+ ok.setCode(res.getCode());
|
|
|
+ return ok;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getHttp(PayCenterEnum payCenterEnum, Map<String, Object> para) {
|
|
|
+ log.info("{}入参->{}", payCenterEnum.getDesc(), JSONObject.toJSONString(para));
|
|
|
+ OkHttpUtils okHttpUtils = OkHttpUtils.builder().url(payCenterAddr + payCenterEnum.getAddr());
|
|
|
+ if (!CollectionUtils.isEmpty(para)) {
|
|
|
+ for (Map.Entry<String, Object> p : para.entrySet()) {
|
|
|
+ //跳过非空参数
|
|
|
+ Object v = p.getValue();
|
|
|
+ String k = p.getKey();
|
|
|
+ if (Objects.isNull(v)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (v instanceof ChannelEnum channelEnum) {
|
|
|
+ okHttpUtils.addPara(k, channelEnum.getChannel());
|
|
|
+ } else if (v instanceof Integer i) {
|
|
|
+ okHttpUtils.addPara(k, String.valueOf(i));
|
|
|
+ } else if (v instanceof Long i) {
|
|
|
+ okHttpUtils.addPara(k, String.valueOf(i));
|
|
|
+ } else if (v instanceof String i) {
|
|
|
+ okHttpUtils.addPara(k, i);
|
|
|
+ } else if ((v.getClass().isArray()) && v instanceof String[] l) {
|
|
|
+ for (int i = 0; i < l.length; i++) {
|
|
|
+ okHttpUtils.addPara(k + "[" + i + "]", l[i]);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ okHttpUtils.addPara(k, v.toString());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String sync;
|
|
|
+ try {
|
|
|
+ sync = okHttpUtils.get().sync();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("中台服务异常", e.getCause());
|
|
|
+ throw new RuntimeException("支付服务异常!");
|
|
|
+ }
|
|
|
+ log.info("{}返回值->{}", payCenterEnum.getDesc(), sync);
|
|
|
+ return changeRes(sync);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String postHttp(PayCenterEnum payCenterEnum, Map<String, Object> para) {
|
|
|
+ log.info("{}入参->{}", payCenterEnum.getDesc(), JSONObject.toJSONString(para));
|
|
|
+ OkHttpUtils okHttpUtils = OkHttpUtils.builder().url(payCenterAddr + payCenterEnum.getAddr());
|
|
|
+ if (!CollectionUtils.isEmpty(para)) {
|
|
|
+ for (Map.Entry<String, Object> p : para.entrySet()) {
|
|
|
+ //跳过非空参数
|
|
|
+ Object v = p.getValue();
|
|
|
+ String k = p.getKey();
|
|
|
+ if (Objects.isNull(v)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (v instanceof ChannelEnum channelEnum) {
|
|
|
+ okHttpUtils.addBodyPara(k, channelEnum.getChannel());
|
|
|
+ } else if (v instanceof Integer i) {
|
|
|
+ okHttpUtils.addBodyPara(k, String.valueOf(i));
|
|
|
+ } else if (v instanceof Long i) {
|
|
|
+ okHttpUtils.addBodyPara(k, String.valueOf(i));
|
|
|
+ } else if (v instanceof String i) {
|
|
|
+ okHttpUtils.addBodyPara(k, i);
|
|
|
+ } else if ((v.getClass().isArray()) && v instanceof String[] l) {
|
|
|
+ for (int i = 0; i < l.length; i++) {
|
|
|
+ okHttpUtils.addPara(k + "[" + i + "]", l[i]);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ okHttpUtils.addBodyPara(k, JSONObject.toJSONString(v));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String sync;
|
|
|
+ try {
|
|
|
+ sync = okHttpUtils.post(true).sync();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("中台服务异常", e.getCause());
|
|
|
+ throw new RuntimeException("支付服务异常!");
|
|
|
+ }
|
|
|
+ log.info("{}返回值->{}", payCenterEnum.getDesc(), sync);
|
|
|
+ return changeRes(sync);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String jsonHttp(PayCenterEnum payCenterEnum, Object object) {
|
|
|
+ String para = object instanceof JSONObject jsonObject ? jsonObject.toJSONString() : JSONObject.toJSONString(object);
|
|
|
+ log.info("{}入参->{}", payCenterEnum.getDesc(), para);
|
|
|
+ OkHttpUtils okHttpUtils = OkHttpUtils.builder().url(payCenterAddr + payCenterEnum.getAddr());
|
|
|
+ okHttpUtils.addBodyJsonStr(para);
|
|
|
+ String sync;
|
|
|
+ try {
|
|
|
+ sync = okHttpUtils.post(true).sync();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("中台服务异常", e.getCause());
|
|
|
+ throw new RuntimeException("支付服务异常!");
|
|
|
+ }
|
|
|
+ log.info("{}返回值->{}", payCenterEnum.getDesc(), sync);
|
|
|
+ return changeRes(sync);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String changeRes(String sync) {
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(sync);
|
|
|
+ //我的泛型是对象 返回值有可能 是对象或数组 {} []
|
|
|
+ //data:[]->转换成 data:null 进入if
|
|
|
+ Object data = jsonObject.get("data");
|
|
|
+ if (Objects.nonNull(data) && data instanceof JSONArray d && d.isEmpty()) {
|
|
|
+ jsonObject.put("data", null);
|
|
|
+ sync = jsonObject.toJSONString();
|
|
|
+ }
|
|
|
+ return sync;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 会员注册信息
|
|
|
+ *
|
|
|
+ * @param uid
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<JSONObject> user(String uid, ChannelEnum channelEnum) {
|
|
|
+ String sync = getHttp(PayCenterEnum.USER, new HashMap<>() {{
|
|
|
+ put("uid", uid);
|
|
|
+ put("channel", channelEnum);
|
|
|
+ put("channels", "xinwang");
|
|
|
+ }});
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 订单状态
|
|
|
+ *
|
|
|
+ * @param type
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<Map<String, String>> withdrawStatus(String type) {
|
|
|
+ if (StringUtils.isBlank(type)) {
|
|
|
+ type = "order";
|
|
|
+ }
|
|
|
+ String finalType = type;
|
|
|
+ String sync = getHttp(PayCenterEnum.WITHDRAW_STATUS, new HashMap<>() {{
|
|
|
+ put("type", finalType);
|
|
|
+ put("channels", "xinwang");
|
|
|
+ }});
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 取消提现
|
|
|
+ *
|
|
|
+ * @param uid
|
|
|
+ * @param orderNo
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<Object> withdrawCancel(String uid, String orderNo) {
|
|
|
+ if (StringUtils.isBlank(uid)) {
|
|
|
+ throw new BusinessException("用户不能为空");
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(orderNo)) {
|
|
|
+ throw new BusinessException("提现订单不能为空");
|
|
|
+ }
|
|
|
+ String sync = postHttp(PayCenterEnum.WITHDRAW_CANCEL, new HashMap<>() {{
|
|
|
+ put("uid", uid);
|
|
|
+ put("order_no", orderNo);
|
|
|
+ }});
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 申请提现
|
|
|
+ *
|
|
|
+ * @param uid
|
|
|
+ * @param channel
|
|
|
+ * @param money
|
|
|
+ * @param remarks
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<Order> withdrawTake(String uid, @NotBlank(message = "渠道不能为空") ChannelEnum channel, Long money, String remarks) {
|
|
|
+ if (StringUtils.isBlank(uid)) {
|
|
|
+ throw new BusinessException("提现用户不能为空");
|
|
|
+ }
|
|
|
+ if (Objects.isNull(channel)) {
|
|
|
+ throw new BusinessException("提现渠道不能为空");
|
|
|
+ }
|
|
|
+ if (Objects.isNull(money)) {
|
|
|
+ throw new BusinessException("提现金额不能为空");
|
|
|
+ }
|
|
|
+ String sync = postHttp(PayCenterEnum.WITHDRAW_TAKE, new HashMap<>() {{
|
|
|
+ put("uid", uid);
|
|
|
+ put("channel", channel);
|
|
|
+ put("money", money);
|
|
|
+ put("remarks", remarks);
|
|
|
+ }});
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 操作记录-分类
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<Map<String, String>> operateCategory() {
|
|
|
+ String sync = getHttp(PayCenterEnum.OPERATE_CATEGORY, new HashMap<>());
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发起预付
|
|
|
+ *
|
|
|
+ * @param uid 乙方uid
|
|
|
+ * @param channel 渠道
|
|
|
+ * @param filter 甲方uid
|
|
|
+ * @param money 金额,分
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<Order> advancePayApply(String uid, ChannelEnum channel, String filter, Long money) {
|
|
|
+ String sync = postHttp(PayCenterEnum.ADVANCE_PAY_APPLY, new HashMap<>() {{
|
|
|
+ put("uid", uid);
|
|
|
+ put("channel", channel);
|
|
|
+ put("money", money);
|
|
|
+ put("filter", filter);
|
|
|
+ }});
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清分结果查询
|
|
|
+ *
|
|
|
+ * @param uid
|
|
|
+ * @param channel
|
|
|
+ * @param businessNo
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<List<SplitDto>> agentPayQuery(String uid, ChannelEnum channel, String businessNo) {
|
|
|
+ String sync = getHttp(PayCenterEnum.AGENT_PAY_QUERY, new HashMap<>() {{
|
|
|
+ put("uid", uid);
|
|
|
+ put("channel", channel);
|
|
|
+ put("business_no", businessNo);
|
|
|
+ put("channels", "xinwang");
|
|
|
+ }});
|
|
|
+ return parseArray(sync, SplitDto.class);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建/更新账户
|
|
|
+ *
|
|
|
+ * @param memberCreate
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<MemberRes> memberIndex(MemberCreate memberCreate) {
|
|
|
+
|
|
|
+ String sync = jsonHttp(PayCenterEnum.MEMBER_INDEX, memberCreate);
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 在线充值
|
|
|
+ *
|
|
|
+ * @param buyUid 付款方/乙方/买货方 账户
|
|
|
+ * @param sellUid 收款方/甲方/供货方 账户
|
|
|
+ * @param channel 渠道方
|
|
|
+ * @param money 金额,单位分
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<PayIndex> payIndex(String buyUid, String sellUid, ChannelEnum channel, Long money) {
|
|
|
+ String sync = postHttp(PayCenterEnum.PAY_INDEX, new HashMap<>() {{
|
|
|
+ put("buy_uid", buyUid);
|
|
|
+ put("sell_uid", sellUid);
|
|
|
+ put("channel", channel);
|
|
|
+ put("money", money);
|
|
|
+ }});
|
|
|
+
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 冻结资金
|
|
|
+ * 中台逻辑:
|
|
|
+ * 先判断预付金额是否足够,足够就冻结预付金额。
|
|
|
+ * 不够则进行追加预付操作,在进行冻结
|
|
|
+ *
|
|
|
+ * @param uid 付款方uid
|
|
|
+ * @param channel 支付通道
|
|
|
+ * @param money 冻结金额,单位分
|
|
|
+ * @param filter 收款方uid
|
|
|
+ * @param businessNo 流水号
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<Freeze> walletFreeze(String uid, ChannelEnum channel, String filter, Long money, String businessNo) {
|
|
|
+ String sync = postHttp(PayCenterEnum.WALLET_FREEZE, new HashMap<>() {{
|
|
|
+ put("uid", uid);
|
|
|
+ put("filter", filter);
|
|
|
+ put("channel", channel);
|
|
|
+ put("money", money);
|
|
|
+ put("business_no", businessNo);
|
|
|
+ }});
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解冻金额
|
|
|
+ *
|
|
|
+ * @param businessNo
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<BusinessNo> walletUnFreeze(String businessNo) {
|
|
|
+ String sync = postHttp(PayCenterEnum.WALLET_UNFREEZE, new HashMap<>() {{
|
|
|
+ put("business_no", businessNo);
|
|
|
+ }});
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清分
|
|
|
+ * 中台逻辑:
|
|
|
+ * 先从预付金额中进行扣除,然后金额不够的情况下在调用三方接口进行清分,然后进行记账
|
|
|
+ * 因为预付业务实际就是真实的清分业务,所以先判断预付金额是否足够
|
|
|
+ *
|
|
|
+ * @param buyUid
|
|
|
+ * @param sellUid
|
|
|
+ * @param channel
|
|
|
+ * @param money
|
|
|
+ * @param batchPayList
|
|
|
+ * @param businessNo
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<BusinessNo> payAgentPay(String buyUid, String sellUid, ChannelEnum channel, Long money, List<PatchPay> batchPayList, String businessNo) {
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ jsonObject.put("buy_uid", buyUid);
|
|
|
+ jsonObject.put("sell_uid", sellUid);
|
|
|
+ jsonObject.put("channel", channel.getChannel());
|
|
|
+ jsonObject.put("money", money);
|
|
|
+ jsonObject.put("batch_pay_list", batchPayList);
|
|
|
+ jsonObject.put("business_no", businessNo);
|
|
|
+ String sync = jsonHttp(PayCenterEnum.PAY_AGENT_PAY, jsonObject);
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清分
|
|
|
+ *
|
|
|
+ * @param buyUid 付款方uid
|
|
|
+ * @param sellUid 收款方
|
|
|
+ * @param channel 渠道
|
|
|
+ * @param money 总清分金额
|
|
|
+ * @param batchPayList 收款方集合
|
|
|
+ * @param businessNo 流水号
|
|
|
+ * @param payType 支付类型 0-默认 1-仅预付支付 2-仅余额支付
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<BusinessNo> payAgentPayV2(String buyUid, String sellUid, ChannelEnum channel, Long money, List<PatchPay> batchPayList, String businessNo, String payType) {
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ jsonObject.put("buy_uid", buyUid);
|
|
|
+ jsonObject.put("sell_uid", sellUid);
|
|
|
+ jsonObject.put("channel", Objects.nonNull(channel) ? channel.getChannel() : "");
|
|
|
+ jsonObject.put("money", money);
|
|
|
+ jsonObject.put("batch_pay_list", batchPayList);
|
|
|
+ jsonObject.put("business_no", businessNo);
|
|
|
+ jsonObject.put("pay_type", payType);
|
|
|
+ String sync = jsonHttp(PayCenterEnum.PAY_AGENT_PAY_V2, jsonObject);
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建钱包
|
|
|
+ *
|
|
|
+ * @param uid
|
|
|
+ * @param channel
|
|
|
+ * @param filter
|
|
|
+ * @param nickname
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R<Object> walletIndex(@NotBlank(message = "uid不能为空") String uid, @NotNull(message = "支付渠道不能为空") ChannelEnum channel, @NotBlank(message = "filter不能为空") String filter, String nickname) {
|
|
|
+ String sync = postHttp(PayCenterEnum.WALLET_INDEX, new HashMap<>() {{
|
|
|
+ put("uid", uid);
|
|
|
+ put("channel", channel);
|
|
|
+ put("filter", filter);
|
|
|
+ put("nickname", nickname);
|
|
|
+ }});
|
|
|
+ return JSONObject.parseObject(sync, new TypeReference<>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|