# ModuleEventEndpointImpl.java

    package cloud.wconnect.frontoffice.config.snsmoduleevent.integration;

    import cloud.wconnect.aws.sns.messaging.annotaion.endpoint.NotificationMessageMapping;
    import cloud.wconnect.aws.sns.messaging.annotaion.endpoint.NotificationSubscriptionMapping;
    import cloud.wconnect.aws.sns.messaging.annotaion.endpoint.NotificationUnsubscribeConfirmationMapping;
    import cloud.wconnect.aws.sns.messaging.annotaion.handlers.NotificationMessage;
    import cloud.wconnect.aws.sns.messaging.annotaion.handlers.NotificationPayload;
    import cloud.wconnect.aws.sns.messaging.annotaion.handlers.NotificationSubject;
    import cloud.wconnect.aws.sns.messaging.core.AwsSignatureVerifier;
    import cloud.wconnect.aws.sns.messaging.handlers.NotificationPayloads;
    import cloud.wconnect.aws.sns.messaging.handlers.NotificationStatus;
    import cloud.wconnect.commonlib.pojo.ModuleEvent;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.context.ApplicationEventPublisher;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import software.amazon.awssdk.services.sns.SnsClient;

    import jakarta.servlet.http.HttpServletRequest;

    /**
     * 手动订阅SNS HTTPS：模块之间接收事件
     *
     * @author zc
     * @date 2023/09/12
     */
    @ConditionalOnProperty(prefix = "w-connect.module-event", name = "status", havingValue = "active")
    @RestController
    @RequestMapping("${w-connect.module-event.endpoint}")
    public class ModuleEventEndpointImpl {

        @Value("${w-connect.module-event.topic}")
        private String topic;

        @Autowired
        private ApplicationEventPublisher publisher;

        @Autowired
        @Qualifier("moduleAwsSignatureVerifier")
        private AwsSignatureVerifier awsSignatureVerifier;

        @Autowired
        @Qualifier("moduleEventSnsClient")
        private SnsClient snsClient;

        @NotificationSubscriptionMapping
        public void handleSubscriptionMessage(NotificationStatus status, @NotificationPayload NotificationPayloads payloads,
                                              HttpServletRequest httpServletRequest) {
            if (this.awsSignatureVerifier.verify(payloads, httpServletRequest)) {
                if (checkTopic(payloads)) {
                    status.confirmSubscription(snsClient);
                }
            }
        }

        @NotificationMessageMapping
        public void handleNotificationMessage(@NotificationSubject String subject, @NotificationMessage String body,
                                              @NotificationPayload NotificationPayloads payloads,
                                              HttpServletRequest httpServletRequest) {
            if (!this.awsSignatureVerifier.verify(payloads, httpServletRequest)) {
                return;
            }

            if (!checkTopic(payloads)) {
                return;
            }

            // TODO 业务层面的数据可信校验
            ModuleEvent event = new ModuleEvent();
            event.setMessageId(httpServletRequest.getHeader("x-amz-sns-message-id"))
                    .setSubject(subject).setBody(body);

            publisher.publishEvent(event);
        }

        @NotificationUnsubscribeConfirmationMapping
        public void handleUnsubscribeMessage(NotificationStatus status, @NotificationPayload NotificationPayloads payloads, HttpServletRequest httpServletRequest) {
            // 不需要处理「取消订阅确认」消息，目前我们没有任何在取消订阅时需要做的事情
    //        if (this.awsSignatureVerifier.verify(payloads, httpServletRequest)) {
    //            if (checkTopic(payloads)) {
    //                status.confirmSubscription(snsClient);
    //            }
    //        }
        }

        /**
         * 确保消息来自于自身业务关注的 sns topic
         */
        private boolean checkTopic(NotificationPayloads payloads) {
            return this.topic.equals(payloads.getTopicArn());
        }
    }