微信支付回调验签失败

2024-10-09 09:33:13.595 INFO 928036 --- [nio-8085-exec-7] c.l.m.portal.controller.WXPayController : into receivePayNotify method=============================================

2024-10-09 09:33:13.595 INFO 928036 --- [nio-8085-exec-7] c.l.m.portal.controller.WXPayController : request is org.apache.catalina.connector.RequestFacade@20a29b37

2024-10-09 09:33:13.596 INFO 928036 --- [nio-8085-exec-7] c.l.m.p.service.impl.WXPayServiceImpl :

wechatPaySerial is [57184D0BFD9FE4506E06B8D84B8E4E2BE46BDEC5] ,

wechatSignature is [e1xRxe6nQhMjo/TbEA7Z1iwrXYfn3Ozd4iSED/vuQ+E01v+0FWEoBPVHStEla9XbBM3Q6qvrs2OcsR9hD87DAgcawabFdr81FQ8csMhOL0OWdvgyXDlMZS+FGTa5LMLBJ4GPnjAivPAB1iE6RhfVjbIx3jdMGbpxxJOKYkrw32s3kjU+dE7gaLoL9TStAIsRr2jt4y6lY8McMWJGWc/0W8VSs3BkHrFmPS9vQGxlSE76yXlbvyzphKbRvPZeFjXQVLicgAd3qpUmo8NLmbeDE3aciCoNVwzJScBAw2RNQum5hKbGrEAohp9mJe1yktgcpEFnxyTzHddhwqi/ifDBBQ==] ,

wechatTimestamp is [1728437594] ,

wechatpayNonce is [ukDaEPvYjkM5choqNcYJwAjiC64BonHH] ,

requestBody is [{"id":"7b2b145f-9cda-5573-8be2-d2d9eaaffa25","create_time":"2024-10-09T09:33:13+08:00","resource_type":"encrypt-resource","event_type":"TRANSACTION.SUCCESS","summary":"支付成功","resource":{"original_type":"transaction","algorithm":"AEAD_AES_256_GCM","ciphertext":"UmpebugBzDwyzkuS8MuBdtdi42jiaiAdlYNT3UxJkWf80e/Zhjt5FFNNECor58hYRjlIH/4YaSOzfiElbp1jWWyjv5Uwu2wk2IJkkHhYpr7WBiv3+vAY5OkGnMkbawVVr7JV1XNAbZlbmi8MJxu/IwjbjtfY8lJ/tWWMPxRyYFVtGt72w7Wm3wdpYTR9tgLdPGSRJfzpSAubGNeHVl7yJP8ZvulpxcGnbUynkXa4J3f7qwe+7pJk3SLQRd+cpbwMn5Udx/L/nYsszmn8CtUgUPfRrGHC2ZffMeAAE5LONeo13du0JQ6i7DmrkWMYoDIr4e+PU73wBHnTm8tbo0Icbba5UyhmF/leNAnWV2Biz2uK+09JAJka1BaRGfZVHGoswnVrTdVG+KYuaabG+6UBQefVpfMuvcsFudtUvxCObBh1wFSZWP+jCXq2b53/XVBI+0F/udleVfbGjsw9w3amqjZnvUv+pt1eTh5v5BkOVXkgOUQA6sE7NLjMldcVIFdkj11ItI6tUVfNPeX8+9+sFdRqARFRFui36cDEEtNHo/HG26cVEDK2WMO7YIKjlTFguA==","associated_data":"transaction","nonce":"P4WRnf2zIvU2"}}]

2024-10-09 09:33:13.598 DEBUG 928036 --- [nio-8085-exec-7] c.w.p.j.core.auth.WechatPay2Credential : authorization message[GET

/v3/certificates?algorithm_type=RSA

1728437593

rG3ETdPayAcKK4a9lvQBEdHh9N8z5I3i

]

2024-10-09 09:33:13.607 DEBUG 928036 --- [nio-8085-exec-7] c.w.p.j.core.auth.WechatPay2Credential : The generated request signature information is[mchid="1692170120",nonce_str="rG3ETdPayAcKK4a9lvQBEdHh9N8z5I3i",timestamp="1728437593",serial_no="1E30E11D67DF818DE69195225C6C27B781417661",signature="D77+/3g+lA0HCFRirTa3lzhSRFHvXHys/Xb8CHNU8WgMcN1HWVusZ/r/H8xyTTUIV6J/We6rIoE70DST81WdXEkisDdebqor6fDi2IPiI0u024uM4xs9Cxe6d4hpvMekr0n0m32gUSFnJrDNehrDsA8KQ33NJ4r++PA8/EbrMmD56vSbpZuQKZnkWazGbV6yz0nbriykP5MbLaKLPWp5FHU3UpoLZvYazO65uqgJnYyKGJtIoiGpauo1PwCZG1Eob9T8kuEt/ABMzztStLIB2/eGLtS1/HaPqwEHarLJQm3WM12RB8cTjUagIuoyh6VyHoce2RwNk+yrr1HG5bLkIg=="]

2024-10-09 09:33:13.776 ERROR 928036 --- [nio-8085-exec-7] c.l.m.p.service.impl.WXPayServiceImpl : sign verification failed

com.wechat.pay.java.core.exception.ValidationException:

Processing WechatPay notification,

signature verification failed,

signType[WECHATPAY2-SHA256-RSA2048]

serial[57184D0BFD9FE4506E06B8D84B8E4E2BE46BDEC5]

message[1728437594

ukDaEPvYjkM5choqNcYJwAjiC64BonHH

{"id":"7b2b145f-9cda-5573-8be2-d2d9eaaffa25","create_time":"2024-10-09T09:33:13+08:00","resource_type":"encrypt-resource",

"event_type":"TRANSACTION.SUCCESS","summary":"支付成功",

"resource":{"original_type":"transaction","algorithm":"AEAD_AES_256_GCM",

"ciphertext":"UmpebugBzDwyzkuS8MuBdtdi42jiaiAdlYNT3UxJkWf80e/Zhjt5FFNNECor58hYRjlIH/4YaSOzfiElbp1jWWyjv5Uwu2wk2IJkkHhYpr7WBiv3+vAY5OkGnMkbawVVr7JV1XNAbZlbmi8MJxu/IwjbjtfY8lJ/tWWMPxRyYFVtGt72w7Wm3wdpYTR9tgLdPGSRJfzpSAubGNeHVl7yJP8ZvulpxcGnbUynkXa4J3f7qwe+7pJk3SLQRd+cpbwMn5Udx/L/nYsszmn8CtUgUPfRrGHC2ZffMeAAE5LONeo13du0JQ6i7DmrkWMYoDIr4e+PU73wBHnTm8tbo0Icbba5UyhmF/leNAnWV2Biz2uK+09JAJka1BaRGfZVHGoswnVrTdVG+KYuaabG+6UBQefVpfMuvcsFudtUvxCObBh1wFSZWP+jCXq2b53/XVBI+0F/udleVfbGjsw9w3amqjZnvUv+pt1eTh5v5BkOVXkgOUQA6sE7NLjMldcVIFdkj11ItI6tUVfNPeX8+9+sFdRqARFRFui36cDEEtNHo/HG26cVEDK2WMO7YIKjlTFguA==",

"associated_data":"transaction","nonce":"P4WRnf2zIvU2"}}

] sign[e1xRxe6nQhMjo/TbEA7Z1iwrXYfn3Ozd4iSED/vuQ+E01v+0FWEoBPVHStEla9XbBM3Q6qvrs2OcsR9hD87DAgcawabFdr81FQ8csMhOL0OWdvgyXDlMZS+FGTa5LMLBJ4GPnjAivPAB1iE6RhfVjbIx3jdMGbpxxJOKYkrw32s3kjU+dE7gaLoL9TStAIsRr2jt4y6lY8McMWJGWc/0W8VSs3BkHrFmPS9vQGxlSE76yXlbvyzphKbRvPZeFjXQVLicgAd3qpUmo8NLmbeDE3aciCoNVwzJScBAw2RNQum5hKbGrEAohp9mJe1yktgcpEFnxyTzHddhwqi/ifDBBQ==]

at com.wechat.pay.java.core.notification.NotificationParser.validateRequest(NotificationParser.java:93) ~[wechatpay-java-core-0.2.14.jar!/:0.2.14]

at com.wechat.pay.java.core.notification.NotificationParser.parse(NotificationParser.java:49) ~[wechatpay-java-core-0.2.14.jar!/:0.2.14]

at com.langke.mall.portal.service.impl.WXPayServiceImpl.receivePayNotify(WXPayServiceImpl.java:222) ~[classes!/:1.0-SNAPSHOT]

at com.langke.mall.portal.controller.WXPayController.receivePayNotify(WXPayController.java:46) [classes!/:1.0-SNAPSHOT]

at com.langke.mall.portal.controller.WXPayController$$FastClassBySpringCGLIB$$b159352.invoke(<generated>) [classes!/:1.0-SNAPSHOT]

at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) [spring-core-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:57) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:58) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89) [spring-aop-5.3.20.jar!/:5.3.20]

at com.langke.mall.common.log.WebLogAspect.doAround(WebLogAspect.java:62) [mall-common-1.0-SNAPSHOT.jar!/:1.0-SNAPSHOT]

at sun.reflect.GeneratedMethodAccessor215.invoke(Unknown Source) ~[na:na]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]

at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]

at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) [spring-aop-5.3.20.jar!/:5.3.20]

at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) [spring-aop-5.3.20.jar!/:5.3.20]

at com.langke.mall.portal.controller.WXPayController$$EnhancerBySpringCGLIB$$92a44f53.receivePayNotify(<generated>) [classes!/:1.0-SNAPSHOT]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111]

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_111]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]

at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]

at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) [spring-web-5.3.20.jar!/:5.3.20]

at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) [spring-web-5.3.20.jar!/:5.3.20]

at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) [spring-webmvc-5.3.20.jar!/:5.3.20]

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) [spring-webmvc-5.3.20.jar!/:5.3.20]

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) [spring-webmvc-5.3.20.jar!/:5.3.20]

at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) [spring-webmvc-5.3.20.jar!/:5.3.20]

at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) [spring-webmvc-5.3.20.jar!/:5.3.20]

at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) [spring-webmvc-5.3.20.jar!/:5.3.20]

at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) [spring-webmvc-5.3.20.jar!/:5.3.20]

at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) [spring-webmvc-5.3.20.jar!/:5.3.20]

at javax.servlet.http.HttpServlet.service(HttpServlet.java:681) [tomcat-embed-core-9.0.63.jar!/:na]

at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) [spring-webmvc-5.3.20.jar!/:5.3.20]

at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) [tomcat-embed-websocket-9.0.63.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) [tomcat-embed-core-9.0.63.jar!/:na]

at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) [spring-web-5.3.20.jar!/:5.3.20]

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) [spring-web-5.3.20.jar!/:5.3.20]

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) [tomcat-embed-core-9.0.63.jar!/:na]

at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) [spring-web-5.3.20.jar!/:5.3.20]

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) [spring-web-5.3.20.jar!/:5.3.20]

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) [tomcat-embed-core-9.0.63.jar!/:na]

at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96) [spring-boot-actuator-2.7.0.jar!/:2.7.0]

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) [spring-web-5.3.20.jar!/:5.3.20]

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) [tomcat-embed-core-9.0.63.jar!/:na]

at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) [spring-web-5.3.20.jar!/:5.3.20]

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) [spring-web-5.3.20.jar!/:5.3.20]

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-embed-core-9.0.63.jar!/:na]

at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.63.jar!/:na]

at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]

解决方案:

复制代码
 //接收回调通知报文

        //获取请求头中的报文签名信息,用于后续验证签名
        //证书序列号(微信平台)   验签的“微信支付平台证书”所对应的平台证书序列号
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");
        //微信传递过来的签名   验签的签名值
        String wechatSignature = request.getHeader("Wechatpay-Signature");
        //验签的时间戳
        String wechatTimestamp = request.getHeader("Wechatpay-Timestamp");
        //验签的随机字符串
        String wechatpayNonce = request.getHeader("Wechatpay-Nonce");

        //获取报文 
//        String requestBody = getRequestBody(request);
        BufferedReader reader = request.getReader();
        String line;
        StringBuilder sb = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        String requestBody = sb.toString();

        log.info("wechatPaySerial is [{}]  , wechatSignature is [{}] , wechatTimestamp is [{}] , wechatpayNonce  is [{}] , requestBody is [{}]",wechatPaySerial,wechatSignature,wechatTimestamp,wechatpayNonce,requestBody);


        // 构造 RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatPaySerial)
                .nonce(wechatpayNonce)
                .signature(wechatSignature)
                .timestamp(wechatTimestamp)
                .body(requestBody)
                .build();

        String wechatpaySerial = config.createEncryptor().getWechatpaySerial();
        log.info("wechatPaySerial is [{}] ", wechatpaySerial);

        //不要用这个,大坑
//        NotificationConfig notificationConfig = new RSAAutoCertificateConfig.Builder()
//                .merchantId(merchantId)
//                .privateKeyFromPath(privateKeyPath)
//                .merchantSerialNumber(wxPlatformSerialNumber)
//                .apiV3Key(apiV3Key)
//                .build();


        log.info("config is : {} ",config);
        // 初始化 NotificationParser
        NotificationParser parser = new NotificationParser((NotificationConfig) config);
复制代码
  try {
            // 以支付通知回调为例,验签、解密并转换成 Transaction
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            log.info("transaction is {} ",transaction);
        } catch (ValidationException e) {
            // 签名验证失败,返回 401 UNAUTHORIZED 状态码
            log.error("sign verification failed", e);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED);
        }

//        // 如果处理失败,应返回 4xx/5xx 的状态码,例如 500 INTERNAL_SERVER_ERROR
//        if (/* process error */) {
//            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
//        }

        // 处理成功,返回 200 OK 状态码
        return ResponseEntity.status(HttpStatus.OK);
相关推荐
尘浮生4 天前
Java项目实战II基于微信小程序的新闻资讯平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·微信·微信小程序·小程序
liulanba5 天前
Kotlin的data class
前端·微信·kotlin
尘浮生6 天前
Java项目实战II基于Spring Boot的工作流程管理系统设计与实现(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·微信·微信小程序·小程序
尘浮生6 天前
Java项目实战II基于微信小程序的课堂助手(开发文档+数据库+源码)
java·开发语言·数据库·微信·微信小程序·小程序·maven
CHEtuzki7 天前
不用来回切换,一个界面管理多个微信
微信
尘浮生7 天前
Java项目实战II基于微信阅读网站小程序的设计与实现(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·微信·微信小程序·小程序
2401_8441379511 天前
PHP中小学优校管理系统小程序源码
微信·微信小程序·小程序·微信公众平台·微信开放平台
真鬼12311 天前
植物大战僵尸杂交版v2.6.1最新版本(附下载链接)
微信·游戏程序
深度学习实战训练营15 天前
albert模型实现微信公众号虚假新闻分类
微信·分类·数据挖掘
2401_8441379515 天前
PHP露营地管理平台小程序系统源码
大数据·微信·微信小程序·小程序·微信公众平台·微信开放平台