Browse Source

feat: "Airwallex 分销明细表 + 订单明细表 + 商品描述数量"
docs: "改一个单词amount"
fix: "删除一个productNum"字段

Ritchie 1 năm trước cách đây
mục cha
commit
e52853ed9c

+ 301 - 19
src/main/java/com/szwl/controller/AirwallexPayController.java

@@ -7,6 +7,9 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.szwl.common.AccessTokenCommon;
 import com.szwl.constant.AirwallexConstant;
 import com.szwl.feign.bean.SzwlFeign;
@@ -16,10 +19,7 @@ import com.szwl.model.bo.JsonMessage;
 import com.szwl.model.bo.R;
 import com.szwl.model.bo.ResponseModel;
 import com.szwl.model.dto.*;
-import com.szwl.model.entity.TAdmin;
-import com.szwl.model.entity.TAirwallexPayment;
-import com.szwl.model.entity.TCoinOrder;
-import com.szwl.model.entity.TEquipment;
+import com.szwl.model.entity.*;
 import com.szwl.model.utils.AccessTokenThreadUtil;
 import com.szwl.service.*;
 import io.swagger.annotations.Api;
@@ -30,6 +30,7 @@ import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.web.bind.annotation.*;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.sql.Timestamp;
 import java.time.OffsetDateTime;
 import java.time.format.DateTimeFormatter;
@@ -50,18 +51,26 @@ public class AirwallexPayController {
 
     TCoinOrderService tCoinOrderService;
 
-    TAirwallexPaymentService tAirwallexPaymentService;
-
-    SzwlFeign szwlFeign;
-
-    public AirwallexPayController(TAdminService tAdminService, AirwallexService airwallexService, TCoinOrderService tCoinOrderService, TAirwallexPaymentService tAirwallexPaymentService, SzwlFeign szwlFeign) {
+    public AirwallexPayController(TAdminService tAdminService, AirwallexService airwallexService, TCoinOrderService tCoinOrderService, TOrderDetailsService tOrderDetailsService, TAirwallexPaymentService tAirwallexPaymentService, SzwlFeign szwlFeign, TAirwallexMchService airwallexMchService) {
         this.tAdminService = tAdminService;
         this.airwallexService = airwallexService;
         this.tCoinOrderService = tCoinOrderService;
+        this.tOrderDetailsService = tOrderDetailsService;
         this.tAirwallexPaymentService = tAirwallexPaymentService;
         this.szwlFeign = szwlFeign;
+        this.airwallexMchService = airwallexMchService;
     }
 
+    TOrderDetailsService tOrderDetailsService;
+
+    TAirwallexPaymentService tAirwallexPaymentService;
+
+    SzwlFeign szwlFeign;
+
+    TAirwallexMchService airwallexMchService;
+
+
+
     @ApiOperation(value = "创建收款人")
     @PostMapping("/caBeneficiary")
     public JsonNode caBeneficiary(@RequestBody CaBeneficiaryRequestDTO requestDTO) {
@@ -144,46 +153,140 @@ public class AirwallexPayController {
         String productName = paymentIntentRequestBody.getProductName();
         String clientId = paymentIntentRequestBody.getClientId();
         Long equipmentId = paymentIntentRequestBody.getEquipmentId();
+        Integer productNumber = paymentIntentRequestBody.getProductNumber();
+
+        // 生成订单编号
+        String sn = tCoinOrderService.initSn(equipmentId);
 
         // 七云还是申泽
         TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(clientId));
+        if (equipment == null || equipmentId == null) {
+            return R.fail("找不到设备");
+        }
 //        System.out.println("设备信息:>>> " + equipment);
         String machineType = equipment.getMachineType(); // 设备类型
         Long adminId = equipment.getAdminId();
         if (adminId == null) {
             return R.fail("找不到设备商家");
         }
-        TAdmin byId = tAdminService.getById(adminId);
-        String companyType = byId.getCompanyType(); // 公司类型
-
+        String adminIdStr = String.valueOf(adminId);
+        // 根据 adminId 获取admin信息中的公司类型
+        TAdmin adminById = R.getDataIfSuccess(szwlFeign.getAdmin(adminIdStr));
+//        TAdmin byId = tAdminService.getById(adminId);
+        String companyType = adminById.getCompanyType(); // 公司类型
+
+        // Airwallex 分账参数
+        ArrayNode altInfos = JsonNodeFactory.instance.arrayNode();
+        // Airwallex 分账明细
+        ObjectNode airDistributionDetails = JsonNodeFactory.instance.objectNode();
+
+        // 查找商品
+        ResponseModel<TProduct> product = szwlFeign.getProduct(String.valueOf(equipmentId), productName);
+        // 获取关联设备的分销
+        TProportion proportion = R.getDataIfSuccess(szwlFeign.getProportion(String.valueOf(equipmentId)));
+        airDistributionDetails = getDistributionDetails(proportion, amount);
 
         // 创建订单
         TCoinOrder tCoinOrder = new TCoinOrder();
+        tCoinOrder.setAdminId(adminById.getId());
+        tCoinOrder.setCreateDate(new Date());
+        tCoinOrder.setSn(sn);
         tCoinOrder.setAmount(amount);
         tCoinOrder.setCurrency(currency);
         tCoinOrder.setMerchantOrderId(merchantOrderId);
         tCoinOrder.setRequestId(requestId);
         tCoinOrder.setProductId(productId);
         tCoinOrder.setProductName(productName);
+        tCoinOrder.setProductNumber(productNumber);
         tCoinOrder.setClientId(clientId);
         tCoinOrder.setEquipmentId(equipmentId);
         // 设置订单支付状态,0未支付,1已支付,3已退款。
         tCoinOrder.setStatus(0);
         tCoinOrder.setIsAir("1");
+        tCoinOrder.setAltInfo(altInfos.toString());
         tCoinOrder.setMachineType(machineType);
         tCoinOrder.setCompanyType(companyType);
+        tCoinOrder.setType(adminById.getType());
+        switch (adminById.getType()) {
+            case 0:
+                tCoinOrder.setAdminProportion(proportion.getAdminProportion());
+                tCoinOrder.setAgencyProportion(proportion.getAgencyProportion());
+                tCoinOrder.setAgencyId(proportion.getAgencyId());
+                break;
+            case 1:
+                tCoinOrder.setAdminProportion(proportion.getAdminProportion());
+                tCoinOrder.setAgencyProportion(proportion.getAgencyProportion());
+                tCoinOrder.setAgencyId(proportion.getAgencyId());
+                tCoinOrder.setMerchantProportion(proportion.getMerchantProportion());
+                tCoinOrder.setMerchantId(proportion.getMerchantId());
+                break;
+            case 2:
+                tCoinOrder.setAdminProportion(proportion.getAdminProportion());
+                tCoinOrder.setAgencyProportion(proportion.getAgencyProportion());
+                tCoinOrder.setAgencyId(proportion.getAgencyId());
+                tCoinOrder.setMerchantProportion(proportion.getMerchantProportion());
+                tCoinOrder.setMerchantId(proportion.getMerchantId());
+                tCoinOrder.setPersonageProportion(proportion.getPersonageProportion());
+                tCoinOrder.setPersonageId(proportion.getPersonageId());
+                break;
+            default:
+                // 如果类型不匹配任何 case,则执行默认逻辑
+                break;
+        }
+        tCoinOrder.setAltInfo(airDistributionDetails.toString());
+
+
+
+        // 订单明细表
+        TOrderDetails tOrderDetails = new TOrderDetails();
+        tOrderDetails.setId(merchantOrderId);
+        tOrderDetails.setAdminId(adminById.getId());
+        tOrderDetails.setEquipmentId(equipmentId);
+        tOrderDetails.setCreateDate(new Date());
+        tOrderDetails.setOrderSn(sn);
+        tOrderDetails.setPrice(amount);
+        tOrderDetails.setProductName(productName);
+        tOrderDetails.setProductNo(product.getData().getNo());
+        tOrderDetails.setProductNumber(productNumber);
+        tOrderDetails.setAmount(amount);
+        tOrderDetails.setRefundStatus("0");
+        tOrderDetails.setCompanyType(companyType);
+        tOrderDetails.setMachineType(machineType);
+
+        String clientSix = clientId.substring(clientId.length() - 6);
+        String productNameMerge = "";
+        if (productNumber > 1) {
+            if (machineType == null || "0".equals(machineType)) {
+                productNameMerge = "棉花糖-" + equipment.getName() + "-" + clientSix;
+            } else {
+                productNameMerge = "爆米花-" + equipment.getName() + "-" + clientSix;
+            }
+        } else {
+            productNameMerge = productName + "-" + equipment.getName() + "-" + clientSix;
+        }
+
+        ObjectMapper mapper = new ObjectMapper();
+        ObjectNode order = mapper.createObjectNode();
+        ArrayNode products = mapper.createArrayNode();
+
+        ObjectNode airProduct = mapper.createObjectNode();
+        // Name of the product. Maximum of 255 characters.
+//        airProduct.put("name", productNameMerge);
+        // Product description. Maximum of 500 characters.
+        airProduct.put("desc", productNameMerge);
+        airProduct.put("quantity", productNumber);
+
+        products.add(airProduct);
+        order.set("products", products);
 
         // 返回payment intent id和client secret
-        Map<String, Object> responseMap = airwallexService.caPaymentIntent(amount, currency, requestId, merchantOrderId);
+        Map<String, Object> responseMap = airwallexService.caPaymentIntent(amount, currency, requestId, merchantOrderId, order);
 
         String paymentIntentId = (String) responseMap.get("id");
         String clientSecret = (String) responseMap.get("client_secret");
 
-        // 把 paymentIntentId 保存到数据库
+        // 把 paymentIntentId 保存到表中
         tCoinOrder.setPaymentIntentId(paymentIntentId);
-        // 将订单存入数据库
-
-        tCoinOrderService.save(tCoinOrder);
 //        boolean save = tOrderAbroadService.save(tOrderAbroad);
 //        System.out.println("将订单存入数据库:" + save);
 
@@ -192,10 +295,11 @@ public class AirwallexPayController {
 //        String mode = AirwallexConstant.MODE;
 //        String locale = "it";
         String qrUrl = AirwallexConstant.QR_URL;
-
         String QR = qrUrl + "?intent_id=" + paymentIntentId + "&client_secret=" + clientSecret + "&currency=" + currency;
 
-        // TODO: 设置分销
+        // 将订单存入数据库
+        tCoinOrderService.save(tCoinOrder);
+        tOrderDetailsService.save(tOrderDetails);
 
         return R.ok().setData(QR);
     }
@@ -461,4 +565,182 @@ public class AirwallexPayController {
         return R.ok(resp);
     }
 
+    /**
+     * 获取 Airwallex 分销明细
+     *
+     * @param proportion
+     * @param price
+     * @return
+     */
+    public ObjectNode getDistributionDetails(TProportion proportion, BigDecimal price) {
+        // 获取分账有几方:0:分账方2个,1:分账方3个,2:分账方4个,3:分账方超4个
+        Integer type = proportion.getType();
+
+        // 空中云汇 分账明细参数
+//        ArrayNode altInfos = new ObjectMapper().createArrayNode();
+        ArrayNode altInfos = JsonNodeFactory.instance.arrayNode();
+        ObjectNode distributionDetails = JsonNodeFactory.instance.objectNode();
+
+        BigDecimal airProportion = null, // 空中云汇平台分销百分比,假设是0
+                selfProportion = null, // 商家自己的分销百分比
+                agencyProportion = null, // 一级分销商分销百分比
+                merchantProportion = null; // 二级分销商分销百分比
+
+        BigDecimal airAmount = null, // 空中云汇的钱,假设是0
+                selfAmount = null, // 商家自己所得的钱
+                agencyAmount = null, // 一级分销商所得的钱
+                merchantAmount = null; // 二级分销商所得的钱
+
+        TAirwallexMch selfAirMch = null, // 商家收款信息
+                agencyAirMch = null, // 一级分销商收款信息
+                merchantAirMch = null; // 二级分销商收款信息
+
+        ObjectNode airJson = null, // 空中云汇
+                selfJson = null, // 商家
+                agencyJson = null, // 一级
+                merchantJson = null; // 二级
+
+        // 取消平台扣手续费,将price四舍五入保留2位小数
+        BigDecimal cutPrice = price.setScale(2, RoundingMode.HALF_UP);
+        BigDecimal refuseAmount = new BigDecimal(0.00);
+
+        switch (type) {
+            case 0: // 分账方有2个:申泽admin + 商家proportion
+                // 目前都暂定空中云汇平台分销为 0
+//                airProportion = proportion.getAdminProportion();
+                // 申泽的分销 eg.1%  不显示
+//                adminProportion = proportion.getAdminProportion();
+                // 商家自己的分销
+                selfProportion = proportion.getProportion();
+                // 平台分销获得利润
+//                airAmount = cutPrice.multiply(airProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_UP);
+                // 商家分销获得利润,五舍六入
+                selfAmount = cutPrice.multiply(selfProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+
+                // Airwallex 平台收款信息表
+//                Long adminId = proportion.getAdminId();
+                LambdaQueryWrapper<TAirwallexMch> wrapper = Wrappers.lambdaQuery();
+                wrapper.eq(TAirwallexMch::getAdminId, proportion.getAdminId());
+                selfAirMch = airwallexMchService.getOne(wrapper);
+
+                // 平台分销
+//                airJson = JsonNodeFactory.instance.objectNode();
+//                // 分账方受益人编号
+//                airJson.put("altMchId", selfAirMch.getBeneficiaryId());
+//                // 受益人所分金额,单位美元$
+//                airJson.put("altAirAmount", airAmount.toString());
+//                altInfos.add(airJson);
+
+                // 商家分销
+                selfJson = JsonNodeFactory.instance.objectNode();
+                selfJson.put("airBeneId", selfAirMch.getBeneficiaryId());
+                selfJson.put("airAmount", selfAmount.toString());
+                altInfos.add(selfJson);
+                break;
+            case 1: // 分账方有3个:申泽admin + 商家proportion + 商家一级agency
+                // 商家自己的分销
+                selfProportion = proportion.getProportion();
+                // 一级代理的分销
+                agencyProportion = proportion.getAgencyProportion();
+                // 商家分销获得利润
+                selfAmount = cutPrice.multiply(selfProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+
+                // Airwallex 平台收款信息表
+                agencyAirMch = airwallexMchService.getAirMch(proportion.getAgencyId());
+                selfAirMch = airwallexMchService.getAirMch(proportion.getAdminId());
+                if (!(agencyProportion.compareTo(refuseAmount) == 0 || agencyProportion == null)) {
+                    // 一级代理获得利润
+                    agencyAmount = cutPrice.multiply(agencyProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+                    agencyJson = JsonNodeFactory.instance.objectNode();
+                    agencyJson.put("airBeneId", agencyAirMch.getBeneficiaryId());
+                    agencyJson.put("airAmount", agencyAmount.toString());
+                    altInfos.add(agencyJson);
+                }
+                // 商家自己获得利润
+                selfJson = JsonNodeFactory.instance.objectNode();
+                selfJson.put("airBeneId", selfAirMch.getBeneficiaryId());
+                selfJson.put("airAmount", selfAmount.toString());
+                altInfos.add(selfJson);
+                break;
+            case 2: // 分账方有4个:申泽admin + 商家self + 商家一级agency + 商家二级merchant
+                // 商家自己的分销
+                selfProportion = proportion.getProportion();
+                // 一级代理的分销
+                agencyProportion = proportion.getAgencyProportion();
+                // 二级代理的分销
+                merchantProportion = proportion.getMerchantProportion();
+
+                // 商家分销获得利润,五舍六入
+                selfAmount = cutPrice.multiply(selfProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+                // Airwallex 平台收款信息表
+                selfAirMch = airwallexMchService.getAirMch(proportion.getAdminId());
+                agencyAirMch = airwallexMchService.getAirMch(proportion.getAgencyId());
+                merchantAirMch = airwallexMchService.getAirMch(proportion.getMerchantId());
+                if (!(agencyProportion.compareTo(refuseAmount) == 0 || agencyProportion == null)) {
+                    // 一级代理获得利润
+                    agencyAmount = cutPrice.multiply(agencyProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+                    agencyJson = JsonNodeFactory.instance.objectNode();
+                    agencyJson.put("airBeneId", agencyAirMch.getBeneficiaryId());
+                    agencyJson.put("airAmount", agencyAmount.toString());
+                    altInfos.add(agencyJson);
+                }
+                if (!(merchantProportion.compareTo(refuseAmount) == 0 || merchantProportion == null)) {
+                    // 二级经销商获得利润
+                    merchantAmount = cutPrice.multiply(merchantProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+                    merchantJson = JsonNodeFactory.instance.objectNode();
+                    merchantJson.put("airBeneId", merchantAirMch.getBeneficiaryId());
+                    merchantJson.put("airAmount", merchantAmount.toString());
+                    altInfos.add(merchantJson);
+                }
+                // 商家自己获得利润
+                selfJson = JsonNodeFactory.instance.objectNode();
+                selfJson.put("airBeneId", selfAirMch.getBeneficiaryId());
+                selfJson.put("airAmount", selfAmount.toString());
+                altInfos.add(selfJson);
+                break;
+            case 3: // 分账方超过4个:申泽admin + 商家self + 商家一级agency + 商家二级merchant + 商家三级personage
+//                personageProportion = proportion.getPersonageProportion();
+                break;
+        }
+        // 计算airAmount的总和
+        BigDecimal sumAmount = BigDecimal.ZERO;
+        Iterator<JsonNode> iterator = altInfos.iterator();
+        while (iterator.hasNext()) {
+            JsonNode jsonNode = iterator.next();
+            String airAmounts = jsonNode.get("airAmount").asText();
+            if (airAmounts.equals("0.00")) {
+                iterator.remove();
+            }
+            if (jsonNode.has("airAmount")) {
+                BigDecimal airAmountSum = new BigDecimal(jsonNode.get("airAmount").asText());
+                sumAmount = sumAmount.add(airAmountSum);
+            }
+        }
+        // 如果sumAmount大于原本price
+        if (sumAmount.compareTo(price) > 0) {
+            BigDecimal subtract = sumAmount.subtract(price);
+            Iterator<JsonNode> iterator1 = altInfos.iterator();
+
+            while (iterator1.hasNext()) {
+                JsonNode jsonNode = iterator1.next();
+                String airBeneId = jsonNode.get("airBeneId").asText();
+//            String airBeneId1 = jsonNode.get("airBeneId").toString();
+
+                if (airBeneId.equals(AirwallexConstant.clientid)) {
+                    BigDecimal airAmount1 = new BigDecimal(jsonNode.get("airAmount").asText());
+                    BigDecimal fixAirAmount = airAmount1.subtract(subtract).max(BigDecimal.ZERO);
+
+//                    ObjectMapper objectMapper = new ObjectMapper();
+//                    ObjectNode objectNode = objectMapper.convertValue(jsonNode, ObjectNode.class);
+//                    objectNode.put("airAmount", fixAirAmount.toString());
+
+                    ((ObjectNode) jsonNode).put("airAmount", fixAirAmount.toString());
+                    break;
+                }
+            }
+        }
+        distributionDetails.put("alt_infos", altInfos);
+        return distributionDetails;
+    }
+
 }

+ 7 - 0
src/main/java/com/szwl/controller/TAirwallexMchController.java

@@ -1,6 +1,10 @@
 package com.szwl.controller;
 
 
+import com.szwl.model.bo.ResponseModel;
+import com.szwl.model.entity.TAirwallexMch;
+import com.szwl.service.TAdminService;
+import com.szwl.service.TAirwallexMchService;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
@@ -17,5 +21,8 @@ import org.springframework.web.bind.annotation.RestController;
 @RequestMapping("/tAirwallexMch")
 public class TAirwallexMchController {
 
+    public ResponseModel<TAirwallexMch> getAirMch(Long id) {
+        return null;
+    }
 }
 

+ 210 - 1
src/main/java/com/szwl/controller/TCoinOrderController.java

@@ -1,13 +1,35 @@
 package com.szwl.controller;
 
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.szwl.constant.AirwallexConstant;
+import com.szwl.constant.HuifuConstant;
+import com.szwl.feign.bean.SzwlFeign;
+import com.szwl.model.bo.R;
+import com.szwl.model.entity.TAirwallexMch;
+import com.szwl.model.entity.THuifuMch;
+import com.szwl.model.entity.TProportion;
+import com.szwl.service.TAirwallexMchService;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Iterator;
+
 /**
  * <p>
- *  前端控制器
+ * 前端控制器
  * </p>
  *
  * @author wuhs
@@ -17,5 +39,192 @@ import org.springframework.web.bind.annotation.RestController;
 @RequestMapping("/tCoinOrder")
 public class TCoinOrderController {
 
+    TAirwallexMchService airwallexMchService;
+
+    SzwlFeign szwlFeign;
+
+    public TCoinOrderController(TAirwallexMchService airwallexMchService, SzwlFeign szwlFeign) {
+        this.airwallexMchService = airwallexMchService;
+        this.szwlFeign = szwlFeign;
+    }
+
+
+    /**
+     * 获取 Airwallex 分销明细
+     *
+     * @param proportion
+     * @param price
+     * @return
+     */
+    public ObjectNode getDistributionDetails(TProportion proportion, BigDecimal price) {
+        // 获取分账有几方:0:分账方2个,1:分账方3个,2:分账方4个,3:分账方超4个
+        Integer type = proportion.getType();
+
+        // 空中云汇 分账明细参数
+//        ArrayNode altInfos = new ObjectMapper().createArrayNode();
+        ArrayNode altInfos = JsonNodeFactory.instance.arrayNode();
+        ObjectNode distributionDetails = JsonNodeFactory.instance.objectNode();
+
+        BigDecimal airProportion = null, // 空中云汇平台分销百分比,假设是0
+                selfProportion = null, // 商家自己的分销百分比
+                agencyProportion = null, // 一级分销商分销百分比
+                merchantProportion = null; // 二级分销商分销百分比
+
+        BigDecimal airAmount = null, // 空中云汇的钱,假设是0
+                selfAmount = null, // 商家自己所得的钱
+                agencyAmount = null, // 一级分销商所得的钱
+                merchantAmount = null; // 二级分销商所得的钱
+
+        TAirwallexMch selfAirMch = null, // 商家收款信息
+                agencyAirMch = null, // 一级分销商收款信息
+                merchantAirMch = null; // 二级分销商收款信息
+
+        ObjectNode airJson = null, // 空中云汇
+                selfJson = null, // 商家
+                agencyJson = null, // 一级
+                merchantJson = null; // 二级
+
+        // 取消平台扣手续费,将price四舍五入保留2位小数
+        BigDecimal cutPrice = price.setScale(2, RoundingMode.HALF_UP);
+        BigDecimal refuseAmount = new BigDecimal(0.00);
+
+        switch (type) {
+            case 0: // 分账方有2个:申泽admin + 商家proportion
+                // 目前都暂定空中云汇平台分销为 0
+//                airProportion = proportion.getAdminProportion();
+                // 申泽的分销 eg.1%  不显示
+//                adminProportion = proportion.getAdminProportion();
+                // 商家自己的分销
+                selfProportion = proportion.getProportion();
+                // 平台分销获得利润
+//                airAmount = cutPrice.multiply(airProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_UP);
+                // 商家分销获得利润,五舍六入
+                selfAmount = cutPrice.multiply(selfProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+
+                // Airwallex 平台收款信息表
+//                Long adminId = proportion.getAdminId();
+                LambdaQueryWrapper<TAirwallexMch> wrapper = Wrappers.lambdaQuery();
+                wrapper.eq(TAirwallexMch::getAdminId, proportion.getAdminId());
+                selfAirMch = airwallexMchService.getOne(wrapper);
+
+                // 平台分销
+//                airJson = JsonNodeFactory.instance.objectNode();
+//                // 分账方受益人编号
+//                airJson.put("altMchId", selfAirMch.getBeneficiaryId());
+//                // 受益人所分金额,单位美元$
+//                airJson.put("altAirAmount", airAmount.toString());
+//                altInfos.add(airJson);
+
+                // 商家分销
+                selfJson = JsonNodeFactory.instance.objectNode();
+                selfJson.put("airBeneId", selfAirMch.getBeneficiaryId());
+                selfJson.put("airAmount", selfAmount.toString());
+                altInfos.add(selfJson);
+                break;
+            case 1: // 分账方有3个:申泽admin + 商家proportion + 商家一级agency
+                // 商家自己的分销
+                selfProportion = proportion.getProportion();
+                // 一级代理的分销
+                agencyProportion = proportion.getAgencyProportion();
+                // 商家分销获得利润
+                selfAmount = cutPrice.multiply(selfProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+
+                // Airwallex 平台收款信息表
+                agencyAirMch = airwallexMchService.getAirMch(proportion.getAgencyId());
+                selfAirMch = airwallexMchService.getAirMch(proportion.getAdminId());
+                if (!(agencyProportion.compareTo(refuseAmount) == 0 || agencyProportion == null)) {
+                    // 一级代理获得利润
+                    agencyAmount = cutPrice.multiply(agencyProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+                    agencyJson = JsonNodeFactory.instance.objectNode();
+                    agencyJson.put("airBeneId", agencyAirMch.getBeneficiaryId());
+                    agencyJson.put("airAmount", agencyAmount.toString());
+                    altInfos.add(agencyJson);
+                }
+                // 商家自己获得利润
+                selfJson = JsonNodeFactory.instance.objectNode();
+                selfJson.put("airBeneId", selfAirMch.getBeneficiaryId());
+                selfJson.put("airAmount", selfAmount.toString());
+                altInfos.add(selfJson);
+                break;
+            case 2: // 分账方有4个:申泽admin + 商家self + 商家一级agency + 商家二级merchant
+                // 商家自己的分销
+                selfProportion = proportion.getProportion();
+                // 一级代理的分销
+                agencyProportion = proportion.getAgencyProportion();
+                // 二级代理的分销
+                merchantProportion = proportion.getMerchantProportion();
+
+                // 商家分销获得利润,五舍六入
+                selfAmount = cutPrice.multiply(selfProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+                // Airwallex 平台收款信息表
+                selfAirMch = airwallexMchService.getAirMch(proportion.getAdminId());
+                agencyAirMch = airwallexMchService.getAirMch(proportion.getAgencyId());
+                merchantAirMch = airwallexMchService.getAirMch(proportion.getMerchantId());
+                if (!(agencyProportion.compareTo(refuseAmount) == 0 || agencyProportion == null)) {
+                    // 一级代理获得利润
+                    agencyAmount = cutPrice.multiply(agencyProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+                    agencyJson = JsonNodeFactory.instance.objectNode();
+                    agencyJson.put("airBeneId", agencyAirMch.getBeneficiaryId());
+                    agencyJson.put("airAmount", agencyAmount.toString());
+                    altInfos.add(agencyJson);
+                }
+                if (!(merchantProportion.compareTo(refuseAmount) == 0 || merchantProportion == null)) {
+                    // 二级经销商获得利润
+                    merchantAmount = cutPrice.multiply(merchantProportion.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_DOWN);
+                    merchantJson = JsonNodeFactory.instance.objectNode();
+                    merchantJson.put("airBeneId", merchantAirMch.getBeneficiaryId());
+                    merchantJson.put("airAmount", merchantAmount.toString());
+                    altInfos.add(merchantJson);
+                }
+                // 商家自己获得利润
+                selfJson = JsonNodeFactory.instance.objectNode();
+                selfJson.put("airBeneId", selfAirMch.getBeneficiaryId());
+                selfJson.put("airAmount", selfAmount.toString());
+                altInfos.add(selfJson);
+                break;
+            case 3: // 分账方超过4个:申泽admin + 商家self + 商家一级agency + 商家二级merchant + 商家三级personage
+//                personageProportion = proportion.getPersonageProportion();
+                break;
+        }
+        // 计算airAmount的总和
+        BigDecimal sumAmount = BigDecimal.ZERO;
+        Iterator<JsonNode> iterator = altInfos.iterator();
+        while (iterator.hasNext()) {
+            JsonNode jsonNode = iterator.next();
+            String airAmounts = jsonNode.get("airAmount").asText();
+            if (airAmounts.equals("0.00")) {
+                iterator.remove();
+            }
+            if (jsonNode.has("airAmount")) {
+                BigDecimal airAmountSum = new BigDecimal(jsonNode.get("airAmount").asText());
+                sumAmount = sumAmount.add(airAmountSum);
+            }
+        }
+        // 如果sumAmount大于原本price
+        if (sumAmount.compareTo(price) > 0) {
+            BigDecimal subtract = sumAmount.subtract(price);
+            Iterator<JsonNode> iterator1 = altInfos.iterator();
+
+            while (iterator1.hasNext()) {
+                JsonNode jsonNode = iterator1.next();
+                String airBeneId = jsonNode.get("airBeneId").asText();
+//            String airBeneId1 = jsonNode.get("airBeneId").toString();
+
+                if (airBeneId.equals(AirwallexConstant.clientid)) {
+                    BigDecimal airAmount1 = new BigDecimal(jsonNode.get("airAmount").asText());
+                    BigDecimal fixAirAmount = airAmount1.subtract(subtract).max(BigDecimal.ZERO);
+
+//                    ObjectMapper objectMapper = new ObjectMapper();
+//                    ObjectNode objectNode = objectMapper.convertValue(jsonNode, ObjectNode.class);
+//                    objectNode.put("airAmount", fixAirAmount.toString());
+
+                    ((ObjectNode) jsonNode).put("airAmount", fixAirAmount.toString());
+                    break;
+                }
+            }
+        }
+        distributionDetails.put("alt_infos", altInfos);
+        return distributionDetails;
+    }
 }
 

+ 3 - 4
src/main/java/com/szwl/controller/TOrderController.java

@@ -192,9 +192,7 @@ public class TOrderController {
             return JsonMessage.error("参数错误");
         }
 
-        if (equipment == null) {
-            return JsonMessage.error("找不到设备");
-        }
+
 
         Long equipmentId = equipment.getId();
         //查找商品
@@ -3233,7 +3231,8 @@ public class TOrderController {
                 merchantJson = new JSONObject();
                 merchantJson.put("altMchNo", selfMch.getAltMchNo());
                 merchantJson.put("altAmount", selfAmount.toString());
-                merchantJson.put("isGuar", "12");altInfo.add(merchantJson);
+                merchantJson.put("isGuar", "12");
+                altInfo.add(merchantJson);
                 break;
         }
         Iterator<Object> iterator = altInfo.iterator();

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 2
src/main/java/com/szwl/mapper/xml/TCoinOrderMapper.xml


+ 2 - 2
src/main/java/com/szwl/mapper/xml/TOrderDetailsMapper.xml

@@ -15,7 +15,7 @@
         <result column="price" property="price" />
         <result column="amount" property="amount" />
         <result column="refund_quantity" property="refundQuantity" />
-        <result column="refund_amout" property="refundAmout" />
+        <result column="refund_amount" property="refundAmount" />
         <result column="refund_status" property="refundStatus" />
         <result column="company_type" property="companyType" />
         <result column="machine_type" property="machineType" />
@@ -23,7 +23,7 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, admin_id, equipment_id, create_date, order_sn, product_no, product_name, product_number, price, amount, refund_quantity, refund_amout, refund_status, company_type, machine_type
+        id, admin_id, equipment_id, create_date, order_sn, product_no, product_name, product_number, price, amount, refund_quantity, refund_amount, refund_status, company_type, machine_type
     </sql>
 
 </mapper>

+ 4 - 0
src/main/java/com/szwl/model/bean/PaymentIntentRequestBody.java

@@ -1,5 +1,6 @@
 package com.szwl.model.bean;
 
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -20,6 +21,9 @@ public class PaymentIntentRequestBody {
 
     private String productName;
 
+    // 每笔订单中一共有n个商品
+    private Integer productNumber;
+
     private String clientId;
 
     private Long equipmentId;

+ 2 - 2
src/main/java/com/szwl/model/entity/TAirwallexMch.java

@@ -12,7 +12,7 @@ import lombok.EqualsAndHashCode;
 
 /**
  * <p>
- * 
+ * Airwallex 用户收款信息表
  * </p>
  *
  * @author wuhs
@@ -41,7 +41,7 @@ public class TAirwallexMch implements Serializable {
     @ApiModelProperty(value = "公司名称")
     private String companyName;
 
-    @ApiModelProperty(value = "实体类型")
+    @ApiModelProperty(value = "实体类型:One of PERSONAL, COMPANY")
     private String entityType;
 
     @ApiModelProperty(value = "账户币种")

+ 0 - 3
src/main/java/com/szwl/model/entity/TCoinOrder.java

@@ -145,9 +145,6 @@ public class TCoinOrder implements Serializable {
     @ApiModelProperty(value = "airwallex交易编号")
     private String paymentIntentId;
 
-    @ApiModelProperty(value = "商品数量,每笔订单中有几个商品")
-    private Integer productNum;
-
     @ApiModelProperty(value = "公司平台,0或空为申泽,1为七云")
     private String companyType;
 

+ 1 - 1
src/main/java/com/szwl/model/entity/TOrderDetails.java

@@ -60,7 +60,7 @@ public class TOrderDetails implements Serializable {
     private Integer refundQuantity;
 
     @ApiModelProperty(value = "退款金额")
-    private BigDecimal refundAmout;
+    private BigDecimal refundAmount;
 
     @ApiModelProperty(value = "退款状态,0:未支付,1:已支付,2:部分退款,3:全部退款,4:退款中")
     private String refundStatus;

+ 2 - 1
src/main/java/com/szwl/service/AirwallexService.java

@@ -1,5 +1,6 @@
 package com.szwl.service;
 
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.szwl.model.bo.R;
 import com.szwl.model.dto.BeneficiaryDTO;
 import com.szwl.model.dto.CaPaymentRequestDTO;
@@ -53,7 +54,7 @@ public interface AirwallexService  {
      * @param merchantOrderId
      * @return
      */
-    Map<String, Object> caPaymentIntent(BigDecimal amount, String currency, String requestId, String merchantOrderId);
+    Map<String, Object> caPaymentIntent(BigDecimal amount, String currency, String requestId, String merchantOrderId, ObjectNode order);
 
     /**
      * 创建一笔退款 Create a Refund

+ 3 - 0
src/main/java/com/szwl/service/TAirwallexMchService.java

@@ -13,4 +13,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface TAirwallexMchService extends IService<TAirwallexMch> {
 
+//    TAirwallexMch getAirwallexId(Long adminId);
+
+    TAirwallexMch getAirMch(Long adminId);
 }

+ 4 - 0
src/main/java/com/szwl/service/TCoinOrderService.java

@@ -13,4 +13,8 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface TCoinOrderService extends IService<TCoinOrder> {
 
+    /**
+     * 生成订单号
+     */
+    String initSn(Long equipmentId);
 }

+ 19 - 1
src/main/java/com/szwl/service/impl/AirwallexServiceImpl.java

@@ -1,6 +1,10 @@
 package com.szwl.service.impl;
 
 import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.szwl.common.AccessTokenCommon;
 import com.szwl.constant.AirwallexConstant;
 import com.szwl.controller.TAreaController;
@@ -74,7 +78,7 @@ public class AirwallexServiceImpl implements AirwallexService {
      * @return
      */
     @Override
-    public Map<String, Object> caPaymentIntent(BigDecimal amount, String currency, String requestId, String merchantOrderId) {
+    public Map<String, Object> caPaymentIntent(BigDecimal amount, String currency, String requestId, String merchantOrderId, ObjectNode order) {
         String accessToken = AccessTokenCommon.ACCESS_TOKEN;
 
         if(accessToken == null || "".equals(accessToken)) {
@@ -87,12 +91,26 @@ public class AirwallexServiceImpl implements AirwallexService {
 //        new BasicHeader("Authorization", AirwallexConstant.BEARER + this.getAccessToken());
         BasicHeader header1 = new BasicHeader("Authorization",AirwallexConstant.BEARER + accessToken);
         headers.add(header1);
+
+        ArrayNode productList = (ArrayNode) order.get("products");
+        List<Map<String,Object>> productMapList = new ArrayList<>();
+        for (JsonNode product : productList) {
+            Map<String, Object> productMap = new HashMap<>();
+            productMap.put("desc", product.get("desc").textValue());
+            productMap.put("quantity", product.get("quantity").intValue());
+            productMapList.add(productMap);
+        }
+        ObjectNode orderNode = new ObjectMapper().createObjectNode();
+        orderNode.set("products", productList);
+
         // body参数
         Map<String, Object> bodyMap = new HashMap<>();
         bodyMap.put("amount", amount);
         bodyMap.put("currency", currency);
         bodyMap.put("request_id", requestId);
         bodyMap.put("merchant_order_id", merchantOrderId);
+        bodyMap.put("order", orderNode);
+
 
         String data = JSON.toJSONString(bodyMap);
         log.info("请求body参数:" +data);

+ 48 - 0
src/main/java/com/szwl/service/impl/TAirwallexMchServiceImpl.java

@@ -1,11 +1,20 @@
 package com.szwl.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.szwl.model.bo.R;
+import com.szwl.model.entity.TAdmin;
 import com.szwl.model.entity.TAirwallexMch;
 import com.szwl.mapper.TAirwallexMchMapper;
+import com.szwl.service.TAdminService;
 import com.szwl.service.TAirwallexMchService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.elasticsearch.search.aggregations.bucket.terms.RareTerms;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * <p>
  *  服务实现类
@@ -17,4 +26,43 @@ import org.springframework.stereotype.Service;
 @Service
 public class TAirwallexMchServiceImpl extends ServiceImpl<TAirwallexMchMapper, TAirwallexMch> implements TAirwallexMchService {
 
+    public TAirwallexMchService airwallexMchService;
+    public TAdminService adminService;
+
+    public TAirwallexMchServiceImpl(TAirwallexMchService airwallexMchService, TAdminService adminService) {
+        this.airwallexMchService = airwallexMchService;
+        this.adminService = adminService;
+    }
+
+//    @Override
+//    public TAirwallexMch getAirwallexId(Long adminId) {
+//        return null;
+//    }
+
+    @Override
+    public TAirwallexMch getAirMch(Long adminId) {
+
+        TAdmin admin = adminService.getById(adminId);
+        if (!admin.getIsAdmined()) {
+            if (admin.getType() <= 1) { // 公司人员
+                TAirwallexMch airwallexMch = new TAirwallexMch();
+                airwallexMch.setEntityType("PERSONAL"); // 商户类型,“0”为个人,“1”为企业
+                return airwallexMch;
+            } else { // 商家
+                TAdmin parentAdmin = adminService.getById(admin.getParentId());
+                LambdaQueryWrapper<TAirwallexMch> wrapper = Wrappers.lambdaQuery();
+                wrapper.eq(TAirwallexMch::getAdminId, Long.valueOf(parentAdmin.getId()));
+
+                List<TAirwallexMch> list = airwallexMchService.list(wrapper);
+                TAirwallexMch airwallexMch = list.get(0);
+                // 刷新 airwallexMch
+//            TAirwallexMch tAirwallexMch = airwallexMchService.getById(airwallexMch.getId());
+                return airwallexMch;
+            }
+        } else {
+
+        }
+
+        return null;
+    }
 }

+ 26 - 0
src/main/java/com/szwl/service/impl/TCoinOrderServiceImpl.java

@@ -6,6 +6,10 @@ import com.szwl.service.TCoinOrderService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.stereotype.Service;
 
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Random;
+
 /**
  * <p>
  *  服务实现类
@@ -17,4 +21,26 @@ import org.springframework.stereotype.Service;
 @Service
 public class TCoinOrderServiceImpl extends ServiceImpl<TCoinOrderMapper, TCoinOrder> implements TCoinOrderService {
 
+    @Override
+    public String initSn(Long equipmentId) {
+        StringBuilder number = new StringBuilder();
+        if (equipmentId != null) {
+            Random random = new Random();
+            /**
+             * 6位随机
+             */
+            for (int i = 0; i < 6; i++) {
+                number.append(String.valueOf(random.nextInt(10)));
+            }
+            /**
+             * 设备id
+             */
+            number.append(equipmentId.toString());
+            /**
+             * 日期
+             */
+            number.append(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
+        }
+        return number.toString();
+    }
 }