Créer un endpoint avec Java/Spring pour Webhooks Shopify

Les Webhooks Shopify sont disponibles afin de notifier une application extérieure sur des évènements de la boutique. Les évènements touchent toutes les entités de la boutique (commande, client, panier, produit ….). Malheureusement Shopify ne fournit pas d’exemple en Java pour le squelette du Endpoint. Notamment il n’est pas évident de reproduire en Java la vérification du Digest permettant de vérifier que la requête est bien issue de Shopify.

Voici l’exemple en Java :

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@EnableAutoConfiguration
@RequestMapping("/api/v1")
public class ShopifyNotifController {
	
	private static final String SHOPIFY_HMAC_KEY = "x-shopify-hmac-sha256";
	private static final String SHOPIFY_APP_SECRET = "[Shopify_secret]";
	
	/**
	 * Loggeur des classes services
	 */
	Logger logger = LoggerFactory.getLogger(ShopifyNotifController.class);
	

	public String hmacDigest(String msg, String keyString, String algo) {
	    String digest = null;
	    try {
	    	SecretKeySpec signingKey = new SecretKeySpec(keyString.getBytes(), algo);
			Mac mac = Mac.getInstance(algo);
			mac.init(signingKey);
			digest = new String(Base64.encodeBase64(mac.doFinal(msg.getBytes())));
	    } catch (Exception exp) {
	    	logger.error("Exception durant le calcul HmacDigest");
	    }
	    return digest;
	  }	
	
	@PostMapping("/orderevent")
	public String orderEvent(@RequestBody String requestWrapper, @RequestHeader MultiValueMap<String, String> headers) {
		String hmacValue = null;
		if (headers.containsKey(SHOPIFY_HMAC_KEY)) {
			hmacValue = headers.getFirst(SHOPIFY_HMAC_KEY);
		}
		
		String hMacStr = this.hmacDigest(requestWrapper,SHOPIFY_APP_SECRET,"HmacSHA256"); 
		if (hmacValue.equals(hMacStr)) {
			logger.info("Vérification de l'origine de l'appel OK");
		} else {
			logger.error("Erreur calcul du digest de Shopify");
		}
		return "OK";

	}

}

Dans l’exemple il faut remplacer la constante SHOPIFY_APP_SECRET par le code de vérification fourni dans la section Webhooks de votre boutique shopify. Le lien vers la doc shopify pour utiliser les webhooks et les exemples de codes en php/python/ruby sur la vérification de l’appel est ici.

0 Comments

Leave a Reply

Votre adresse e-mail ne sera pas publiée.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.