diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/api/shouman/JsonOrderCreationRequestBody.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/api/shouman/JsonOrderCreationRequestBody.java
new file mode 100644
index 000000000..896817d18
--- /dev/null
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/api/shouman/JsonOrderCreationRequestBody.java
@@ -0,0 +1,18 @@
+package org.jeecg.modules.business.domain.api.shouman;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+
+public class JsonOrderCreationRequestBody extends OrderCreationRequestBody {
+
+ private final String jsonString;
+ public JsonOrderCreationRequestBody(String jsonString) {
+ super(null, null);
+ this.jsonString = jsonString;
+ }
+
+ @Override
+ public JSONObject parameters() {
+ return JSON.parseObject(jsonString);
+ }
+}
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/api/shouman/OrderCreationRequest.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/api/shouman/OrderCreationRequest.java
new file mode 100644
index 000000000..dd21ab36c
--- /dev/null
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/api/shouman/OrderCreationRequest.java
@@ -0,0 +1,8 @@
+package org.jeecg.modules.business.domain.api.shouman;
+
+public class OrderCreationRequest extends Request {
+
+ public OrderCreationRequest(JsonOrderCreationRequestBody body) {
+ super(body);
+ }
+}
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/api/shouman/Request.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/api/shouman/Request.java
new file mode 100644
index 000000000..92ffbb4a3
--- /dev/null
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/api/shouman/Request.java
@@ -0,0 +1,104 @@
+package org.jeecg.modules.business.domain.api.shouman;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.parser.Feature;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.jeecg.common.util.RestUtil;
+import org.jeecg.modules.business.entity.Shouman.ShoumanOrder;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * This class contains some key information and necessary procedures
+ * to send a request body to ShouMan API, for example target URL,
+ * correspondent HTTP method, procedure to generate authorization.
+ *
+ * Subclass should implement the send() method by specifying the real response class and constructing it.
+ */
+@Slf4j
+public abstract class Request {
+ private final static String BASE_URL = "http://xmsmdz.xyldiy.com:8012/api";
+ private static final HttpMethod METHOD = HttpMethod.POST;
+ private static final String KEY = "BpQWy6AtvKcixjePQ4ZMuvBqUyIsXWWX";
+ private static final String SHOP_CODE = "8ee5c82004c44049b9f22a0ed8dc4db3";
+ private static final String SHIPPING_SERVICE_LEVEL_CATEGORY = "Standard";
+ private final RequestBody body;
+
+ public Request(RequestBody body) {
+ this.body = body;
+ }
+
+ /**
+ * Sent request to the mabang API with a request body.
+ *
+ * @return the response of the body or null, if response
+ */
+ public ResponseEntity rawSend(ShoumanOrder shoumanOrder) {
+ int attempts = 0;
+ HttpHeaders headers = new HttpHeaders();
+ headers.add(HttpHeaders.CONTENT_TYPE, "application/json");
+
+ String bodyString = generateJsonBodyString(body);
+ String signatureString = generateSignForJson(bodyString);
+ String signatureMd5 = DigestUtils.md5Hex(signatureString).toUpperCase();
+ shoumanOrder.setSignatureString(signatureString);
+ shoumanOrder.setSignatureMd5(signatureMd5);
+ headers.add("signature", signatureMd5);
+ while (attempts++ < 5) {
+ try {
+ return RestUtil.request(BASE_URL + body.path(), METHOD, headers, null, bodyString, String.class);
+ } catch (Exception e) {
+ log.error("Request failed on attempt n°" + attempts);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Convert body's json parameters to json string with the necessary extra parameter to
+ * send request.
+ *
+ * @param body body to convert
+ * @return json string
+ */
+ private static String generateJsonBodyString(RequestBody body) {
+ JSONObject param = new JSONObject();
+ param.putAll(body.parameters());
+ param.put("shipmentServiceLevelCategory", SHIPPING_SERVICE_LEVEL_CATEGORY);
+ param.put("isSendStandardPro", true);
+ param.put("shopCode", SHOP_CODE);
+ return param.toJSONString();
+ }
+
+ private static String generateSignForJson(String jsonString) {
+ log.info("JSON:{}", jsonString);
+ if (jsonString.isEmpty()) {
+ return null;
+ }
+ JSONObject jsonObject = JSONObject.parseObject(jsonString, Feature.OrderedField);
+ Map maps = jsonObject.getInnerMap();
+ ArrayList arrayList = new ArrayList<>();
+ for (Map.Entry entry : maps.entrySet()) {
+ arrayList.add(entry.getKey() + "=" + entry.getValue() + "&");
+ }
+ if (arrayList.isEmpty()) {
+ return null;
+ }
+ String[] strArray = arrayList.toArray(new String[0]);
+ Arrays.sort(strArray);
+ StringBuilder stringBuffer = new StringBuilder();
+ for (String param : strArray) {
+ stringBuffer.append(param);
+ }
+ String params = stringBuffer + "key=" + KEY;
+ log.info("Signature:{}", params);
+ return params;
+ }
+}
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/ShoumanOrderSendJob.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/ShoumanOrderSendJob.java
new file mode 100644
index 000000000..48cf22683
--- /dev/null
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/ShoumanOrderSendJob.java
@@ -0,0 +1,70 @@
+package org.jeecg.modules.business.domain.job;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.modules.business.domain.api.shouman.JsonOrderCreationRequestBody;
+import org.jeecg.modules.business.domain.api.shouman.OrderCreationRequest;
+import org.jeecg.modules.business.domain.api.shouman.OrderCreationRequestBody;
+import org.jeecg.modules.business.domain.api.shouman.Request;
+import org.jeecg.modules.business.entity.Country;
+import org.jeecg.modules.business.entity.Shouman.ShoumanOrder;
+import org.jeecg.modules.business.entity.ShoumanOrderContent;
+import org.jeecg.modules.business.mapper.CountryMapper;
+import org.jeecg.modules.business.mapper.PlatformOrderContentMapper;
+import org.jeecg.modules.business.service.IShoumanOrderService;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static java.util.stream.Collectors.toMap;
+
+@Slf4j
+public class ShoumanOrderSendJob implements Job {
+
+ @Autowired
+ private IShoumanOrderService shoumanOrderService;
+
+ @Override
+ public void execute(JobExecutionContext context) throws JobExecutionException {
+ log.info("Started Shouman order send job");
+ List shoumanOrders = shoumanOrderService.findShoumanOrderToSend();
+ log.info("Retrieved {} Shouman orders to send to ShoumanAPI", shoumanOrders.size());
+
+ log.info("Started building and sending Shouman order requests");
+ for (ShoumanOrder shoumanOrder : shoumanOrders) {
+ String platformOrderId = shoumanOrder.getPlatformOrderId();
+ log.info("Started building Shouman Order {}", platformOrderId);
+ OrderCreationRequest request = new OrderCreationRequest(new JsonOrderCreationRequestBody(shoumanOrder.getOrderJson()));
+ log.info("Finished building Shouman Order {}", platformOrderId);
+ log.info("Started sending Shouman Order {}", platformOrderId);
+ String resultString = request.rawSend(shoumanOrder).getBody();
+ log.info("Finished sending Shouman Order {}", platformOrderId);
+ JSONObject json = JSON.parseObject(resultString);
+ Object status = json.get("status");
+ if (status != null) {
+ if (((Integer) status) == 1) {
+ log.info("Shouman Order {} ended with success", platformOrderId);
+ shoumanOrder.setSuccess(status.toString());
+ } else {
+ log.info("Shouman Order {} failed", platformOrderId);
+ }
+ }
+ }
+ log.info("Finished building and sending Shouman order requests");
+
+ log.info("Started updating Shouman Orders in DB");
+ shoumanOrderService.updateBatchById(shoumanOrders);
+ log.info("Finished updating Shouman Orders in DB");
+
+ log.info("Finished Shouman order send job");
+ }
+
+}