WECHAT Partagez le développement de la fonction
Après une journée, j'ai développé la fonction d'envoyer WeChat à des amis et de le partager avec mon cercle d'amis. Je le partagerai avec vous ici pour éviter les détours.
1. Programme côté serveur
package com.wimedia.Controller; import java.io.ioexception; import java.security.MessagediGest; import java.security.nosuchalgorithmexception; import java.text.parseexception; import java.text.simpledateForat; import java.util.arrays; import java.utitil.date; import; javax.servlet.http.httpservletRequest; import javax.servlet.http.httpservletResponse; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.contrelleur; org.springframework.web.bind.annotation.requestmapping; import com.google.gson.gson; import com.wimedia.model.ticket; import com.wimedia.service.articlesolrservice; import com.wimedia.service.ticketrepository; com.wimedia.service.ticketRepositorySolr; import com.wimedia.utils.getrandomstr; import com.wimedia.utils.signaturebean; import com.wimedia.utils.weixin.weixinutil; / ** * * * <p> Projet: Mryl_phone_v2 </p> * * <p> Package: com.wimedia.controller </p> * * <p> Description: WECHAT Share Controller </p> * * <p> Company: Wimedia </p> * * @ athor: Songjia * * @ Date: 2016-7-15 09:34:10 Am * * / @ Controller @ requestmapping ("/ WeixinshaReConTroller WeixinshareController {@autowired privé ticketRepositorySolr ticketRepositorySolr; @RequestMapping ("/ getSignature") public String getSIGNATURE (HttpServLetRequest Request, HttpServletResponse Response) lève ioException, parseException {// obtenir la chaîne de page de signature Url = request.getParamètre ("url"); SimpledateFormat Format = new SimpledateFormat ("Yyyy-mm-dd hh: mm: ss"); // Obtenez la balise de la base de données et vérifiez si la balise expire. Ticket OldTicket = TicketRepositorySolr.GetTticketByid ("20160114wiImdIamryLSong1152"); if (oldTicket == null) {// La première fois que vous accédez, la balise n'existe pas. ExecuteTticket (réponse, "1", URL, format); retourner null; } else {// La balise existe, déterminez si la balise est chronométrée de la chaîne oldacquiretime = oldticket.getacquiretime (); Long Difference = format.Parse (format.format (new Date ())). GetTime () - Format.Parse (OldAcQuiretime) .getTime (); if (différence> 71000000) {// Le délai d'expiration de la balise, accédez au serveur WeChat pour demander le délai d'expiration de la balise est de 7200 secondes (72000000 millisecondes) ExecuteTticket (réponse, "2", URL, format); retourner null; } else {// La balise n'a pas chronométré / ** * Remarques * 1. Le non-claim et l'horodatage utilisé pour la signature doivent être les mêmes que le non-clos et l'horodatage dans wx.config. * 2. L'URL utilisée pour la signature doit être l'URL complète de la page appelant l'interface JS. * 3. Pour des raisons de sécurité, les développeurs doivent implémenter la logique de signature du côté du serveur. * **** Il est facile de faire des erreurs lors de la configuration de la signature en fonction du point 1. Vous devez passer le non-claire et l'horodatage qui génère le billet pour le client *** * / String Signature = Signature (OldTicket.GetNoNCETR (), OldTicket.GetTimeStamp (), OldTicket.GetNonCestr (), URL); SignatureBean SignatureBean = new SignatureBean (); SignatureBean.SetNoncestr (OldTicket.GetNonCetr ()); SignatureBean.SetSignature (signature); SignatureBean.SettimeStamp (OldTicket.GettimeStamp ()); SignatureBean.SetUrl (URL); Response.SetContentType ("Text / HTML; charSet = UTF-8"); réponse.getWriter (). print (new gson (). tojson (SignatureBean)); retourner null; }}} / ** * * <p> Projet: mryl_phone_v2 </p> * * <p>: mryl_phone_v2 </p> * * <p> Description: La méthode pour mettre à jour et obtenir des billets. Parce que le SOLR est utilisé, la mise à jour est la même que la nouvelle. S'il n'y a pas d'identification, il sera ajouté. S'il est responsable, mise à jour </p> * * <p> Company: wiimedia </p> * * @ athor: Songjia * * @ Date: 2016-7-15 09:45:00 AM * * / public void ExecuteTticket (httpservletResponse Response, String Flag Getrandomstr (); String NONCESTR = RandomStr.getRandomString (15); // Obtenez l'horodatage de la chaîne d'horodatage de signature = long.toString (System.currentTimemillis ()); // demande AccessToken String AccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=Client_Credential&appid=your appid & secret = votre clé"; String tokenjson = weixinutil.httprequest (AccessTokenUrl, "get", null); Gson gson = new gson (); ShareAccess_token token = gson.fromjson (tokenjson, shareAccess_token.class); String to = token.getAccess_token (); // Obtenez la chaîne de balise urlTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getTicket?access_token=" + à + "& type = jsapi"; String ticketjson = weixinutil.httprequest (urlticket, "get", null); Ticket Ticket = gson.fromjson (TicketJson, Ticket.class); String t = Ticket.GetTicket (); // String UUID = UUID.RandomuUid (). ToString (). Trim (). RempaceALL ("-", ""); // mon ID de billet est un temps d'acquisition de chaîne morte = format.format (new Date ()); Ticket.SetTid ("20160114wiimmediamrylsong1152"); ticket.setacquiretime (acquiretime); ticket.settimestamp (horodat); ticket.setNonCestr (nonCest); // Parce que le SOLR est utilisé, la méthode de mise à jour et d'ajout est la même. Vous pouvez le modifier en fonction de vos besoins spécifiques. Cet article ne publiera plus de code. if (Flag.equals ("2")) {TicketRepositorySolr.AddTickettoSolr (Ticket); } else {ticketRepositorySolr.AddtickettoSolr (ticket); } / ** * Remarques * 1. Le non-claim et l'horodatage utilisé pour la signature doivent être les mêmes que le non -cestr et l'horodatage dans wx.config. * 2. L'URL utilisée pour la signature doit être l'URL complète de la page appelant l'interface JS. * 3. Pour des raisons de sécurité, les développeurs doivent implémenter la logique de signature du côté du serveur. * * Selon le point 1, il est facile de faire des erreurs lors de la configuration de la signature. Vous devez passer le non-clos et l'horodatage qui génère le billet pour le client * * / String Signature = Signature (T, horodatage, nonCestr, URL); SignatureBean SignatureBean = new SignatureBean (); SignatureBean.SetNoncestr (non -cestr); SignatureBean.SetSignature (signature); SignatureBean.Settimestamp (horodatage); SignatureBean.SetUrl (URL); Response.SetContentType ("Text / HTML; charSet = UTF-8"); réponse.getWriter (). print (new gson (). tojson (SignatureBean)); } / ** * * <p> Projet: mryl_phone_v2 </p> * * <p>: mryl_phone_v2 </p> * * <p> Description: Signature basée sur les balises, horodatage, clés, urls </p> * * <p> Company: wiiMedia </p> * * @ athor: Songjia * * @ date: 2016-15 09:37:13 Amor: * * * @ date: 2016-7-15 Signature de chaîne privée (chaîne jsapi_ticket, horodatage de chaîne, String nonCest, URL de chaîne) {jsapi_ticket = "jsapi_ticket =" + jsapi_ticket; TimeStamp = "TimeStamp =" + horodatage; noncestr = "noncestr =" + non -cestr; url = "url =" + url; String [] arr = new String [] {JSAPI_TICKET, horodatage, noncestr, url}; // Trier le jeton de dictionnaire, horodatage, non-claim, paramètres URL Arrays.sort (arr); StringBuilder Content = new StringBuilder (); for (int i = 0; i <arr.length; i ++) {content.append (arr [i]); if (i! = arr.length - 1) {content.append ("&"); }} MessagediGest md = null; String tmptr = null; essayez {md = messagediGest.getInstance ("sha-1"); // Splice trois chaînes de paramètres dans une chaîne pour le byte de cryptage SHA1 [] digest = md.digest (content.toString (). GetBytes ()); tmptr = bytetoStr (digest); } catch (NosuchalgorithMexception e) {e.printStackTrace (); } contenu = null; retour tmptr; } / ** * Convertir les octets en chaîne hexadécimale * * @param mbyte * @return * / private static String byteTohexstr (byte mbyte) {char [] digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', ',', ', D', ',' 8 ',' 9 ',', ',', ', D' ',', '8', '9' 'E', 'f'}; char [] temparr = nouveau char [2]; temparr [0] = numérique [(mbyte >>> 4) & 0x0f]; temparr [1] = numérique [mbyte & 0x0f]; String s = new String (temparr); retour s; } / ** * Convertir le tableau d'octet en chaîne hexadécimale * * @param bytearray * @return * / private static String bytetoStr (byte [] bytearray) {String strdigest = ""; for (int i = 0; i <bytearray.length; i ++) {strdigest + = bytetohexstr (bytearray [i]); } return strdigest; } class shareAccess_token {private String Access_token; La chaîne privée expires_in; String public getAccess_token () {return Access_token; } public void SetAccess_token (String AccessToken) {Access_token = AccessToken; } public String getExpires_in () {return expires_in; } public void setExpires_in (String expiresin) {exires_in = exireSin; }}}2. Code client.
<script type = "text / javascript"> var url = window.location.href; var ArticleId = ""; var sharetitle = "Informations médicales de demain"; var shareMgurl = ""; var userInfo = localStorage.getItem ("_ userInfo"); horodatage var; var noncestr; Var Signature; // Obtenez la signature $ .ajax ({type: "get", URL: "WeixinshareController / api / Inteface / Getsignature", // data: {Timestamp: Timestamp, noncestr: nonCestr, url: url}, data: {url: url}, fonction: fonction (data) {var objdata = json. (Data); TimeStamp = objdata.timestamp; fonction wxshare () {wx.config ({debug: false, // activer le mode de débogage, les valeurs de retour de toutes les API appelées seront alertées sur le client. L'identificateur de l'horodatage officiel du compte: l'horodatage, // requis, générer l'horodatage de la signature noncestr: noncestr, // requis, générer la chaîne aléatoire de signature Signature: signature, // requise, signature, voir l'annexe 1 jsapiliste: [`` OnMenushareAppMessage '] // La liste des interfaces de js est indiquée, et la liste des interfaces JS est une liste de js à utiliser, et la liste des interfaces JS est une liste de js à utiliser, les interfaces JS sont les interfaces 2 à utiliser, et la liste des js est indiquée 2. }); } wx.ready (function () {// Après la vérification des informations de configuration, la méthode Ready sera exécutée. Tous les appels d'interface doivent être obtenus une fois que l'interface de configuration a obtenu le résultat. // La configuration est un fonctionnement asynchrone d'un client. Peut être appelé directement sans les mettre dans la fonction prête. '', // Si le type est de la musique ou de la vidéo, vous devez fournir un lien de données, la valeur par défaut est un succès vide: function () {// Fonction de rappel exécutée après que l'utilisateur a confirmé le partage,}, annuler: function () {// la fonction de rappel exécutée après que l'utilisateur annule le partage}}); // ----------------------- "Share to Friends" wx.onmenusharetemeline ({title: 'Tomorrow Medical Information', // Partager le lien de titre: '', // lien de partage imgurl: ShareImgurl, // Partager l'icône Success: function () {// Fonction de rappel exécutée après le partage des canons utilisateur}, la fonction ();) {// Fonction de rappel exécutée après le partage des canons utilisateur}););); // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- partage}, annuler: function () {// La fonction de rappel exécutée après que l'utilisateur annule le partage}}); // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------3. Les outils et modèles requis par le serveur
① Ticket
package com.wimedia.model; billet de classe publique {String privé Tid; ticket de chaîne privé; String privé errcode; chaîne privée errmsg; La chaîne privée expires_in; Temps d'acquisition de chaînes privées; String privé NONCESTR; Timestamp de chaîne privée; Ticket public (String Tid, String Ticket, String errcode, String errmsg, String expiresIn, String AcquisitionTime, String NONCESTR, String Timestamp) {super (); this.tid = tid; this.Ticket = ticket; this.errcode = errcode; this.errmsg = errmsg; expires_in = expiresIn; this.acquiretime = acquiretime; this.Noncestr = nonCest; this.timestamp = horodatage; } public String gettid () {return tid; } public void Settid (String tid) {this.tid = tid; } public String getTicket () {return ticket; } public void Settticket (String Ticket) {this.ticket = ticket; } public String getErCode () {return errCode; } public void seterRCode (String errCode) {this.errcode = errcode; } public String getErrmsg () {return errmsg; } public void seterRmsg (String errmsg) {this.errmsg = errmsg; } public String getExpires_in () {return expires_in; } public void setExpires_in (String expiresin) {exires_in = exireSin; } public String getacQuiretime () {return AcquisitionTime; } public void SetAcQuiretime (String Acquiretime) {this.acquiretime = acquiretime; } public String getNonCestr () {return nonCest; } public void setNonCestr (String nonCestr) {this.NonCestr = nonCestl; } public String gettimestamp () {return horodatamp; } public void settimestamp (string horodatamp) {this.timestamp = horodatamp; }} ② L'entreprise ajoutée à la base de données est implémentée en fonction de vos besoins.
③ Getrandomstr
Package com.wiimedia.utils; import java.util.random; classe publique getrandomstr {/ ** * * <p> Projet: mryl_phone_v2 </p> * * <p>: mryl_phone_v2 * @ Date: 2016-7-14 11:14:46 AM * * / public String getrandomString (int longueur) {String Base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; Aléatoire aléatoire = nouveau aléatoire (); StringBuffer sb = new StringBuffer (); pour (int i = 0; i <longueur; i ++) {int SB.APPEND (Base.Charat (numéro)); } return sb.toString (); }}④ Signaturebean
package com.wimedia.utils; public class SignatureBean {private String NONCESTR; URL de chaîne privée; Timestamp de chaîne privée; Signature de chaîne privée; Public String getNonCestr () {return nonCest; } public void setNonCestr (String nonCestr) {this.NonCestr = nonCestl; } public String getUrl () {return url; } public void setUrl (string url) {this.url = url; } public String gettimestamp () {return horodatamp; } public void settimestamp (string horodatamp) {this.timestamp = horodatamp; } public String getSignature () {return Signature; } public void setSignature (String Signature) {this.signature = signature; }}⑤ Weixinutil
Package com.wimedia.utils.weixin; import java.io.bufferedeader; import java.io.inputstream; import java.io.inputstreamreader; import java.io.outputstream; import java.net.connectException; import java.net.url; import javax.net.sssl.httpsurlconnection; import; javax.net.ssl.sslcontext; Importer javax.net.ssl.sslsocketfactory; Importer javax.net.ssl.trustManager; / ** * * <p> Projet: Mryl_Phone_v2 * <p> Compagnie: wiimedia </p> * * @ athor: Songjia * * @ Date: 2016-7-15 09:37:13 AM * * / Classe publique Weixinutil {/ ** * Adresse de demande HTTPS HTTP de l'objet JSON via jsonObject.get (key)) * / public static String httpRequest (string requestUrl, string requestMethod, string outputstr) {stringBuffer tamper = new StringBuffer (); essayez {// créer un objet SSLContext et initialiser TrustManager [] tm = {new MyX509TrustManager ()}; SslContext sslcontext = sslcontext.getInstance ("ssl", "sunjsse"); sslcontext.init (null, tm, new java.security.securerAndom ()); // Obtenez l'objet SSLSocketFactory de l'objet SSLContext ci-dessus sslSocketFactory ssf = sslContext.getSocketFactory (); Url url = nouvelle URL (requestUrl); HttpSurlConnection httpurlConn = (httpSurlConnection) url.openconnection (); httpurlConn.SetsSLSocketFactory (SSF); httpurlConn.setDoOutput (true); httpurlConn.setDoInput (true); httpurlConn.seTUsecaches (false); // Définir la méthode de la demande (get / post) httpurlConn.setRequestMethod (requestMethod); if ("get" .equalsIgnoreCase (requestMethod)) httpurlConn.connect (); // Lorsqu'il y a des données qui doivent être soumises si (null! = OutputStream outputStream = httpurlConn.getOutputStream (); // Portez l'attention au format de codage pour empêcher la chinois barbble outporestream.write (outputstr.getbytes ("utf-8")); outputstream.write. ht-streamine inputStreamReader = new inputStreamReader (inputStream, "utf-8"); tampon.close (); "";;}4. À ce stade, la fonction de partage a été développée, mais vous rencontrerez de nombreux problèmes lors de la génération de signature. Voici quelques méthodes de dépannage pour les défaillances de WX.Config.
① Confirmez si la signature générée est correcte dans le http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign fourni par WeChat pour vérification
② Si le non-claire, horodatage utilisé dans WX.Config est cohérent avec le non-claire et l'horodatage correspondants utilisés pour signer ... comme ci-dessus (1. Code du serveur)
(Il est possible qu'en raison du problème de l'ordre de chargement de la page JS, la signature générée par le serveur, le non-cistres et l'horodatage n'ont pas été obtenues dans wx.config).
③ Confirmez que l'URL est l'URL complète de la page, y compris la partie Get Paramètre qui doit être supprimée du # suivant # suivant
④ L'Apid en config est-il cohérent avec l'AppID utilisé pour obtenir JSAPI_TICKET?
⑤ Error {errmsg: config: ok} est le rendement normal du mode de débogage et désactiver le mode de débogage. D'ACCORD
wx.config débogue: false,
Cet article a été compilé dans "Résumé du didacticiel Android WeChat Development" et "Java WeChat Development Tutorial Résumé" accueille tout le monde pour apprendre et lire.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.