From 0b7c409aff156bc4d5605893e860c0c3652b9cd8 Mon Sep 17 00:00:00 2001
From: k94314517 <8417338+k94314517@user.noreply.gitee.com>
Date: 星期四, 17 七月 2025 19:25:30 +0800
Subject: [PATCH] 111
---
server/admin/src/main/java/com/doumee/job/AutoCommentJob.java | 34 +
server/admin/src/main/java/com/doumee/job/AutoGrabOrdersJob.java | 34 +
server/web/src/main/java/com/doumee/api/web/ConfigApi.java | 2
server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java | 3
server/services/src/main/java/com/doumee/dao/business/model/WithdrawalOrders.java | 8
server/services/src/main/java/com/doumee/config/wx/WXPayUtility.java | 456 +++++++++++++++++++
server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java | 6
server/services/src/main/java/com/doumee/config/wx/TransferToUser.java | 312 +++++++++++++
server/services/src/main/java/com/doumee/dao/vo/OrderReleaseVO.java | 21
server/services/src/main/java/com/doumee/service/business/WithdrawalOrdersService.java | 5
server/services/src/main/java/com/doumee/service/business/MemberService.java | 2
server/services/src/main/java/com/doumee/service/business/OrdersService.java | 9
server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java | 103 ++++
server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java | 15
server/services/src/main/java/com/doumee/api/common/PublicCloudController.java | 3
server/admin/src/main/java/com/doumee/job/InitializeCodeJob.java | 34 +
server/services/src/main/resources/application-dev.yml | 16
server/web/src/main/java/com/doumee/api/web/AccountApi.java | 13
server/admin/src/main/java/com/doumee/job/AutoConfirmJob.java | 34 +
server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java | 5
server/web/src/main/java/com/doumee/api/web/UserApi.java | 29 +
server/web/src/main/java/com/doumee/api/web/OrdersApi.java | 12
server/pom.xml | 2
server/services/src/main/java/com/doumee/dao/business/model/MemberRevenue.java | 2
server/services/src/main/java/com/doumee/dao/business/model/Orders.java | 6
server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java | 19
server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java | 152 ++++-
server/services/src/main/java/com/doumee/dao/business/model/Member.java | 7
28 files changed, 1,276 insertions(+), 68 deletions(-)
diff --git a/server/admin/src/main/java/com/doumee/job/AutoCommentJob.java b/server/admin/src/main/java/com/doumee/job/AutoCommentJob.java
new file mode 100644
index 0000000..402b5cb
--- /dev/null
+++ b/server/admin/src/main/java/com/doumee/job/AutoCommentJob.java
@@ -0,0 +1,34 @@
+package com.doumee.job;
+
+import com.doumee.core.job.BaseJob;
+import com.doumee.core.job.JobContext;
+import com.doumee.core.job.JobParam;
+import com.doumee.service.business.OrdersService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鑷姩璇勪环
+ * @author dm
+ * @since 2025/03/31 16:44
+ */
+@Slf4j
+@Component("AutoCommentJob")
+public class AutoCommentJob extends BaseJob {
+
+ @Autowired
+ private OrdersService ordersService;
+
+ @Override
+ public JobContext execute(JobParam param) {
+ JobContext jobContext = new JobContext();
+ try {
+ ordersService.autoComment();
+ jobContext.setContext("鑷姩璇勪环");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return jobContext;
+ }
+}
diff --git a/server/admin/src/main/java/com/doumee/job/AutoConfirmJob.java b/server/admin/src/main/java/com/doumee/job/AutoConfirmJob.java
new file mode 100644
index 0000000..74fe0fb
--- /dev/null
+++ b/server/admin/src/main/java/com/doumee/job/AutoConfirmJob.java
@@ -0,0 +1,34 @@
+package com.doumee.job;
+
+import com.doumee.core.job.BaseJob;
+import com.doumee.core.job.JobContext;
+import com.doumee.core.job.JobParam;
+import com.doumee.service.business.OrdersService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鑷姩纭璁㈠崟淇敼
+ * @author dm
+ * @since 2025/03/31 16:44
+ */
+@Slf4j
+@Component("AutoConfirmJob")
+public class AutoConfirmJob extends BaseJob {
+
+ @Autowired
+ private OrdersService ordersService;
+
+ @Override
+ public JobContext execute(JobParam param) {
+ JobContext jobContext = new JobContext();
+ try {
+ ordersService.autoConfirm();
+ jobContext.setContext("鑷姩纭璁㈠崟淇敼");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return jobContext;
+ }
+}
diff --git a/server/admin/src/main/java/com/doumee/job/AutoGrabOrdersJob.java b/server/admin/src/main/java/com/doumee/job/AutoGrabOrdersJob.java
new file mode 100644
index 0000000..5bcb7af
--- /dev/null
+++ b/server/admin/src/main/java/com/doumee/job/AutoGrabOrdersJob.java
@@ -0,0 +1,34 @@
+package com.doumee.job;
+
+import com.doumee.core.job.BaseJob;
+import com.doumee.core.job.JobContext;
+import com.doumee.core.job.JobParam;
+import com.doumee.service.business.OrdersService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鑷姩娲惧崟
+ * @author dm
+ * @since 2025/03/31 16:44
+ */
+@Slf4j
+@Component("AutoGrabOrdersJob")
+public class AutoGrabOrdersJob extends BaseJob {
+
+ @Autowired
+ private OrdersService ordersService;
+
+ @Override
+ public JobContext execute(JobParam param) {
+ JobContext jobContext = new JobContext();
+ try {
+ ordersService.autoGrabOrders();
+ jobContext.setContext("鑷姩娲惧崟");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return jobContext;
+ }
+}
diff --git a/server/admin/src/main/java/com/doumee/job/InitializeCodeJob.java b/server/admin/src/main/java/com/doumee/job/InitializeCodeJob.java
new file mode 100644
index 0000000..4d66167
--- /dev/null
+++ b/server/admin/src/main/java/com/doumee/job/InitializeCodeJob.java
@@ -0,0 +1,34 @@
+package com.doumee.job;
+
+import com.doumee.core.job.BaseJob;
+import com.doumee.core.job.JobContext;
+import com.doumee.core.job.JobParam;
+import com.doumee.service.business.OrdersService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鍒濆鍖栬鍗曠紪鍙�
+ * @author dm
+ * @since 2025/03/31 16:44
+ */
+@Slf4j
+@Component("InitializeCodeJob")
+public class InitializeCodeJob extends BaseJob {
+
+ @Autowired
+ private OrdersService ordersService;
+
+ @Override
+ public JobContext execute(JobParam param) {
+ JobContext jobContext = new JobContext();
+ try {
+ ordersService.initializeCode();
+ jobContext.setContext("鍒濆鍖栬鍗曠紪鍙�");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return jobContext;
+ }
+}
diff --git a/server/pom.xml b/server/pom.xml
index 3c9dcf4..3ba17e0 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -262,6 +262,8 @@
<artifactId>wechatpay-java</artifactId>
<version>0.2.12</version>
</dependency>
+
+
<!-- <dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-storage-blob</artifactId>
diff --git a/server/services/src/main/java/com/doumee/api/common/PublicCloudController.java b/server/services/src/main/java/com/doumee/api/common/PublicCloudController.java
index 738848c..f4addb1 100644
--- a/server/services/src/main/java/com/doumee/api/common/PublicCloudController.java
+++ b/server/services/src/main/java/com/doumee/api/common/PublicCloudController.java
@@ -61,7 +61,7 @@
})
@PostMapping(value = "/upload", headers = "content-type=multipart/form-data")
@ResponseBody
- public void upload(HttpServletRequest request, HttpServletResponse response, String folder) throws Exception {
+ public void upload(HttpServletRequest request, HttpServletResponse response, String folder,String flag) throws Exception {
Date d1 = new Date();
log.error("鎬诲緱涓婁紶鏂囦欢鎴愬姛=============寮�濮�========="+DateUtil.getPlusTime2(d1));
if(Objects.isNull(folder)){
@@ -105,6 +105,7 @@
fileJSON.put("imgaddr", fName);
fileJSON.put("imgname", fileName);
fileJSON.put("originname", originname);
+ fileJSON.put("flag", flag);
context.put("data",fileJSON);
context.put("message","璇锋眰鎴愬姛");
writerJson(response, context);
diff --git a/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java b/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java
index f1e4399..06ec043 100644
--- a/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java
+++ b/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java
@@ -112,7 +112,8 @@
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, jwtProperties.getSecret())
.compact();
- redisTemplate.opsForValue().set(Constants.REDIS_TOKEN_KEY+token,JSONObject.toJSONString(member),jwtProperties.getExpiration(), TimeUnit.MILLISECONDS);
+ redisTemplate.opsForValue().set(Constants.REDIS_TOKEN_KEY+token,JSONObject.toJSONString(member),
+ jwtProperties.getExpiration(), TimeUnit.MILLISECONDS);
return token;
}
diff --git a/server/services/src/main/java/com/doumee/config/wx/TransferToUser.java b/server/services/src/main/java/com/doumee/config/wx/TransferToUser.java
new file mode 100644
index 0000000..af0b96e
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/config/wx/TransferToUser.java
@@ -0,0 +1,312 @@
+package com.doumee.config.wx;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+import okhttp3.*;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @Author : Rk
+ * @create 2025/7/17 9:19
+ */
+public class TransferToUser {
+
+ private static String HOST = "https://api.mch.weixin.qq.com";
+ private static String METHOD = "POST";
+ private static String PATH = "/v3/fund-app/mch-transfer/transfer-bills";
+ private static String CANCEL_PATH = "/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}/cancel";
+
+
+ public static void main(String[] args) {
+ // TODO: 璇峰噯澶囧晢鎴峰紑鍙戝繀瑕佸弬鏁帮紝鍙傝�冿細https://pay.weixin.qq.com/doc/v3/merchant/4013070756
+ TransferToUser client = new TransferToUser(
+ "1229817002", // 鍟嗘埛鍙凤紝鏄敱寰俊鏀粯绯荤粺鐢熸垚骞跺垎閰嶇粰姣忎釜鍟嗘埛鐨勫敮涓�鏍囪瘑绗︼紝鍟嗘埛鍙疯幏鍙栨柟寮忓弬鑰� https://pay.weixin.qq.com/doc/v3/merchant/4013070756
+ "3FE90C2F3D40A56E1C51926F31B8A8D22426CCE0", // 鍟嗘埛API璇佷功搴忓垪鍙凤紝濡備綍鑾峰彇璇峰弬鑰� https://pay.weixin.qq.com/doc/v3/merchant/4013053053
+ "d://wechatApiclient_key.pem", // 鍟嗘埛API璇佷功绉侀挜鏂囦欢璺緞锛屾湰鍦版枃浠惰矾寰�
+ "PUB_KEY_ID_0112298170022025071700291836000600", // 寰俊鏀粯鍏挜ID锛屽浣曡幏鍙栬鍙傝�� https://pay.weixin.qq.com/doc/v3/merchant/4013038816
+ "d://pub_key.pem" // 寰俊鏀粯鍏挜鏂囦欢璺緞锛屾湰鍦版枃浠惰矾寰�
+ );
+
+ TransferToUserRequest request = new TransferToUserRequest();
+ request.appid = "wxcd2b89fd2ff065f8"; //灏忕▼搴廼d
+ request.outBillNo = "plfk2020042016";
+ request.transferSceneId = "1005";
+ request.openid = "oKKHU5IFKpss_DIbFX1lqghFJOEg";
+ request.userName = client.encrypt("鏂芥棴杈�");
+ request.transferAmount = 91L;
+ request.transferRemark = "~~~";
+ request.notifyUrl = "https://www.weixin.qq.com/wxpay/pay.php";
+ request.userRecvPerception = "鍔冲姟鎶ラ叕";
+ request.transferSceneReportInfos = new ArrayList<>();
+ {
+ TransferSceneReportInfo item0 = new TransferSceneReportInfo();
+ item0.infoType = "宀椾綅绫诲瀷";
+ item0.infoContent = "瀹屾垚璁㈠崟";
+ request.transferSceneReportInfos.add(item0);
+ TransferSceneReportInfo item1 = new TransferSceneReportInfo();
+ item1.infoType = "鎶ラ叕璇存槑";
+ item1.infoContent = "璁㈠崟鎶ラ叕";
+ request.transferSceneReportInfos.add(item1);
+ };
+ try {
+ TransferToUserResponse response = client.testRun(request);
+
+ // TODO: 璇锋眰鎴愬姛锛岀户缁笟鍔¢�昏緫
+ System.out.println(JSONObject.toJSONString(response));
+ } catch (WXPayUtility.ApiException e) {
+ // TODO: 璇锋眰澶辫触锛屾牴鎹姸鎬佺爜鎵ц涓嶅悓鐨勯�昏緫
+ e.printStackTrace();
+ }
+ }
+
+ private final String mchid;
+ private final String certificateSerialNo;
+ private final PrivateKey privateKey;
+ private final String wechatPayPublicKeyId;
+ private final PublicKey wechatPayPublicKey;
+
+ public TransferToUser(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) {
+ this.mchid = mchid;
+ this.certificateSerialNo = certificateSerialNo;
+ this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);
+ this.wechatPayPublicKeyId = wechatPayPublicKeyId;
+ this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
+ }
+
+ public TransferToUserResponse testRun(TransferToUserRequest request) {
+ String uri = PATH;
+ String reqBody = WXPayUtility.toJson(request);
+
+ Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
+ reqBuilder.addHeader("Accept", "application/json");
+ reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
+ reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody));
+ reqBuilder.addHeader("Content-Type", "application/json");
+ RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
+ reqBuilder.method(METHOD, requestBody);
+ Request httpRequest = reqBuilder.build();
+
+ // 鍙戦�丠TTP璇锋眰
+ OkHttpClient client = new OkHttpClient.Builder().build();
+ try (Response httpResponse = client.newCall(httpRequest).execute()) {
+ String respBody = WXPayUtility.extractBody(httpResponse);
+ if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
+ // 2XX 鎴愬姛锛岄獙璇佸簲绛旂鍚�
+ WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
+ httpResponse.headers(), respBody);
+
+ // 浠嶩TTP搴旂瓟鎶ユ枃鏋勫缓杩斿洖鏁版嵁
+ return WXPayUtility.fromJson(respBody, TransferToUserResponse.class);
+ } else {
+ throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
+ }
+ }
+
+ public TransferToUserResponse run(TransferToUserRequest request,String name) {
+ String uri = PATH;
+ request.appid = WxMiniConfig.wxProperties.getSubAppId();
+ request.transferSceneId = "1005";
+ request.userRecvPerception = "鍔冲姟鎶ラ叕";
+ if(request.transferAmount >= 30){
+ request.userName = this.encrypt(name);
+ }
+
+ request.transferSceneReportInfos = new ArrayList<>();
+ {
+ TransferSceneReportInfo item0 = new TransferSceneReportInfo();
+ item0.infoType = "宀椾綅绫诲瀷";
+ item0.infoContent = "瀹屾垚璁㈠崟";
+ request.transferSceneReportInfos.add(item0);
+ TransferSceneReportInfo item1 = new TransferSceneReportInfo();
+ item1.infoType = "鎶ラ叕璇存槑";
+ item1.infoContent = "璁㈠崟鎶ラ叕";
+ request.transferSceneReportInfos.add(item1);
+ };
+ String reqBody = WXPayUtility.toJson(request);
+
+ Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
+ reqBuilder.addHeader("Accept", "application/json");
+ reqBuilder.addHeader("Wechatpay-Serial", WxMiniConfig.wxProperties.getWechatPayPublicKeyId());
+ reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(WxMiniConfig.wxProperties.getMchId(),
+ WxMiniConfig.wxProperties.getWechatSerialNumer(),
+ WXPayUtility.loadPrivateKeyFromPath(WxMiniConfig.wxProperties.getWechatPrivateKeyPath()),
+ METHOD, uri, reqBody));
+
+// reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody));
+ reqBuilder.addHeader("Content-Type", "application/json");
+ RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
+ reqBuilder.method(METHOD, requestBody);
+ Request httpRequest = reqBuilder.build();
+
+ // 鍙戦�丠TTP璇锋眰
+ OkHttpClient client = new OkHttpClient.Builder().build();
+ try (Response httpResponse = client.newCall(httpRequest).execute()) {
+ String respBody = WXPayUtility.extractBody(httpResponse);
+ if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
+ // 2XX 鎴愬姛锛岄獙璇佸簲绛旂鍚�
+ WXPayUtility.validateResponse(WxMiniConfig.wxProperties.getWechatPayPublicKeyId(), WXPayUtility.loadPublicKeyFromPath(WxMiniConfig.wxProperties.getWechatPubKeyPath()),
+ httpResponse.headers(), respBody);
+
+ // 浠嶩TTP搴旂瓟鎶ユ枃鏋勫缓杩斿洖鏁版嵁
+ return WXPayUtility.fromJson(respBody, TransferToUserResponse.class);
+ } else {
+ throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
+ }
+ }
+
+
+ public TransferToUser.CancelTransferResponse cancelRun(TransferToUser.CancelTransferRequest request) {
+ String uri = CANCEL_PATH;
+ uri = uri.replace("{out_bill_no}", WXPayUtility.urlEncode(request.outBillNo));
+
+ Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
+ reqBuilder.addHeader("Accept", "application/json");
+ reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
+ reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(WxMiniConfig.wxProperties.getMchId(),
+ WxMiniConfig.wxProperties.getWechatSerialNumer(),
+ WXPayUtility.loadPrivateKeyFromPath(WxMiniConfig.wxProperties.getWechatPrivateKeyPath()),
+ METHOD, uri, null));
+ reqBuilder.addHeader("Content-Type", "application/json");
+ RequestBody emptyBody = RequestBody.create(null, "");
+ reqBuilder.method(METHOD, emptyBody);
+ Request httpRequest = reqBuilder.build();
+
+ // 鍙戦�丠TTP璇锋眰
+ OkHttpClient client = new OkHttpClient.Builder().build();
+ try (Response httpResponse = client.newCall(httpRequest).execute()) {
+ String respBody = WXPayUtility.extractBody(httpResponse);
+ if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
+ // 2XX 鎴愬姛锛岄獙璇佸簲绛旂鍚�
+ WXPayUtility.validateResponse(WxMiniConfig.wxProperties.getWechatPayPublicKeyId(), WXPayUtility.loadPublicKeyFromPath(WxMiniConfig.wxProperties.getWechatPubKeyPath()),
+ httpResponse.headers(), respBody);
+
+ // 浠嶩TTP搴旂瓟鎶ユ枃鏋勫缓杩斿洖鏁版嵁
+ return WXPayUtility.fromJson(respBody, TransferToUser.CancelTransferResponse.class);
+ } else {
+ throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
+ }
+ }
+
+
+
+ public String encrypt(String plainText) {
+ return WXPayUtility.encrypt(this.wechatPayPublicKey, plainText);
+ }
+
+ public static class TransferToUserResponse {
+ @SerializedName("out_bill_no")
+ public String outBillNo;
+
+ @SerializedName("transfer_bill_no")
+ public String transferBillNo;
+
+ @SerializedName("create_time")
+ public String createTime;
+
+ @SerializedName("state")
+ public TransferBillStatus state;
+
+ @SerializedName("package_info")
+ public String packageInfo;
+ }
+
+ public enum TransferBillStatus {
+ @SerializedName("ACCEPTED")
+ ACCEPTED,
+ @SerializedName("PROCESSING")
+ PROCESSING,
+ @SerializedName("WAIT_USER_CONFIRM")
+ WAIT_USER_CONFIRM,
+ @SerializedName("TRANSFERING")
+ TRANSFERING,
+ @SerializedName("SUCCESS")
+ SUCCESS,
+ @SerializedName("FAIL")
+ FAIL,
+ @SerializedName("CANCELING")
+ CANCELING,
+ @SerializedName("CANCELLED")
+ CANCELLED
+ }
+
+ public static class TransferSceneReportInfo {
+ @SerializedName("info_type")
+ public String infoType;
+
+ @SerializedName("info_content")
+ public String infoContent;
+ }
+
+ public static class TransferToUserRequest {
+
+ @SerializedName("appid")
+ public String appid;
+
+ @SerializedName("out_bill_no")
+ public String outBillNo;
+
+ @SerializedName("transfer_scene_id")
+ public String transferSceneId;
+
+ @SerializedName("openid")
+ public String openid;
+
+ @SerializedName("user_name")
+ public String userName;
+
+ @SerializedName("transfer_amount")
+ public Long transferAmount;
+
+ @SerializedName("transfer_remark")
+ public String transferRemark;
+
+ @SerializedName("notify_url")
+ public String notifyUrl;
+
+ @SerializedName("user_recv_perception")
+ public String userRecvPerception;
+
+ @SerializedName("transfer_scene_report_infos")
+ public List<TransferSceneReportInfo> transferSceneReportInfos;
+ }
+
+ public static class CancelTransferResponse {
+ @SerializedName("out_bill_no")
+ public String outBillNo;
+
+ @SerializedName("transfer_bill_no")
+ public String transferBillNo;
+
+ @SerializedName("state")
+ public String state;
+
+ @SerializedName("update_time")
+ public String updateTime;
+ }
+
+ public static class CancelTransferRequest {
+ @SerializedName("out_bill_no")
+ @Expose(serialize = false)
+ public String outBillNo;
+ }
+
+}
diff --git a/server/services/src/main/java/com/doumee/config/wx/WXPayUtility.java b/server/services/src/main/java/com/doumee/config/wx/WXPayUtility.java
new file mode 100644
index 0000000..bf29e52
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/config/wx/WXPayUtility.java
@@ -0,0 +1,456 @@
+package com.doumee.config.wx;
+
+
+import com.google.gson.ExclusionStrategy;
+import com.google.gson.FieldAttributes;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.annotations.Expose;
+import com.wechat.pay.java.core.util.GsonUtil;
+import okhttp3.Headers;
+import okhttp3.Response;
+import okio.BufferedSource;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.time.DateTimeException;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Base64;
+import java.util.Map;
+import java.util.Objects;
+
+public class WXPayUtility {
+ private static final Gson gson = new GsonBuilder()
+ .disableHtmlEscaping()
+ .addSerializationExclusionStrategy(new ExclusionStrategy() {
+ @Override
+ public boolean shouldSkipField(FieldAttributes fieldAttributes) {
+ final Expose expose = fieldAttributes.getAnnotation(Expose.class);
+ return expose != null && !expose.serialize();
+ }
+
+ @Override
+ public boolean shouldSkipClass(Class<?> aClass) {
+ return false;
+ }
+ })
+ .addDeserializationExclusionStrategy(new ExclusionStrategy() {
+ @Override
+ public boolean shouldSkipField(FieldAttributes fieldAttributes) {
+ final Expose expose = fieldAttributes.getAnnotation(Expose.class);
+ return expose != null && !expose.deserialize();
+ }
+
+ @Override
+ public boolean shouldSkipClass(Class<?> aClass) {
+ return false;
+ }
+ })
+ .create();
+ private static final char[] SYMBOLS =
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
+ private static final SecureRandom random = new SecureRandom();
+
+ /**
+ * 灏� Object 杞崲涓� JSON 瀛楃涓�
+ */
+ public static String toJson(Object object) {
+ return gson.toJson(object);
+ }
+
+ /**
+ * 灏� JSON 瀛楃涓茶В鏋愪负鐗瑰畾绫诲瀷鐨勫疄渚�
+ */
+ public static <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
+ return gson.fromJson(json, classOfT);
+ }
+
+ /**
+ * 浠庡叕绉侀挜鏂囦欢璺緞涓鍙栨枃浠跺唴瀹�
+ *
+ * @param keyPath 鏂囦欢璺緞
+ * @return 鏂囦欢鍐呭
+ */
+ private static String readKeyStringFromPath(String keyPath) {
+ try {
+ return new String(Files.readAllBytes(Paths.get(keyPath)), StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ /**
+ * 璇诲彇 PKCS#8 鏍煎紡鐨勭閽ュ瓧绗︿覆骞跺姞杞戒负绉侀挜瀵硅薄
+ *
+ * @param keyString 绉侀挜鏂囦欢鍐呭锛屼互 -----BEGIN PRIVATE KEY----- 寮�澶�
+ * @return PrivateKey 瀵硅薄
+ */
+ public static PrivateKey loadPrivateKeyFromString(String keyString) {
+ try {
+ keyString = keyString.replace("-----BEGIN PRIVATE KEY-----", "")
+ .replace("-----END PRIVATE KEY-----", "")
+ .replaceAll("\\s+", "");
+ return KeyFactory.getInstance("RSA").generatePrivate(
+ new PKCS8EncodedKeySpec(Base64.getDecoder().decode(keyString)));
+ } catch (NoSuchAlgorithmException e) {
+ throw new UnsupportedOperationException(e);
+ } catch (InvalidKeySpecException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * 浠� PKCS#8 鏍煎紡鐨勭閽ユ枃浠朵腑鍔犺浇绉侀挜
+ *
+ * @param keyPath 绉侀挜鏂囦欢璺緞
+ * @return PrivateKey 瀵硅薄
+ */
+ public static PrivateKey loadPrivateKeyFromPath(String keyPath) {
+ return loadPrivateKeyFromString(readKeyStringFromPath(keyPath));
+ }
+
+ /**
+ * 璇诲彇 PKCS#8 鏍煎紡鐨勫叕閽ュ瓧绗︿覆骞跺姞杞戒负鍏挜瀵硅薄
+ *
+ * @param keyString 鍏挜鏂囦欢鍐呭锛屼互 -----BEGIN PUBLIC KEY----- 寮�澶�
+ * @return PublicKey 瀵硅薄
+ */
+ public static PublicKey loadPublicKeyFromString(String keyString) {
+ try {
+ keyString = keyString.replace("-----BEGIN PUBLIC KEY-----", "")
+ .replace("-----END PUBLIC KEY-----", "")
+ .replaceAll("\\s+", "");
+ return KeyFactory.getInstance("RSA").generatePublic(
+ new X509EncodedKeySpec(Base64.getDecoder().decode(keyString)));
+ } catch (NoSuchAlgorithmException e) {
+ throw new UnsupportedOperationException(e);
+ } catch (InvalidKeySpecException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * 浠� PKCS#8 鏍煎紡鐨勫叕閽ユ枃浠朵腑鍔犺浇鍏挜
+ *
+ * @param keyPath 鍏挜鏂囦欢璺緞
+ * @return PublicKey 瀵硅薄
+ */
+ public static PublicKey loadPublicKeyFromPath(String keyPath) {
+ return loadPublicKeyFromString(readKeyStringFromPath(keyPath));
+ }
+
+ /**
+ * 鍒涘缓鎸囧畾闀垮害鐨勯殢鏈哄瓧绗︿覆锛屽瓧绗﹂泦涓篬0-9a-zA-Z]锛屽彲鐢ㄤ簬瀹夊叏鐩稿叧鐢ㄩ��
+ */
+ public static String createNonce(int length) {
+ char[] buf = new char[length];
+ for (int i = 0; i < length; ++i) {
+ buf[i] = SYMBOLS[random.nextInt(SYMBOLS.length)];
+ }
+ return new String(buf);
+ }
+
+ /**
+ * 浣跨敤鍏挜鎸夌収 RSA_PKCS1_OAEP_PADDING 绠楁硶杩涜鍔犲瘑
+ *
+ * @param publicKey 鍔犲瘑鐢ㄥ叕閽ュ璞�
+ * @param plaintext 寰呭姞瀵嗘槑鏂�
+ * @return 鍔犲瘑鍚庡瘑鏂�
+ */
+ public static String encrypt(PublicKey publicKey, String plaintext) {
+ final String transformation = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
+
+ try {
+ Cipher cipher = Cipher.getInstance(transformation);
+ cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+ return Base64.getEncoder().encodeToString(cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)));
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+ throw new IllegalArgumentException("The current Java environment does not support " + transformation, e);
+ } catch (InvalidKeyException e) {
+ throw new IllegalArgumentException("RSA encryption using an illegal publicKey", e);
+ } catch (BadPaddingException | IllegalBlockSizeException e) {
+ throw new IllegalArgumentException("Plaintext is too long", e);
+ }
+ }
+
+ /**
+ * 浣跨敤绉侀挜鎸夌収鎸囧畾绠楁硶杩涜绛惧悕
+ *
+ * @param message 寰呯鍚嶄覆
+ * @param algorithm 绛惧悕绠楁硶锛屽 SHA256withRSA
+ * @param privateKey 绛惧悕鐢ㄧ閽ュ璞�
+ * @return 绛惧悕缁撴灉
+ */
+ public static String sign(String message, String algorithm, PrivateKey privateKey) {
+ byte[] sign;
+ try {
+ Signature signature = Signature.getInstance(algorithm);
+ signature.initSign(privateKey);
+ signature.update(message.getBytes(StandardCharsets.UTF_8));
+ sign = signature.sign();
+ } catch (NoSuchAlgorithmException e) {
+ throw new UnsupportedOperationException("The current Java environment does not support " + algorithm, e);
+ } catch (InvalidKeyException e) {
+ throw new IllegalArgumentException(algorithm + " signature uses an illegal privateKey.", e);
+ } catch (SignatureException e) {
+ throw new RuntimeException("An error occurred during the sign process.", e);
+ }
+ return Base64.getEncoder().encodeToString(sign);
+ }
+
+ /**
+ * 浣跨敤鍏挜鎸夌収鐗瑰畾绠楁硶楠岃瘉绛惧悕
+ *
+ * @param message 寰呯鍚嶄覆
+ * @param signature 寰呴獙璇佺殑绛惧悕鍐呭
+ * @param algorithm 绛惧悕绠楁硶锛屽锛歋HA256withRSA
+ * @param publicKey 楠岀鐢ㄥ叕閽ュ璞�
+ * @return 绛惧悕楠岃瘉鏄惁閫氳繃
+ */
+ public static boolean verify(String message, String signature, String algorithm,
+ PublicKey publicKey) {
+ try {
+ Signature sign = Signature.getInstance(algorithm);
+ sign.initVerify(publicKey);
+ sign.update(message.getBytes(StandardCharsets.UTF_8));
+ return sign.verify(Base64.getDecoder().decode(signature));
+ } catch (SignatureException e) {
+ return false;
+ } catch (InvalidKeyException e) {
+ throw new IllegalArgumentException("verify uses an illegal publickey.", e);
+ } catch (NoSuchAlgorithmException e) {
+ throw new UnsupportedOperationException("The current Java environment does not support" + algorithm, e);
+ }
+ }
+
+ /**
+ * 鏍规嵁寰俊鏀粯APIv3璇锋眰绛惧悕瑙勫垯鏋勯�� Authorization 绛惧悕
+ *
+ * @param mchid 鍟嗘埛鍙�
+ * @param certificateSerialNo 鍟嗘埛API璇佷功搴忓垪鍙�
+ * @param privateKey 鍟嗘埛API璇佷功绉侀挜
+ * @param method 璇锋眰鎺ュ彛鐨凥TTP鏂规硶锛岃浣跨敤鍏ㄥぇ鍐欒〃杩帮紝濡� GET銆丳OST銆丳UT銆丏ELETE
+ * @param uri 璇锋眰鎺ュ彛鐨刄RL
+ * @param body 璇锋眰鎺ュ彛鐨凚ody
+ * @return 鏋勯�犲ソ鐨勫井淇℃敮浠楢PIv3 Authorization 澶�
+ */
+ public static String buildAuthorization(String mchid, String certificateSerialNo,
+ PrivateKey privateKey,
+ String method, String uri, String body) {
+ String nonce = createNonce(32);
+ long timestamp = Instant.now().getEpochSecond();
+
+ String message = String.format("%s\n%s\n%d\n%s\n%s\n", method, uri, timestamp, nonce,
+ body == null ? "" : body);
+
+ String signature = sign(message, "SHA256withRSA", privateKey);
+
+ return String.format(
+ "WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",signature=\"%s\"," +
+ "timestamp=\"%d\",serial_no=\"%s\"",
+ mchid, nonce, signature, timestamp, certificateSerialNo);
+ }
+
+ /**
+ * 瀵瑰弬鏁拌繘琛� URL 缂栫爜
+ *
+ * @param content 鍙傛暟鍐呭
+ * @return 缂栫爜鍚庣殑鍐呭
+ */
+ public static String urlEncode(String content) {
+ try {
+ return URLEncoder.encode(content, StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * 瀵瑰弬鏁癕ap杩涜 URL 缂栫爜锛岀敓鎴� QueryString
+ *
+ * @param params Query鍙傛暟Map
+ * @return QueryString
+ */
+ public static String urlEncode(Map<String, Object> params) {
+ if (params == null || params.isEmpty()) {
+ return "";
+ }
+
+ int index = 0;
+ StringBuilder result = new StringBuilder();
+ for (Map.Entry<String, Object> entry : params.entrySet()) {
+ result.append(entry.getKey())
+ .append("=")
+ .append(urlEncode(entry.getValue().toString()));
+ index++;
+ if (index < params.size()) {
+ result.append("&");
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * 浠庡簲绛斾腑鎻愬彇 Body
+ *
+ * @param response HTTP 璇锋眰搴旂瓟瀵硅薄
+ * @return 搴旂瓟涓殑Body鍐呭锛孊ody涓虹┖鏃惰繑鍥炵┖瀛楃涓�
+ */
+ public static String extractBody(Response response) {
+ if (response.body() == null) {
+ return "";
+ }
+
+ try {
+ BufferedSource source = response.body().source();
+ return source.readUtf8();
+ } catch (IOException e) {
+ throw new RuntimeException(String.format("An error occurred during reading response body. Status: %d", response.code()), e);
+ }
+ }
+
+ /**
+ * 鏍规嵁寰俊鏀粯APIv3搴旂瓟楠岀瑙勫垯瀵瑰簲绛旂鍚嶈繘琛岄獙璇侊紝楠岃瘉涓嶉�氳繃鏃舵姏鍑哄紓甯�
+ *
+ * @param wechatpayPublicKeyId 寰俊鏀粯鍏挜ID
+ * @param wechatpayPublicKey 寰俊鏀粯鍏挜瀵硅薄
+ * @param headers 寰俊鏀粯搴旂瓟 Header 鍒楄〃
+ * @param body 寰俊鏀粯搴旂瓟 Body
+ */
+ public static void validateResponse(String wechatpayPublicKeyId, PublicKey wechatpayPublicKey,
+ Headers headers,
+ String body) {
+ String timestamp = headers.get("Wechatpay-Timestamp");
+ try {
+ Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestamp));
+ // 鎷掔粷杩囨湡璇锋眰
+ if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= 5) {
+ throw new IllegalArgumentException(
+ String.format("Validate http response,timestamp[%s] of httpResponse is expires, "
+ + "request-id[%s]",
+ timestamp, headers.get("Request-ID")));
+ }
+ } catch (DateTimeException | NumberFormatException e) {
+ throw new IllegalArgumentException(
+ String.format("Validate http response,timestamp[%s] of httpResponse is invalid, " +
+ "request-id[%s]", timestamp,
+ headers.get("Request-ID")));
+ }
+ String message = String.format("%s\n%s\n%s\n", timestamp, headers.get("Wechatpay-Nonce"),
+ body == null ? "" : body);
+ String serialNumber = headers.get("Wechatpay-Serial");
+ if (!Objects.equals(serialNumber, wechatpayPublicKeyId)) {
+ throw new IllegalArgumentException(
+ String.format("Invalid Wechatpay-Serial, Local: %s, Remote: %s", wechatpayPublicKeyId,
+ serialNumber));
+ }
+ String signature = headers.get("Wechatpay-Signature");
+
+ boolean success = verify(message, signature, "SHA256withRSA", wechatpayPublicKey);
+ if (!success) {
+ throw new IllegalArgumentException(
+ String.format("Validate response failed,the WechatPay signature is incorrect.%n"
+ + "Request-ID[%s]\tresponseHeader[%s]\tresponseBody[%.1024s]",
+ headers.get("Request-ID"), headers, body));
+ }
+ }
+
+ /**
+ * 寰俊鏀粯API閿欒寮傚父锛屽彂閫丠TTP璇锋眰鎴愬姛锛屼絾杩斿洖鐘舵�佺爜涓嶆槸 2XX 鏃舵姏鍑烘湰寮傚父
+ */
+ public static class ApiException extends RuntimeException {
+ private static final long serialVersionUID = 2261086748874802175L;
+
+ private final int statusCode;
+ private final String body;
+ private final Headers headers;
+ private final String errorCode;
+ private final String errorMessage;
+
+ public ApiException(int statusCode, String body, Headers headers) {
+ super(String.format("寰俊鏀粯API璁块棶澶辫触锛孲tatusCode: [%s], Body: [%s], Headers: [%s]", statusCode, body, headers));
+ this.statusCode = statusCode;
+ this.body = body;
+ this.headers = headers;
+
+ if (body != null && !body.isEmpty()) {
+ JsonElement code;
+ JsonElement message;
+
+ try {
+ JsonObject jsonObject = GsonUtil.getGson().fromJson(body, JsonObject.class);
+ code = jsonObject.get("code");
+ message = jsonObject.get("message");
+ } catch (JsonSyntaxException ignored) {
+ code = null;
+ message = null;
+ }
+ this.errorCode = code == null ? null : code.getAsString();
+ this.errorMessage = message == null ? null : message.getAsString();
+ } else {
+ this.errorCode = null;
+ this.errorMessage = null;
+ }
+ }
+
+ /**
+ * 鑾峰彇 HTTP 搴旂瓟鐘舵�佺爜
+ */
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ /**
+ * 鑾峰彇 HTTP 搴旂瓟鍖呬綋鍐呭
+ */
+ public String getBody() {
+ return body;
+ }
+
+ /**
+ * 鑾峰彇 HTTP 搴旂瓟 Header
+ */
+ public Headers getHeaders() {
+ return headers;
+ }
+
+ /**
+ * 鑾峰彇 閿欒鐮� 锛堥敊璇簲绛斾腑鐨� code 瀛楁锛�
+ */
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+ /**
+ * 鑾峰彇 閿欒娑堟伅 锛堥敊璇簲绛斾腑鐨� message 瀛楁锛�
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+ }
+}
\ No newline at end of file
diff --git a/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java b/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java
index 3c9cf04..e0b82bb 100644
--- a/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java
+++ b/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java
@@ -36,7 +36,7 @@
public static JsapiServiceExtension jsapiExtService;
public static BillDownloadService billDownloadService;
public static WxPayProperties wxProperties;
-
+ public static TransferToUser transferToUser;
@Autowired
private WxPayProperties wxPayProperties;
@@ -49,6 +49,8 @@
this.load_WxMaService();
this.load_wxPayService();
this.load_wxPayV2Service();
+ this.load_transferToUser();
+ this.load_transferToUser();
this.wxProperties = wxPayProperties;
}
/**
@@ -134,7 +136,18 @@
// }
+ public void load_transferToUser()
+ {
+ TransferToUser transferToUser = new TransferToUser(
+ StringUtils.trimToNull(wxPayProperties.getMchId()), //鍟嗘埛id
+ StringUtils.trimToNull(wxPayProperties.getWechatSerialNumer()), //鍟嗘埛API璇佷功搴忓垪鍙凤紝濡備綍鑾峰彇璇峰弬鑰� https://pay.weixin.qq.com/doc/v3/merchant/4013053053
+ StringUtils.trimToNull(wxPayProperties.getWechatPrivateKeyPath()), // 鍟嗘埛API璇佷功绉侀挜鏂囦欢璺緞锛屾湰鍦版枃浠惰矾寰�
+ StringUtils.trimToNull(wxPayProperties.getWechatPayPublicKeyId()), // 寰俊鏀粯鍏挜ID锛屽浣曡幏鍙栬鍙傝�� https://pay.weixin.qq.com/doc/v3/merchant/4013038816
+ StringUtils.trimToNull(wxPayProperties.getWechatPubKeyPath()) // 寰俊鏀粯鍏挜鏂囦欢璺緞锛屾湰鍦版枃浠惰矾寰�
+ );
+ this.transferToUser = transferToUser;
+ }
}
diff --git a/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java b/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java
index e5c948d..b9d5af5 100644
--- a/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java
+++ b/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java
@@ -63,4 +63,10 @@
private String privateKeyPath ;
private String privateCertPath;// gybike
+
+ private String wechatSerialNumer;
+ private String wechatPayPublicKeyId; // 寰俊鏀粯鍏挜ID
+ private String wechatPubKeyPath; //寰俊鏀粯鍏挜鏂囦欢璺緞
+ private String wechatPrivateKeyPath;
+
}
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/Member.java b/server/services/src/main/java/com/doumee/dao/business/model/Member.java
index d041151..474874c 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/Member.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/Member.java
@@ -190,4 +190,11 @@
@TableField(exist = false)
private IdentityInfo chefIdentityModel;
+ @ApiModelProperty(value = "鎺ュ崟鏉冮噸", example = "1")
+ @TableField(exist = false)
+ private Integer level;
+
+ @ApiModelProperty(value = "璺濈", example = "1")
+ @TableField(exist = false)
+ private BigDecimal distance;
}
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/MemberRevenue.java b/server/services/src/main/java/com/doumee/dao/business/model/MemberRevenue.java
index 5415345..dd1f568 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/MemberRevenue.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/MemberRevenue.java
@@ -47,7 +47,7 @@
@ApiModelProperty(value = "浼氬憳涓婚敭", example = "1")
private Integer memberId;
- @ApiModelProperty(value = "鍙樺姩绫诲瀷:0=鐢ㄥ伐鍗曟敹鍏ワ紱1=璐ц繍鍗曟敹鍏ワ紱2=渚涢鍗曟敹鍏ワ紱3=鎻愮幇鐢宠锛�", example = "1")
+ @ApiModelProperty(value = "鍙樺姩绫诲瀷:0=鐢ㄥ伐鍗曟敹鍏ワ紱1=璐ц繍鍗曟敹鍏ワ紱2=渚涢鍗曟敹鍏ワ紱3=鎻愮幇鐢宠锛�4=鎻愮幇澶辫触閫�鍥�", example = "1")
private Integer type;
@ApiModelProperty(value = "鏀舵敮绫诲瀷:1=鏀跺叆锛�-1=鏀嚭锛�", example = "1")
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/Orders.java b/server/services/src/main/java/com/doumee/dao/business/model/Orders.java
index 50289c1..a3f0a7b 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/Orders.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/Orders.java
@@ -90,10 +90,10 @@
@ApiModelProperty(value = "鐢ㄥ伐绫诲瀷:0=閲囨憳宸ワ紱1=鍒嗘嫞宸ワ紱2=鍖呰宸ワ紱锛堢敤宸ヨ鍗曪級", example = "1")
private Integer workType;
- @ApiModelProperty(value = "璁′环鏁伴噺1(澶╂暟/鐢ㄨ溅娆℃暟/灏忔椂/鏂ゆ暟)", example = "1")
+ @ApiModelProperty(value = "璁′环鏁伴噺1((閲嶉噺/浜烘暟/锛堝ぉ鏁�/灏忔椂/閲嶉噺锛�/锛堝ぉ鏁�/娆℃暟锛�/鐢ㄩ澶╂暟)", example = "1")
private Integer priceNum1;
- @ApiModelProperty(value = "璁′环鏁伴噺2(浜烘暟/鐢ㄩ浠芥暟)", example = "1")
+ @ApiModelProperty(value = "璁′环鏁伴噺2(鍒嗘嫞宸�/鍖呰宸� 浜烘暟)", example = "1")
private Integer priceNum2;
@ApiModelProperty(value = "闇�姹傝ˉ鍏�")
@@ -102,10 +102,8 @@
@ApiModelProperty(value = "璐圭敤鏍囧噯", example = "1")
private Long price;
-
@ApiModelProperty(value = "棰勪及璐圭敤", example = "1")
private Long estimatedAccount;
-
@ApiModelProperty(value = "瀹為檯鏀粯璐圭敤", example = "1")
private Long payAccount;
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/WithdrawalOrders.java b/server/services/src/main/java/com/doumee/dao/business/model/WithdrawalOrders.java
index 02ed5ef..4b5050e 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/WithdrawalOrders.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/WithdrawalOrders.java
@@ -27,7 +27,7 @@
@ApiModelProperty(value = "鏄惁宸插垹闄� 0鏈垹闄� 1宸插垹闄�", example = "1")
@ExcelColumn(name="鏄惁宸插垹闄� 0鏈垹闄� 1宸插垹闄�")
- private Byte deleted;
+ private Integer deleted;
@ApiModelProperty(value = "鍒涘缓浜虹紪鐮�", example = "1")
@ExcelColumn(name="鍒涘缓浜虹紪鐮�")
@@ -84,4 +84,10 @@
@ApiModelProperty(value = "鍏宠仈璁㈠崟涓婚敭 orders", example = "1")
@ExcelColumn(name="鍏宠仈璁㈠崟涓婚敭 orders")
private Integer objId;
+
+ @ApiModelProperty(value = "鎻愮幇鐢宠鍗曞彿")
+ @ExcelColumn(name="鎻愮幇鐢宠鍗曞彿")
+ private String outBillNo;
+
+
}
diff --git a/server/services/src/main/java/com/doumee/dao/vo/OrderReleaseVO.java b/server/services/src/main/java/com/doumee/dao/vo/OrderReleaseVO.java
new file mode 100644
index 0000000..011b69e
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/dao/vo/OrderReleaseVO.java
@@ -0,0 +1,21 @@
+package com.doumee.dao.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @Author : Rk
+ * @create 2025/7/10 15:09
+ */
+@Data
+public class OrderReleaseVO {
+
+ @ApiModelProperty(value = "璁㈠崟涓婚敭")
+ private Integer id;
+
+ @ApiModelProperty(value = "鏀粯璇︽儏")
+ private Object object;
+
+}
diff --git a/server/services/src/main/java/com/doumee/service/business/MemberService.java b/server/services/src/main/java/com/doumee/service/business/MemberService.java
index 3255553..c09bdf0 100644
--- a/server/services/src/main/java/com/doumee/service/business/MemberService.java
+++ b/server/services/src/main/java/com/doumee/service/business/MemberService.java
@@ -149,4 +149,6 @@
Member getMemberInfo(Integer memberId);
UserCenterVO getPlatformAboutUs();
+
+ void logOff(String token,Integer memberId);
}
diff --git a/server/services/src/main/java/com/doumee/service/business/OrdersService.java b/server/services/src/main/java/com/doumee/service/business/OrdersService.java
index 4132624..283b40f 100644
--- a/server/services/src/main/java/com/doumee/service/business/OrdersService.java
+++ b/server/services/src/main/java/com/doumee/service/business/OrdersService.java
@@ -9,6 +9,7 @@
import com.doumee.dao.dto.ConfirmUpdOrderDTO;
import com.doumee.dao.dto.DoneOrderDTO;
import com.doumee.dao.dto.UpdOrderDataDTO;
+import com.doumee.dao.vo.OrderReleaseVO;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import java.util.List;
@@ -26,7 +27,7 @@
* @param orders 瀹炰綋瀵硅薄
* @return Integer
*/
- Object create(Orders orders);
+ OrderReleaseVO create(Orders orders);
/**
* 涓婚敭鍒犻櫎
@@ -137,4 +138,10 @@
void autoComment();
void autoConfirm();
+
+ Long getTotal(Orders orders);
+
+ void autoGrabOrders();
+
+ void initializeCode();
}
diff --git a/server/services/src/main/java/com/doumee/service/business/WithdrawalOrdersService.java b/server/services/src/main/java/com/doumee/service/business/WithdrawalOrdersService.java
index 3f99a0f..3ca45be 100644
--- a/server/services/src/main/java/com/doumee/service/business/WithdrawalOrdersService.java
+++ b/server/services/src/main/java/com/doumee/service/business/WithdrawalOrdersService.java
@@ -1,5 +1,6 @@
package com.doumee.service.business;
+import com.doumee.config.wx.TransferToUser;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.dao.business.model.WithdrawalOrders;
@@ -97,6 +98,8 @@
*/
long count(WithdrawalOrders withdrawalOrders);
- void applyWithdrawal(WithdrawalDTO withdrawalDTO);
+ TransferToUser.TransferToUserResponse applyWithdrawal(WithdrawalDTO withdrawalDTO);
+
+ void cancelTransfer(TransferToUser.CancelTransferRequest request);
}
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
index 9b1f873..fdab8b9 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
@@ -254,10 +254,15 @@
List<Category> categoryList = categoryMapper.selectList(new QueryWrapper<Category>().lambda().eq(Category::getDeleted,Constants.ZERO).eq(Category::getStatus,Constants.ZERO)
.eq(Objects.nonNull(type),Category::getType,type));
if(com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(categoryList)){
+ String path = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.RESOURCE_PATH).getCode()
+ +systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.CATEGORY_FILES).getCode();
for (Category category:categoryList) {
if(StringUtils.isNotBlank(category.getDetail())){
category.setDetailList(JSONArray.parseArray(category.getDetail()));
}
+ if(StringUtils.isNotBlank(category.getIcon())){
+ category.setIconFull(path + category.getIcon());
+ }
}
}
return categoryList;
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
index 6602688..25d4e53 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
@@ -2,6 +2,7 @@
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
+import com.alibaba.fastjson.JSONObject;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.config.jwt.JwtTokenUtil;
import com.doumee.config.wx.WxMiniConfig;
@@ -33,13 +34,16 @@
import nonapi.io.github.classgraph.json.Id;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
+import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Random;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -342,7 +346,10 @@
@Override
public void editMemberInfo(Member member){
if(Objects.isNull(member)
- || ( StringUtils.isBlank(member.getCoverImage()) || StringUtils.isBlank(member.getName()) || StringUtils.isBlank(member.getNickName()) || Objects.isNull(member.getAutoReceiveStatus()) )){
+ || ( StringUtils.isBlank(member.getCoverImage())
+ && StringUtils.isBlank(member.getName())
+ && StringUtils.isBlank(member.getNickName())
+ && Objects.isNull(member.getAutoReceiveStatus()) )){
throw new BusinessException(ResponseStatus.BAD_REQUEST);
}
memberMapper.update(new UpdateWrapper<Member>().lambda()
@@ -381,6 +388,11 @@
Member member = this.findById(memberId);
if(Objects.isNull(member)){
throw new BusinessException(ResponseStatus.DATA_EMPTY);
+ }
+ if(StringUtils.isNotBlank(member.getCoverImage())){
+ String path = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.RESOURCE_PATH).getCode()
+ +systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.MEMBER_FILES).getCode();
+ member.setFullCoverImage(path + member.getCoverImage());
}
UserCenterVO userCenterVO = new UserCenterVO();
userCenterVO.setReleaseTaskTotal(Constants.ZERO);
@@ -422,6 +434,11 @@
return userCenterVO;
}
+ @Override
+ public void logOff(String token,Integer memberId){
+ memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" openid = null ").eq(Member::getId,memberId));
+ jwtTokenUtil.logoutForH5(token);
+ }
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
index 8bd112f..a640402 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
@@ -17,6 +17,7 @@
import com.doumee.dao.business.*;
import com.doumee.dao.business.model.*;
import com.doumee.dao.dto.*;
+import com.doumee.dao.vo.OrderReleaseVO;
import com.doumee.service.business.OrdersService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -42,10 +43,7 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
+import java.util.*;
import java.util.concurrent.TimeUnit;
/**
@@ -91,7 +89,8 @@
@Override
@Transactional(rollbackFor = {Exception.class,BusinessException.class})
- public Object create(Orders orders) {
+ public OrderReleaseVO create(Orders orders) {
+ OrderReleaseVO orderReleaseVO = new OrderReleaseVO();
Object objects = null;
this.initVerification(orders);
orders.setCreateTime(new Date());
@@ -120,15 +119,16 @@
orders.setStatus(Constants.ordersStatus.waitPay.getKey());
//鍞よ捣鏀粯涓氬姟
objects = this.getWxPayResponse(orders,orders.getMember().getOpenid());
+ orderReleaseVO.setObject(objects);
}else{
orders.setStatus(Constants.ordersStatus.wait.getKey());
}
ordersMapper.insert(orders);
+ orderReleaseVO.setId(orders.getId());
if(com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(orders.getMultifileList())){
List<Multifile> multifileList = orders.getMultifileList();
for (Multifile multifile:multifileList) {
if(Objects.isNull(multifile)
- || Objects.isNull(multifile.getObjType())
|| StringUtils.isEmpty(multifile.getFileurl())
|| StringUtils.isEmpty(multifile.getName())){
throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"闄勪欢淇℃伅閿欒");
@@ -159,7 +159,7 @@
.replace("{param}",orderTypeInfo);
this.saveOrderLog(orders,ordersLog,
logInfo,orders.getReleaseMemberId(),null);
- return objects;
+ return orderReleaseVO;
}
private Object getWxPayResponse(Orders orders,String openid){
@@ -219,7 +219,7 @@
|| Objects.isNull(orders.getStartDate())
|| Objects.isNull(orders.getEndDate())
|| StringUtil.isBlank(orders.getLocation())
- || StringUtil.isBlank(orders.getLocationRemark())
+ || (!Constants.equalsInteger(Constants.ONE,orders.getType())&&StringUtil.isBlank(orders.getLocationRemark()))
|| StringUtil.isBlank(orders.getLinkPhone())
|| Objects.isNull(orders.getLat())
|| Objects.isNull(orders.getLgt())
@@ -263,9 +263,9 @@
for (WayInfoDTO wayInfoDTO:orders.getWayInfoDTOList()) {
if(Objects.isNull(wayInfoDTO)
||StringUtils.isEmpty(wayInfoDTO.getLocation())
- ||StringUtils.isEmpty(wayInfoDTO.getProvince())
- ||StringUtils.isEmpty(wayInfoDTO.getCity())
- ||StringUtils.isEmpty(wayInfoDTO.getArea())
+// ||StringUtils.isEmpty(wayInfoDTO.getProvince())
+// ||StringUtils.isEmpty(wayInfoDTO.getCity())
+// ||StringUtils.isEmpty(wayInfoDTO.getArea())
||Objects.isNull(wayInfoDTO.getLat())
||Objects.isNull(wayInfoDTO.getLgt())
){
@@ -298,6 +298,9 @@
throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"閲戦璁$畻閿欒!");
}
}
+
+
+
@@ -600,12 +603,17 @@
throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"韬唤淇℃伅寮傚父锛岃鑱旂郴绠$悊鍛�");
}
}
- orders.setUpdateTime(new Date());
- orders.setAcceptType(Constants.ZERO);
- orders.setAcceptTime(new Date());
- orders.setAcceptMemberId(member.getId());
- orders.setStatus(Constants.ordersStatus.accept.getKey());
- ordersMapper.updateById(orders);
+
+ ordersMapper.update(new UpdateWrapper<Orders>().lambda().eq(Orders::getId,orders.getId())
+ .set(Orders::getUpdateTime,new Date())
+ .set(Orders::getAcceptType,Constants.ZERO)
+ .set(Orders::getAcceptTime,new Date())
+ .set(Orders::getAcceptMemberId,member.getId())
+ .set(Orders::getStatus,Constants.ordersStatus.accept.getKey())
+ );
+
+
+
//鏇存柊鎺ュ崟閲�
memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" publish_num = (publish_num + 1 )").eq(Member::getId,member.getId()));
@@ -701,8 +709,8 @@
.set(Orders::getEndDate,updOrderDataDTO.getEndDate())
.set(Orders::getTotalDays,updOrderDataDTO.getTotalDays())
.set(Orders::getIsUpdate,Constants.ONE)
- .set(Orders::getIsUpdateTime,"now()")
- .set(Orders::getUpdateTime,"now()")
+ .set(Orders::getIsUpdateTime,new Date())
+ .set(Orders::getUpdateTime,new Date())
.set(Orders::getEstimatedAccount,total)
.eq(Orders::getId,orders.getId())
);
@@ -715,12 +723,22 @@
}
+ @Override
public Long getTotal(Orders orders){
+ if(Objects.isNull(orders)
+ ||Objects.isNull(orders.getPrice())
+ ||Objects.isNull(orders.getPriceNum1())){
+ throw new BusinessException(ResponseStatus.BAD_REQUEST);
+ }
if(
(Constants.equalsInteger(orders.getType(),Constants.ZERO) && Constants.equalsInteger(orders.getWorkType(),Constants.ZERO ))
|| Constants.equalsInteger(orders.getType(),Constants.ONE)
){
orders.setPriceNum2(Constants.ONE);
+ }else{
+ if(Objects.isNull(orders.getPriceNum2())){
+ throw new BusinessException(ResponseStatus.BAD_REQUEST);
+ }
}
return orders.getPrice() * orders.getPriceNum1() * orders.getPriceNum2();
}
@@ -757,7 +775,7 @@
if( Constants.equalsInteger(confirmUpdOrderDTO.getStatus(),Constants.ONE)){
ordersMapper.update(new UpdateWrapper<Orders>().lambda()
.set(Orders::getIsUpdate,Constants.TWO)
- .set(Orders::getUpdateTime,"now()")
+ .set(Orders::getUpdateTime,new Date())
.eq(Orders::getId,orders.getId())
);
//璁板綍鍚屾剰淇敼鐨勬棩蹇�
@@ -767,7 +785,7 @@
}else{
ordersMapper.update(new UpdateWrapper<Orders>().lambda()
.set(Orders::getIsUpdate,Constants.TWO)
- .set(Orders::getUpdateTime,"now()")
+ .set(Orders::getUpdateTime,new Date())
.set(Orders::getStatus,Constants.ordersStatus.wait.getKey())
.set(Orders::getAcceptMemberId,null)
.set(Orders::getAcceptType,null)
@@ -824,8 +842,8 @@
}
ordersMapper.update(new UpdateWrapper<Orders>().lambda()
.set(Orders::getStatus,Constants.ordersStatus.cancel.getKey())
- .set(Orders::getUpdateTime,"now()")
- .set(Orders::getCancelTime,"now()")
+ .set(Orders::getUpdateTime,new Date())
+ .set(Orders::getCancelTime,new Date())
.set(Orders::getCancelType,Constants.ZERO)
.eq(Orders::getId,orders.getId())
);
@@ -862,8 +880,8 @@
}
ordersMapper.update(new UpdateWrapper<Orders>().lambda()
.set(Orders::getStatus,Constants.ordersStatus.cancel.getKey())
- .set(Orders::getUpdateTime,"now()")
- .set(Orders::getCancelTime,"now()")
+ .set(Orders::getUpdateTime,new Date())
+ .set(Orders::getCancelTime,new Date())
.set(Orders::getCancelType,Constants.ONE)
.eq(Orders::getId,orders.getId())
);
@@ -917,7 +935,7 @@
throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"璺濈璁㈠崟寮�濮嬫椂闂翠笉瓒�"+cancelTimeHour+"灏忔椂,鏃犳硶鍙栨秷璁㈠崟锛屽闇�澶勭悊璇疯仈绯诲鏈�");
}
ordersMapper.update(new UpdateWrapper<Orders>().lambda()
- .set(Orders::getUpdateTime,"now()")
+ .set(Orders::getUpdateTime,new Date())
.set(Orders::getStatus,Constants.ordersStatus.wait.getKey())
.set(Orders::getAcceptMemberId,null)
.set(Orders::getAcceptType,null)
@@ -1059,8 +1077,8 @@
ordersMapper.update(new UpdateWrapper<Orders>().lambda()
.set(Orders::getCommentStatus,Constants.ONE)
- .set(Orders::getUpdateTime,"now()")
- .set(Orders::getCommentTime,"now()")
+ .set(Orders::getUpdateTime,new Date())
+ .set(Orders::getCommentTime,new Date())
.set(Orders::getCommentLevel,commentDTO.getLevel())
.set(Orders::getCommentType,Constants.ZERO)
.eq(Orders::getId,orders.getId())
@@ -1098,10 +1116,10 @@
}else{
//澶勭悊鏀粯瀹屾垚閫昏緫
ordersMapper.update(new UpdateWrapper<Orders>().lambda()
- .set(Orders::getUpdateTime,"now()")
+ .set(Orders::getUpdateTime,new Date())
.set(Orders::getStatus,Constants.ordersStatus.wait)
.set(Orders::getPayStatus,Constants.ONE)
- .set(Orders::getPayTime,"now()")
+ .set(Orders::getPayTime,new Date())
.set(Orders::getPayMethod,Constants.ZERO)
.set(Orders::getWxExternalNo,paymentNo)
.eq(Orders::getId,orders.getId())
@@ -1119,13 +1137,13 @@
}else{
//澶勭悊鏀粯瀹屾垚閫昏緫
ordersMapper.update(new UpdateWrapper<Orders>().lambda()
- .set(Orders::getUpdateTime,"now()")
+ .set(Orders::getUpdateTime,new Date())
.set(Orders::getStatus,Constants.FOUR)
.set(Orders::getPayStatus,Constants.ONE)
- .set(Orders::getPayTime,"now()")
+ .set(Orders::getPayTime,new Date())
.set(Orders::getPayMethod,Constants.ZERO)
.set(Orders::getWxExternalNo,paymentNo)
- .set(Orders::getFinishTime,"now()")
+ .set(Orders::getFinishTime,new Date())
.eq(Orders::getId,orders.getId())
);
@@ -1367,19 +1385,60 @@
}
-
- //todo 鑷姩娲惧崟
+ /**
+ * 鑷姩娲惧崟
+ */
+ @Override
public void autoGrabOrders(){
-// String autoConfirmTime = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.AUTO_DISPATCH_DISTANCE).getCode();
-// List<Orders> ordersList = ordersMapper.selectList(new QueryWrapper<Orders>().lambda()
-// .eq(Orders::getStatus,Constants.FOUR).eq(Orders::getCommentStatus,Constants.ZERO)
-// .apply(" DATE_ADD(finish_time, INTERVAL 7 DAY) < now() ")
-// .last("limit 100")
-// );
+ String autoConfirmTime = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.AUTO_DISPATCH).getCode();
+ List<Orders> ordersList = ordersMapper.selectList(new QueryWrapper<Orders>().lambda()
+ .eq(Orders::getStatus,Constants.ONE).eq(Orders::getCommentStatus,Constants.ZERO)
+ .apply(" DATE_ADD(create_time, INTERVAL "+autoConfirmTime+" MINUTE) < now() ")
+ .last("limit 100")
+ );
+ for (Orders orders:ordersList) {
+ BigDecimal lat = orders.getLat();
+ BigDecimal lgt = orders.getLgt();
+ //鏌ヨ鑼冨洿鍐呯殑浼氬憳
+ List<Member> memberList = memberMapper.selectList(new MPJLambdaWrapper<Member>().selectAll(Member.class)
+ .select(" ifnull((select r.level from receive_weight r where r.RECEIVE_MAX > t.RECEIVE_NUM and t.RECEIVE_NUM > r.RECEIVE_MIN limit 1 ),0) " ,Member::getLevel)
+ .select( " ifnull( (select CONVERT( ST_Distance_Sphere ( POINT ( ii.lgt, ii.lat ), POINT ( "+lgt+", "+lat+" )) /1000,DECIMAL(15,2)) from identity_info ii where ii.AUDIT_STATUS = 2 and type = 0 and ii.member_id = t.ID limit 1 ),0) ",Member::getDistance )
+ .apply(" id in (" +
+ " select ii.member_id from identity_info ii where ii.AUDIT_STATUS = 2 and type = '"+orders.getType()+"' " +
+ " and ( CONVERT( ST_Distance_Sphere ( POINT ( ii.lgt, ii.lat ), POINT ( "+lgt+", "+lat+" )) /1000,DECIMAL(15,2))) < 100 " +
+ ") ")
+ .orderByDesc(Member::getLevel)
+ .orderByDesc(Member::getScore)
+ .orderByAsc(Member::getDistance)
+ .last(" limit 1 ")
+ );
+ if(CollectionUtils.isEmpty(memberList)){
+ continue;
+ }
+ Member member = memberList.get(Constants.ZERO);
+ //鑷姩娲惧崟
+ Orders model = ordersMapper.selectById(orders.getStatus());
+ if(!Constants.equalsInteger(model.getStatus(),Constants.ONE)){
+ continue;
+ }
+ ordersMapper.update(new UpdateWrapper<Orders>().lambda().eq(Orders::getId,model.getId())
+ .set(Orders::getUpdateTime,new Date())
+ .set(Orders::getAcceptType,Constants.ONE)
+ .set(Orders::getAcceptTime,new Date())
+ .set(Orders::getAcceptMemberId,member.getId())
+ .set(Orders::getStatus,Constants.ordersStatus.accept.getKey())
+ );
+ //鏇存柊鎺ュ崟閲�
+ memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" publish_num = (publish_num + 1 )").eq(Member::getId,member.getId()));
+ //鍒涘缓鎿嶄綔鏃ュ織
+ Constants.OrdersLog ordersLog = Constants.OrdersLog.AUTO;
+ this.saveOrderLog(orders,ordersLog,
+ ordersLog.getInfo(),member.getId(),null);
+ }
}
//鑷姩璇勪环 璁㈠崟瀹屾垚7澶╁悗鑷姩璇勪环4鏄�
@@ -1395,8 +1454,8 @@
for (Orders orders:ordersList) {
ordersMapper.update(new UpdateWrapper<Orders>().lambda()
.set(Orders::getCommentStatus,Constants.ONE)
- .set(Orders::getUpdateTime,"now()")
- .set(Orders::getCommentTime,"now()")
+ .set(Orders::getUpdateTime,new Date())
+ .set(Orders::getCommentTime,new Date())
.set(Orders::getCommentLevel,Constants.FOUR)
.set(Orders::getCommentType,Constants.ZERO)
.eq(Orders::getId,orders.getId())
@@ -1430,7 +1489,7 @@
for (Orders orders:ordersList) {
ordersMapper.update(new UpdateWrapper<Orders>().lambda()
.set(Orders::getIsUpdate,Constants.TWO)
- .set(Orders::getUpdateTime,"now()")
+ .set(Orders::getUpdateTime,new Date())
.eq(Orders::getId,orders.getId())
);
//璁板綍鍚屾剰淇敼鐨勬棩蹇�
@@ -1442,6 +1501,11 @@
}
+ @Override
+ public void initializeCode(){
+ //鏇存柊缂撳瓨
+ redisTemplate.opsForValue().set(Constants.RedisKeys.ORDER_CODE,0);
+ }
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java
index 6c9445e..82c3236 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java
@@ -1,5 +1,10 @@
package com.doumee.service.business.impl;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.doumee.config.wx.TransferToUser;
+import com.doumee.config.wx.WXPayUtility;
+import com.doumee.config.wx.WxMiniConfig;
import com.doumee.core.constants.Constants;
import com.doumee.core.constants.ResponseStatus;
import com.doumee.core.exception.BusinessException;
@@ -22,10 +27,12 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.List;
import java.util.Objects;
+import java.util.UUID;
/**
* 鎻愮幇鐢宠璁板綍Service瀹炵幇
@@ -171,10 +178,9 @@
* 鎻愮幇鐢宠
* @param withdrawalDTO
*/
-
@Override
@Transactional(rollbackFor = {BusinessException.class,Exception.class})
- public void applyWithdrawal(WithdrawalDTO withdrawalDTO){
+ public TransferToUser.TransferToUserResponse applyWithdrawal(WithdrawalDTO withdrawalDTO){
if(Objects.isNull(withdrawalDTO)
|| Objects.isNull(withdrawalDTO.getAmount())){
throw new BusinessException(ResponseStatus.BAD_REQUEST);
@@ -186,23 +192,108 @@
if(member.getAmount() < withdrawalDTO.getAmount()){
throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝鍙彁鐜颁綑棰濅笉瓒炽��");
}
+ if(StringUtils.isEmpty(member.getName())){
+ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"璇峰厛鍘荤淮鎶ょ湡瀹炲鍚嶅悗杩涜鎻愮幇鐢宠");
+ }
WithdrawalOrders withdrawalOrders = new WithdrawalOrders();
withdrawalOrders.setCreateTime(new Date());
withdrawalOrders.setMemberId(member.getId());
+ withdrawalOrders.setOutBillNo(UUID.randomUUID().toString().replace("-",""));
withdrawalOrders.setAmount(withdrawalDTO.getAmount());
withdrawalOrders.setStatus(Constants.ZERO);
withdrawalOrders.setType(Constants.ZERO);
+ withdrawalOrders.setDeleted(Constants.ZERO);
- //TODO 鍙戣捣鎻愮幇鐢宠
+ //鍙戣捣鎻愮幇鐢宠
+ TransferToUser.TransferToUserRequest transferToUserRequest = new TransferToUser.TransferToUserRequest();
+ transferToUserRequest.openid = member.getOpenid();
+ transferToUserRequest.outBillNo = withdrawalOrders.getOutBillNo();
+ transferToUserRequest.transferAmount = withdrawalDTO.getAmount();
+ transferToUserRequest.transferRemark = "鎻愮幇鐢宠";
+// transferToUserRequest.userName = member.getName();
+ try {
+ TransferToUser.TransferToUserResponse response = WxMiniConfig.transferToUser.run(transferToUserRequest,member.getName());
+ withdrawalOrders.setRemark(JSONObject.toJSONString(response));
+ if(response.state.name().equals("WAIT_USER_CONFIRM") || response.state.name().equals("ACCEPTED")){
+ withdrawalOrders.setWxExternalNo(response.transferBillNo);
+ }
+ withdrawalOrdersMapper.insert(withdrawalOrders);
+ //鏇存柊鐢ㄦ埛浣欓
+ memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" AMOUNT = AMOUNT - " + withdrawalDTO.getAmount() ).eq(Member::getId,member.getId()));
+
+ //瀛樺偍娴佹按璁板綍
+ MemberRevenue memberRevenue = new MemberRevenue();
+ memberRevenue.setCreateTime(new Date());
+ memberRevenue.setMemberId(member.getId());
+ memberRevenue.setType(Constants.THREE);
+ memberRevenue.setOptType(-Constants.ONE);
+ memberRevenue.setBeforeAmount(member.getAmount());
+ memberRevenue.setAmount(withdrawalOrders.getAmount());
+ memberRevenue.setAfterAmount(member.getAmount() - withdrawalOrders.getAmount());
+ memberRevenue.setObjId(withdrawalOrders.getId());
+ memberRevenue.setObjType(Constants.ONE);
+ memberRevenue.setDeleted(Constants.ZERO);
+ memberRevenue.setStatus(Constants.TWO);
+ memberRevenueMapper.insert(memberRevenue);
+ return response;
+ } catch (WXPayUtility.ApiException e) {
+ String message = JSONObject.parseObject(e.getBody()).getString("message");
+ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),message);
+ }
+ }
+ @Override
+ public void cancelTransfer(TransferToUser.CancelTransferRequest request){
+ if(Objects.isNull(request)
+ || StringUtils.isEmpty(request.outBillNo)){
+ throw new BusinessException(ResponseStatus.BAD_REQUEST);
+ }
+ WithdrawalOrders withdrawalOrders = withdrawalOrdersMapper.selectOne(new QueryWrapper<WithdrawalOrders>().lambda().eq(WithdrawalOrders::getOutBillNo,request.outBillNo).last("limit 1"));
+ if(Objects.isNull(withdrawalOrders)){
+ throw new BusinessException(ResponseStatus.DATA_EMPTY);
+ }
+ Member member = memberMapper.selectById(withdrawalOrders.getMemberId());
+ if(Objects.isNull(member)){
+ throw new BusinessException(ResponseStatus.DATA_EMPTY);
+ }
+ try {
+ TransferToUser.CancelTransferResponse response = WxMiniConfig.transferToUser.cancelRun(request);
+ if(response.state.equals("CANCELING")){
+ //鏍囪鎻愮幇澶辫触 鍔犲洖瀵瑰簲鐨勬彁鐜伴噾棰�
+ withdrawalOrdersMapper.update(new UpdateWrapper<WithdrawalOrders>()
+ .lambda().set(WithdrawalOrders::getStatus,Constants.TWO)
+ .eq(WithdrawalOrders::getId,withdrawalOrders.getId()));
- //鏇存柊鐢ㄦ埛浣欓
+ memberRevenueMapper.update(new UpdateWrapper<MemberRevenue>().lambda().set(MemberRevenue::getStatus,Constants.ONE)
+ .set(MemberRevenue::getUpdateTime,new Date())
+ .eq(MemberRevenue::getObjId,withdrawalOrders.getId()))
+ ;
+ //鏇存柊鐢ㄦ埛浣欓
+ memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" AMOUNT = AMOUNT + " + withdrawalOrders.getAmount() ).eq(Member::getId,withdrawalOrders.getMemberId()));
- //瀛樺偍娴佹按璁板綍
+ //瀛樺偍娴佹按璁板綍
+ MemberRevenue memberRevenue = new MemberRevenue();
+ memberRevenue.setCreateTime(new Date());
+ memberRevenue.setMemberId(withdrawalOrders.getMemberId());
+ memberRevenue.setType(Constants.FOUR);
+ memberRevenue.setOptType(Constants.ONE);
+ memberRevenue.setBeforeAmount(member.getAmount());
+ memberRevenue.setAmount(withdrawalOrders.getAmount());
+ memberRevenue.setAfterAmount(member.getAmount() + withdrawalOrders.getAmount());
+ memberRevenue.setObjId(withdrawalOrders.getId());
+ memberRevenue.setObjType(Constants.ONE);
+ memberRevenue.setDeleted(Constants.ZERO);
+ memberRevenue.setStatus(Constants.ZERO);
+ memberRevenueMapper.insert(memberRevenue);
-
+ }
+ System.out.println(JSONObject.toJSONString(response));
+ } catch (WXPayUtility.ApiException e) {
+ String message = JSONObject.parseObject(e.getBody()).getString("message");
+ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),message);
+ }
}
diff --git a/server/services/src/main/resources/application-dev.yml b/server/services/src/main/resources/application-dev.yml
index 0f36468..add081e 100644
--- a/server/services/src/main/resources/application-dev.yml
+++ b/server/services/src/main/resources/application-dev.yml
@@ -85,7 +85,7 @@
pay:
#鏈嶅姟鍟�---------start-------
appId: wx48fd8faa35cc8277
- mchId: 1661770902
+ mchId: 1229817002 #1661770902
apiV3Key: iF3kC8pL8dZ9iU3hN5fX9zI6eF4xQ6fT
serialNumer: 368B835A194384FD583B83B77977B84127D2F655
mchKey: W97N53Q71326D6JZ2E9HY5M4VT4BAC8S
@@ -96,9 +96,17 @@
#keyPath: /usr/local/aliConfig/bike/apiclient_cert.p12
#privateCertPath: /usr/local/aliConfig/bike/apiclient_cert.pem
#privateKeyPath: /usr/local/aliConfig/bike/apiclient_key.pem
- # keyPath: d://apiclient_cert.p12
- # privateCertPath: d://apiclient_cert.pem
- # privateKeyPath: d://apiclient_key.pem
+ keyPath: d://apiclient_cert.p12
+ privateCertPath: d://apiclient_cert.pem
+ privateKeyPath: d://apiclient_key.pem
+
+
+ #鍟嗘埛淇℃伅
+ wechatSerialNumer: 3FE90C2F3D40A56E1C51926F31B8A8D22426CCE0
+ wechatPayPublicKeyId: PUB_KEY_ID_0112298170022025071700291836000600
+ wechatPubKeyPath: d://pub_key.pem
+ wechatPrivateKeyPath: d://wechatApiclient_key.pem
+
#鏈嶅姟鍟�-------------end---
existsSub: 1
appSecret: 1ceb7c9dff3c4330d653adc3ca55ea24
diff --git a/server/web/src/main/java/com/doumee/api/web/AccountApi.java b/server/web/src/main/java/com/doumee/api/web/AccountApi.java
index 66c5721..df272ad 100644
--- a/server/web/src/main/java/com/doumee/api/web/AccountApi.java
+++ b/server/web/src/main/java/com/doumee/api/web/AccountApi.java
@@ -1,5 +1,6 @@
package com.doumee.api.web;
+import com.doumee.config.jwt.JwtTokenUtil;
import com.doumee.core.annotation.LoginRequired;
import com.doumee.core.annotation.trace.Trace;
import com.doumee.core.model.ApiResponse;
@@ -53,6 +54,16 @@
return ApiResponse.success("鎿嶄綔鎴愬姛",memberService.wxAuthPhone(wxPhoneRequest));
}
-
+ @LoginRequired
+ @ApiOperation(value = "閫�鍑虹櫥褰�", notes = "灏忕▼搴忕")
+ @GetMapping("/logOff")
+ @ApiImplicitParams({
+ @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
+ })
+ public ApiResponse logOff() {
+ String token = this.getRequest().getHeader(JwtTokenUtil.HEADER_KEY);
+ memberService.logOff(token,getMemberId());
+ return ApiResponse.success("鎿嶄綔鎴愬姛");
+ }
}
diff --git a/server/web/src/main/java/com/doumee/api/web/ConfigApi.java b/server/web/src/main/java/com/doumee/api/web/ConfigApi.java
index 187160a..17e8ed7 100644
--- a/server/web/src/main/java/com/doumee/api/web/ConfigApi.java
+++ b/server/web/src/main/java/com/doumee/api/web/ConfigApi.java
@@ -1,5 +1,6 @@
package com.doumee.api.web;
+import com.doumee.core.annotation.LoginRequired;
import com.doumee.core.annotation.trace.Trace;
import com.doumee.core.model.ApiResponse;
import com.doumee.dao.business.model.Category;
@@ -34,6 +35,7 @@
@Autowired
private CategoryService categoryService;
+ @LoginRequired
@ApiOperation(value = "鑾峰彇鍒嗙被鍒楄〃", notes = "灏忕▼搴忕")
@GetMapping("/getCategoryList")
@ApiImplicitParams({
diff --git a/server/web/src/main/java/com/doumee/api/web/OrdersApi.java b/server/web/src/main/java/com/doumee/api/web/OrdersApi.java
index 6ca26a2..38571fa 100644
--- a/server/web/src/main/java/com/doumee/api/web/OrdersApi.java
+++ b/server/web/src/main/java/com/doumee/api/web/OrdersApi.java
@@ -13,6 +13,7 @@
import com.doumee.dao.dto.ConfirmUpdOrderDTO;
import com.doumee.dao.dto.DoneOrderDTO;
import com.doumee.dao.dto.UpdOrderDataDTO;
+import com.doumee.dao.vo.OrderReleaseVO;
import com.doumee.service.business.IdentityInfoService;
import com.doumee.service.business.MemberService;
import com.doumee.service.business.OrdersService;
@@ -51,7 +52,7 @@
@ApiImplicitParams({
@ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
})
- public ApiResponse<Object> release(@RequestBody Orders orders) {
+ public ApiResponse<OrderReleaseVO> release(@RequestBody Orders orders) {
orders.setMember(this.getMemberResponse());
return ApiResponse.success("鎿嶄綔鎴愬姛",ordersService.create(orders));
}
@@ -185,6 +186,15 @@
return ApiResponse.success("鎿嶄綔鎴愬姛",ordersService.getDetail(orderId,this.getMemberResponse().getUseIdentity()));
}
+ @LoginRequired
+ @ApiOperation("鑾峰彇棰勮閲戦锛堝垎锛�")
+ @PostMapping("/getTotal")
+ @ApiImplicitParams({
+ @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
+ })
+ public ApiResponse<Long> getTotal(@RequestBody Orders orders) {
+ return ApiResponse.success(ordersService.getTotal(orders));
+ }
}
diff --git a/server/web/src/main/java/com/doumee/api/web/UserApi.java b/server/web/src/main/java/com/doumee/api/web/UserApi.java
index 8e97ae8..30cac74 100644
--- a/server/web/src/main/java/com/doumee/api/web/UserApi.java
+++ b/server/web/src/main/java/com/doumee/api/web/UserApi.java
@@ -1,5 +1,6 @@
package com.doumee.api.web;
+import com.doumee.config.wx.TransferToUser;
import com.doumee.core.annotation.LoginRequired;
import com.doumee.core.annotation.trace.Trace;
import com.doumee.core.model.ApiResponse;
@@ -8,12 +9,14 @@
import com.doumee.dao.business.model.IdentityInfo;
import com.doumee.dao.business.model.Member;
import com.doumee.dao.business.model.MemberRevenue;
+import com.doumee.dao.dto.WithdrawalDTO;
import com.doumee.dao.dto.WxPhoneRequest;
import com.doumee.dao.vo.AccountResponse;
import com.doumee.dao.vo.UserCenterVO;
import com.doumee.service.business.IdentityInfoService;
import com.doumee.service.business.MemberRevenueService;
import com.doumee.service.business.MemberService;
+import com.doumee.service.business.WithdrawalOrdersService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@@ -46,6 +49,9 @@
@Autowired
private MemberRevenueService memberRevenueService;
+
+ @Autowired
+ private WithdrawalOrdersService withdrawalOrdersService;
@ApiOperation(value = "鑾峰彇绯荤粺閰嶇疆", notes = "灏忕▼搴忕")
@@ -153,6 +159,29 @@
return ApiResponse.success(memberRevenueService.findPage(pageWrap));
}
+ @LoginRequired
+ @ApiOperation("鎻愮幇鐢宠")
+ @PostMapping("/applyWithdrawal")
+ @ApiImplicitParams({
+ @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
+ })
+ public ApiResponse<TransferToUser.TransferToUserResponse> applyWithdrawal (@RequestBody WithdrawalDTO withdrawalDTO) {
+ withdrawalDTO.setMember(this.getMemberResponse());
+ return ApiResponse.success("鎿嶄綔鎴愬姛",withdrawalOrdersService.applyWithdrawal(withdrawalDTO));
+ }
+
+
+
+ @LoginRequired
+ @ApiOperation("鎾ら攢鎻愮幇鐢宠")
+ @PostMapping("/cancelTransfer")
+ @ApiImplicitParams({
+ @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
+ })
+ public ApiResponse cancelTransfer (@RequestBody TransferToUser.CancelTransferRequest request) {
+ withdrawalOrdersService.cancelTransfer(request);
+ return ApiResponse.success("鎿嶄綔鎴愬姛");
+ }
}
--
Gitblit v1.9.3