Browse Source

微信扫码订单线下自提一键发货功能,注意(fsStorePaymentMapper.getPaymentUsetInfoList查询方法自己按照实际情况调整查询日期)

yjwang 1 day ago
parent
commit
95cf539d5e

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

@@ -334,4 +334,20 @@ public class FsStorePaymentScrmController extends BaseController
     {
     {
         return toAjax(fsStorePaymentService.deleteFsStorePaymentByIds(paymentIds));
         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();
+    }
 }
 }

+ 12 - 0
fs-service/src/main/java/com/fs/hisStore/mapper/FsStorePaymentScrmMapper.java

@@ -9,6 +9,7 @@ import com.fs.hisStore.domain.FsStorePaymentScrm;
 import com.fs.hisStore.param.FsStorePaymentParam;
 import com.fs.hisStore.param.FsStorePaymentParam;
 import com.fs.hisStore.param.FsStoreStatisticsParam;
 import com.fs.hisStore.param.FsStoreStatisticsParam;
 import com.fs.hisStore.vo.FsStorePaymentStatisticsVO;
 import com.fs.hisStore.vo.FsStorePaymentStatisticsVO;
+import com.fs.hisStore.vo.FsStorePaymentUsetVo;
 import com.fs.hisStore.vo.FsStorePaymentVO;
 import com.fs.hisStore.vo.FsStorePaymentVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Select;
@@ -371,4 +372,15 @@ public interface FsStorePaymentScrmMapper
 
 
     @Select("select * from fs_store_payment_scrm where pay_code=#{payCode}")
     @Select("select * from fs_store_payment_scrm where pay_code=#{payCode}")
     FsStorePaymentScrm selectFsStorePaymentByPaymentCode(String payCode);
     FsStorePaymentScrm selectFsStorePaymentByPaymentCode(String payCode);
+
+    /**
+     * 获取查询用户支付信息
+     * @return list
+     **/
+    List<FsStorePaymentUsetVo> getPaymentUsetInfoList();
+
+    /**
+     * 批量更新发货状态
+     * **/
+    void batchUpadte(@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 getWxaCodeByPayment(FsStorePaymentGetWxaCodeParam param);
 
 
     R paymentByWxaCode(FsStorePaymentPayParam param);
     R paymentByWxaCode(FsStorePaymentPayParam param);
+
+    /**
+     * 批量导入更新微信订单发货状态
+     * **/
+    R oneClickShipping();
 }
 }

+ 93 - 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.math.BigDecimal;
 
 
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.*;
+import java.util.stream.Collectors;
 
 
 
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 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.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSON;
@@ -41,8 +46,10 @@ import com.fs.his.service.IFsUserService;
 import com.fs.his.service.IFsUserWxService;
 import com.fs.his.service.IFsUserWxService;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.his.utils.HttpUtil;
 import com.fs.his.utils.HttpUtil;
+import com.fs.hisStore.config.StoreConfig;
 import com.fs.hisStore.enums.SysConfigEnum;
 import com.fs.hisStore.enums.SysConfigEnum;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.param.*;
+import com.fs.hisStore.vo.FsStorePaymentUsetVo;
 import com.fs.huifuPay.domain.HuiFuCreateOrder;
 import com.fs.huifuPay.domain.HuiFuCreateOrder;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
 import com.fs.huifuPay.sdk.opps.core.utils.HuiFuUtils;
 import com.fs.huifuPay.sdk.opps.core.utils.HuiFuUtils;
@@ -53,6 +60,7 @@ import com.fs.hisStore.vo.FsStorePaymentStatisticsVO;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
 import com.fs.system.oss.OSSFactory;
 import com.fs.system.service.ISysConfigService;
 import com.fs.system.service.ISysConfigService;
+import com.fs.utils.TwelveDigitSnowflake;
 import com.fs.wx.miniapp.config.WxMaProperties;
 import com.fs.wx.miniapp.config.WxMaProperties;
 import com.fs.hisStore.domain.FsUserScrm;
 import com.fs.hisStore.domain.FsUserScrm;
 import com.fs.hisStore.service.IFsUserScrmService;
 import com.fs.hisStore.service.IFsUserScrmService;
@@ -71,6 +79,7 @@ import com.github.binarywang.wxpay.service.WxPayService;
 import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
 import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
 import com.google.common.reflect.TypeToken;
 import com.google.common.reflect.TypeToken;
 import com.google.gson.Gson;
 import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.error.WxErrorException;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
@@ -91,6 +100,7 @@ import javax.servlet.http.HttpServletRequest;
  * @date 2022-06-20
  * @date 2022-06-20
  */
  */
 @Service
 @Service
+@Slf4j
 public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
 public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
 {
 {
     Logger logger = LoggerFactory.getLogger(getClass());
     Logger logger = LoggerFactory.getLogger(getClass());
@@ -949,4 +959,87 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
             return R.error(result.getResp_desc());
             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()) {
+                //获取支付信息
+                List<FsStorePaymentUsetVo> paymentList = fsStorePaymentMapper.getPaymentUsetInfoList();
+                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<>();
+                    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 {
+                                successList.add(v.getBankTransactionId());
+                            }
+                        }
+                        //批量更新数据
+                        if (!successList.isEmpty()) {
+                            fsStorePaymentMapper.batchUpadte(successList);
+                        }
+                    }
+                }
+            }
+
+
+            return R.ok(builder.toString().equals("") ? "操作成功!" : builder.toString());
+        } catch (Exception e) {
+            log.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) {
+            log.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);
+        }
+    }
+}

+ 24 - 0
fs-service/src/main/resources/mapper/hisStore/FsStorePaymentScrmMapper.xml

@@ -200,5 +200,29 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </if>
         </if>
     </select>
     </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' 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>
 </mapper>
 </mapper>