¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | <artifactId>wechatpay-java</artifactId> |
| | | <version>0.2.12</version> |
| | | </dependency> |
| | | |
| | | |
| | | <!-- <dependency> |
| | | <groupId>com.azure.spring</groupId> |
| | | <artifactId>spring-cloud-azure-starter-storage-blob</artifactId> |
| | |
| | | }) |
| | | @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)){ |
| | |
| | | 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); |
| | |
| | | .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; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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"; //å°ç¨åºid |
| | | 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(); |
| | | |
| | | // åéHTTPè¯·æ± |
| | | 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); |
| | | |
| | | // ä»HTTPåºçæ¥ææå»ºè¿åæ°æ® |
| | | 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(); |
| | | |
| | | // åéHTTPè¯·æ± |
| | | 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); |
| | | |
| | | // ä»HTTPåºçæ¥ææå»ºè¿åæ°æ® |
| | | 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(); |
| | | |
| | | // åéHTTPè¯·æ± |
| | | 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); |
| | | |
| | | // ä»HTTPåºçæ¥ææå»ºè¿åæ°æ® |
| | | 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; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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 ç¾åç®æ³ï¼å¦ï¼SHA256withRSA |
| | | * @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 è¯·æ±æ¥å£çHTTPæ¹æ³ï¼è¯·ä½¿ç¨å
¨å¤§å表述ï¼å¦ GETãPOSTãPUTãDELETE |
| | | * @param uri è¯·æ±æ¥å£çURL |
| | | * @param body è¯·æ±æ¥å£çBody |
| | | * @return æé 好ç微信æ¯ä»APIv3 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); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 坹忰Mapè¿è¡ 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å
容ï¼Body为空æ¶è¿å空å符串 |
| | | */ |
| | | 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é误å¼å¸¸ï¼åéHTTPè¯·æ±æåï¼ä½è¿åç¶æç 䏿¯ 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访é®å¤±è´¥ï¼StatusCode: [%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; |
| | | } |
| | | } |
| | | } |
| | |
| | | public static JsapiServiceExtension jsapiExtService; |
| | | public static BillDownloadService billDownloadService; |
| | | public static WxPayProperties wxProperties; |
| | | |
| | | public static TransferToUser transferToUser; |
| | | @Autowired |
| | | private WxPayProperties wxPayProperties; |
| | | |
| | |
| | | this.load_WxMaService(); |
| | | this.load_wxPayService(); |
| | | this.load_wxPayV2Service(); |
| | | this.load_transferToUser(); |
| | | this.load_transferToUser(); |
| | | this.wxProperties = wxPayProperties; |
| | | } |
| | | /** |
| | |
| | | // } |
| | | |
| | | |
| | | 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; |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | private String privateKeyPath ; |
| | | private String privateCertPath;// gybike |
| | | |
| | | |
| | | private String wechatSerialNumer; |
| | | private String wechatPayPublicKeyId; // 微信æ¯ä»å
¬é¥ID |
| | | private String wechatPubKeyPath; //微信æ¯ä»å
¬é¥æä»¶è·¯å¾ |
| | | private String wechatPrivateKeyPath; |
| | | |
| | | } |
| | |
| | | @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; |
| | | } |
| | |
| | | @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") |
| | |
| | | @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 = "éæ±è¡¥å
") |
| | |
| | | @ApiModelProperty(value = "è´¹ç¨æ å", example = "1") |
| | | private Long price; |
| | | |
| | | |
| | | @ApiModelProperty(value = "é¢ä¼°è´¹ç¨", example = "1") |
| | | private Long estimatedAccount; |
| | | |
| | | |
| | | @ApiModelProperty(value = "å®é
æ¯ä»è´¹ç¨", example = "1") |
| | | private Long payAccount; |
| | |
| | | |
| | | @ApiModelProperty(value = "æ¯å¦å·²å é¤ 0æªå é¤ 1å·²å é¤", example = "1") |
| | | @ExcelColumn(name="æ¯å¦å·²å é¤ 0æªå é¤ 1å·²å é¤") |
| | | private Byte deleted; |
| | | private Integer deleted; |
| | | |
| | | @ApiModelProperty(value = "å建人ç¼ç ", example = "1") |
| | | @ExcelColumn(name="å建人ç¼ç ") |
| | |
| | | @ApiModelProperty(value = "å
³è订åä¸»é® orders", example = "1") |
| | | @ExcelColumn(name="å
³è订åä¸»é® orders") |
| | | private Integer objId; |
| | | |
| | | @ApiModelProperty(value = "æç°ç³è¯·åå·") |
| | | @ExcelColumn(name="æç°ç³è¯·åå·") |
| | | private String outBillNo; |
| | | |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | |
| | | } |
| | |
| | | Member getMemberInfo(Integer memberId); |
| | | |
| | | UserCenterVO getPlatformAboutUs(); |
| | | |
| | | void logOff(String token,Integer memberId); |
| | | } |
| | |
| | | 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; |
| | |
| | | * @param orders å®ä½å¯¹è±¡ |
| | | * @return Integer |
| | | */ |
| | | Object create(Orders orders); |
| | | OrderReleaseVO create(Orders orders); |
| | | |
| | | /** |
| | | * 主é®å é¤ |
| | |
| | | void autoComment(); |
| | | |
| | | void autoConfirm(); |
| | | |
| | | Long getTotal(Orders orders); |
| | | |
| | | void autoGrabOrders(); |
| | | |
| | | void initializeCode(); |
| | | } |
| | |
| | | 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; |
| | |
| | | */ |
| | | long count(WithdrawalOrders withdrawalOrders); |
| | | |
| | | void applyWithdrawal(WithdrawalDTO withdrawalDTO); |
| | | TransferToUser.TransferToUserResponse applyWithdrawal(WithdrawalDTO withdrawalDTO); |
| | | |
| | | void cancelTransfer(TransferToUser.CancelTransferRequest request); |
| | | |
| | | } |
| | |
| | | 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; |
| | |
| | | |
| | | 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; |
| | |
| | | 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; |
| | | |
| | | /** |
| | |
| | | @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() |
| | |
| | | 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); |
| | |
| | | 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); |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | 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; |
| | |
| | | |
| | | 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; |
| | | |
| | | /** |
| | |
| | | |
| | | @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()); |
| | |
| | | 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(),"éä»¶ä¿¡æ¯é误"); |
| | |
| | | .replace("{param}",orderTypeInfo); |
| | | this.saveOrderLog(orders,ordersLog, |
| | | logInfo,orders.getReleaseMemberId(),null); |
| | | return objects; |
| | | return orderReleaseVO; |
| | | } |
| | | |
| | | private Object getWxPayResponse(Orders orders,String openid){ |
| | |
| | | || 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()) |
| | |
| | | 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()) |
| | | ){ |
| | |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"éé¢è®¡ç®é误!"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | |
| | | 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())); |
| | | |
| | |
| | | .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()) |
| | | ); |
| | |
| | | } |
| | | |
| | | |
| | | @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(); |
| | | } |
| | |
| | | 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()) |
| | | ); |
| | | //è®°å½åæä¿®æ¹çæ¥å¿ |
| | |
| | | }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) |
| | |
| | | } |
| | | 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()) |
| | | ); |
| | |
| | | } |
| | | 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()) |
| | | ); |
| | |
| | | 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) |
| | |
| | | |
| | | 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()) |
| | |
| | | }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()) |
| | |
| | | }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()) |
| | | ); |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | //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æ |
| | |
| | | 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()) |
| | |
| | | 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()) |
| | | ); |
| | | //è®°å½åæä¿®æ¹çæ¥å¿ |
| | |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void initializeCode(){ |
| | | //æ´æ°ç¼å |
| | | redisTemplate.opsForValue().set(Constants.RedisKeys.ORDER_CODE,0); |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | 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; |
| | |
| | | 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å®ç° |
| | |
| | | * æç°ç³è¯· |
| | | * @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); |
| | |
| | | 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); |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | pay: |
| | | #æå¡å---------start------- |
| | | appId: wx48fd8faa35cc8277 |
| | | mchId: 1661770902 |
| | | mchId: 1229817002 #1661770902 |
| | | apiV3Key: iF3kC8pL8dZ9iU3hN5fX9zI6eF4xQ6fT |
| | | serialNumer: 368B835A194384FD583B83B77977B84127D2F655 |
| | | mchKey: W97N53Q71326D6JZ2E9HY5M4VT4BAC8S |
| | |
| | | #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 |
| | |
| | | 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; |
| | |
| | | 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("æä½æå"); |
| | | } |
| | | |
| | | } |
| | |
| | | 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; |
| | |
| | | @Autowired |
| | | private CategoryService categoryService; |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "è·ååç±»å表", notes = "å°ç¨åºç«¯") |
| | | @GetMapping("/getCategoryList") |
| | | @ApiImplicitParams({ |
| | |
| | | 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; |
| | |
| | | @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)); |
| | | } |
| | |
| | | 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)); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | |
| | | @Autowired |
| | | private MemberRevenueService memberRevenueService; |
| | | |
| | | @Autowired |
| | | private WithdrawalOrdersService withdrawalOrdersService; |
| | | |
| | | |
| | | @ApiOperation(value = "è·åç³»ç»é
ç½®", notes = "å°ç¨åºç«¯") |
| | |
| | | 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("æä½æå"); |
| | | } |
| | | |
| | | |
| | | } |