如何实现webhook通知

在开发中,有些外部系统需要依赖我们系统的数据,如系统数据发生变更需要告知外部系统(外部系统可能有很多个),我们初步想用webhook的方式来实现,想知道webhook是怎么用的。怎么搭建需要什么技术

webhook 的概念很简单,webhook 就是一个简单的 HTTP 回调。当发生某些事情时,HTTP POST 调用的注册 URL 作为简单通知。

换句话说,我们所说的 Webhook 是在 Web 应用程序中,当某些事情发生时,通过 HTTP POST 调用自动注册的 URL 以通知 Web 应用程序上的用户您请求的数据状态已更改,请查看它。

1.> 首先,我们将创建一个 API,从用户那里获取 KYC 信息,然后通过 RestTemplate 将此信息发送给第三方应用程序以验证用户信息,第三方将 Json Response 作为 KYC 详细信息提交返回给用户.

UserKYCController class
package com.example.com.controller;

@Api
@RestController
@RequestMapping(value = UrlConstant.BASE_URI_V1)
public class UserKYCController {

    private Logger logger = LoggerFactory.getLogger(UserKYCController.class);

    @Autowired
    private UserKYCService userKYCService;

    /**
     * @param userKYCInput
     * @param result
     * @return
     */
    @RequestMapping(value = UrlConstant.UPLOAD_CONSUMER_KYC_DOCUMENT, method = RequestMethod.POST)
    public ResponseEntity<Object> uploadKYCDetails(@Valid @RequestBody UserKYCInput userKYCInput,
            BindingResult result) {

    if (result.hasErrors()) {
    return ResponseHandler.response(HttpStatus.BAD_REQUEST, true, ErrorCollectionUtil.getError(result),
    ErrorCode.ERROR, Message("bad.request"),
    ResponseCode.ACKNOWLEDGE_OPTIONAL_RESPONSE_OBJECT, ErrorCollectionUtil.getErrorMap(result));
    }

    ResponseEntity<String> response = userKYCService.sendUserKyc(userKYCInput);
    if (response != null) {
    return ResponseHandler.response(HttpStatus.OK, false, Message("user.KYC.save.success"),
    ErrorCode.OK, ResponseCode.ACKNOWLEDGE, response);
    } else {
    genericUtil.saveData(userKYCInput);
    return ResponseHandler.response(HttpStatus.INTERNAL_SERVER_ERROR, true,
    Message("user.KYC.save.failure"), ErrorCode.ERROR,
    ResponseCode.ACKNOWLEDGE_OPTIONAL_RESPONSE_OBJECT);
    }
    }

}
 
 
UserKYCServiceImpl class
package com.example.com.service.Userkyc;


@Service
public class UserKYCServiceImpl implements UserKYCService {

    public static final Logger logger = LoggerFactory.getLogger(UserKYCServiceImpl.class);

    @Autowired
    private UserKYCRepository userKYCRepository;

    @Value("${user.kyc.restTemplate.url}")
    private String kycClientURL;

    @Value("${user.kyc.restTemplate.authKey}")
    private String kycAuthKey;

    @Autowired
    private UserService userService;
    
    @Override
    public ResponseEntity<String> sendUserKyc(UserKYCInput userKYCDetail) {
        RestTemplate restTemplate = new RestTemplate();
        String url = kycClientURL;
        String base64Creds = kycAuthKey;

        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Basic " + base64Creds);
        HttpEntity<UserKYCInput> request = new HttpEntity<>(userKYCDetail, headers);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
        uploadUserKyc(userKYCDetail, response);
        return response;
    }

    
}

2.> 其次,我们将创建另一个 API,并且此 API URL 已在发送用户 KYC 信息的第三方应用程序中注册,当验证成功时,第三方将使用更新的 Json 响应自动调用我们注册的 URL,或者我们可以说用户会通过调用这个注册 URL 被第三方自动通知,所以这个 URL 被称为(Webhook URL)。

UserKYCWebhookController class
package com.example.com.controller;

@Api
@RestController
@RequestMapping(value = UrlConstant.BASE_KYC_WEBHOOK_URI_V1)
public class UserKYCWebhookController {

    private static final Logger logger = getLogger(UserKYCWebhookController.class);

    @Autowired
    private UserKYCService userKYCService;

    @Autowired
    private WebHookDetailsService webHookDetailsService;

    @Autowired
    private PasswordEncoderUtil passwordEncoderUtil;
    
    /**
     * @param notificationDto
     * @param httpRequest
     * @throws Exception
     */
    @RequestMapping(value = UrlConstant.CONSUMER_KYC_WEBHOOK_NOTIFICATION_REQUEST, method = RequestMethod.POST)
    public void getKYCWebhookData(@RequestBody Map<String, Object> notificationDto,HttpServletRequest httpRequest) {

    final String authorization = httpRequest.getHeader("Authorization");
    logger.debug("authorization {}", authorization);
    if (authorization != null && authorization.startsWith("Basic")) {
    String base64Credentials = authorization.substring("Basic".length()).trim();
    String credentials = new String(Base64.getDecoder().decode(base64Credentials), Charset.forName("UTF-8"));
    final String[] values = credentials.split(":", 2);
    String userName = values[0].trim();
    String password = values[1].trim();

    WebHookDetails details = webHookDetailsService.getwebHookDetailsByUserName(userName);

    if (Objects.nonNull(details)) {

    String tid = notificationDto.get("tid").toString();
    String state = notificationDto.get("state").toString();
                
    Map<String, Object> response = new HashMap<>();
    response.put("tid", tid);
    response.put("state", state);

    if (passwordEncoderUtil.matches(password, details.getPassword())) {
    userKYCService.saveWebhookUpdatedResponse(response);
    } else {
    logger.debug("response == {}", false);
    }

    }
    }
    }

}

这就是使用 spring web 应用程序实现 webhook 的全部内容。

webhook,简单的来说就是给外部用户提供一个数据推送接口,比如飞书的机器人,企业微信的机器人都是如此。

对于你的应用场景有两种解决办法;

1.你们提供数据变更的接口,让第三方来定时调用;优点:一次开发其他的第三方都可以调用;缺点:数据没有更新也会定时请求,请求量大的时候,需要考虑并发量及性能。而当请求时间间隔设置长后,数据更新通知实时性不高。

2.第三方提供接收数据的接口,你需要维护众多第三方接口,你这边数据变更及时调用所有的第三方接口。优点:及时;缺点:线下沟通成本高,需要第三方都提供数据接口。

webhook没太了解过,但是你需要的消息推送功能我觉得MQTT或许也挺合适的,就是不知道你的具体的应用场景是什么样的,如果技术选型已经确定的话就无视我吧

让外部系统提供一个http接口地址给你,
当你的系统发生变化的时候,就逐个调用这些http接口。

如有帮助,请采纳,十分感谢!

很简单,可以参考一下钉钉的机器人,建一个群,然后添加一个机器人,然后把webhook复制出来之后调用api就可以实现了

webhook告警通知功能

SLS告警最佳实践——Webhook通知最佳实践
https://developer.aliyun.com/article/858912