申冬 vor 3 Monaten
Commit
a0d026993d

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+/target/
+/.idea/

+ 61 - 0
pom.xml

@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.6.7</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.zzyd</groupId>
+    <artifactId>shouqianba-starter</artifactId>
+    <version>1.0</version>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <version>3.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.8</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+
+
+</project>

+ 31 - 0
src/main/java/com/zzyd/config/AutoConfiguration.java

@@ -0,0 +1,31 @@
+package com.zzyd.config;
+
+import com.zzyd.util.SQBHttpClient;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.reactive.function.client.WebClient;
+
+@EnableConfigurationProperties(ConfigProperties.class)
+@Configuration
+public class AutoConfiguration {
+
+    private ConfigProperties properties;
+
+    private WebClient webClient;
+
+    public AutoConfiguration(ConfigProperties properties , WebClient.Builder webClientBuilder) {
+        this.properties = properties;
+        this.webClient = webClientBuilder.baseUrl(properties.getUrl()).build();
+    }
+
+
+    @Bean
+    @ConditionalOnMissingBean
+    public SQBHttpClient sqbHttpClient(){
+        return new SQBHttpClient(properties,webClient);
+    }
+
+
+}

+ 33 - 0
src/main/java/com/zzyd/config/ConfigProperties.java

@@ -0,0 +1,33 @@
+package com.zzyd.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Getter
+@Setter
+@ConfigurationProperties(prefix = "shouqianba")
+public class ConfigProperties {
+
+    /**
+     *@Descriptio: vendorSn
+     */
+    private String vendorSn = "91802199";
+
+    /**
+     *@Descriptio: vendorKey
+     */
+    private String vendorKey = "967ae5544445ee4dbba92c27272c1951";
+
+    /**
+     *@Descriptio: appId
+     */
+    private String appId = "2024072400007417";
+
+    /**
+     *@Descriptio: url
+     */
+    private String url = "https://vsi-api.shouqianba.com";
+
+
+}

+ 67 - 0
src/main/java/com/zzyd/request/ActivateRequest.java

@@ -0,0 +1,67 @@
+package com.zzyd.request;
+
+import com.zzyd.request.base.IBaseRequest;
+import com.zzyd.response.ActivateResponse;
+import lombok.Data;
+
+/**
+ * @Description: 请求参数对象,用于激活请求。
+ */
+@Data
+public class ActivateRequest implements IBaseRequest<ActivateRequest, ActivateResponse> {
+
+    /**
+     * @Description: 应用ID
+     */
+    private String app_id;
+
+    /**
+     * @Description: 激活码内容
+     */
+    private String code;
+
+    /**
+     * @Description: 设备ID,内容自行定义,同一个app_id下唯一;为了方便识别,建议具有一定的格式;
+     * 例如:品牌名称+支付场景
+     */
+    private String device_id;
+
+    /**
+     * @Description: 第三方终端号,必须保证在app_id下唯一
+     */
+    private String client_sn;
+
+    /**
+     * @Description: 终端名
+     */
+    private String name;
+
+    /**
+     * @Description: 当前系统信息,如:Android5.0
+     */
+    private String os_info;
+
+    /**
+     * @Description: SDK版本
+     */
+    private String sdk_version;
+
+    /**
+     * @Description: 方法路径后缀
+     * @return 请求路径的后缀
+     */
+    @Override
+    public String apiPathSuffix() {
+        return "/terminal/activate";
+    }
+
+    @Override
+    public boolean level1Data() {
+        return true;
+    }
+
+    @Override
+    public boolean activate() {
+        return true;
+    }
+}

+ 45 - 0
src/main/java/com/zzyd/request/AutoCancelRequest.java

@@ -0,0 +1,45 @@
+package com.zzyd.request;
+
+import com.zzyd.request.base.IBaseRequest;
+import com.zzyd.response.AutoCancelResponse;
+import lombok.Data;
+
+/**
+ * @Description: 请求参数对象,用于自动撤单请求。
+ */
+@Data
+public class AutoCancelRequest implements IBaseRequest<AutoCancelRequest, AutoCancelResponse> {
+
+    /**
+     * @Description: 收钱吧终端ID
+     */
+    private String terminal_sn;
+
+    /**
+     * @Description: 收钱吧系统订单号
+     */
+    private String sn;
+
+    /**
+     * @Description: 商户自己的订单号
+     */
+    private String client_sn;
+
+    /**
+     * @Description: 方法路径后缀
+     * @return 请求路径的后缀
+     */
+    @Override
+    public String apiPathSuffix() {
+        return "/upay/v2/cancel";
+    }
+
+    /**
+     * @Description: 返回值是否为集合
+     * @return 如果返回值是集合,返回true;否则返回false
+     */
+    @Override
+    public boolean ifList() {
+        return false;
+    }
+}

+ 56 - 0
src/main/java/com/zzyd/request/CheckinRequest.java

@@ -0,0 +1,56 @@
+package com.zzyd.request;
+
+import com.zzyd.request.base.IBaseRequest;
+import com.zzyd.response.CheckinResponse;
+import lombok.Data;
+
+/**
+ * @Description: 请求参数对象,用于终端签到请求。
+ */
+@Data
+public class CheckinRequest implements IBaseRequest<CheckinRequest, CheckinResponse> {
+
+    /**
+     * @Description: 终端号
+     */
+    private String terminal_sn;
+
+    /**
+     *@Description: 终端密钥
+     */
+    private String terminal_key;
+
+    /**
+     * @Description: 设备唯一身份ID
+     */
+    private String device_id;
+
+    /**
+     * @Description: 当前系统信息,如:Android5.0
+     */
+    private String os_info;
+
+    /**
+     * @Description: SDK版本
+     */
+    private String sdk_version;
+
+
+    /**
+     * @Description: 方法路径后缀
+     * @return 请求路径的后缀
+     */
+    @Override
+    public String apiPathSuffix() {
+        return "/terminal/checkin";
+    }
+
+    /**
+     * @Description: 返回值是否为一级数据
+     * @return 如果返回值是一级数据,返回true;否则返回false
+     */
+    @Override
+    public boolean level1Data() {
+        return true;
+    }
+}

+ 45 - 0
src/main/java/com/zzyd/request/ManualRevokeRequest.java

@@ -0,0 +1,45 @@
+package com.zzyd.request;
+
+import com.zzyd.request.base.IBaseRequest;
+import com.zzyd.response.ManualRevokeResponse;
+import lombok.Data;
+
+/**
+ * @Description: 请求参数对象,用于手动撤单请求。
+ */
+@Data
+public class ManualRevokeRequest implements IBaseRequest<ManualRevokeRequest, ManualRevokeResponse> {
+
+    /**
+     * @Description: 收钱吧终端ID
+     */
+    private String terminal_sn;
+
+    /**
+     * @Description: 收钱吧系统订单号
+     */
+    private String sn;
+
+    /**
+     * @Description: 商户自己的订单号
+     */
+    private String client_sn;
+
+    /**
+     * @Description: 方法路径后缀
+     * @return 请求路径的后缀
+     */
+    @Override
+    public String apiPathSuffix() {
+        return "/upay/v2/revoke";
+    }
+
+    /**
+     * @Description: 返回值是否为集合
+     * @return 如果返回值是集合,返回true;否则返回false
+     */
+    @Override
+    public boolean ifList() {
+        return false;
+    }
+}

+ 50 - 0
src/main/java/com/zzyd/request/QueryRequest.java

@@ -0,0 +1,50 @@
+package com.zzyd.request;
+
+import com.zzyd.request.base.IBaseRequest;
+import com.zzyd.response.QueryResponse;
+import lombok.Data;
+
+/**
+ * @Description: 请求参数对象,用于查询请求。
+ */
+@Data
+public class QueryRequest implements IBaseRequest<QueryRequest, QueryResponse> {
+
+    /**
+     * @Description: 收钱吧终端ID
+     */
+    private String terminal_sn;
+
+    /**
+     * @Description: 收钱吧系统订单号
+     */
+    private String sn;
+
+    /**
+     * @Description: 商户自己的订单号
+     */
+    private String client_sn;
+
+    /**
+     * @Description: 退款序列号
+     */
+    private String refund_request_no;
+
+    /**
+     * @Description: 方法路径后缀
+     * @return 请求路径的后缀
+     */
+    @Override
+    public String apiPathSuffix() {
+        return "/upay/v2/query";
+    }
+
+    /**
+     * @Description: 返回值是否为集合
+     * @return 如果返回值是集合,返回true;否则返回false
+     */
+    @Override
+    public boolean ifList() {
+        return false;
+    }
+}

+ 110 - 0
src/main/java/com/zzyd/request/RefundRequest.java

@@ -0,0 +1,110 @@
+package com.zzyd.request;
+
+import com.zzyd.request.base.IBaseRequest;
+import com.zzyd.response.RefundResponse;
+import lombok.Data;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 请求参数对象,用于退款请求。
+ */
+@Data
+public class RefundRequest implements IBaseRequest<RefundRequest, RefundResponse> {
+
+    /**
+     * @Description: 收钱吧终端ID
+     */
+    private String terminal_sn;
+
+    /**
+     * @Description: 收钱吧唯一订单号
+     */
+    private String sn;
+
+    /**
+     * @Description: 商户订单号
+     */
+    private String client_sn;
+
+    /**
+     * @Description: 退款序列号
+     */
+    private String refund_request_no;
+
+    /**
+     * @Description: 操作员
+     */
+    private String operator;
+
+    /**
+     * @Description: 退款金额
+     */
+    private String refund_amount;
+
+    /**
+     * @Description: 扩展参数集合
+     */
+    private Map<String, String> extended;
+
+    /**
+     * @Description: 商品详情,格式为数组,元素为json对象
+     */
+    private List<GoodsDetail> goods_details;
+
+    /**
+     * @Description: 反射参数
+     */
+    private String reflect;
+
+    /**
+     * @Description: 方法路径后缀
+     * @return 请求路径的后缀
+     */
+    @Override
+    public String apiPathSuffix() {
+        return "/upay/v2/refund";
+    }
+
+    /**
+     * @Description: 返回值是否为集合
+     * @return 如果返回值是集合,返回true;否则返回false
+     */
+    @Override
+    public boolean ifList() {
+        return false;
+    }
+
+    @Data
+    public static class GoodsDetail {
+        /**
+         * @Description: 商品的编号
+         */
+        private String goods_id;
+
+        /**
+         * @Description: 商品名称
+         */
+        private String goods_name;
+
+        /**
+         * @Description: 商品退款金额
+         */
+        private String refund_amount;
+
+        /**
+         * @Description: 商品数量
+         */
+        private Integer quantity;
+
+        /**
+         * @Description: 商品单价
+         */
+        private String price;
+
+        /**
+         * @Description: 优惠类型
+         */
+        private Integer promotion_type;
+    }
+}

+ 55 - 0
src/main/java/com/zzyd/request/TradePushRequest.java

@@ -0,0 +1,55 @@
+package com.zzyd.request;
+
+import com.zzyd.request.base.IBaseRequest;
+import lombok.Data;
+
+/**
+ * @Description: 请求参数对象,用于交易推送请求。
+ */
+@Data
+public class TradePushRequest implements IBaseRequest<TradePushRequest, String> {
+
+    /**
+     * @Description: 收钱吧终端号
+     */
+    private String terminal_sn;
+
+    /**
+     * @Description: 商户订单号
+     */
+    private String out_trade_no;
+
+    /**
+     * @Description: 订单金额
+     */
+    private String total_amount;
+
+    /**
+     * @Description: 推送时间(时间戳,13位)
+     */
+    private String trade_time;
+
+    /**
+     * @Description: 推送设备号
+     */
+    private String target_device_id;
+
+    /**
+     * @Description: 回调地址
+     */
+    private String notify_url;
+
+    /**
+     * @Description: 订单备注
+     */
+    private String remark;
+
+    /**
+     * @Description: 方法路径后缀
+     * @return 请求路径的后缀
+     */
+    @Override
+    public String apiPathSuffix() {
+        return "/appPush/tradePush";
+    }
+}

+ 120 - 0
src/main/java/com/zzyd/request/base/IBaseRequest.java

@@ -0,0 +1,120 @@
+package com.zzyd.request.base;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+import com.zzyd.response.base.CommonResponse;
+import com.zzyd.util.SQBHttpClient;
+
+import java.io.Serializable;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Objects;
+
+public interface IBaseRequest<T extends IBaseRequest,R> extends Serializable {
+
+    /**
+     * 方法路径后缀
+     * @return
+     */
+    String apiPathSuffix();
+
+    /**
+     * 返回值是否为集合
+     * @return
+     */
+    default boolean ifList(){
+        return false;
+    };
+
+    /**
+     *
+     * @return
+     */
+    default boolean level1Data(){
+        return false;
+    }
+
+    /**
+     * 是否激活接口
+     * @return
+     */
+    default boolean activate(){
+        return false;
+    }
+
+
+
+    @SuppressWarnings("unchecked")
+    default CommonResponse<R> doExecute() {
+        Type genericInterface = this.getClass().getGenericInterfaces()[0];
+        Class<R> responseClass;
+        if (genericInterface instanceof ParameterizedType) {
+            Type[] actualTypeArguments = ((ParameterizedType) genericInterface).getActualTypeArguments();
+            if(actualTypeArguments.length==1){
+                responseClass = (Class<R>) String.class;
+            }
+            Type actualType = actualTypeArguments[1];
+            responseClass = (Class<R>) actualType;
+            if (actualType instanceof ParameterizedType) {
+                Type rawType = ((ParameterizedType) actualType).getRawType();
+                //处理是否集合
+                if (List.class.equals(rawType)) {
+                    Type[] listTypeArguments = ((ParameterizedType) actualType).getActualTypeArguments();
+                    if (listTypeArguments.length > 0) {
+                        responseClass = (Class<R>) listTypeArguments[0];
+                    } else {
+                        throw new IllegalStateException("无法获取泛型类型R的Class对象");
+                    }
+                }
+            }
+        } else {
+            throw new IllegalStateException("无法获取泛型类型R的Class对象");
+        }
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+            // 设置命名策略为蛇形转驼峰
+            mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
+            // 使用 responseClass 构建 JavaType
+            JavaType javaType;
+            if(ifList()){
+                JavaType listType = TypeFactory.defaultInstance().constructCollectionType(List.class, responseClass);
+                // 构建包含 List 的 CommonResponse 的 JavaType
+                javaType = mapper.getTypeFactory().constructParametricType(CommonResponse.class, listType);
+
+            }else{
+                javaType = mapper.getTypeFactory().constructParametricType(CommonResponse.class, responseClass);
+            }
+            // 执行文件请求并获取 JSON 字符串
+            String responseJson = SQBHttpClient.doExecute(this);
+            JSONObject jsonObject = JSONObject.parseObject(responseJson);
+            Object error = jsonObject.get("error_code");
+            if(!Objects.isNull(error) && error.toString().length()>0){
+                throw new RuntimeException((String) error);
+            }
+            JSONObject response = JSONObject.parseObject(JSONObject.toJSONString(jsonObject.get("biz_response")));
+            if(!Objects.isNull(response.get("error_code")) && response.get("error_code").toString().length()>0){
+                throw new RuntimeException((String) response.get("error_message"));
+            }
+            if(level1Data()){
+                SQBHttpClient.terminalSn = response.getString("terminal_sn");
+                SQBHttpClient.terminalKey = response.getString("terminal_key");
+                javaType = TypeFactory.defaultInstance().constructType(responseClass);
+                CommonResponse<R> commonResponse = new CommonResponse<>();
+                commonResponse.setResultCode("200");
+                commonResponse.setBizResponse(mapper.readValue(response.toJSONString(), javaType));
+                return commonResponse;
+            }
+            // 将 JSON 字符串反序列化为 CommonResponse 对象
+            return mapper.readValue(response.toJSONString(), javaType);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

+ 20 - 0
src/main/java/com/zzyd/response/ActivateResponse.java

@@ -0,0 +1,20 @@
+package com.zzyd.response;
+
+import lombok.Data;
+
+/**
+ * @Description: 响应参数对象,用于激活请求的响应。
+ */
+@Data
+public class ActivateResponse {
+
+    /**
+     * @Description: 终端号
+     */
+    private String terminalSn;
+
+    /**
+     * @Description: 终端密钥
+     */
+    private String terminalKey;
+}

+ 100 - 0
src/main/java/com/zzyd/response/AutoCancelResponse.java

@@ -0,0 +1,100 @@
+package com.zzyd.response;
+
+import lombok.Data;
+
+/**
+ * @Description: 响应参数对象,用于自动撤单请求的响应。
+ */
+@Data
+public class AutoCancelResponse {
+
+    /**
+     * @Description: 结果码
+     */
+    private String resultCode;
+
+    /**
+     * @Description: 错误码
+     */
+    private String errorCode;
+
+    /**
+     * @Description: 错误消息
+     */
+    private String errorMessage;
+
+    /**
+     * @Description: 收钱吧终端ID
+     */
+    private String terminalSn;
+
+    /**
+     * @Description: 收钱吧唯一订单号
+     */
+    private String sn;
+
+    /**
+     * @Description: 商户订单号
+     */
+    private String clientSn;
+
+    /**
+     * @Description: 流水状态
+     */
+    private String status;
+
+    /**
+     * @Description: 订单状态
+     */
+    private String orderStatus;
+
+    /**
+     * @Description: 支付方式
+     */
+    private String payway;
+
+    /**
+     * @Description: 支付方式名称
+     */
+    private String paywayName;
+
+    /**
+     * @Description: 支付平台的订单凭证号
+     */
+    private String tradeNo;
+
+    /**
+     * @Description: 交易总金额
+     */
+    private String totalAmount;
+
+    /**
+     * @Description: 剩余金额
+     */
+    private String netAmount;
+
+    /**
+     * @Description: 本次操作金额
+     */
+    private String settlementAmount;
+
+    /**
+     * @Description: 上次操作在收钱吧的完成时间
+     */
+    private String finishTime;
+
+    /**
+     * @Description: 上次操作在支付平台完成的时间
+     */
+    private String channelFinishTime;
+
+    /**
+     * @Description: 商品概述
+     */
+    private String subject;
+
+    /**
+     * @Description: 操作员
+     */
+    private String operator;
+}

+ 20 - 0
src/main/java/com/zzyd/response/CheckinResponse.java

@@ -0,0 +1,20 @@
+package com.zzyd.response;
+
+import lombok.Data;
+
+/**
+ * @Description: 响应参数对象,用于终端签到请求的响应。
+ */
+@Data
+public class CheckinResponse {
+
+    /**
+     * @Description: 终端号
+     */
+    private String terminalSn;
+
+    /**
+     * @Description: 终端密钥
+     */
+    private String terminalKey;
+}

+ 100 - 0
src/main/java/com/zzyd/response/ManualRevokeResponse.java

@@ -0,0 +1,100 @@
+package com.zzyd.response;
+
+import lombok.Data;
+
+/**
+ * @Description: 响应参数对象,用于手动撤单请求的响应。
+ */
+@Data
+public class ManualRevokeResponse {
+
+    /**
+     * @Description: 结果码
+     */
+    private String resultCode;
+
+    /**
+     * @Description: 错误码
+     */
+    private String errorCode;
+
+    /**
+     * @Description: 错误消息
+     */
+    private String errorMessage;
+
+    /**
+     * @Description: 收钱吧终端ID
+     */
+    private String terminalSn;
+
+    /**
+     * @Description: 收钱吧唯一订单号
+     */
+    private String sn;
+
+    /**
+     * @Description: 商户订单号
+     */
+    private String clientSn;
+
+    /**
+     * @Description: 流水状态
+     */
+    private String status;
+
+    /**
+     * @Description: 订单状态
+     */
+    private String orderStatus;
+
+    /**
+     * @Description: 支付方式
+     */
+    private String payway;
+
+    /**
+     * @Description: 支付方式名称
+     */
+    private String paywayName;
+
+    /**
+     * @Description: 支付平台的订单凭证号
+     */
+    private String tradeNo;
+
+    /**
+     * @Description: 交易总金额
+     */
+    private String totalAmount;
+
+    /**
+     * @Description: 剩余金额
+     */
+    private String netAmount;
+
+    /**
+     * @Description: 本次操作金额
+     */
+    private String settlementAmount;
+
+    /**
+     * @Description: 上次操作在收钱吧的完成时间
+     */
+    private String finishTime;
+
+    /**
+     * @Description: 上次操作在支付平台完成的时间
+     */
+    private String channelFinishTime;
+
+    /**
+     * @Description: 商品概述
+     */
+    private String subject;
+
+    /**
+     * @Description: 操作员
+     */
+    private String operator;
+}

+ 120 - 0
src/main/java/com/zzyd/response/PaymentCallbackResponse.java

@@ -0,0 +1,120 @@
+package com.zzyd.response;
+
+import lombok.Data;
+import java.util.List;
+
+/**
+ * @Description: 回调接口参数对象,用于支付成功或失败订单信息推送。
+ */
+@Data
+public class PaymentCallbackResponse {
+
+    /**
+     * @Description: 收钱吧唯一订单号
+     */
+    private String sn;
+
+    /**
+     * @Description: 商户订单号
+     */
+    private String clientSn;
+
+    /**
+     * @Description: 支付服务商订单号,只有支付成功时才有值返回
+     */
+    private String tradeNo;
+
+    /**
+     * @Description: 流水状态
+     */
+    private String status;
+
+    /**
+     * @Description: 订单状态
+     */
+    private String orderStatus;
+
+    /**
+     * @Description: 支付方式,一级支付方式
+     */
+    private String payway;
+
+    /**
+     * @Description: 二级支付方式
+     */
+    private String subPayway;
+
+    /**
+     * @Description: 付款人ID,支付平台(微信,支付宝)上的付款人ID
+     */
+    private String payerUid;
+
+    /**
+     * @Description: 付款人账号,支付平台上(微信,支付宝)的付款人账号
+     */
+    private String payerLogin;
+
+    /**
+     * @Description: 交易总额
+     */
+    private String totalAmount;
+
+    /**
+     * @Description: 实收金额,如果没有退款,这个字段等于totalAmount。否则等于 totalAmount减去退款金额
+     */
+    private String netAmount;
+
+    /**
+     * @Description: 本次操作金额,本次支付金额
+     */
+    private String settlementAmount;
+
+    /**
+     * @Description: 交易概述
+     */
+    private String subject;
+
+    /**
+     * @Description: 付款动作在收钱吧的完成时间,时间戳
+     */
+    private String finishTime;
+
+    /**
+     * @Description: 付款动作在支付服务商的完成时间,时间戳,只有支付成功时才有值返回
+     */
+    private String channelFinishTime;
+
+    /**
+     * @Description: 操作员,门店操作员
+     */
+    private String operator;
+
+    /**
+     * @Description: 反射参数,透传参数
+     */
+    private String reflect;
+
+    /**
+     * @Description: 优惠详情,格式为json,内容有两部分 goodsDetails为数组,内容为核销单品信息,voucherDetails为数组,内容为核销券信息
+     */
+    private String providerResponse;
+
+    /**
+     * @Description: 活动优惠,订单内活动优惠信息概览,格式为数组,元素为json对象
+     */
+    private List<Payment> paymentList;
+
+    @Data
+    public static class Payment {
+
+        /**
+         * @Description: 活动类型
+         */
+        private String type;
+
+        /**
+         * @Description: 活动出资总金额
+         */
+        private String amountTotal;
+    }
+}

+ 116 - 0
src/main/java/com/zzyd/response/QueryResponse.java

@@ -0,0 +1,116 @@
+package com.zzyd.response;
+
+import lombok.Data;
+import java.util.List;
+
+/**
+ * @Description: 响应参数对象,用于查询请求的响应。
+ */
+@Data
+public class QueryResponse {
+
+    /**
+     * @Description: 结果码
+     */
+    private String resultCode;
+
+    /**
+     * @Description: 错误码
+     */
+    private String errorCode;
+
+    /**
+     * @Description: 错误消息
+     */
+    private String errorMessage;
+
+    /**
+     * @Description: 收钱吧终端ID
+     */
+    private String terminalSn;
+
+    /**
+     * @Description: 收钱吧唯一订单号
+     */
+    private String sn;
+
+    /**
+     * @Description: 商户订单号
+     */
+    private String clientSn;
+
+    /**
+     * @Description: 流水状态
+     */
+    private String status;
+
+    /**
+     * @Description: 订单状态
+     */
+    private String orderStatus;
+
+    /**
+     * @Description: 支付方式
+     */
+    private String payway;
+
+    /**
+     * @Description: 支付方式名称
+     */
+    private String paywayName;
+
+    /**
+     * @Description: 付款人id
+     */
+    private String payerUid;
+
+    /**
+     * @Description: 支付平台的订单凭证号
+     */
+    private String tradeNo;
+
+    /**
+     * @Description: 交易总金额
+     */
+    private String totalAmount;
+
+    /**
+     * @Description: 剩余金额
+     */
+    private String netAmount;
+
+    /**
+     * @Description: 本次操作金额
+     */
+    private String settlementAmount;
+
+    /**
+     * @Description: 上次操作在收钱吧的完成时间
+     */
+    private String finishTime;
+
+    /**
+     * @Description: 上次操作在支付平台完成的时间
+     */
+    private String channelFinishTime;
+
+    /**
+     * @Description: 商品概述
+     */
+    private String subject;
+
+    /**
+     * @Description: 操作员
+     */
+    private String operator;
+
+    /**
+     * @Description: 优惠详情
+     */
+    private String providerResponse;
+
+    /**
+     * @Description: 活动优惠
+     */
+    private List<String> paymentList;
+}

+ 100 - 0
src/main/java/com/zzyd/response/RefundResponse.java

@@ -0,0 +1,100 @@
+package com.zzyd.response;
+
+import lombok.Data;
+
+/**
+ * @Description: 响应参数对象,用于退款请求的响应。
+ */
+@Data
+public class RefundResponse {
+
+    /**
+     * @Description: 结果码
+     */
+    private String resultCode;
+
+    /**
+     * @Description: 错误码
+     */
+    private String errorCode;
+
+    /**
+     * @Description: 错误消息
+     */
+    private String errorMessage;
+
+    /**
+     * @Description: 收钱吧终端ID
+     */
+    private String terminalSn;
+
+    /**
+     * @Description: 收钱吧唯一订单号
+     */
+    private String sn;
+
+    /**
+     * @Description: 商户订单号
+     */
+    private String clientSn;
+
+    /**
+     * @Description: 退款流水状态
+     */
+    private String status;
+
+    /**
+     * @Description: 订单状态
+     */
+    private String orderStatus;
+
+    /**
+     * @Description: 支付方式
+     */
+    private String payway;
+
+    /**
+     * @Description: 支付方式名称
+     */
+    private String paywayName;
+
+    /**
+     * @Description: 支付平台的订单凭证号
+     */
+    private String tradeNo;
+
+    /**
+     * @Description: 交易总金额
+     */
+    private String totalAmount;
+
+    /**
+     * @Description: 剩余金额
+     */
+    private String netAmount;
+
+    /**
+     * @Description: 本次操作金额
+     */
+    private String settlementAmount;
+
+    /**
+     * @Description: 退款动作在收钱吧的完成时间
+     */
+    private String finishTime;
+
+    /**
+     * @Description: 退款动作在支付平台完成的时间
+     */
+    private String channelFinishTime;
+
+    /**
+     * @Description: 商品概述
+     */
+    private String subject;
+
+    /**
+     * @Description: 操作员
+     */
+    private String operator;
+}

+ 36 - 0
src/main/java/com/zzyd/response/base/CommonResponse.java

@@ -0,0 +1,36 @@
+package com.zzyd.response.base;
+
+import lombok.Data;
+
+/**
+ * @Description: 通用接口响应对象,用于统一处理所有接口的响应格式。
+ */
+@Data
+public class CommonResponse<T> {
+
+    /**
+     * @Description: 通讯响应码
+     * 200:通讯成功;
+     * 400:客户端错误;
+     * 500:服务端错误
+     */
+    private String resultCode;
+
+    /**
+     * @Description: 通讯错误码
+     * 通讯失败时返回,具体值见附录《公共错误码》
+     */
+    private String errorCode;
+
+    /**
+     * @Description: 通讯错误信息描述
+     * 通讯失败时返回,具体信息见附录《公共错误码》
+     */
+    private String errorMessage;
+
+    /**
+     * @Description: 业务响应数据
+     * 通讯成功时返回,数据类型为泛型T
+     */
+    private T bizResponse;
+}

+ 17 - 0
src/main/java/com/zzyd/util/MD5Util.java

@@ -0,0 +1,17 @@
+package com.zzyd.util;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+import java.io.UnsupportedEncodingException;
+
+public class MD5Util {
+
+    public static String encryptMd5(String string) throws UnsupportedEncodingException {
+        return encryptMd5(string, "UTF-8");
+    }
+
+    public static String encryptMd5(String string, String charSet) throws UnsupportedEncodingException {
+        return DigestUtils.md5Hex(string.getBytes(charSet));
+    }
+
+}

+ 73 - 0
src/main/java/com/zzyd/util/SQBHttpClient.java

@@ -0,0 +1,73 @@
+package com.zzyd.util;
+
+import com.alibaba.fastjson.JSONObject;
+import com.zzyd.config.ConfigProperties;
+import com.zzyd.request.base.IBaseRequest;
+import org.springframework.http.MediaType;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+
+import javax.annotation.PostConstruct;
+import java.io.UnsupportedEncodingException;
+
+public class SQBHttpClient {
+
+    public static SQBHttpClient client;
+
+    private ConfigProperties properties;
+
+    private WebClient webClient;
+
+    public static String terminalKey = "";
+
+    public static String terminalSn = "";
+
+    public SQBHttpClient(ConfigProperties properties, WebClient webClient) {
+        this.properties = properties;
+        this.webClient = webClient;
+    }
+
+    @PostConstruct
+    public void init(){
+        client = this;
+    }
+
+    public static <T extends IBaseRequest>String doExecute(T apiRequest){
+        String sn = client.properties.getVendorSn();
+        String key = client.properties.getVendorKey();
+        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(apiRequest));
+        if(apiRequest.apiPathSuffix().equals("/terminal/checkin")){
+            terminalSn = jsonObject.getString("terminal_sn");
+            terminalKey = jsonObject.getString("terminal_key");
+            jsonObject.remove("terminal_key");
+        }
+        if(!apiRequest.activate()){
+            if(terminalSn.length()==0){
+                throw new RuntimeException("请先签到设备,每天签到一次!");
+            }
+            sn = terminalSn;
+            key = terminalKey;
+        }
+        String param = jsonObject.toJSONString();
+        Mono<String> response = client.webClient.post()
+                .uri(client.properties.getUrl()+apiRequest.apiPathSuffix())
+                .contentType(MediaType.valueOf("application/json; charset=UTF-8"))
+                .header("Authorization",sn + " " + getSign(param+key))
+                .bodyValue(param)
+                .retrieve()
+                .bodyToMono(String.class);
+        return response.block();
+    }
+
+
+    public static String getSign(String signStr) {
+        try{
+            String md5 = MD5Util.encryptMd5(signStr);
+            return md5;
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            return  null ;
+        }
+    }
+
+}

+ 2 - 0
src/main/resources/META-INF/spring.factories

@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.zzyd.config.AutoConfiguration