Selaa lähdekoodia

添加微信发货

xgb 20 tuntia sitten
vanhempi
commit
66ba9ec234

+ 16 - 0
fs-admin/src/main/java/com/fs/hisStore/controller/FsStorePaymentScrmController.java

@@ -295,4 +295,20 @@ public class FsStorePaymentScrmController extends BaseController
     {
         return toAjax(fsStorePaymentService.deleteFsStorePaymentByIds(paymentIds));
     }
+
+    /**
+     * 一键发货
+     * @return R
+     * **/
+    @Log(title = "发货同步导入", businessType = BusinessType.IMPORT)
+    @PostMapping("/oneClickShipping")
+    public R oneClickShipping() {
+
+        try {
+            return fsStorePaymentService.oneClickShipping();
+        }catch (Exception e){
+            e.getStackTrace();
+        }
+        return R.ok();
+    }
 }

+ 4 - 0
fs-service/src/main/java/com/fs/hisStore/config/StoreConfig.java

@@ -26,4 +26,8 @@ public class StoreConfig implements Serializable {
     private Boolean isBrushOrders;//是否开启刷单按钮
 
     private Integer orderAttribution; // 下单归属 1 多销售 2单销售
+
+    private Boolean isWeChatShipping;//是否开启微信发货
+
+    private String weChatShippingAppIds;// 需要微信发货的小程序
 }

+ 14 - 1
fs-service/src/main/java/com/fs/hisStore/mapper/FsStorePaymentScrmMapper.java

@@ -4,11 +4,11 @@ import java.util.List;
 import java.util.Map;
 
 import com.alibaba.fastjson.JSONObject;
-import com.fs.his.domain.FsStorePayment;
 import com.fs.hisStore.domain.FsStorePaymentScrm;
 import com.fs.hisStore.param.FsStorePaymentParam;
 import com.fs.hisStore.param.FsStoreStatisticsParam;
 import com.fs.hisStore.vo.FsStorePaymentStatisticsVO;
+import com.fs.hisStore.vo.FsStorePaymentUsetVo;
 import com.fs.hisStore.vo.FsStorePaymentVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -352,4 +352,17 @@ public interface FsStorePaymentScrmMapper
 
     @Select("select * from fs_store_payment_scrm where pay_code=#{payCode}")
     FsStorePaymentScrm selectFsStorePaymentByPaymentCode(String payCode);
+
+    /**
+     * 获取查询用户支付信息
+     * @return list
+     **/
+    List<FsStorePaymentUsetVo> getPaymentUsetInfoList(@Param("appIds") String[] appIds);
+
+    /**
+     * 批量更新发货状态
+     * **/
+    void batchUpadte(@Param("list") List<String> list);
+
+    void batchUpadteFailed(@Param("list") List<String> list);
 }

+ 5 - 0
fs-service/src/main/java/com/fs/hisStore/service/IFsStorePaymentScrmService.java

@@ -116,4 +116,9 @@ public interface IFsStorePaymentScrmService
     R getWxaCodeByPayment(FsStorePaymentGetWxaCodeParam param);
 
     R paymentByWxaCode(FsStorePaymentPayParam param);
+
+    /**
+     * 批量导入更新微信订单发货状态
+     * **/
+    R oneClickShipping();
 }

+ 94 - 0
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStorePaymentScrmServiceImpl.java

@@ -3,11 +3,16 @@ package com.fs.hisStore.service.impl;
 
 import java.math.BigDecimal;
 
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.stream.Collectors;
 
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
+import cn.binarywang.wx.miniapp.bean.shop.request.shipping.*;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
@@ -37,8 +42,10 @@ import com.fs.his.service.IFsUserService;
 import com.fs.his.service.IFsUserWxService;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.his.utils.HttpUtil;
+import com.fs.hisStore.config.StoreConfig;
 import com.fs.hisStore.enums.SysConfigEnum;
 import com.fs.hisStore.param.*;
+import com.fs.hisStore.vo.FsStorePaymentUsetVo;
 import com.fs.huifuPay.domain.HuiFuCreateOrder;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
 import com.fs.huifuPay.service.HuiFuService;
@@ -48,6 +55,7 @@ import com.fs.hisStore.vo.FsStorePaymentStatisticsVO;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
 import com.fs.system.service.ISysConfigService;
+import com.fs.utils.TwelveDigitSnowflake;
 import com.fs.wx.miniapp.config.WxMaProperties;
 import com.fs.hisStore.domain.FsUserScrm;
 import com.fs.hisStore.service.IFsUserScrmService;
@@ -906,4 +914,90 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
             return R.error(result.getResp_desc());
         }
     }
+
+    @Override
+    public R oneClickShipping() {
+        try {
+            StringBuilder builder = new StringBuilder();
+            //获取商城配置
+            String json = configService.selectConfigByKey("store.config");
+            StoreConfig config = JSONUtil.toBean(json, StoreConfig.class);
+            //验证是否开启微信发货
+            if (config.getIsWeChatShipping() != null && config.getIsWeChatShipping()) {
+                //获取支付信息
+                String[] appIds = config.getWeChatShippingAppIds().split(",");
+                List<FsStorePaymentUsetVo> paymentList = fsStorePaymentMapper.getPaymentUsetInfoList(appIds);
+                if (paymentList.isEmpty()) {
+                    return R.ok("操作成功,暂无同步订单信息!");
+                }
+                String uploadTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"))
+                        .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+                Map<String, List<FsStorePaymentUsetVo>> paymentUsetVoMap = paymentList.stream().collect(Collectors.groupingBy(FsStorePaymentUsetVo::getAppId));
+                for (Map.Entry<String, List<FsStorePaymentUsetVo>> entry : paymentUsetVoMap.entrySet()) {
+                    List<String> successList = new ArrayList<>();
+                    List<String> failedList = new ArrayList<>();
+                    String appId = entry.getKey();
+                    List<FsStorePaymentUsetVo> userPayments = entry.getValue();
+                    final WxMaService wxService = WxMaConfiguration.getMaService(appId);
+                    if (!userPayments.isEmpty()) {
+                        for (FsStorePaymentUsetVo v : userPayments) {
+                            // 上传物流信息到微信
+                            if (uploadShippingInfoToWechat(wxService, v, uploadTime)) {
+                                successList.add(v.getBankTransactionId());
+                            }else {
+                                failedList.add(v.getBankTransactionId());
+                            }
+                        }
+                        //批量更新数据
+                        if (!successList.isEmpty()) {
+                            fsStorePaymentMapper.batchUpadte(successList);
+                        }
+                        if(!failedList.isEmpty()){
+                            fsStorePaymentMapper.batchUpadteFailed(failedList);
+                        }
+                    }
+                }
+            }
+            return R.ok(builder.toString().equals("") ? "操作成功!" : builder.toString());
+        } catch (Exception e) {
+            logger.error("导入发货单快递信息失败", e);
+            return R.error("导入失败:" + e.getMessage());
+        }
+    }
+
+    private boolean uploadShippingInfoToWechat(WxMaService wxService,
+                                               FsStorePaymentUsetVo dto,
+                                               String uploadTime) {
+        try {
+            WxMaOrderShippingInfoUploadRequest request = new WxMaOrderShippingInfoUploadRequest();
+            OrderKeyBean orderKeyBean = new OrderKeyBean();
+            orderKeyBean.setOrderNumberType(2);
+            orderKeyBean.setTransactionId(dto.getBankTransactionId());//交易订单号ID
+            request.setOrderKey(orderKeyBean);
+            request.setDeliveryMode(1);
+            request.setLogisticsType(4);
+            List<ShippingListBean> shippingList = new ArrayList<>();
+            ShippingListBean shippingListBean = new ShippingListBean();
+            //默认物品信息
+            shippingListBean.setTrackingNo(String.valueOf(new TwelveDigitSnowflake(1).nextId()));
+            shippingListBean.setExpressCompany("FS");
+            shippingListBean.setItemDesc("默认商品");
+            ContactBean contactBean = new ContactBean();
+            contactBean.setReceiverContact(dto.getPhone());
+            shippingListBean.setContact(contactBean);
+
+            shippingList.add(shippingListBean);
+            request.setShippingList(shippingList);
+            request.setUploadTime(uploadTime);
+            // 设置支付者信息
+            PayerBean payerBean = new PayerBean();
+            payerBean.setOpenid(dto.getOpenId());
+            request.setPayer(payerBean);
+            // 上传物流信息
+            return wxService.getWxMaOrderShippingService().upload(request).getErrCode() == 0;
+        } catch (Exception e) {
+            logger.error("上传物流信息到微信失败,订单号: {}", dto.getBankTransactionId(), e);
+            return false;
+        }
+    }
 }

+ 20 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStorePaymentUsetVo.java

@@ -0,0 +1,20 @@
+package com.fs.hisStore.vo;
+
+import lombok.Data;
+
+@Data
+public class FsStorePaymentUsetVo {
+    //交易订单号
+    private String bankTransactionId;
+
+    //openId
+    private String openId;
+
+    //手机号
+    private String phone;
+
+    /**
+     * appId
+     * **/
+    private String appId;
+}

+ 89 - 0
fs-service/src/main/java/com/fs/utils/TwelveDigitSnowflake.java

@@ -0,0 +1,89 @@
+package com.fs.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class TwelveDigitSnowflake {
+    private final long START_TIMESTAMP = 1672502400000L;
+    private final long MACHINE_BIT = 5;
+    private final long SEQUENCE_BIT = 7;
+    private final long TIMESTAMP_BIT = 30;
+    private final long MAX_MACHINE_NUM = ~(-1L << MACHINE_BIT);
+    private final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);
+
+    private final long MACHINE_LEFT = SEQUENCE_BIT;
+    private final long TIMESTAMP_LEFT = SEQUENCE_BIT + MACHINE_BIT;
+
+    private long machineId;
+    private long sequence = 0L;
+    private long lastTimeStamp = -1L;
+
+    // 构造函数,传入机器ID
+    public TwelveDigitSnowflake(long machineId) {
+        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
+            throw new IllegalArgumentException("机器ID超出范围");
+        }
+        this.machineId = machineId;
+    }
+
+    // 生成下一个ID
+    public synchronized long nextId() {
+        long currentTimeStamp = getCurrentTimeStamp();
+
+        // 处理时钟回拨
+        if (currentTimeStamp < lastTimeStamp) {
+            long offset = lastTimeStamp - currentTimeStamp;
+            if (offset <= 5) {
+                try {
+                    wait(offset);
+                    currentTimeStamp = getCurrentTimeStamp();
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            } else { // 超过5毫秒回拨,抛出异常
+                throw new RuntimeException("时钟回拨异常,无法生成ID");
+            }
+        }
+
+        if (currentTimeStamp == lastTimeStamp) {
+            sequence = (sequence + 1) & MAX_SEQUENCE;
+            if (sequence == 0) {
+                currentTimeStamp = getNextMill();
+            }
+        } else {
+            sequence = 0L;
+        }
+
+        lastTimeStamp = currentTimeStamp;
+
+        // 组合ID:时间戳 + 机器ID + 序列号
+        long id = ((currentTimeStamp - START_TIMESTAMP) << TIMESTAMP_LEFT)
+                | (machineId << MACHINE_LEFT)
+                | sequence;
+        return id;
+    }
+
+    private long getNextMill() {
+        long mill = getCurrentTimeStamp();
+        while (mill <= lastTimeStamp) {
+            mill = getCurrentTimeStamp();
+        }
+        return mill;
+    }
+
+    private long getCurrentTimeStamp() {
+        return System.currentTimeMillis();
+    }
+
+    public static void main(String[] args) {
+        TwelveDigitSnowflake snowflake = new TwelveDigitSnowflake(1);
+        Map<String,Long> check=new HashMap<>();
+        for (int i = 0; i < 10000000; i++) {
+            long id = snowflake.nextId();
+            if(check.containsKey(String.valueOf(id))){
+                throw new RuntimeException("雪花ID重复啦!!!!!!!");
+            }
+            check.put(String.valueOf(id),0L);
+        }
+    }
+}

+ 42 - 1
fs-service/src/main/resources/mapper/hisStore/FsStorePaymentScrmMapper.xml

@@ -28,10 +28,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="orderId"    column="order_id"    />
         <result property="isPayRemain"    column="is_pay_remain"    />
         <result property="payMode"    column="pay_mode"    />
+        <result property="appId"    column="app_id"    />
     </resultMap>
 
     <sql id="selectFsStorePaymentVo">
-        select payment_id,pay_mode, pay_code, pay_type_code, pay_money, pay_time, create_time, trade_no, user_id, open_id, business_type, business_order_id, status,remark,company_id,company_user_id,dept_id,bank_transaction_id,bank_serial_no,refund_money,refund_time,order_id,is_pay_remain from fs_store_payment_scrm
+        select payment_id,pay_mode, pay_code, pay_type_code, pay_money, pay_time, create_time, trade_no, user_id, open_id, business_type, business_order_id, status,remark,company_id,company_user_id,dept_id,bank_transaction_id,bank_serial_no,refund_money,refund_time,order_id,is_pay_remain,app_id from fs_store_payment_scrm
 
     </sql>
 
@@ -88,6 +89,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="orderId != null">order_id,</if>
             <if test="isPayRemain != null">is_pay_remain,</if>
             <if test="payMode != null">pay_mode,</if>
+            <if test="appId != null">app_id,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="payCode != null">#{payCode},</if>
@@ -112,6 +114,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="orderId != null">#{orderId},</if>
             <if test="isPayRemain != null">#{isPayRemain},</if>
             <if test="payMode != null">#{payMode},</if>
+            <if test="appId != null">#{appId},</if>
         </trim>
     </insert>
 
@@ -140,6 +143,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="orderId != null">order_id = #{orderId},</if>
             <if test="isPayRemain != null">is_pay_remain = #{isPayRemain},</if>
             <if test="payMode != null">pay_mode = #{payMode},</if>
+            <if test="appId != null">app_id = #{appId},</if>
         </trim>
         where payment_id = #{paymentId}
     </update>
@@ -192,5 +196,42 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </if>
     </select>
 
+    <select id="getPaymentUsetInfoList" resultType="com.fs.hisStore.vo.FsStorePaymentUsetVo">
+        SELECT
+            sp.bank_transaction_id,
+            sp.open_id,
+            sp.app_id,
+            CASE
+                WHEN TRIM(fu.phone) IS NOT NULL AND TRIM(fu.phone) != '' THEN fu.phone
+                ELSE CONCAT(
+                        ELT(FLOOR(1 + RAND() * 6), '13', '14', '15', '17', '18', '19'),
+                        LPAD(FLOOR(RAND() * 1000000000), 9, '0')
+                    )
+                END AS phone
+        FROM
+            fs_store_payment_scrm sp
+                LEFT JOIN fs_user fu ON sp.user_id = fu.user_id
+        WHERE
+            sp.status = 1    and sp.is_shipment = 0 and sp.business_type = 1 AND sp.pay_time > '2025-11-27 00:00:00'
+            and app_id in
+            <foreach item="appId" collection="appIds" open="(" separator="," close=")">
+                #{appId}
+            </foreach>
+
+            order by sp.pay_time desc LIMIT 500
+    </select>
+
+    <update id="batchUpadte">
+        update fs_store_payment_scrm set is_shipment = 1 where bank_transaction_id in
+        <foreach item="bankTransactionId" collection="list" open="(" separator="," close=")">
+            #{bankTransactionId}
+        </foreach>
+    </update>
 
+    <update id="batchUpadteFailed">
+        update fs_store_payment_scrm set is_shipment = -1 where bank_transaction_id in
+        <foreach item="bankTransactionId" collection="list" open="(" separator="," close=")">
+            #{bankTransactionId}
+        </foreach>
+    </update>
 </mapper>

+ 5 - 0
fs-user-app/src/main/java/com/fs/app/controller/store/StoreOrderScrmController.java

@@ -357,6 +357,7 @@ public class StoreOrderScrmController extends AppBaseController {
                 storePayment.setUserId(user.getUserId());
                 storePayment.setBusinessOrderId(order.getId().toString());
                 storePayment.setOrderId(order.getId());
+                storePayment.setAppId(param.getAppId());
                 fsStorePaymentMapper.insertFsStorePayment(storePayment);
 
                 if (fsPayConfig.getType().equals("hf")){
@@ -435,6 +436,7 @@ public class StoreOrderScrmController extends AppBaseController {
                 storePayment.setUserId(user.getUserId());
                 storePayment.setBusinessOrderId(order.getId().toString());
                 storePayment.setOrderId(order.getId());
+                storePayment.setAppId(param.getAppId());
                 fsStorePaymentMapper.insertFsStorePayment(storePayment);
 
                 FsStoreOrderScrm storeOrder = new FsStoreOrderScrm();
@@ -620,6 +622,7 @@ public class StoreOrderScrmController extends AppBaseController {
             storePayment.setBusinessOrderId(order.getId().toString());
             storePayment.setOrderId(order.getId());
             storePayment.setIsPayRemain(1);
+            storePayment.setAppId(param.getAppId());
             fsStorePaymentMapper.insertFsStorePayment(storePayment);
 
             if (fsPayConfig.getType().equals("hf")){
@@ -739,6 +742,7 @@ public class StoreOrderScrmController extends AppBaseController {
             storePayment.setUserId(user.getUserId());
             storePayment.setBusinessOrderId(order.getId().toString());
             storePayment.setOrderId(order.getId());
+//            storePayment.setAppId(para);
             fsStorePaymentMapper.insertFsStorePayment(storePayment);
 
             if (fsPayConfig.getType().equals("hf")){
@@ -859,6 +863,7 @@ public class StoreOrderScrmController extends AppBaseController {
             storePayment.setBusinessOrderId(order.getId().toString());
             storePayment.setOrderId(order.getId());
             storePayment.setIsPayRemain(1);
+//            storePayment.setAppId(param.get);
             fsStorePaymentMapper.insertFsStorePayment(storePayment);
 
             if (fsPayConfig.getType().equals("hf")){