完成基本京粉功能推送,订单统计,订单拉取的稳定版初版

This commit is contained in:
Leo
2024-11-11 00:02:27 +08:00
parent 19f1095a7c
commit 9c1c18b71d
38 changed files with 4628 additions and 185 deletions

17
.idea/dataSources.xml generated
View File

@@ -1,13 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="jd@134.175.126.60" uuid="eb8a6f9c-c8ff-4224-9875-8dd3cf91a680">
<data-source source="LOCAL" name="@192.168.8.88" uuid="d0f6174d-14a9-4a99-9dfa-6f782ed4fa8d">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<imported>true</imported>
<remarks>$PROJECT_DIR$/src/main/resources/application.yml</remarks>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://134.175.126.60:33306/jd?characterEncoding=utf-8&amp;useSSL=true&amp;serverTimezone=GMT</jdbc-url>
<jdbc-url>jdbc:mysql://192.168.8.88:3306/?characterEncoding=utf-8&amp;useSSL=true&amp;serverTimezone=GMT</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
@@ -16,5 +15,17 @@
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
<data-source source="LOCAL" name="7@192.168.8.88" uuid="02bd8878-dd85-4337-9b25-55ca707e2a81">
<driver-ref>redis</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>jdbc.RedisDriver</jdbc-driver>
<jdbc-url>jdbc:redis://192.168.8.88:6379/7</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
<property name="com.intellij.clouds.kubernetes.db.container.port" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

9
.idea/jpa.xml generated Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JpaBuddyIdeaProjectConfig">
<option name="defaultUnitInitialized" value="true" />
<option name="reLastEntityCreationPackage" value="src/main/java/cn/van/business/model" />
<option name="renamerInitialized" value="true" />
<option name="reverseEngineeringLastDbConnectionId" value="d0f6174d-14a9-4a99-9dfa-6f782ed4fa8d__jd" />
</component>
</project>

5
.idea/misc.xml generated
View File

@@ -11,4 +11,7 @@
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8(202)" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
<component name="ProjectType">
<option name="id" value="jpab" />
</component>
</project>

1
.idea/sqldialects.xml generated
View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/src/main/java/cn/van/business/model/update-schema.sql" dialect="GenericSQL" />
<file url="PROJECT" dialect="MySQL" />
</component>
</project>

124
.idea/uiDesigner.xml generated Normal file
View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

12
pom.xml
View File

@@ -65,13 +65,16 @@
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.8</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
@@ -82,6 +85,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- Maven 插件 -->

View File

@@ -1,4 +1,4 @@
package cn.van.business.controller;
package cn.van.business.controller.jd;
import cn.van.business.util.JDUtils;
import org.springframework.web.bind.annotation.RequestMapping;

View File

@@ -0,0 +1,85 @@
package cn.van.business.controller.wx;
import cn.van.business.model.wx.WxMessage;
import cn.van.business.util.WxMessageConsumer;
import com.alibaba.fastjson2.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Leo
* @version 1.0
* @create 2023/12/18 0018 下午 05:12V
* @description
*/
@Controller
@RequestMapping("/wx")
@RestController
public class WXListener {
private static final Logger logger = LoggerFactory.getLogger(WXListener.class);
@Autowired
private WxMessageConsumer wxMessageConsumer;
/**
* {
* "event": 10009,
* "wxid": "wxid_kr145nk7l0an31",
* "data": {
* "type": "D0003",* "des": "鏀跺埌娑堟伅",
* "data": {
* "timeStamp": "1702951964728",
* "fromType": 1,
* "msgType": 1,
* "msgSource": 0,
* "fromWxid": "wxid_ytpc72mdoskt22",
* "finalFromWxid": "",
* "atWxidList": [],
* "silence": 0,
* "membercount": 0,
* "signature": "v1_MllZwZMZ",
* "msg": "785",
* "msgBase64": "Nzg1"
* },
* "timestamp": "1702951964740",
* "wxid": "wxid_kr145nk7l0an31",
* "port": 16888,
* "pid": 10468,
* "flag": "7777"
* }
* }
**/
@RequestMapping("/message")
public String message(@RequestBody String requestBody) throws Exception {
WxMessage message = JSONObject.parseObject(requestBody, WxMessage.class);
wxMessageConsumer.consume(message);
return "OK";
}
//@RequestMapping("/test")
//public String test(@RequestBody String requestBody) {
//
// System.out.println("测试接口收到数据:");
// System.out.println(requestBody);
// return "OK";
//}
//@RequestMapping("/receive_msg")
//public String receiveMsg(@RequestBody String requestBody) throws Exception {
//
// System.out.println("测试接口收到数据:");
// System.out.println(requestBody);
// WxMessage message = JSONObject.parseObject(requestBody, WxMessage.class);
// wxMessageConsumer.consume(message);
//
// return "OK";
//}
}

View File

@@ -0,0 +1,94 @@
package cn.van.business.enums;
/**
* @author Leo
* @version 1.0
* @create 2023/12/19 0019 上午 10:27
* @description
*/
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public enum EventType implements IEnum {
// New Events
INJECTED_SUCCESS(10000, "注入成功"),
ACCOUNT_CHANGED(10014, "账号变动事件"),
GROUP_MESSAGE_RECEIVED(10008, "收到群聊消息"),
PRIVATE_MESSAGE_RECEIVED(10009, "收到私聊消息"),
OWN_MESSAGE_SENT(10010, "自己发出消息"),
TRANSFER_EVENT(10006, "转账事件"),
REVOKE_EVENT(10013, "撤回事件"),
FRIEND_REQUEST(10011, "好友请求"),
PAYMENT_EVENT(10007, "支付事件"),
AUTH_EXPIRED(99999, "授权到期"),
QR_CODE_PAYMENT_RECEIVED(10015, "二维码收款事件"),
GROUP_MEMBER_CHANGED(10016, "群成员变动事件");
private final int key;
private final String name;
EventType(int key, String name) {
this.key = key;
this.name = name;
}
public static EventType get(int key) {
for (EventType e : EventType.values()) {
if (e.getKey() == key) {
return e;
}
}
return null;
}
public static String getName(Integer key) {
//if (Object.isNotEmpty(key)) {
EventType[] items = EventType.values();
for (EventType item : items) {
if (item.getKey() == key) {
return item.getName();
}
}
//}
return "";
}
public static Map<String, String> getKeyValue() {
Map<String, String> map = new HashMap<>();
EventType[] items = EventType.values();
for (EventType item : items) {
map.put(item.getKey() + "", item.getName());
}
return map;
}
public static List<Map<String, Object>> getSelectItems() {
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
EventType[] items = EventType.values();
for (EventType item : items) {
Map<String, Object> map = new HashMap<>();
map.put("label", item.getName());
map.put("value", item.getKey());
result.add(map);
}
return result;
}
@Override
@JsonValue
public Integer getKey() {
return key;
}
@Override
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,87 @@
package cn.van.business.enums;
/**
* @author Leo
* @version 1.0
* @create 2023/12/19 0019 上午 10:27
* @description
*/
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public enum FromType implements IEnum {
/**
* fromType 来源类型1|私聊 2|群聊 3|公众号
*/
PRIVATE(10009, "私聊"),
GROUP(10008, "群聊"),
MP(3, "公众号");
private final int key;
private final String name;
FromType(int key, String name) {
this.key = key;
this.name = name;
}
public static FromType get(int key) {
for (FromType e : FromType.values()) {
if (e.getKey() == key) {
return e;
}
}
return null;
}
public static String getName(Integer key) {
//if (Object.isNotEmpty(key)) {
FromType[] items = FromType.values();
for (FromType item : items) {
if (item.getKey() == key) {
return item.getName();
}
}
//}
return "";
}
public static Map<String, String> getKeyVlue() {
Map<String, String> map = new HashMap<>();
FromType[] items = FromType.values();
for (FromType item : items) {
map.put(item.getKey() + "", item.getName());
}
return map;
}
public static List<Map<String, Object>> getSelectItems() {
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
FromType[] items = FromType.values();
for (FromType item : items) {
Map<String, Object> map = new HashMap<>();
map.put("label", item.getName());
map.put("value", item.getKey());
result.add(map);
}
return result;
}
@Override
@JsonValue
public Integer getKey() {
return key;
}
@Override
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,14 @@
package cn.van.business.enums;
/**
* @author Leo
* @version 1.0
* @create 2023/12/19 0019 上午 10:33
* @description
*/
public interface IEnum {
Integer getKey();
String getName();
}

View File

@@ -0,0 +1,14 @@
package cn.van.business.enums;
/**
* @author Leo
* @version 1.0
* @create 2023/12/19 0019 上午 10:33
* @description
*/
public interface IEnumForString {
String getKey();
String getName();
}

View File

@@ -0,0 +1,94 @@
package cn.van.business.enums;
/**
* @author Leo
* @version 1.0
* @create 2023/12/19 0019 上午 10:27
* @description
*/
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public enum JdOrderType implements IEnum {
// New Events
INJECTED_SUCCESS(10000, "注入成功"),
ACCOUNT_CHANGED(10014, "账号变动事件"),
GROUP_MESSAGE_RECEIVED(10008, "收到群聊消息"),
PRIVATE_MESSAGE_RECEIVED(10009, "收到私聊消息"),
OWN_MESSAGE_SENT(10010, "自己发出消息"),
TRANSFER_EVENT(10006, "转账事件"),
REVOKE_EVENT(10013, "撤回事件"),
FRIEND_REQUEST(10011, "好友请求"),
PAYMENT_EVENT(10007, "支付事件"),
AUTH_EXPIRED(99999, "授权到期"),
QR_CODE_PAYMENT_RECEIVED(10015, "二维码收款事件"),
GROUP_MEMBER_CHANGED(10016, "群成员变动事件");
private final int key;
private final String name;
JdOrderType(int key, String name) {
this.key = key;
this.name = name;
}
public static JdOrderType get(int key) {
for (JdOrderType e : JdOrderType.values()) {
if (e.getKey() == key) {
return e;
}
}
return null;
}
public static String getName(Integer key) {
//if (Object.isNotEmpty(key)) {
JdOrderType[] items = JdOrderType.values();
for (JdOrderType item : items) {
if (item.getKey() == key) {
return item.getName();
}
}
//}
return "";
}
public static Map<String, String> getKeyValue() {
Map<String, String> map = new HashMap<>();
JdOrderType[] items = JdOrderType.values();
for (JdOrderType item : items) {
map.put(item.getKey() + "", item.getName());
}
return map;
}
public static List<Map<String, Object>> getSelectItems() {
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
JdOrderType[] items = JdOrderType.values();
for (JdOrderType item : items) {
Map<String, Object> map = new HashMap<>();
map.put("label", item.getName());
map.put("value", item.getKey());
result.add(map);
}
return result;
}
@Override
@JsonValue
public Integer getKey() {
return key;
}
@Override
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,91 @@
package cn.van.business.enums;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Leo
* @version 1.0
* @create 2023/12/19 0019 下午 02:31
* @description
*/
public enum MsgTypeEnum implements IEnum {
/**
msgType
1|文本 3|图片 34|语音
42|名片 43|视频 47|动态表情
48|地理位置 49|分享链接或附件 2001|红包
2002|小程序 2003|群邀请 10000|系统消息 * */
TEXT(1, "文本"),
IMAGE(3, "图片"),
VOICE(34, "语音"),
ANIMATION(47, "动态表情"),
//名片 42
CARD(42, "名片"),
VIDEO(43, "视频"),
SHARE(49, "分享链接或附件"),
LOCATION(48, "位置"),
REDPACKET(2001, "红包"),
MINIPROGRAM(2002, "小程序"),
GROUP_INVITE(2003, "群邀请"),
SYSTEM(10000, "系统消息"),
;
private final int key;
private final String name;
MsgTypeEnum(int key, String name) {
this.key = key;
this.name = name;
}
public static String getName(Integer key) {
for (MsgTypeEnum msgTypeEnum : MsgTypeEnum.values()) {
if (msgTypeEnum.key == key) {
return msgTypeEnum.name;
}
}
return null;
}
public static Map<String, String> getKeyVlue() {
Map<String, String> map = new HashMap<>();
for (MsgTypeEnum msgTypeEnum : MsgTypeEnum.values()) {
map.put(msgTypeEnum.key + "", msgTypeEnum.name);
}
return map;
}
public static List<Map<String, Object>> getSelectItems() {
List<Map<String, Object>> list = new ArrayList<>();
for (MsgTypeEnum msgTypeEnum : MsgTypeEnum.values()) {
Map<String, Object> map = new HashMap<>();
map.put("key", msgTypeEnum.key);
map.put("value", msgTypeEnum.name);
list.add(map);
}
return list;
}
public static MsgTypeEnum get(int key) {
for (MsgTypeEnum msgTypeEnum : MsgTypeEnum.values()) {
if (msgTypeEnum.key == key) {
return msgTypeEnum;
}
}
return null;
}
public Integer getKey() {
return key;
}
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,57 @@
package cn.van.business.enums;
import java.util.HashMap;
import java.util.Map;
/**
* @author Leo
* @version 1.0
* @create 2024/11/9 下午3:08
* @description
*/
public class ValidCodeConverter {
private static final Map<Integer, String> codeDescriptions = new HashMap<>();
static {
codeDescriptions.put(-1, "未知");
codeDescriptions.put(2, "无效-拆单");
codeDescriptions.put(3, "无效-取消");
codeDescriptions.put(4, "无效-京东帮帮主订单");
codeDescriptions.put(5, "无效-账号异常");
codeDescriptions.put(6, "无效-赠品类目不返佣");
codeDescriptions.put(7, "无效-校园订单");
codeDescriptions.put(8, "无效-企业订单");
codeDescriptions.put(9, "无效-团购订单");
codeDescriptions.put(11, "无效-乡村推广员下单");
codeDescriptions.put(13, "违规订单-其他");
codeDescriptions.put(14, "无效-来源与备案网址不符");
codeDescriptions.put(15, "待付款");
codeDescriptions.put(16, "已付款");
codeDescriptions.put(17, "已完成(购买用户确认收货)");
codeDescriptions.put(19, "无效-佣金比例为0");
codeDescriptions.put(20, "无效-此复购订单对应的首购订单无效");
codeDescriptions.put(21, "无效-云店订单");
codeDescriptions.put(22, "无效-PLUS会员佣金比例为0");
codeDescriptions.put(23, "无效-支付有礼");
codeDescriptions.put(24, "已付定金");
codeDescriptions.put(25, "违规订单-流量劫持");
codeDescriptions.put(26, "违规订单-流量异常");
codeDescriptions.put(27, "违规订单-违反京东平台规则");
codeDescriptions.put(28, "违规订单-多笔交易异常");
codeDescriptions.put(29, "无效-跨屏跨店");
codeDescriptions.put(30, "无效-累计件数超出类目上限");
codeDescriptions.put(31, "无效-黑名单sku");
codeDescriptions.put(33, "超市卡充值订单");
codeDescriptions.put(34, "无效-推卡订单无效");
}
/**
* 获取有效码所对应的描述
*
* @param code 有效码
* @return 对应的描述信息
*/
public String getCodeDescription(Integer code) {
return codeDescriptions.getOrDefault(code, "代码描述未定义");
}
}

View File

@@ -0,0 +1,129 @@
package cn.van.business.enums;
/**
* @author Leo
* @version 1.0
* @create 2023/12/19 0019 上午 10:27
* @description
*/
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
import java.util.*;
public enum WXReqType {
/**
* * 获取微信列表 (X0000)
* * 微信状态检测(Q0000)
* * 发送文本消息(Q0001)
* * 修改下载图片 (Q0002)
* * 获取个人信息 (Q0003)
* * 查询对象信(Q0004)
* * 获取好友列表(Q0005)
* * 获取群聊列表(Q0006)
* * 获取公众号列表(Q0007)
* * 获取群成员列表(Q0008)
* * 发送聊天记录(Q0009)
* * 发送图片 (Q0010)
* * 发送本地文件(Q0011)
* * 发送分享链接(Q0012)
* * 发送小程序(Q0013)
* * 发送音乐分享(Q0014)
* * 发送XML (Q0015)
* * 确认收款 (Q0016)
* * 同意好友请求(Q0017)
* * 添加好友通过v3(Q0018)
* * 添加好友_通过wxid (Q0019)
* * 查询陌生人信息(Q0020)
* * 邀请进群(Q0021)
* * 删除好友(Q0022)
* * 修改对象备注(Q0023)
* * 修改群聊名称(Q0024)
* * 发送名片(Q0025)
*/
GET_WX_LIST("getWeChatList", "获取微信列表"),
GET_WX_STATUS("checkWeChat", "微信状态检测"),
SEND_TEXT_MESSAGE("sendText", "发送文本消息"),
UPDATE_DOWNLOAD_IMAGE("Q0002", "修改下载图片"),
GET_USER_INFO("Q0003", "获取个人信息"),
QUERY_OBJECT_INFO("Q0004", "查询对象信"),
GET_FRIEND_LIST("Q0005", "获取好友列表"),
GET_GROUP_LIST("Q0006", "获取群聊列表"),
GET_MP_LIST("Q0007", "获取公众号列表"),
GET_GROUP_MEMBER_LIST("Q0008", "获取群成员列表"),
SEND_CHAT_RECORD("Q0009", "发送聊天记录"),
SEND_IMAGE("Q0010", "发送图片"),
SEND_LOCAL_FILE("Q0011", "发送本地文件"),
SEND_SHARE_LINK("Q0012", "发送分享链接"),
SEND_MINIPROGRAM("Q0013", "发送小程序"),
SEND_MUSIC_SHARE("Q0014", "发送音乐分享"),
SEND_XML("Q0015", "发送XML"),
CONFIRM_RECEIPT("Q0016", "确认收款"),
AGREE_FRIEND_REQUEST("Q0017", "同意好友请求"),
ADD_FRIEND_V3("Q0018", "添加好友通过v3"),
ADD_FRIEND_WXID("Q0019", "添加好友_通过wxid"),
QUERY_STRANGER_INFO("Q0020", "查询陌生人信息"),
INVITE_GROUP("Q0021", "邀请进群"),
DELETE_FRIEND("Q0022", "删除好友"),
MODIFY_OBJECT_REMARK("Q0023", "修改对象备注"),
MODIFY_GROUP_NAME("Q0024", "修改群聊名称");
private final String type;
@Getter
private final String name;
WXReqType(String type, String name) {
this.type = type;
this.name = name;
}
public static WXReqType get(String key) {
for (WXReqType e : WXReqType.values()) {
if (Objects.equals(e.getType(), key)) {
return e;
}
}
return null;
}
public static String getName(String key) {
//if (Object.isNotEmpty(key)) {
WXReqType[] items = WXReqType.values();
for (WXReqType item : items) {
if (Objects.equals(item.getType(), key)) {
return item.getName();
}
}
//}
return "";
}
public static Map<String, String> getKeyVlue() {
Map<String, String> map = new HashMap<>();
WXReqType[] items = WXReqType.values();
for (WXReqType item : items) {
map.put(item.getType() + "", item.getName());
}
return map;
}
public static List<Map<String, Object>> getSelectItems() {
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
WXReqType[] items = WXReqType.values();
for (WXReqType item : items) {
Map<String, Object> map = new HashMap<>();
map.put("label", item.getName());
map.put("value", item.getType());
result.add(map);
}
return result;
}
@JsonValue
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,86 @@
package cn.van.business.model.jd;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable;
/**
* @author Leo
* @version 1.0
* @create 2024/11/6 下午10:19
* @description
*/
public class CategoryInfoVO implements Serializable {
private Long cid1;
private Long cid2;
private Long cid3;
private String cid1Name;
private String cid2Name;
private String cid3Name;
public CategoryInfoVO() {
}
@JsonProperty("cid1")
public void setCid1(Long cid1) {
this.cid1 = cid1;
}
@JsonProperty("cid1")
public Long getCid1() {
return this.cid1;
}
@JsonProperty("cid2")
public void setCid2(Long cid2) {
this.cid2 = cid2;
}
@JsonProperty("cid2")
public Long getCid2() {
return this.cid2;
}
@JsonProperty("cid3")
public void setCid3(Long cid3) {
this.cid3 = cid3;
}
@JsonProperty("cid3")
public Long getCid3() {
return this.cid3;
}
@JsonProperty("cid1Name")
public void setCid1Name(String cid1Name) {
this.cid1Name = cid1Name;
}
@JsonProperty("cid1Name")
public String getCid1Name() {
return this.cid1Name;
}
@JsonProperty("cid2Name")
public void setCid2Name(String cid2Name) {
this.cid2Name = cid2Name;
}
@JsonProperty("cid2Name")
public String getCid2Name() {
return this.cid2Name;
}
@JsonProperty("cid3Name")
public void setCid3Name(String cid3Name) {
this.cid3Name = cid3Name;
}
@JsonProperty("cid3Name")
public String getCid3Name() {
return this.cid3Name;
}
}

View File

@@ -1,4 +1,4 @@
package cn.van.business.model;
package cn.van.business.model.jd;
import javax.persistence.*;

View File

@@ -1,4 +1,4 @@
package cn.van.business.model;
package cn.van.business.model.jd;
/**
* @author Leo

View File

@@ -1,74 +0,0 @@
CREATE TABLE goods_info
(
id BIGINT AUTO_INCREMENT NOT NULL,
owner VARCHAR(255) NULL,
main_sku_id VARCHAR(255) NULL,
product_id VARCHAR(255) NULL,
image_url VARCHAR(255) NULL,
shop_name VARCHAR(255) NULL,
shop_id VARCHAR(255) NULL,
CONSTRAINT pk_goods_info PRIMARY KEY (id)
);
CREATE TABLE order_rows
(
id VARCHAR(255) NOT NULL,
order_id BIGINT NULL,
parent_id BIGINT NULL,
order_time datetime NULL,
finish_time datetime NULL,
modify_time datetime NULL,
order_emt INT NULL,
plus INT NULL,
union_id BIGINT NULL,
sku_id BIGINT NULL,
sku_name VARCHAR(255) NULL,
sku_num INT NULL,
sku_return_num INT NULL,
sku_frozen_num INT NULL,
price DOUBLE NULL,
commission_rate DOUBLE NULL,
sub_side_rate DOUBLE NULL,
subsidy_rate DOUBLE NULL,
final_rate DOUBLE NULL,
estimate_cos_price DOUBLE NULL,
estimate_fee DOUBLE NULL,
actual_cos_price DOUBLE NULL,
actual_fee DOUBLE NULL,
valid_code INT NULL,
trace_type INT NULL,
position_id BIGINT NULL,
site_id BIGINT NULL,
union_alias VARCHAR(255) NULL,
pid VARCHAR(255) NULL,
cid1 BIGINT NULL,
cid2 BIGINT NULL,
cid3 BIGINT NULL,
sub_union_id VARCHAR(255) NULL,
union_tag VARCHAR(255) NULL,
pop_id BIGINT NULL,
ext1 VARCHAR(255) NULL,
pay_month VARCHAR(255) NULL,
cp_act_id BIGINT NULL,
union_role INT NULL,
gift_coupon_ocs_amount DOUBLE NULL,
gift_coupon_key VARCHAR(255) NULL,
balance_ext VARCHAR(255) NULL,
sign VARCHAR(255) NULL,
pro_price_amount DOUBLE NULL,
rid BIGINT NULL,
goods_info_id BIGINT NULL,
express_status INT NULL,
channel_id BIGINT NULL,
sku_tag VARCHAR(255) NULL,
item_id VARCHAR(255) NULL,
caller_item_id VARCHAR(255) NULL,
order_tag VARCHAR(255) NULL,
CONSTRAINT pk_order_rows PRIMARY KEY (id)
);
ALTER TABLE order_rows
ADD CONSTRAINT uc_order_rows_goods_info UNIQUE (goods_info_id);
ALTER TABLE order_rows
ADD CONSTRAINT FK_ORDER_ROWS_ON_GOODS_INFO FOREIGN KEY (goods_info_id) REFERENCES goods_info (id);

View File

@@ -0,0 +1,24 @@
package cn.van.business.model.wx;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
@Getter
@Setter
@Entity
@Table(name = "setting")
public class Setting {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "setting_key", nullable = false)
private String settingKey;
@Column(name = "setting_value")
private String settingValue;
}

View File

@@ -0,0 +1,59 @@
package cn.van.business.model.wx;
/**
* @author Leo
* @version 1.0
* @create 2024/11/8 下午10:58
* @description
*/
import lombok.Data;
import java.util.List;
/**
* Main class representing the structure of the received WX message.
*/
@Data
public class WxEventMessage {
private Integer event;
private String wxid;
private MessageData data;
/**
* Inner class to encapsulate the data section of the message.
*/
@Data
public static class MessageData {
private String type;
private String des;
private EventData data;
private Long timestamp;
private String wxid;
private Integer port;
private Integer pid;
private String flag;
/**
* Inner class to encapsulate the nested data section within the data.
*/
@Data
public static class EventData {
private Long timeStamp;
private Integer fromType;
private Integer msgType;
private Integer msgSource;
private String fromWxid;
private String finalFromWxid;
private List<String> atWxidList; // List to store the WX IDs in the atWxidList array.
private Integer silence;
private Integer membercount;
private String signature;
private String msg;
private String msgId;
private String msgBase64;
}
}
}

View File

@@ -0,0 +1,58 @@
package cn.van.business.model.wx;
/**
* @author Leo
* @version 1.0
* @create 2024/11/9 上午12:06
* @description
*/
import lombok.Data;
import java.util.List;
/**
* Entity class representing the structure of the WX message event.
*/
@Data
public class WxMessage {
private Integer event;
private String wxid;
private DataSection data;
/**
* Nested class to hold the data section of the WX message.
*/
@Data
public static class DataSection {
private String type;
private String des;
private InnerData data;
private Long timestamp;
private String wxid;
private Integer port;
private Integer pid;
private String flag;
/**
* Nested class for the innermost data structure.
*/
@Data
public static class InnerData {
private Long timeStamp;
private Integer fromType;
private Integer msgType;
private Integer msgSource;
private String fromWxid;
private String finalFromWxid;
private List<String> atWxidList;
private Integer silence;
private Integer membercount;
private String signature;
private String msg;
private String msgId;
private String msgBase64;
}
}
}

View File

@@ -0,0 +1,60 @@
package cn.van.business.model.wx;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
@Getter
@Setter
@Entity
@Table(name = "wx_message_data_for_chat")
public class WxMessageDataForChat {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "timeStamp")
private Long timeStamp;
@Column(name = "fromType")
private Integer fromType;
@Column(name = "msgType")
private Integer msgType;
@Column(name = "msgSource")
private Integer msgSource;
@Column(name = "fromWxid")
private String fromWxid;
@Column(name = "finalFromWxid")
private String finalFromWxid;
@Column(name = "atWxidList")
private String atWxidList;
@Column(name = "silence")
private Integer silence;
@Column(name = "membercount")
private Integer membercount;
@Column(name = "signature")
private String signature;
@Column(name = "msg", length = 1000)
private String msg;
@Column(name = "msgBase64", length = 1000)
private String msgBase64;
@Column(name = "msgId")
private String msgId;
@Column(name = "msgTypeStr")
private String msgTypeStr;
}

View File

@@ -0,0 +1,40 @@
package cn.van.business.model.wx;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.math.BigDecimal;
@Getter
@Setter
@Entity
@Table(name = "wx_message_data_for_transfer")
public class WxMessageDataForTransfer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "fromWxid", nullable = false)
private String fromWxid;
@Column(name = "msgSource")
private Integer msgSource;
@Column(name = "transType")
private Integer transType;
@Column(name = "money", precision = 10, scale = 2)
private BigDecimal money;
@Column(name = "memo")
private String memo;
@Column(name = "transferid", nullable = false)
private String transferid;
@Column(name = "invalidtime")
private Integer invalidtime;
}

View File

@@ -0,0 +1,40 @@
package cn.van.business.model.wx;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.math.BigDecimal;
@Getter
@Setter
@Entity
@Table(name = "wx_user")
public class WxUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "wxid", nullable = false)
private String wxid;
@Column(name = "money_leiji", precision = 10, scale = 2)
private BigDecimal moneyLeiji;
@Column(name = "money_shengyu", precision = 10, scale = 2)
private BigDecimal moneyShengyu;
@Column(name = "count_chongzhi", precision = 10, scale = 2)
private BigDecimal countChongzhi;
@Column(name = "count_xiaofei", precision = 10, scale = 2)
private BigDecimal countXiaofei;
@Column(name = "name")
private String name;
@Column(name = "status")
private Integer status;
}

View File

@@ -7,7 +7,7 @@ package cn.van.business.repository;
* @description
*/
import cn.van.business.model.OrderRow;
import cn.van.business.model.jd.OrderRow;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@@ -25,4 +25,8 @@ public interface OrderRowRepository extends JpaRepository<OrderRow, String> {
// 根据有效码查询订单行
List<OrderRow> findByValidCode(int validCode);
// 查找 validCode != 15 或者 !=-1 的订单行 ,并且按orderTime 降序
List<OrderRow> findByValidCodeNotInOrderByOrderTimeDesc(int[] validCodes);
}

View File

@@ -0,0 +1,17 @@
package cn.van.business.repository;
import cn.van.business.model.wx.Setting;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface SettingRepository extends JpaRepository<Setting, Integer> {
// Find a setting by its unique key
Optional<Setting> findBySettingKey(String settingKey);
// You could add more queries if needed, example:
// List<Setting> findBySettingKeyStartingWith(String prefix);
}

View File

@@ -0,0 +1,26 @@
package cn.van.business.repository;
import cn.van.business.model.wx.WxMessageDataForChat;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface WxMessageDataForChatRepository extends JpaRepository<WxMessageDataForChat, Integer> {
// 根据消息来源wxid查询消息记录
List<WxMessageDataForChat> findByFromWxid(String fromWxid);
// 根据消息类型查询消息记录
List<WxMessageDataForChat> findByMsgType(Integer msgType);
// 根据消息ID查询单条消息记录
WxMessageDataForChat findByMsgId(String msgId);
// 添加其他可能需要的自定义查询方法,例如:
// 根据消息类型和是否是静默消息查询
List<WxMessageDataForChat> findByMsgTypeAndSilence(Integer msgType, Integer silence);
// 根据消息来源和消息类型查询
List<WxMessageDataForChat> findByFromWxidAndMsgType(String fromWxid, Integer msgType);
}

View File

@@ -0,0 +1,30 @@
package cn.van.business.repository;
import cn.van.business.model.wx.WxMessageDataForTransfer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
import java.util.List;
@Repository
public interface WxMessageDataForTransferRepository extends JpaRepository<WxMessageDataForTransfer, Integer> {
// Find transfers by the sender's WeChat ID
List<WxMessageDataForTransfer> findByFromWxid(String fromWxid);
// Find a single transfer by its unique transfer ID
WxMessageDataForTransfer findByTransferid(String transferid);
// Find transfers by transaction type
List<WxMessageDataForTransfer> findByTransType(Integer transType);
// Find transfers that have a specific amount of money
List<WxMessageDataForTransfer> findByMoney(BigDecimal money);
// Optional: Find transfers by msgSource, which could represent different sources or contexts of the transactions
List<WxMessageDataForTransfer> findByMsgSource(Integer msgSource);
// Optional: Find transfers by their invalid time parameter
List<WxMessageDataForTransfer> findByInvalidtime(Integer invalidtime);
}

View File

@@ -0,0 +1,30 @@
package cn.van.business.repository;
import cn.van.business.model.wx.WxUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
@Repository
public interface WxUserRepository extends JpaRepository<WxUser, Integer> {
// Find users by their wxid
Optional<WxUser> findByWxid(String wxid);
// Find users by their name
List<WxUser> findByName(String name);
// Find users by status
List<WxUser> findByStatus(Integer status);
// Optional: Find users by the range of total accumulated money
List<WxUser> findByMoneyLeijiBetween(BigDecimal min, BigDecimal max);
// Optional: Find users by the remaining money
List<WxUser> findByMoneyShengyuLessThanEqual(BigDecimal amount);
// Add more customized queries as needed based on your application requirements
}

View File

@@ -1,17 +1,22 @@
package cn.van.business.util;
import cn.van.business.model.GoodsInfoVO;
import cn.van.business.model.OrderRow;
import cn.van.business.enums.ValidCodeConverter;
import cn.van.business.model.jd.GoodsInfoVO;
import cn.van.business.model.jd.OrderRow;
import cn.van.business.repository.OrderRowRepository;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.util.DateUtils;
import com.jd.open.api.sdk.DefaultJdClient;
import com.jd.open.api.sdk.JdClient;
import com.jd.open.api.sdk.domain.kplunion.OrderService.request.query.OrderRowReq;
import com.jd.open.api.sdk.domain.kplunion.OrderService.response.query.GoodsInfo;
import com.jd.open.api.sdk.domain.kplunion.OrderService.response.query.OrderRowResp;
import com.jd.open.api.sdk.domain.kplunion.promotioncommon.PromotionService.request.get.PromotionCodeReq;
import com.jd.open.api.sdk.request.kplunion.UnionOpenOrderRowQueryRequest;
import com.jd.open.api.sdk.request.kplunion.UnionOpenPromotionCommonGetRequest;
import com.jd.open.api.sdk.response.kplunion.UnionOpenOrderRowQueryResponse;
import com.jd.open.api.sdk.response.kplunion.UnionOpenPromotionCommonGetResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
@@ -21,9 +26,12 @@ import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import static java.lang.Thread.sleep;
@@ -37,109 +45,31 @@ import static java.lang.Thread.sleep;
public class JDUtils {
private static final String SERVER_URL =
"https://api.jd.com/routerjson";
// van论坛
private static final String APP_KEY =
"98e21c89ae5610240ec3f5f575f86a59";
private static final String SECRET_KEY =
"3dcb6b23a1104639ac433fd07adb6dfb";
// 导购的
//private static final String APP_KEY = "faf410cb9587dc80dc7b31e321d7d322";
//private static final String SECRET_KEY =
// "a4fb15d7bedd4316b97b4e96e4effc1c";
//accessToken
private static final String ACCESS_TOKEN = "";
//标记唯一订单行:订单+sku维度的唯一标识
private static final String ORDER_ROW_KEY = "jd:order:row:";
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private OrderRowRepository orderRowRepository;
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
/**
* 拉取最新的订单
*/
@Scheduled(cron = "0 * * * * ?") // 每分钟执行一次
public void fetchLatestOrder() throws Exception {
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastMinute = now.minusMinutes(1).withSecond(0).withNano(0);
UnionOpenOrderRowQueryResponse response = fetchOrdersForDateTime(lastMinute, true); // 真实代表实时订单
if (response != null){
int code = response.getQueryResult().getCode();
if (code == 200) {
if (response.getQueryResult().getCode() == 200) {
OrderRowResp[] orderRowResps = response.getQueryResult().getData();
if (orderRowResps == null) {
return;
}
for (OrderRowResp orderRowResp : orderRowResps) {
// 固化到数据库
OrderRow orderRow = createOrderRow(orderRowResp);
// 订单号不存在就保存,存在就更新订单状态
orderRowRepository.save(orderRow);
}
}
}
}
}
/**
* 拉取历史订单
*/
public void fetchHistoricalOrders() throws Exception {
// 从设定的开始日期到昨天的同一时间
LocalDateTime startDate = LocalDateTime.of(2024, 7, 1, 0, 0);
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastHour = now.minusHours(1).withMinute(0).withSecond(0).withNano(0);
while (!startDate.isEqual(lastHour)) {
UnionOpenOrderRowQueryResponse response = fetchOrdersForDateTime(startDate, false); // 假的代表历史订单
if (response != null){
int code = response.getQueryResult().getCode();
if (code == 200) {
if (response.getQueryResult().getCode() == 200) {
OrderRowResp[] orderRowResps = response.getQueryResult().getData();
if (orderRowResps == null) {
continue;
}
for (OrderRowResp orderRowResp : orderRowResps) {
// 固化到数据库
OrderRow orderRow = createOrderRow(orderRowResp);
// 订单号不存在就保存,存在就更新订单状态
orderRowRepository.save(orderRow);
}
}
}
sleep(1000);
}
startDate = startDate.plusHours(1);
}
}
/**
* 根据指定的日期时间拉取订单
*/
public UnionOpenOrderRowQueryResponse fetchOrdersForDateTime(LocalDateTime dateTime, boolean isRealTime) throws Exception {
LocalDateTime endTime = isRealTime ? dateTime.plusMinutes(1) : dateTime.plusHours(1);
String key = dateTime.format(DATE_TIME_FORMATTER);
String hourRange = isRealTime ? "minute" : "hour";
SetOperations<String, String> setOps = redisTemplate.opsForSet();
// 检查是否标记为已拉取
if (Boolean.TRUE.equals(setOps.isMember(key, hourRange))) {
System.out.println(dateTime.format(DATE_TIME_FORMATTER) + " 已经拉取,跳过");
return null;
}
// 调用 API 以拉取订单
UnionOpenOrderRowQueryResponse unionOpenOrderRowQueryResponse = getUnionOpenOrderRowQueryResponse(dateTime, endTime);
// 标记已拉取
setOps.add(key, hourRange);
return unionOpenOrderRowQueryResponse;
}
@Autowired
private WXUtil wxUtil;
/**
* 将 响应参数转化为 OrderRow并返回
* */
*/
private static OrderRow createOrderRow(OrderRowResp orderRowResp) {
OrderRow orderRow = new OrderRow();
orderRow.setOrderId(orderRowResp.getOrderId());
@@ -212,6 +142,240 @@ public class JDUtils {
return orderRow;
}
private static List<OrderRow> filterOrdersByDate(List<OrderRow> orderRows, int daysBack) {
LocalDate now = LocalDate.now();
return orderRows.stream()
.filter(order -> {
// 将 Date 转换为 LocalDate
LocalDate orderDate = order.getOrderTime().toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
// 计算是否在给定的天数内
return !orderDate.isBefore(now.minusDays(daysBack)) && !orderDate.isAfter(now);
})
.collect(Collectors.toList());
}
/**
* 拉取最新的订单 1440分钟
*/
@Scheduled(cron = "0 * * * * ?") // 每分钟执行一次
public void fetchLatestOrder() throws Exception {
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastMinute = now.minusMinutes(10).withSecond(0).withNano(0);
UnionOpenOrderRowQueryResponse response = fetchOrdersForDateTime(lastMinute, true); // 真实代表实时订单
if (response != null) {
int code = response.getQueryResult().getCode();
if (code == 200) {
if (response.getQueryResult().getCode() == 200) {
OrderRowResp[] orderRowResps = response.getQueryResult().getData();
if (orderRowResps == null) {
return;
}
for (OrderRowResp orderRowResp : orderRowResps) {
// 固化到数据库
OrderRow orderRow = createOrderRow(orderRowResp);
// 订单号不存在就保存,存在就更新订单状态
orderRowRepository.save(orderRow);
}
}
}
}
}
@Scheduled(cron = "0 * * * * ?") // 每分钟执行一次
public void sendOrderToWx() {
int[] parm = {-1, 17};
List<OrderRow> orderRows = orderRowRepository.findByValidCodeNotInOrderByOrderTimeDesc(parm);
if (!orderRows.isEmpty()) {
for (OrderRow orderRow : orderRows) {
orderToWx(orderRow, true);
}
}
}
/**
* 指令
*/
public void sendOrderToWxByOrder(String order) {
int[] parm = {-1};
List<OrderRow> orderRows = orderRowRepository.findByValidCodeNotInOrderByOrderTimeDesc(parm);
/**
* 菜单:
* 今日统计
* 昨天统计
* 最近七天统计
* 最近一个月统计
* 今天订单
* 昨天订单
* */
String content = null;
switch (order) {
case "菜单":
content = "菜单:京粉 +命令 \n 如: 京粉 今日统计\r";
content += "今日统计\r";
content += "昨天统计\r";
content += "最近七天统计\r";
content += "最近一个月统计\r";
content += "今天订单\r";
content += "昨天订单\r";
break;
case "今日统计": {
List<OrderRow> todayOrders = filterOrdersByDate(orderRows, 0);
// 订单总数,已付款,已取消,佣金总计
content = "今日统计:";
content += "订单总数:" + todayOrders.size() + "\r";
content += "已付款:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
break;
}
case "昨天统计": {
List<OrderRow> yesterdayOrders = filterOrdersByDate(orderRows, 1);
content = "昨天统计:";
content += "订单总数:" + yesterdayOrders.size() + "\r";
content += "已付款:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
break;
}
case "最近七天统计":
List<OrderRow> last7DaysOrders = filterOrdersByDate(orderRows, 7);
content = "最近七天统计:";
content += "订单总数:" + last7DaysOrders.size() + "\r";
content += "已付款:" + last7DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + last7DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + last7DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
break;
case "最近一个月统计":
List<OrderRow> last30DaysOrders = filterOrdersByDate(orderRows, 30);
content = "最近一个月统计:";
content += "订单总数:" + last30DaysOrders.size() + "\r";
content += "已付款:" + last30DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + last30DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + last30DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
break;
case "今天订单": {
List<OrderRow> todayOrders = filterOrdersByDate(orderRows, 0);
// 订单总数,已付款,已取消,佣金总计
content = "今日统计:";
content += "订单总数:" + todayOrders.size() + "\r";
content += "已付款:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
for (OrderRow orderRow : todayOrders) {
orderToWx(orderRow, false);
}
break;
}
case "昨天订单": {
List<OrderRow> yesterdayOrders = filterOrdersByDate(orderRows, 1);
content = "昨天统计:";
content += "订单总数:" + yesterdayOrders.size() + "\r";
content += "已付款:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
for (OrderRow orderRow : yesterdayOrders) {
orderToWx(orderRow, false);
}
break;
}
}
if (content != null) {
wxUtil.sendTextMessage(WXUtil.super_admin_wxid, content, 1, WXUtil.super_admin_wxid);
}
}
private void orderToWx(OrderRow orderRow, Boolean isAutoFlush) {
// 查询订单状态
Integer newValidCode = orderRow.getValidCode();
String oldValidCode = redisTemplate.opsForValue().get(ORDER_ROW_KEY + orderRow.getId());
Integer lastValidCode = 0;
// 更新 Redis 状态
redisTemplate.opsForValue().set(ORDER_ROW_KEY + orderRow.getId(), String.valueOf(orderRow.getValidCode()));
if (Util.isNotEmpty(oldValidCode)) {
lastValidCode = Integer.valueOf(oldValidCode);
}
// 如果订单状态没变化,就不发送
if (isAutoFlush && lastValidCode.equals(newValidCode)) {
} else {
String content;
content = getFormattedOrderInfo(orderRow);
// 推送
wxUtil.sendTextMessage(WXUtil.super_admin_wxid, content, 1, WXUtil.super_admin_wxid);
try {
sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public String getFormattedOrderInfo(OrderRow orderRow) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ValidCodeConverter converter = new ValidCodeConverter();
String orderInfo =
"商品名称:" + orderRow.getSkuName() + "\r"
+ "订单+sku" + orderRow.getId() + "\r"
+ "订单号:" + orderRow.getOrderId() + "(" + (orderRow.getPlus() == 1 ? "plus" : "非plus") + ")\r"
+ "佣金比例:" + orderRow.getCommissionRate() + "%\r\r"
+ "商品单价:" + orderRow.getPrice() + "\r"
+ "商品数量:" + orderRow.getSkuNum() + "\r"
+ "商品总价:" + (orderRow.getPrice() * orderRow.getSkuNum()) + "\r"
+ "订单总价:" + (orderRow.getActualCosPrice() * orderRow.getSkuNum()) + "\r"
+ "预估计佣金额:" + orderRow.getEstimateCosPrice() + "\n"
+ "推客的预估佣金:" + orderRow.getEstimateFee() + "\r"
+ "实际计算佣金的金额:" + orderRow.getActualCosPrice() + "\r"
+ "下单时间:" + formatter.format(orderRow.getOrderTime()) + "\r"
+ "完成时间:" + (orderRow.getFinishTime() != null ? formatter.format(orderRow.getFinishTime()) : "未完成") + "\r\n"
+ "订单状态:" + (converter.getCodeDescription(orderRow.getValidCode())) + "\r";
return orderInfo + "祝 财源滚滚";
}
/**
* 根据指定的日期时间拉取订单
*/
public UnionOpenOrderRowQueryResponse fetchOrdersForDateTime(LocalDateTime dateTime, boolean isRealTime) throws Exception {
LocalDateTime endTime = isRealTime ? dateTime.plusMinutes(10) : dateTime.plusHours(1);
String key = dateTime.format(DATE_TIME_FORMATTER);
String hourRange = isRealTime ? "minute" : "hour";
SetOperations<String, String> setOps = redisTemplate.opsForSet();
// 检查是否标记为已拉取
//if (Boolean.TRUE.equals(setOps.isMember(key, hourRange))) {
// System.out.println(dateTime.format(DATE_TIME_FORMATTER) + " 已经拉取,跳过");
// return null;
//}
// 调用 API 以拉取订单
UnionOpenOrderRowQueryResponse unionOpenOrderRowQueryResponse = getUnionOpenOrderRowQueryResponse(dateTime, endTime);
// 标记已拉取
setOps.add(key, hourRange);
return unionOpenOrderRowQueryResponse;
}
/**
* 获取订单列表
*
@@ -224,11 +388,10 @@ public class JDUtils {
String startTime = start.format(DATE_TIME_FORMATTER);
String endTime = end.format(DATE_TIME_FORMATTER);
// 模拟 API 调用
System.out.println("调用API - 从 " + startTime
+ "" + endTime);
//System.out.println("调用API - 从 " + startTime
// + " 到 " + endTime);
// 实际的 API 调用逻辑应在这里进行
String accessToken = "";
JdClient client = new DefaultJdClient(SERVER_URL, accessToken, APP_KEY, SECRET_KEY);
JdClient client = new DefaultJdClient(SERVER_URL, ACCESS_TOKEN, APP_KEY, SECRET_KEY);
UnionOpenOrderRowQueryRequest request = new UnionOpenOrderRowQueryRequest();
OrderRowReq orderReq = new OrderRowReq();
orderReq.setPageIndex(1);
@@ -250,4 +413,78 @@ public class JDUtils {
return client.execute(request);
}
/**
* 转链
*/
String transfer(String url) throws Exception {
JdClient client = new DefaultJdClient(SERVER_URL, ACCESS_TOKEN, APP_KEY, SECRET_KEY);
UnionOpenPromotionCommonGetRequest request = new UnionOpenPromotionCommonGetRequest();
request.setVersion("1.0");
request.setSignmethod("md5");
PromotionCodeReq promotionCodeReq = new PromotionCodeReq();
promotionCodeReq.setMaterialId(url);
promotionCodeReq.setSiteId(
"4101253066");
promotionCodeReq.setSceneId(1);
promotionCodeReq.setCommand(1);
promotionCodeReq.setProType(5);
request.setPromotionCodeReq(promotionCodeReq);
UnionOpenPromotionCommonGetResponse response = client.execute(request);
String jsonString = JSON.toJSONString(response);
System.out.println(jsonString);
//
//System.out.println(request.getAppJsonParams());
//System.out.println(request.getPromotionCodeReq());
//
//System.out.println("--------");
//System.out.println(response.getGetResult().getCode());
//System.out.println(response.getGetResult().getMessage());
//System.out.println(response.getGetResult().getData().getClickURL());
//System.out.println(response.getGetResult().getData().getJCommand());
return response.getGetResult().getData().getClickURL();
}
// 拉取历史订单 2880 次请求
@Scheduled(cron = "0 0 8,23 * * ?")
public void fetchHistoricalOrders() throws Exception {
// 从设定的开始日期到昨天的同一时间
System.out.println("开始拉取历史订单");
// 拉最近两个月的订单
// 获取当前时间,并调整为整点开始
LocalDateTime startDate = LocalDateTime.now().minusMonths(2).truncatedTo(ChronoUnit.HOURS);
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastHour = now.minusHours(1).withMinute(0).withSecond(0).withNano(0);
while (!startDate.isEqual(lastHour)) {
UnionOpenOrderRowQueryResponse response = fetchOrdersForDateTime(startDate, false); // 假的代表历史订单
if (response != null) {
int code = response.getQueryResult().getCode();
if (code == 200) {
if (response.getQueryResult().getCode() == 200) {
OrderRowResp[] orderRowResps = response.getQueryResult().getData();
if (orderRowResps == null) {
continue;
}
for (OrderRowResp orderRowResp : orderRowResps) {
// 固化到数据库
OrderRow orderRow = createOrderRow(orderRowResp);
// 订单号不存在就保存,存在就更新订单状态
orderRowRepository.save(orderRow);
sleep(1000);
}
}
}
}
startDate = startDate.plusHours(1);
}
}
}

View File

@@ -0,0 +1,353 @@
package cn.van.business.util;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static cn.hutool.core.thread.ThreadUtil.sleep;
/**
* @author Leo
* @version 1.0
* @create 2023/12/22 0022 上午 09:59
* @description
*/
@Component
public class QLUtil {
//client_id
public static final String CLIENT_ID = "Ouv_S9gk5LpV";
//client_secret
public static final String CLIENT_SECRET = "1pLjAIfBBzu1_UA9q-hOj778";
public static final String QL_TOKEN_KEY = "QL_TOKEN_KEY";
//private static final RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
private static final Logger logger = LoggerFactory.getLogger(QLUtil.class);
/**
* 1. 在系统设置 -> 应用设置 -> 添加应用权限目前支持5个模块可以选择多个模块。选择一个模块之后可读写此模块的所有接口。
* 2. 使用生成的 client_id 和 client_secret 请求获取token接口 http://localhost:5700/open/auth/token?client_id=xxxxxx&client_secret=xxxxxxxx
* 3. 上面接口返回的token有效期为30天可用于请求青龙的接口 curl 'http://localhost:5700/open/envs?searchValue=&t=1630032278171' -H 'Authorization: Bearer
* 接口返回的token'
* 4. openapi的接口与系统正常接口的区别就是青龙里的是/api/envsopenapi是/open/envs即就是青龙接口中的api换成open
*/
public static String QL_BASE_URL = "http://134.175.126.60:45700";
public static final String GET_TOKEN = QL_BASE_URL + "/open/auth/token";
// /open/envs
public static final String GET_ENV = QL_BASE_URL + "/open/envs";
// /open/crons
public static final String GET_CRON = QL_BASE_URL + "/open/crons";
private Environment env;
@Autowired
private StringRedisTemplate redisTemplate;
public QLUtil(Environment env) {
this.env = env;
QL_BASE_URL = env.getProperty("config.QL_BASE_URL");
}
public String getToken() {
String token = null;
token = redisTemplate.opsForValue().get(QL_TOKEN_KEY);
if (StrUtil.isNotEmpty(token)) {
} else {
//HashMap<String, String> map = new HashMap<>();
//map.put("client_id", CLIENT_ID);
//map.put("client_secret", CLIENT_SECRET);
//String jsonStr = JSON.toJSONString(map);
while (Util.isNotEmpty(token)) {
//* 2. 使用生成的 client_id 和 client_secret 请求获取token接口 http://localhost:5700/open/auth/token?client_id=xxxxxx&client_secret=xxxxxxxx
String responseStr = HttpRequest.get(GET_TOKEN + "?client_id=" + CLIENT_ID + "&client_secret=" + CLIENT_SECRET).execute().body();
if (ObjectUtil.isNotEmpty(responseStr)) {
//{"code":200,"data":{"token":"950e3060-d714-4f6a-9839-c098a116f0a8","token_type":"Bearer","expiration":1705743778}}
JSONObject jsonObject = JSON.parseObject(responseStr);
if (Objects.equals(String.valueOf(jsonObject.getString("code")), "200")) {
JSONObject response = jsonObject.getJSONObject("data");
redisTemplate.opsForValue().set(QL_TOKEN_KEY, (String) response.get("token"), (int) response.get("expiration"), TimeUnit.SECONDS);
token = (String) response.get("token");
}
}
sleep(500);
}
}
return token;
}
// get /envs
/**
* @return
* @throws
* @description 获取所有环境变量
*/
public JSONArray getEnv(String searchKey) {
String token = getToken();
JSONArray result = new JSONArray();
int maxRetryCount = 3;
int retryCount = 0;
String getUrl = GET_ENV + "?searchValue=&t=1630032278171";
if (Util.isNotEmpty(searchKey)) {
getUrl = GET_ENV + "?searchValue=" + searchKey + "&t=1630032278171";
}
while (result.size() == 0 && retryCount < maxRetryCount) {
String responseStr = HttpRequest.get(getUrl).header("Authorization", "Bearer " + token).execute().body();
if (ObjectUtil.isNotEmpty(responseStr)) {
JSONObject qlResponse = JSONObject.parseObject(responseStr);
if (qlResponse.getString("code").equals("200")) {
result = (JSONArray) qlResponse.get("data");
//result = null;
}
}
retryCount++;
sleep(1000);
}
return result;
}
/**
* @param name
* @return
* @throws
* @description 检查是否存在环境变量存在返回值不存在返回null
*/
//public String getEnvValue(String name) {
// JSONObject jsonObject = getEnv();
// if (ObjectUtil.isNotEmpty(jsonObject)) {
// return jsonObject.getJSONObject(name).getString("value");
// }
// return null;
//}
// post /envs
// {
// "value": "123",
// "name": "test_add",
// "remarks": "新建测试"
//}
/**
* @param name
* @param remarks
* @param value
* @return
* @throws
* @description 添加环境变量 name 环境变量名value 环境变量值remarks 环境变量备注
* 如果存在一样的value 会返回 400
* 如果添加成功,就返回 TRUE ,否则返回 FALSE
*/
public Boolean addEnv(String value, String name, String remarks) {
String token = getToken();
JSONObject result = new JSONObject();
List<QLEnv> bodyArr = Collections.singletonList(new QLEnv(value, name, remarks));
logger.info("addEnv 请求body {}", JSON.toJSONString(bodyArr));
// 设置最大重试次数
int maxRetryCount = 3;
int retryCount = 0;
while (Util.isEmpty(result) && retryCount < maxRetryCount) {
String responseStr = HttpRequest.post(GET_ENV)
.header("Authorization", "Bearer " + token)
.body(JSON.toJSONString(bodyArr))
.execute()
.body();
logger.info("responseStr 响应 {}", responseStr);
if (Util.isNotEmpty(responseStr)) {
JSONObject qlResponse = JSONObject.parseObject(responseStr);
String code = qlResponse.getString("code");
if ("200".equals(code)) {
logger.info("200 响应 {}", qlResponse);
result = (JSONObject) qlResponse.get("data");
return true;
} else if ("400".equals(code)) {
logger.info("400 响应 {}", qlResponse);
result = (JSONObject) qlResponse.get("message");
break;
}
}
retryCount++;
sleep(1000);
}
return false;
}
// http://134.175.126.60:45700/api/crons?searchValue=&page=1&size=20&filters={}&queryString={%22filters%22:null,%22sorts%22:null,%22filterRelation%22:%22and%22}&t=1703148561868
/**
* @param searchKey
* @return
* @throws
* @description 获取定时任务列表
*/
public List<Cron> getCron(String searchKey) {
String token = getToken();
List<Cron> cronList = new ArrayList<>();
int maxRetryCount = 3;
int retryCount = 0;
String getUrl = GET_CRON + "?searchValue=&t=1630032278171";
if (Util.isNotEmpty(searchKey)) {
getUrl = GET_CRON + "?searchValue=" + searchKey + "&t=1630032278171";
}
while (cronList.size() == 0 && retryCount < maxRetryCount) {
String responseStr = HttpRequest.get(getUrl).header("Authorization", "Bearer " + token).execute().body();
if (ObjectUtil.isNotEmpty(responseStr)) {
JSONObject qlResponse = JSONObject.parseObject(responseStr);
String code = qlResponse.getString("code");
//{"code":200,"data":{"data":[],"total":0}}
if ("200".equals(code)) {
logger.info("200 响应 {}", qlResponse);
JSONObject dataObj = qlResponse.getJSONObject("data");
if (dataObj.getInteger("total") == 0) {
} else {
ArrayList data = JSONObject.parseObject(dataObj.getString("data"), ArrayList.class);
System.out.println(data.size());
}
} else if ("400".equals(code)) {
logger.info("400 响应 {}", qlResponse);
//result = (JSONArray) qlResponse.get("message");
}
retryCount++;
sleep(500);
}
}
return null;
}
/*
* 请求网址:
* http://134.175.126.60:45700/api/crons/run?t=1703148561868
* 请求方法:
* PUT*/
//public JSONObject runCron(String cronId) {
// String token = getToken();
// if (StrUtil.isNotEmpty(token)) {
// for (int i = 0; i < 3; i++) {
// String responseStr = HttpRequest.put(GET_CRON + "?cronId=" + cronId).header("Authorization", "Bearer " + token).execute().body();
// if (ObjectUtil.isNotEmpty(responseStr)) {
// QLResponse qlResponse = JSON.parseObject(responseStr, QLResponse.class);
// if (Objects.equals(String.valueOf(qlResponse.getCode()), "200")) {
// return qlResponse.getData();
// }
// }
// sleep(500);
// }
// }
// return null;
//}
/**
* }
* async ["getLoginedUserInfo"](_0x4ef1fe = {}) {
* let _0x26ac1b = false;
* try {
* const _0x3daa7c = {
* "token": this.token
* };
* const _0xe8bb64 = {
* "fn": "getLoginedUserInfo",
* "method": "get",
* "url": "https://i.meituan.com/wrapapi/getLoginedUserInfo",
* "searchParams": _0x3daa7c
* };
* let {
* result: _0x48e5d7
* } = await this.request(_0xe8bb64);
* if (_0x48e5d7?.["mobile"]) {
* _0x26ac1b = true;
* this.name = _0x48e5d7.nickName;
* this.userId = Number(_0x48e5d7.userId);
* this.log("登录成功");
* } else {
* this.log("获取账号信息失败, ck可能失效");//, {"notify": true}
* await expireNotify(this.userId, this.index);
* }
* } catch (_0x232c57) {
* console.log(_0x232c57);
* } finally {
* return _0x26ac1b;
* }
* }
*/
// 通过token 获取用户信息
// url https://i.meituan.com/wrapapi/getLoginedUserInfo
// 参数 token
// get
public HashMap<String, String> getLoginedUserInfo(String token) {
String responseStr = HttpRequest.get("https://i.meituan.com/wrapapi/getLoginedUserInfo" + "?token=" + token).header("token", token).execute().body();
HashMap<String, String> result = new HashMap<>();
if (ObjectUtil.isNotEmpty(responseStr)) {
JSONObject qlResponse = JSON.parseObject(responseStr);
//{"userId":"3822095266","nickName":"XLP200660795","growthValue":null,"growthLevel":null,"avatarUrl":"","mobile":"15817969021"}
if (qlResponse.containsKey("mobile")) {
result.put("mobile", qlResponse.getString("mobile"));
}
if (qlResponse.containsKey("nickName")) {
result.put("nickName", qlResponse.getString("nickName"));
}
}
return result;
}
// new QLEnv(value, name, remarks)
@Data
@AllArgsConstructor
@NoArgsConstructor
private static class QLEnv {
private String value;
private String name;
private String remarks;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
private class Cron {
private long id;
private String name;
private String command;
private String schedule;
private String timestamp;
private boolean saved;
private long status;
private long isSystem;
private long pid;
private long isDisabled;
private long isPinned;
private String logPath;
private List<Object> labels;
private long lastRunningTime;
private long lastExecutionTime;
private long subID;
private String createdAt;
private String updatedAt;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,242 @@
package cn.van.business.util;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.van.business.enums.WXReqType;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.util.HashMap;
/**
* @author Leo
* @version 1.0
* @create 2023/12/22 0022 上午 09:59
* @description
*/
@Component
public class WXUtil {
private static final Logger logger = LoggerFactory.getLogger(WXUtil.class);
public static final String super_admin_wxid = "wxid_ytpc72mdoskt22";
/**
* url http://127.0.0.1:7777/DaenWxHook/httpapi/
* 获取微信列表 (X0000)
* 微信状态检测(Q0000)
* 发送文本消息(Q0001)
* 修改下载图片 (Q0002)
* 获取个人信息 (Q0003)
* 查询对象信(Q0004)
* 获取好友列表(Q0005)
* 获取群聊列表(Q0006)
* 获取公众号列表(Q0007)
* 获取群成员列表(Q0008)
* 发送聊天记录(Q0009)
* 发送图片 (Q0010)
* 发送本地文件(Q0011)
* 发送分享链接(Q0012)
* 发送小程序(Q0013)
* 发送音乐分享(Q0014)
* 发送XML (Q0015)
* 确认收款 (Q0016)
* 同意好友请求(Q0017)
* 添加好友通过v3(Q0018)
* 添加好友_通过wxid (Q0019)
* 查询陌生人信息(Q0020)
* 邀请进群(Q0021)
* 删除好友(Q0022)
* 修改对象备注(Q0023)
* 修改群聊名称(Q0024)
* 发送名片(Q0025)
*/
public static String WX_BASE_URL;
private Environment env;
@Autowired
public WXUtil(Environment env) {
this.env = env;
WX_BASE_URL = env.getProperty("config.WX_BASE_URL");
System.out.println("WX_BASE_URL:" + WX_BASE_URL);
}
// 获取微信列表
public JSONObject getWxList() {
WxReqDate wxReqDate = createWxReqData(WXReqType.GET_WX_LIST);
String responseStr = HttpRequest.post(WX_BASE_URL).body(JSON.toJSONString(wxReqDate)).execute().body();
if (ObjectUtil.isNotEmpty(responseStr)) {
return JSON.parseObject(responseStr);
} else {
return null;
}
}
// 发送文本消息 msgType 1:私聊 2:群发
public JSONObject sendTextMessage(String wxid, String content, Integer msgType, String fromwxid) {
// 全部打印
logger.info("发送文本消息 msgType: " + msgType + " wxid: " + wxid + " fromwxid: " + fromwxid + " content: " + content);
// 如果是自己的微信,所有信息都加上少爷
if (wxid.equals(super_admin_wxid) || fromwxid.equals(super_admin_wxid)) {
content = "超管: 凡 \r\n" + content;
}
//JSONObject wxList = getWxList();
//JSONObject wxBotInfo = (JSONObject) wxList.getJSONArray("result").get(0);
//botWxid = wxBotInfo.getString("wxid");
//
////
//WxReqDate wxReqDate = createWxReqData(WXReqType.SEND_TEXT_MESSAGE);
JSONObject jsonObject = new JSONObject();
jsonObject.put("type", WXReqType.SEND_TEXT_MESSAGE.getType());
//if ((msgType.equals(1))) {
// jsonObject.put("wxid", wxid);
// content = content;
//}
////[@,wxid=对象wxid,nick=对象昵称,isAuto=true]
//if ((msgType.equals(2))) {
// jsonObject.put("wxid", fromwxid);
// content = "[@,wxid=" + wxid + ",nick=6,isAuto=true] " + content;
//}
/*
* {
"wxid": "filehelper",
"msg": "666大佬~"
}*/
JSONObject data = new JSONObject();
data.put("msg", content);
data.put("wxid", wxid);
jsonObject.put("data", data);
System.out.println(JSON.toJSONString(jsonObject));
//wxReqDate.setData(jsonObject);
while (Util.isNotEmpty(wxid)) {
String responseStr = HttpRequest.post(WX_BASE_URL).body(JSON.toJSONString(jsonObject)).execute().body();
if (ObjectUtil.isNotEmpty(responseStr)) {
JSONObject response = JSON.parseObject(responseStr);
//WxResponse wxResponse = JSON.parseObject(responseStr, WxResponse.class);
//System.out.println(wxResponse);
//if (Objects.equals(String.valueOf(wxResponse.getCode()), "200")) {
// return wxResponse.getData();
//}
//JSONObject jsonObject = HttpUtil.sendPost(url, wxReqDate.getData());
logger.info("消息响应:" + response.toString());
return response;
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return null;
}
//private JSONObject sendWxReq(WxReqDate wxReqDate) {
// if (wxReqDate == null) {
// return null;
// } else {
// logger.info("wxReqDate: {}", wxReqDate);
//
// String responseStr = HttpRequest.post(WX_BASE_URL).body(JSON.toJSONString(wxReqDate)).execute().body();
// if (ObjectUtil.isNotEmpty(responseStr)) {
// JSONObject jsonObject = JSON.parseObject(responseStr);
// //WxResponse wxResponse = JSON.parseObject(responseStr, WxResponse.class);
// //System.out.println(wxResponse);
// //if (Objects.equals(String.valueOf(wxResponse.getCode()), "200")) {
// // return wxResponse.getData();
// //}
// //JSONObject jsonObject = HttpUtil.sendPost(url, wxReqDate.getData());
// return jsonObject;
// }
// }
//
// return null;
// }
//}
/**
* {
* "type": "Q0016",
* "data": {
* "wxid": "wxid_3sx9sjgq99kd22",
* "transferid": "1000050001202207161417697440336"
* }
* }
*/
public JSONObject queRenShouKuan(String wxid, String transferid) {
String botWxid = "";
JSONObject wxList = getWxList();
JSONObject wxBotInfo = (JSONObject) wxList.getJSONArray("result").get(0);
botWxid = wxBotInfo.getString("wxid");
WxReqDate wxReqDate = createWxReqData(WXReqType.CONFIRM_RECEIPT);
HashMap<String, String> body = new HashMap<>();
body.put("wxid", wxid);
body.put("transferid", transferid);
JSONObject jsonObject = new JSONObject(body);
wxReqDate.setData(jsonObject);
String responseStr = HttpRequest.post(WX_BASE_URL + "?wxid=" + botWxid).body(JSON.toJSONString(wxReqDate)).execute().body();
logger.info("确认收款结果responseStr: {}", responseStr);
if (ObjectUtil.isNotEmpty(responseStr)) {
return JSON.parseObject(responseStr);
} else {
return null;
}
}
public WxReqDate createWxReqData(WXReqType wxReqType) {
WxReqDate wxReqDate = new WxReqDate(wxReqType.getType(), null);
return wxReqDate;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
private class WxResponse {
/**
* {
* "code": 200,
* "msg": "操作成功",
* "result": {},
* "wxid": "wxid_3sq4tklb6c3121",
* "port": 7305,
* "pid": 12384,
* "flag": "7777",
* "timestamp": "1657462661814"
* }
*/
private Integer code;
private String msg;
private JSONObject result;
private String wxid;
private Integer port;
private Integer pid;
private String flag;
private String timestamp;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
private class WxReqDate {
//{
// "type": "X0000",
// "data": {}
//}
private String type;
private JSONObject data;
}
}

View File

@@ -0,0 +1,794 @@
package cn.van.business.util;
import cn.van.business.enums.FromType;
import cn.van.business.model.wx.WxMessage;
import cn.van.business.repository.SettingRepository;
import cn.van.business.repository.WxMessageDataForChatRepository;
import cn.van.business.repository.WxUserRepository;
import com.alibaba.fastjson2.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Leo
* @version 1.0
* @create 2023/12/19 0019 上午 11:03
* @description
*/
@Component
public class WxMessageConsumer {
private static final String meituanCookie = "meituanCookie";
/**
* key开头的为 setting 的 key
*/
private static final String key_caiDan_user = "用户菜单";
private static final String key_caiDan_admin = "管理员菜单";
/**
* order 开头的是接受的指令
*/
private static final String order_caiDan = "菜单";
private static final String order_admin = "管理员";
/**/
private static final Logger logger = LoggerFactory.getLogger(WxMessageConsumer.class);
/**
* 临时参数
* 每次扣费
*/
private static final BigDecimal priceOfMT20 = new BigDecimal("0.2");
private static final Integer fromGR = 10008;
private static final String SERVER_URL = "https://api.jd.com/routerjson";
private static final String accessToken = "";
private static final String appKey = "98e21c89ae5610240ec3f5f575f86a59";
private static final String appSecret = "3dcb6b23a1104639ac433fd07adb6dfb";
private final WXUtil wxUtil;
private final QLUtil qlUtil;
private final WxMessageDataForChatRepository wxMessageDataForChatRepository;
private final WxUserRepository wxUserRepository;
private final SettingRepository settingRepository;
private final JDUtils jdUtils;
@Autowired
public WxMessageConsumer(WXUtil wxUtil, QLUtil qlUtil,
@Lazy WxMessageDataForChatRepository wxMessageDataForChatService,
@Lazy WxUserRepository wxUserRepository,
@Lazy SettingRepository settingRepository,
@Lazy JDUtils jdUtils) {
this.wxUtil = wxUtil;
this.qlUtil = qlUtil;
this.wxMessageDataForChatRepository = wxMessageDataForChatService;
this.wxUserRepository = wxUserRepository;
this.settingRepository = settingRepository;
this.jdUtils = jdUtils;
}
/**
* 从京东商品 URL 中提取产品 ID
*
* @param url 需要解析的 URL
* @return 提取出的产品 ID
*/
public static String extractProductId(String url) {
// 使用正则表达式匹配 pattern 包含 /product/ 后跟一系列数字,结束于 .html
Pattern pattern = Pattern.compile("/product/(\\d+)\\.html");
Matcher matcher = pattern.matcher(url);
if (matcher.find()) {
return matcher.group(1); // 返回第一个捕获组(产品 ID
}
return null; // 如果没有找到匹配项,返回 null
}
//private Boolean heiMingDan(String wxid) {
// // 0 正常 1 黑名单
// //
// boolean flag = false;
// WxUser wxUser = wxUserRepository.getOne(Wrappers.query(new WxUser()).eq("wxid", wxid));
// if (Util.isNotEmpty(wxUser)) {
// if (wxUser.getStatus().equals(1)) {
// flag = true;
// }
// }
// return flag;
//}
//private Boolean isNew(String wxid) {
// // 0 是 1 不是
// boolean flag = false;
// WxUser wxUser = wxUserRepository.getOne(Wrappers.query(new WxUser()).eq("wxid", wxid));
// if (Util.isNotEmpty(wxUser)) {
// if (wxUser.getIsnew().equals(0)) {
// flag = true;
// }
// }
// return flag;
//}
//private Boolean isNew(Integer isNew) {
// // 0 是 1 不是
// boolean flag = false;
// if (isNew.equals(0)) {
// flag = true;
// }
// return flag;
//}
/**
* @param wxMessage
* @return
* @throws
* @description
*/
//private void handleTransferEvent(WxMessage wxMessage) {
// Integer msgType = 1;
//
// /**
// * {
// * "fromWxid": "wxid_ytpc72mdoskt22", 对方wxid
// * "msgSource": 1, 1|收到转账 2|对方接收转账 3|发出转账 4|自己接收转账 5|对方退还 6|自己退还
// * "transType": 1, 1|即时到账 2|延时到账
// * "money": "2.00", 金额,单位元
// * "memo": "", 转账备注
// * "transferid": "1000050001202312250424037787039", 转账ID
// * "invalidtime": "1703577220" 10位时间戳
// * }*/
// JSONObject data = wxMessage.getData().getJSONObject("data");
// if (data == null) {
// return;
// }
// WxMessageDataForTransfer wxMessageDataForTransfer = data.to(WxMessageDataForTransfer.class);
//
// String result = null;
// String wxid = wxMessageDataForTransfer.getFromwxid();
//
//
//
// if (heiMingDan(wxid)) {
// result = "您已被拉黑,请联系客服!";
// } else {
// if (wxMessageDataForTransfer.getTranstype().equals(2)) {
// result = "请勿使用延时到账功能。累计三次将永久拉黑!";
// } else {
//
// JSONObject shouKuanResult = wxUtil.queRenShouKuan(wxid, wxMessageDataForTransfer.getTransferid());
// if (shouKuanResult == null) {
// result = "查询转账失败,请稍后再试。";
// }
// if (shouKuanResult != null && shouKuanResult.getInteger("code") == 200) {
// BigDecimal money = wxMessageDataForTransfer.getMoney();
// if (money.compareTo(BigDecimal.ZERO) > 0) {
// WxUser wxUser = wxUserService.getOne(Wrappers.query(new WxUser()).eq("wxid", wxid));
// wxUser.setMoneyLeiji(wxUser.getMoneyLeiji().add(money));
// wxUser.setMoneyShengyu(wxUser.getMoneyShengyu().add(money));
// wxUser.setCountChongzhi(wxUser.getCountChongzhi().add(BigDecimal.ONE));
// wxUserService.updateById(wxUser);
// result = "收到转账" + money + "元,已成功存入账户。感谢您的使用。";
// }
// }
//
// }
//
// }
// wxUtil.sendTextMessage(wxid, result, msgType, null);
//
//}
private static String getUrlStr(String msg) {
//String urlPattern = "https?://[\\w-\\.]+(\\.[a-z]{2,})?(/[\\w-./?%&=]*)?"
String urlPattern = "https?://[^\\s]+?\\.(html|htm)(\\?[^\\s]*?)?";
Pattern pattern = Pattern.compile(urlPattern);
Matcher matcher = pattern.matcher(msg);
// 检查是否存在URL如果存在则打印出来
String finallyUrl = null;
if (matcher.find()) {
finallyUrl = matcher.group();
System.out.println("Extracted URL: " + finallyUrl);
} else {
System.out.println("No URL found in the given text.");
}
if (finallyUrl != null && finallyUrl.endsWith("?")) {
// 移除最后一个字符(即问号)
finallyUrl = finallyUrl.substring(0, finallyUrl.length() - 1);
}
if (finallyUrl.contains("item.m.jd.com/product")) {
finallyUrl = finallyUrl.replace("item.m.jd.com/product", "item.jd.com");
}
return finallyUrl;
}
//@Async("threadPoolTaskExecutor")
public void consume(WxMessage wxMessage) throws Exception {
//logger.info("接收到消息 : {}", wxMessage);
if (wxMessage.getEvent() == null) {
return;
}
/**
* 需要处理 私聊 和 转账消息
* 其他消息暂时不处理
* 私聊需要解析是否美团领券
* 转账需要对接会员系统
*
* */
WxMessage.DataSection data = wxMessage.getData();
if (FromType.PRIVATE.getKey().equals(wxMessage.getEvent())) {
handlePrivateMessage(wxMessage);
} else if (FromType.GROUP.getKey().equals(wxMessage.getEvent())) {
//handleGroupMessage(wxMessage);
}
//if (event.equals(EventType.TRANSFER_EVENT.getKey())) {
// handleTransferEvent(wxMessage);
//}
}
/**
* 处理私聊消息
*
* @param wxMessage
*/
private void handlePrivateMessage(WxMessage wxMessage) throws Exception {
Integer msgType = 1;
// 做业务处理
//logger.info("处理消息: {}", JSON.toJSONString(wxMessage));
/**
* {
* "event": 10009,
* "wxid": "wxid_nq6r0w9v12612",
* "data": {
* "type": "recvMsg",
* "des": "收到消息",
* "data": {
* "timeStamp": "1716620300237",
* "fromType": 1,
* "msgType": 1,
* "msgSource": 0,
* "fromWxid": "wxid_3sq4tklb6c3121",
* "finalFromWxid": "",
* "atWxidList": [],
* "silence": 0,
* "membercount": 0,
* "signature": "V1_uKhKVjB1|v1_uKhKVjB1",
* "msg": " 你在干嘛呢",
* "msgId": "4937897417714063715",
* "msgBase64": "IOS9oOWcqOW5suWYm+WRog=="
* },
* "timestamp": "1716620300238",
* "wxid": "wxid_nq6r0w9v12612",
* "port": 8888,
* "pid": 3944,
* "flag": "7888"
* }
* }
* */
WxMessage.DataSection data = wxMessage.getData();
WxMessage.DataSection.InnerData innerData = data.getData();
Integer event = wxMessage.getEvent();
if (Util.isAnyEmpty(innerData.getMsg(), innerData.getFromWxid())) {
logger.info("消息内容为空,不处理");
return;
}
String msg = innerData.getMsg();
//美团 20-7 + https://i.meituan.com/mttouch/page/account?userId=3822095266&token=AgHdIkm2tAGHc9SQSiG7M8xCx1LbTue9D2HPOAun2eYl3ou7BeEw1uGrGZH-DxmEiUgsbA1v9SM4DQAAAAC6HAAAz0rTXmkB_CIHin08hCu68mFv5k6nUc2q6_CfZqEdBcngRK_xD8Sx5fE4rfdq-yAJ, msgbase64=576O5ZuiIDIwLTcgKyBodHRwczovL2kubWVpdHVhbi5jb20vbXR0b3VjaC9wYWdlL2FjY291bnQ/dXNlcklkPTM4MjIwOTUyNjYmdG9rZW49QWdIZElrbTJ0QUdIYzlTUVNpRzdNOHhDeDFMYlR1ZTlEMkhQT0F1bjJlWWwzb3U3QmVFdzF1R3JHWkgtRHhtRWlVZ3NiQTF2OVNNNERRQUFBQUM2SEFBQXowclRYbWtCX0NJSGluMDhoQ3U2OG1GdjVrNm5VYzJxNl9DZlpxRWRCY25nUktfeEQ4U3g1ZkU0cmZkcS15QUo=
if (msg.startsWith("转链")) {
String wxid;
if (Objects.equals(event, fromGR)) {
wxid = innerData.getFromWxid();
} else {
wxid = innerData.getFinalFromWxid();
}
// 使用正则表达式匹配URL
//从 转链https://item.m.jd.com/product/100065976064.html?utm_user=plusmember&gx=RnAomTM2bGbfy59DrNFzDHu0uUde7Oc&gxd=RnAoxWMLamXdwpscqIV-D94totD10SY&ad_od=share&utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=CopyURL_shareid64b2a4939719b1d3173112851071496926_shangxiang_none
// 获取 100065976064
logger.info("处理转链消息");
//String finallyUrl = getUrlStr(msg);
//String finallyUrl = extractProductId(msg);
String finallyUrl = msg.substring(2);
if (Util.isNotEmpty(finallyUrl)) {
String transferResultUrl = jdUtils.transfer(finallyUrl);
wxUtil.sendTextMessage(wxid, transferResultUrl, msgType, null);
}
} else if (msg.startsWith("京粉 ")) {
jdUtils.sendOrderToWxByOrder(msg.replace("京粉 ", ""));
}
//else if (msg.startsWith("美团 ")) {
// logger.info("处理美团的消息");
// msg = msg.substring(msg.indexOf("https://i.meituan.com/mttouch/page/account"));
// String[] all = msg.split("\\?");
//
// if (all.length == 2) {
// String wxid = null;
// if (wxMessage.getFromtype().equals(fromGR)) {
// wxid = wxMessage.getFromid();
// } else {
// wxid = wxMessage.getFromgid();
// }
// String httpData = all[1];
// String[] httpDataArr = httpData.split("&");
// if (httpDataArr.length == 2) {
// // 调用美团
// //String result = mt20(wxid, httpDataArr[0].split("=")[1], httpDataArr[1].split("=")[1]);
//
// //wxUtil.sendTextMessage(wxid, result, msgType, null);
// } else {
//
// wxUtil.sendTextMessage(wxid, "请检查提交的数据格式是否正确。", msgType, null);
// }
// }
//} else if ("余额".equals(msg)) {
// String wxid = null;
// if (wxMessageDataForChat.getFromtype() == 1) {
// wxid = wxMessageDataForChat.getFromwxid();
// } else if (wxMessageDataForChat.getFromtype() == 2) {
// wxid = wxMessageDataForChat.getFinalfromwxid();
// }
// WxUser wxUser = wxUserService.getOne(Wrappers.query(new WxUser()).eq("wxid", wxid));
// String result = "";
// if (Util.isNotEmpty(wxUser)) {
// result = "您的余额为:" + wxUser.getMoneyLeiji() + "元\r";
// result = result + " 您的消费次数为:" + wxUser.getCountXiaofei() + "次\r";
// result = result + " 您的充值次数为:" + wxUser.getCountChongzhi() + "次\r";
// result = result + " 您的累计充值为:" + wxUser.getMoneyLeiji() + "元";
// } else {
// result = "暂未查询到充值记录。\r";
// }
//
//
// wxUtil.sendTextMessage(wxid, result, msgType, null);
//} else if ("体验".equals(msg)) {
// String wxid = null;
// if (wxMessageDataForChat.getFromtype() == 1) {
// wxid = wxMessageDataForChat.getFromwxid();
// } else if (wxMessageDataForChat.getFromtype() == 2) {
// wxid = wxMessageDataForChat.getFinalfromwxid();
// }
// String result = "";
// if (heiMingDan(wxid)) {
// result = "黑名单!";
// } else {
// WxUser wxUser = wxUserService.getOne(Wrappers.query(new WxUser()).eq("wxid", wxid));
// if (isNew(wxUser.getIsnew())) {
// wxUser.setMoneyLeiji(wxUser.getMoneyLeiji().add(new BigDecimal(1)));
// wxUser.setMoneyShengyu(wxUser.getMoneyShengyu().add(new BigDecimal(1)));
// wxUser.setCountChongzhi(wxUser.getCountChongzhi().add(BigDecimal.ONE));
// wxUser.setIsnew(1);
// wxUserService.updateById(wxUser);
// result = "体验成功,您已成功充值" + 1.00 + "元,已成功存入账户。感谢您的使用。";
// } else {
// result = "您已体验过,请勿重复体验。";
// }
//
// }
//
// wxUtil.sendTextMessage(wxid, result, msgType, null);
//
//}// 用户返回用户菜单
//else if (order_caiDan.equals(msg)) {
// String wxid = null;
// if (wxMessageDataForChat.getFromtype() == 1) {
// wxid = wxMessageDataForChat.getFromwxid();
// } else if (wxMessageDataForChat.getFromtype() == 2) {
// wxid = wxMessageDataForChat.getFinalfromwxid();
// }
// String result = "";
// String puTong = getSetting(key_caiDan_user);
// String chaoJi = getSetting(key_caiDan_admin);
// if (isSuperAdminUser(wxid)) {
// result = "用户菜单:" + puTong + " 管理员菜单:" + chaoJi;
// } else {
// result = "用户菜单:" + puTong;
// }
//
// wxUtil.sendTextMessage(wxid, result, msgType, wxMessageDataForChat.getFromwxid());
//}
// wxMessageDataForChatService.save(wxMessageDataForChat);
}
/**
* @param wxMessage
* @return
* @throws
* @description 处理群聊消息
*/
// private void handleGroupMessage (WxMessage wxMessage){
// Integer msgType = 2;
// /**
// * 接收到消息 : WxMessage(event=10009, wxid=wxid_kr145nk7l0an31, data={"type":"D0003","des":"收到消息","data":{"timeStamp":"1703128368100","fromType":1,"msgT两次ype":1,"msgSource":0,"fromWxid":"wxid_ytpc72mdoskt22","finalFromWxid":"","atWxidList":[],"silence":0,"membercount":0,"signature":"v1_vXrWK/iB","msg":"嗨鲁个迷紫123","msgBase64":"5Zeo6bKB5Liq6L+357SrMTIz"},"timestamp":"1703128368112","wxid":"wxid_kr145nk7l0an31","port":16888,"pid":10468,"flag":"7777"})
// * 需要get 两次 data 字段*/
// JSONObject data = wxMessage.getData().getJSONObject("data");
// if (data == null) {
// return;
// }
//
//
// /**{"type":"D0003","des":"收到消息","data":{"timeStamp":"1702957325031","fromType":1,"msgType":1,"msgSource":0,"fromWxid":"wxid_ytpc72mdoskt22","finalFromWxid":"","atWxidList":[],"silence":0,"membercount":0,"signature":"v1_OJXJYpvM","msg":"在不","msgBase64":"5Zyo5LiN"},"timestamp":"1702957325041","wxid":"wxid_kr145nk7l0an31","port":16888,"pid":10468,"flag":"7777"}
// * */
// WxMessageDataForChat wxMessageDataForChat = data.to(WxMessageDataForChat.class);
//
// // 做业务处理
// logger.info("处理消息: {}", wxMessageDataForChat.toString());
//
// /**
// * timeStamp 收到这条消息的13位现行时间戳
// * fromType 来源类型1|私聊 2|群聊 3|公众号
// * msgType 消息类型1|文本 3|图片 34|语音 42|名片 43|视频 47|动态表情 48|地理位置 49|分享链接或附件 2001|红包 2002|小程序 2003|群邀请 10000|系统消息
// * msgSource 消息来源0|别人发送 1|自己手机发送
// * fromWxid fromType=1时为好友wxidfromType=2时为群wxidfromType=3时公众号wxid
// * finalFromWxid 仅fromType=2时有效为群内发言人wxid
// * atWxidList 仅fromType=2且msgSource=0时有效为消息中艾特人wxid列表
// * silence 仅fromType=2时有效0
// * membercount 仅fromType=2时有效群成员数量
// * signature 消息签名
// * msg 消息内容
// * msgBase64 消息内容的Base64
// * */
// if (Util.isAnyEmpty(wxMessageDataForChat.getMsg(), wxMessageDataForChat.getFromwxid(), wxMessageDataForChat.getFromtype())) {
// logger.info("消息内容为空,不处理");
// return;
// }
// String atwxidlist = wxMessageDataForChat.getAtwxidlist();
// if (Util.isNotEmpty((atwxidlist))) {
// JSONObject wxList = wxUtil.getWxList();
// JSONObject wxBotInfo = (JSONObject) wxList.getJSONArray("result").get(0);
// String botWxid = wxBotInfo.getString("wxid");
//
// if (atwxidlist.contains(botWxid)) {
// String[] split = wxMessageDataForChat.getMsg().split(" ");
// String msg;
// if (split.length == 2) {
// msg = split[1];
// } else {
// String[] newArray = new String[split.length - 1];
// System.arraycopy(split, 1, newArray, 0, newArray.length);
// StringBuilder stringBuilder = new StringBuilder();
// Iterator<String> iterator = Arrays.stream(newArray).iterator();
// while (iterator.hasNext()) {
// String s = iterator.next();
// stringBuilder.append(s).append(" ");
// }
// msg = stringBuilder.toString();
// }
//
////美团 20-7 + https://i.meituan.com/mttouch/page/account?userId=3822095266&token=AgHdIkm2tAGHc9SQSiG7M8xCx1LbTue9D2HPOAun2eYl3ou7BeEw1uGrGZH-DxmEiUgsbA1v9SM4DQAAAAC6HAAAz0rTXmkB_CIHin08hCu68mFv5k6nUc2q6_CfZqEdBcngRK_xD8Sx5fE4rfdq-yAJ, msgbase64=576O5ZuiIDIwLTcgKyBodHRwczovL2kubWVpdHVhbi5jb20vbXR0b3VjaC9wYWdlL2FjY291bnQ/dXNlcklkPTM4MjIwOTUyNjYmdG9rZW49QWdIZElrbTJ0QUdIYzlTUVNpRzdNOHhDeDFMYlR1ZTlEMkhQT0F1bjJlWWwzb3U3QmVFdzF1R3JHWkgtRHhtRWlVZ3NiQTF2OVNNNERRQUFBQUM2SEFBQXowclRYbWtCX0NJSGluMDhoQ3U2OG1GdjVrNm5VYzJxNl9DZlpxRWRCY25nUktfeEQ4U3g1ZkU0cmZkcS15QUo=
// if (msg.startsWith("美团 20-7 ")) {
// logger.info("处理美团的消息");
// msg = msg.substring(msg.indexOf("https://i.meituan.com/mttouch/page/account"));
// String[] all = msg.split("\\?");
//
// if (all.length == 2) {
// String wxid = null;
// if (wxMessageDataForChat.getFromtype() == 1) {
// wxid = wxMessageDataForChat.getFromwxid();
// } else if (wxMessageDataForChat.getFromtype() == 2) {
// wxid = wxMessageDataForChat.getFinalfromwxid();
// }
// String httpData = all[1];
// String[] httpDataArr = httpData.split("&");
// if (httpDataArr.length == 2) {
// String result = mt20(wxMessageDataForChat.getFinalfromwxid(), httpDataArr[0].split("=")[1], httpDataArr[1].split("=")[1]);
//
// wxUtil.sendTextMessage(wxMessageDataForChat.getFinalfromwxid(), result, msgType, wxMessageDataForChat.getFromwxid());
// } else {
//
// wxUtil.sendTextMessage(wxMessageDataForChat.getFinalfromwxid(), "请检查提交的数据格式是否正确。", msgType, wxMessageDataForChat.getFromwxid());
// }
//
// }
// } else if ("[转账待你接收,可在手机上查看]".equals(msg)) {
//
// wxUtil.sendTextMessage(wxMessageDataForChat.getFinalfromwxid(), "暂不支持群内转账功能,请私聊进行转账充值。", msgType, wxMessageDataForChat.getFromwxid());
// } else if ("余额".equals(msg)) {
// String wxid = null;
// if (wxMessageDataForChat.getFromtype() == 1) {
// wxid = wxMessageDataForChat.getFromwxid();
// } else if (wxMessageDataForChat.getFromtype() == 2) {
// wxid = wxMessageDataForChat.getFinalfromwxid();
// }
// WxUser wxUser = wxUserService.getOne(Wrappers.query(new WxUser()).eq("wxid", wxid));
// String result = "";
// if (Util.isNotEmpty(wxUser)) {
// result = "您的余额为:" + wxUser.getMoneyLeiji() + "元\r";
// result = result + " 您的消费次数为:" + wxUser.getCountXiaofei() + "次\r";
// result = result + " 您的充值次数为:" + wxUser.getCountChongzhi() + "次\r";
// result = result + " 您的累计充值为:" + wxUser.getMoneyLeiji() + "元";
// } else {
// result = "暂未查询到充值记录。\r";
// }
//
//
// wxUtil.sendTextMessage(wxid, result, msgType, wxMessageDataForChat.getFromwxid());
// } else if ("体验".equals(msg)) {
// String wxid = null;
// if (wxMessageDataForChat.getFromtype() == 1) {
// wxid = wxMessageDataForChat.getFromwxid();
// } else if (wxMessageDataForChat.getFromtype() == 2) {
// wxid = wxMessageDataForChat.getFinalfromwxid();
// }
// String result = "";
// if (heiMingDan(wxid)) {
// result = "黑名单!";
// } else {
// WxUser wxUser = wxUserService.getOne(Wrappers.query(new WxUser()).eq("wxid", wxid));
// if (isNew(wxUser.getIsnew())) {
// wxUser.setMoneyLeiji(wxUser.getMoneyLeiji().add(new BigDecimal(1)));
// wxUser.setMoneyShengyu(wxUser.getMoneyShengyu().add(new BigDecimal(1)));
// wxUser.setCountChongzhi(wxUser.getCountChongzhi().add(BigDecimal.ONE));
// wxUser.setIsnew(1);
// wxUserService.updateById(wxUser);
// result = "体验成功,您已成功充值" + 1.00 + "元,已成功存入账户。感谢您的使用。";
// } else {
// result = "您已体验过,请勿重复体验。";
// }
//
// }
//
// wxUtil.sendTextMessage(wxid, result, msgType, wxMessageDataForChat.getFromwxid());
//
// } else if (msg.startsWith("S")) {
// logger.info("处理超级管理员的消息");
// String wxid = null;
// if (wxMessageDataForChat.getFromtype() == 1) {
// wxid = wxMessageDataForChat.getFromwxid();
// } else if (wxMessageDataForChat.getFromtype() == 2) {
// wxid = wxMessageDataForChat.getFinalfromwxid();
// }
// if (!isSuperAdminUser(wxid)) {
// return;
// }
//
// String result = "";
// if (heiMingDan(wxid)) {
// result = "黑名单!";
// } else {
// String[] split1 = msg.split("\\+");
// String superAdminOrder = split1[1];
// if ("设置普通菜单".equals(superAdminOrder)) {
// if (split1.length == 3) {
// String value = split1[2];
// Setting setting = settingService.getOne(new QueryWrapper<Setting>().eq("setting_key", key_caiDan_admin));
// setting.setSettingValue(value);
// settingService.saveOrUpdate(setting);
// result = "设置成功!";
// } else {
// result = "设置失败!";
// }
// } else if ("设置超级菜单".equals(superAdminOrder)) {
// if (split1.length == 3) {
// String value = split1[2];
// Setting setting = settingService.getOne(new QueryWrapper<Setting>().eq("setting_key", key_caiDan_admin));
// setting.setSettingValue(value);
// settingService.saveOrUpdate(setting);
// result = "设置成功!";
// } else {
// result = "设置失败!";
// }
// } else if ("查询管理员".equals(superAdminOrder)) {
// result = getSetting(order_admin);
// } else if ("添加管理员".equals(superAdminOrder)) {
// if (split1.length == 3) {
// String value = split1[2];
// Setting setting = settingService.getOne(new QueryWrapper<Setting>().eq("setting_key", order_admin));
// setting.setSettingValue(value.concat(",").concat(setting.getSettingValue()));
// settingService.saveOrUpdate(setting);
// result = "设置成功!";
// } else {
// result = "设置失败!";
// }
// } else if ("删除管理员".equals(superAdminOrder)) {
// if (split1.length == 3) {
// String value = split1[2];
// Setting setting = settingService.getOne(new QueryWrapper<Setting>().eq("setting_key", order_admin));
// setting.setSettingValue(setting.getSettingValue().replace(value, ""));
// settingService.saveOrUpdate(setting);
// result = "设置成功!";
// } else {
// result = "设置失败!";
// }
// }
// //
// //if ()
//
// wxUtil.sendTextMessage(wxid, result, msgType, wxMessageDataForChat.getFromwxid());
// }
// }
// // 管理员返回两种菜单
// else if (order_caiDan.equals(msg)) {
// String wxid = null;
// if (wxMessageDataForChat.getFromtype() == 1) {
// wxid = wxMessageDataForChat.getFromwxid();
// } else if (wxMessageDataForChat.getFromtype() == 2) {
// wxid = wxMessageDataForChat.getFinalfromwxid();
// }
// String result = "";
// String puTong = getSetting(key_caiDan_user);
// String chaoJi = getSetting(key_caiDan_admin);
// if (isSuperAdminUser(wxid)) {
// result = "用户菜单:" + puTong + " 管理员菜单:" + chaoJi;
// } else {
// result = "用户菜单:" + puTong;
// }
//
// wxUtil.sendTextMessage(wxid, result, msgType, wxMessageDataForChat.getFromwxid());
// }
// }
// wxMessageDataForChatService.save(wxMessageDataForChat);
//
// }
//
// }
// private String getSetting(String key) {
// if (Util.isNotEmpty(key)) {
// Setting value = settingRepository.getOne(new QueryWrapper<Setting>().eq("setting_key", key));
// return value.getSettingValue();
// } else {
// return null;
// }
// }
//private boolean isSuperAdminUser(String wxid) {
// boolean flag = false;
// Setting setting = settingRepository.getOne(new QueryWrapper<Setting>().eq("setting_key", "管理员"));
// if (Util.isNotEmpty(setting)) {
// if (setting.getSettingValue().contains(wxid)) {
// flag = true;
// }
// }
// return flag;
//}
/**
* @param userId
* @param token
* @return
* @throws
* @description
*/
//private String mt20(String wxid, String userId, String token) {
// /**
// * 1 查询用户余额
// * 2 调用青龙的添加环境变量
// * 3 执行美团领券
// * 4 删除环境变量
// * 5 改写返回的消息内容返回给用户
// * */
// logger.info("查询用户余额");
// HashMap<String, Object> checkYuE = checkYuE(wxid);
// Boolean isRun = (Boolean) checkYuE.get("isRun");
// String info = (String) checkYuE.get("info");
// BigDecimal yuE = (BigDecimal) checkYuE.get("yuE");
// //isRun = true;
//
// // 余额可以支持一次扣费
// if (isRun) {
// // 调用青龙 成功
// return runQL(token, wxid, 1);
//
// } else {
// // 调用青龙 失败
// logger.info("余额不支持一次扣费");
// return info;
// }
//
//}
/**
* @param wxid
* @return
* @throws
* @description 根据 wxid 查询余额
*/
//private HashMap<String, Object> checkYuE(String wxid) {
//
// HashMap<String, Object> result = new HashMap<>();
// BigDecimal yuE = BigDecimal.ZERO;
// String info = "";
// Boolean isRun = false;
// WxUser wxUser = wxUserRepository.getOne(Wrappers.query(new WxUser()).eq("wxid", wxid));
// if (Util.isEmpty(wxUser)) {
// info = "未进行过充值,请先充值后使用。";
// } else {
// // 如果余额小于等于零
// if (wxUser.getMoneyShengyu().compareTo(BigDecimal.ZERO) <= 0) {
// info = "账户余额不足,请先充值后使用。";
// }
//
// if (wxUser.getMoneyShengyu().compareTo(priceOfMT20) < 0) {
// info = "剩余余额不足以支持本次扣费,请先充值后使用。";
// } else {
// isRun = true;
// }
// }
//
// // 返回结果
// result.put("yuE", yuE);
// result.put("info", info);
// result.put("isRun", isRun);
// return result;
//}
/**
* @param wxid
* @param time 调用次数,后期可以改成包月还是一次 ,目前都是 1
* @param token
* @return
* @throws
* @description
*/
private String runQL(String token, String wxid, Integer time) {
/**
* 1. 在系统设置 -> 应用设置 -> 添加应用权限目前支持5个模块可以选择多个模块。选择一个模块之后可读写此模块的所有接口。
* 2. 使用生成的 client_id 和 client_secret 请求获取token接口 http://localhost:5700/open/auth/token?client_id=xxxxxx&client_secret=xxxxxxxx
* 3. 上面接口返回的token有效期为30天可用于请求青龙的接口 curl 'http://localhost:5700/open/envs?searchValue=&t=1630032278171' -H 'Authorization: Bearer
* 接口返回的token'
* 4. openapi的接口与系统正常接口的区别就是青龙里的是/api/envsopenapi是/open/envs即就是青龙接口中的api换成open
* */
//String responseStr = HttpRequest.post(QL_BASE_URL + getToken())
// .body(JSON.toJSONString(jsonMap))//头信息,多个头信息多次调用此方法即可
// .execute().body();
/*
* 1.查询有没有这个环境变量
* 2.没有就创建
* 3.有就修改 环境变量名 需要 wxid + 手机号
* 4.执行crons
* 5.如果是一次性的time = 1 ,就删除环境变量(考虑改成禁用)
* 6.拿到青龙的结果
* */
//new QLUtil().getEnv(remark)
HashMap<String, String> loginedUserInfo = qlUtil.getLoginedUserInfo(token);
if (Util.isNotEmpty(loginedUserInfo)) {
String mobile = loginedUserInfo.get("mobile");
String nickName = loginedUserInfo.get("nickName");
String remark = wxid + "+" + mobile + "+" + nickName;
JSONArray env = qlUtil.getEnv(token);
logger.info("1 查询环境变量 env = " + env);
// 第一次用 token 查询
if (env.size() == 0) {
env = qlUtil.getEnv(wxid + "+" + mobile);
}
// 第二次用 wxid + mobile 查询,如果不存在就直接创建
if (env.size() == 0) {
Boolean addEnv = qlUtil.addEnv(token, meituanCookie, remark);
logger.info("2 使用token查询不存在环境变量向青龙添加变量 addEnv = " + addEnv);
} else {
// 如果存在则说明 需要更新token
logger.info("3 环境变量已存在{}", env);
}
// 这时候已经有了环境变量可以执行crons
qlUtil.getCron("美团");
//logger.info("查询crons cron = " + cron);
return "runQL 调用成功";
} else {
return "获取用户信息失败";
}
}
}

View File

@@ -0,0 +1,51 @@
server:
port: 6666
spring:
application:
name: wxSend
#数据源配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.8.88:3306/jd?characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8
username: root
password: mysql_7sjTXH
#redis配置
redis:
host: 192.168.8.88
port: 6379
database: 7
timeout: 1800000
lettuce:
pool:
max-active: 20
#最大阻塞等待时间(负数表示没限制)
max-wait: -1
max-idle: 5
min-idle: 0
password: redis_6PZ52S # 文件上传
servlet:
multipart:
# 单个文件大小
max-file-size: 20MB
# 设置总上传的文件大小
max-request-size: 20MB
#MyWebMvcConfig中开启@EnableWebMvc则失效
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
# # 对象字段为null不显示
# default-property-inclusion: non_null
# 资源信息
messages:
# 国际化资源文件路径
basename: i18n/messages
# 日志配置
logging:
level:
cn.van: debug
org.springframework: warn
config:
WX_BASE_URL: http://192.168.8.208:7777/qianxun/httpapi?wxid=wxid_kr145nk7l0an31
QL_BASE_URL: http://134.175.126.60:35700

View File

@@ -1,5 +1,5 @@
server:
port: 36888
port: 6666
spring:
application:
name: wxSend