Desenvolvimento da função de compartilhamento do WeChat
Depois de um dia, desenvolvi a função de enviar o WeChat para os amigos e compartilhá -lo ao meu círculo de amigos. Vou compartilhar com você aqui para evitar desvios.
1. Programa do lado do servidor
pacote com.wimedia.controller; importar java.io.ioException; importar java.security.Messagedigest; importar java.security.nosuchalgorithMexception; import java.text.parseexception; imporjat; javax.servlet.http.httpServletRequest; importar javax.servlet.http.httpServletResponse; importar org.springframework.beans.factory.annotation.autowired; import.springframework.stereotype.Controller; org.springframework.web.bind.annotation.requestmapping; importar com.google.gson.gson; importação com.wimedia.model.Ticket; import com.wimedia.service.articlesolrservice com.wimedia.service.ticketRepositorySolr; importar com.wimedia.utils.getrandomstr; import com.wimedia.utils.signaturebean; importar com.wimedia.utils.weixin.weixinutil;/** * * * <p> Project: mryl_phone_phone_phone_phone_phone_phone_phone_phone_phone_phone_phone_phone_phone_Phone_Phone_Phone_Phone_Phone. *<p> Pacote: com.wimedia.controller </p> * *<p> Descrição: WeChat Share Controller </p> * *<p> Empresa: wimedia </p> * *@athor: Songjia * *@Data: 2016-7-15 09:34:10 */controlador@@sappMapping (2016-7-15 09:34:10 * */controlador@@requestMapping (2016-7-11 WeixinshareController {@AUTOWIRED PRIVADO TicketRepositorySolr ticketRepositorySolr; @RequestMapping ("/GetSignature") Public String GetSignature (solicitação httpServletRequest, httpServletResponse resposta) lança a ioException, parseException {// Obter link de assinatura Link String URL = request.getParameter ("url"); SimpledateFormat formato = new SimpleDateFormat ("AAAA-MM-DD HH: MM: SS"); // Obtenha a tag do banco de dados e verifique se a tag expira. Ticket OldTicket = TicketRepositorySolr.getticketbyId ("20160114WiImediamrylSong1152"); if (OldTicket == NULL) {// Na primeira vez que você acessa, a tag não existe. executEticket (resposta, "1", URL, formato); retornar nulo; } else {// A tag existe, determine se a tag é cronometrada string antigoCquiretime = OldTicket.getAcquiretime (); longa diferença = format.parse (format.format (new date ())). gettime ()-format.parse (antigoCireTime) .gettime (); if (diferença> 71000000) {// O tempo limite da tag, vá para o servidor WeChat para solicitar que o tempo limite da etiqueta tenha 7200 segundos (72000000 milissegundos) executeticket (resposta, "2", URL, formato); retornar nulo; } else {// A tag não cronometrou/*** Notas* 1. O não -CESTRO e o registro de data e hora usados para assinatura devem ser os mesmos que o não -CEST e o registro de data e hora no wx.config. * 2. O URL usado para assinatura deve ser o URL completo da página chamando a interface JS. * 3. Por razões de segurança, os desenvolvedores devem implementar a lógica de assinatura no lado do servidor. ***** É fácil cometer erros ao configurar a assinatura de acordo com o ponto 1. Você precisa passar pelo não -restos e registro de data e hora que gera o bilhete para o cliente ****/ string assinatura = assinatura (OldTicket.getTicket (), urlTicket.gettimestamp (), OldTicket.getNoncest (), url); SignatureBean SignatureBean = new SignatureBean (); SignatureBean.SetNonceST (OldTicket.getNoCest ()); SignatureBean.SetSignature (assinatura); SignatureBean.setTimestamp (OldTicket.getTimestamp ()); SignatureBean.Seturl (URL); Response.setContentType ("Texto/html; charset = utf-8"); Response.getWriter (). Print (new Gson (). Tojson (SignatureBean)); retornar nulo; }}}/** * * <p> Projeto: mryl_phone_v2 </p> * * <p>: mryl_phone_v2 </p> * * <p> Descrição: o método para atualizar e obter tickets. Como o Solr é usado, a atualização é a mesma que a nova. Se não houver identificação, será adicionado. If it is responsible, update</p> * *<p>Company:Wiimedia</p> * *@Athor:SongJia * *@Date:2016-7-15 09:45:00 am * */ public void executeTicket(HttpServletResponse response,String flag,String url,SimpleDateFormat format) throws IOException{ //Get the signature and then the string GetRandomStr randomStr = new GetRandomstr (); String noncestr = aleatomstr.getrandomstring (15); // Obtenha o timestamp de assinatura Timestamp = Long.ToString (System.CurrentTimemillis ()); // Solicite AccessToken String AccessTokenurl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=Ur Appid & Secret = Your Key"; 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 (); // obtenha a tag string urlticket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+a+"& 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 (). Replaceall ("-", ""); // meu ID do ingresso é um tempo de aquisição de string morto = format.format (new Date ()); ticket.settid ("20160114WiImediamrylSong1152"); ticket.setAcquiretime (Aquisição); ticket.settimestamp (registro de data e hora); ticket.setNonceST (não -CEST); // Como o Solr é usado, o método de atualização e adição é o mesmo. Você pode modificá -lo de acordo com suas necessidades específicas. Este artigo não será mais postar o código. if (flag.equals ("2")) {ticketRepositorySolr.addtickettosolr (ticket); } else {ticketRepositorySolr.addtickettosolr (ticket); } /*** NOTAS* 1. O não -CEst e o registro de data e hora usado para assinatura deve ser o mesmo que o não -CEST e o timestamp no wx.config. * 2. O URL usado para assinatura deve ser o URL completo da página chamando a interface JS. * 3. Por razões de segurança, os desenvolvedores devem implementar a lógica de assinatura no lado do servidor. * * De acordo com o ponto 1, é fácil cometer erros ao configurar a assinatura. Você precisa passar pelo não -cesto e no registro de data e hora que gera o ticket para o cliente * */ string assinatura = assinatura (t, registro de data e hora, não -cest, URL); SignatureBean SignatureBean = new SignatureBean (); SignatureBean.setNonceST (não -CEST); SignatureBean.SetSignature (assinatura); SignatureBean.setTimestamp (Timestamp); SignatureBean.Seturl (URL); Response.setContentType ("Texto/html; charset = utf-8"); Response.getWriter (). Print (new Gson (). Tojson (SignatureBean)); }/** * * <p> Projeto: mryl_phone_v2 </p> * * <p>: mryl_phone_v2 </p> * * <p> Descrição: assinatura baseada em tags, registro de data e hora, keys, Urls </p> * * <p> Empresa: Wiimedia </p> *@ Signature String Private (String JSAPI_TICKET, String Timestamp, String Non -Cest, String URL) {JSAPI_TICKET = "JSAPI_TICKET =" + JSAPI_TICKET; Timestamp = "Timestamp =" + Timestamp; noncestr = "noncestr =" + não -cest; url = "url =" + url; String [] arr = new String [] {JSAPI_TICKET, TIMESTAMP, NONCEST, URL}; // Classifica o token de dicionário, o registro de data e hora, os parâmetros de URL, os parâmetros de 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 tmpstr = null; tente {md = Messagedigest.getInstance ("sha-1"); // emenda de três seqüências de parâmetros em uma string para sha1 de criptografia byte [] digery = md.digest (content.toString (). GetBytes ()); tmpstr = bytetostr (Digest); } catch (nosuchalgorithMexception e) {e.printStackTrace (); } content = null; retornar tmpstr; } /** * Convert bytes to hexadecimal string* * @param mByte * @return */ private static String byteToHexStr(byte mByte) { char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'f'}; char [] temparr = novo char [2]; temparr [0] = dígito [(mbyte >>> 4) e 0x0f]; temparr [1] = dígito [mbyte & 0x0f]; String s = new string (temparr); retorno s; } / ** * Converta a matriz de bytes em string hexadecimal * * @param bytearray * @return * / string estática privada bytetostr (byte [] bytearray) {string strDigest = ""; for (int i = 0; i <bytearray.length; i ++) {strDigest+= bytetoHexstr (bytearray [i]); } retornar strDigest; } classe shareaccess_token {private string access_token; String privada expira_in; public String 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) {expires_in = expiresin; }}}2. Código do cliente.
<script type = "text/javascript"> var url = window.location.href; var artigoId = ""; var sharetitle = "Informações médicas de amanhã"; var shareImGurl = ""; var userInfo = localStorage.getItem ("_ userInfo"); var timestamp; var noncestr; var assinatura; // obtenha a assinatura $ .ajax ({type: "get", url: "weixinsharecontroller/api/inteface/getSignature", // dados: {timestamp: timestamp, não -cest: não -cest, (url: url}: data: {url: url}, sucess: function (dados) {data: dates; Timestamp = objdata.timestamp; function wxshare () {wx.config ({debug: false, // LIGUE o modo de depuração, os valores de retorno de todas as APIs chamados serão alertados no cliente. Para visualizar os parâmetros passados, você pode abri-los no lado do pc. identifier of the official account timestamp:timestamp, // Required, generate the timestamp of the signature nonceStr: noncestr, // Required, generate the random string of signature signature: signature, // Required, signing, see Appendix 1 jsApiList: [ 'onMenuShareAppMessage' ] // Required, list of JS interfaces to be used, and list of all JS interfaces is shown in Appendix 2 }); } wx.ready (function () {// Após a verificação da informação de configuração, o método pronto será executado. Todas as chamadas de interface devem ser obtidas após a interface de configuração obter o resultado. gatilhos, eles podem ser chamados diretamente sem colocá-los na função pronta. DATAURL: '', // Se o tipo for música ou vídeo, você precisará fornecer um link de dados, o padrão é o sucesso vazio: function () {// Função de retorno de chamada executada após o usuário confirmar o compartilhamento,}, cancel: function () {// função de retorno de chamada executada após o usuário cancelar o compartilhamento}}); // ----------------------- "Compartilhe para amigos" WX.onMenusharetimeline ({Title: 'Tomorrow Medical Information', // Compartilhe o link do título: '', // Compartilhe link imgul: shareImgurl, // compartilhe icon suced: function () {// função de retorno de retorno do usuário}, cancel: function () {) {) função de retorno do usuário}, cancel: função () {) {// //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The callback function executed after the user confirms the compartilhando}, cancel: function () {// a função de retorno de chamada executada após o usuário cancelar o compartilhamento}}); // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------3. As ferramentas e modelos exigidos pelo servidor
① Ticket
pacote com.wimedia.model; ticket de classe pública {private string tid; Ticket String Private; String privada Errcode; String privada errmsg; String privada expira_in; Private String AquisitionTime; String privada não -CEST; Timestamp privado de string; Ticket público (string tid, string ticket, string errcode, string errmsg, string expiresin, string aquisição de tempo, string noncest, string timestamp) {super (); this.tid = tid; this.Ticket = Ticket; this.errcode = errcode; this.errmsg = errmsg; expires_in = expiresin; this.acquiretime = ACTIMETIME; this.NonceST = não -cest; this.timestamp = timestamp; } public string gettid () {return tid; } public void SettId (string tid) {this.tid = tid; } public string getticket () {return ticket; } public void Setticket (Ticket String) {this.Ticket = Ticket; } public String getERRRCODE () {return errcode; } public void Seterrcode (string errcode) {this.errcode = errcode; } public string geterrrsg () {return errmsg; } public void Seterrmsg (string errmsg) {this.errmsg = errmsg; } public string getExpires_in () {return expires_in; } public void setExpires_in (string expiresin) {expires_in = expiresin; } public string getAcquiretime () {return aquisitionTime; } public void setAcquireTime (string adquirtime) {this.acquiretime = adquirtime; } public string getNoCest () {return Non -CEST; } public void SetNoCest (String não -CEST) {this.NonceST = Non -CEST; } public string gettimestamp () {return timestamp; } public void setTimestamp (string timestamp) {this.timestamp = timestamp; }} ② O negócio adicionado ao banco de dados é implementado de acordo com suas necessidades.
③ Getrandomstr
pacote com.wiimedia.utils; importar java.util.random; public class Getrandomstr {/** * * <p> Projeto: mryl_phone_v2 </p> * * <p>: Mryl_phone_v2 </p> * * Descrição: gerar uma instant string </p> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *@Data: 2016-7-14 11:14:46 * */ public string getRandomString (int length) {string base = "abcdefghijklmnopqrstuvwxyz0123456789"; Aleatório aleatório = novo aleatório (); StringBuffer sb = new StringBuffer (); for (int i = 0; i <comprimento; i ++) {int number = aleatom.nextInt (base.length ()); sb.append (base.charat (número)); } return sb.toString (); }}④ SignatureBean
pacote com.wimedia.utils; public class SignatureBean {private string não -cestr; URL privado de string; Timestamp privado de string; assinatura privada de string; public String getNoCest () {return Non -Cestr; } public void SetNoCest (String não -CEST) {this.NonceST = Non -CEST; } public string geturl () {return url; } public void Seturl (String url) {this.url = url; } public string gettimestamp () {return timestamp; } public void setTimestamp (string timestamp) {this.timestamp = timestamp; } public string getSignature () {return assinatura; } public void SetSignature (String Signature) {this.signature = Signature; }}Weixinutil
package com.wimedia.utils.weixin;import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.ConnectException;import java.net.URL;import javax.net.ssl.HttpsURLConnection;import javax.net.ssl.ssslContext; importar javax.net.ssl.ssSocketFactory; importar javax.net.sssl.trustmanager;/** * * <p> Projeto: mryl_phone_v2 </p> * * <p>: MRIGLUERTL_VPOLE_V2 </P> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * <p> Empresa: Wiimedia </p> * * @athor: Songjia * * @Data: 2016-7-15 09:37:13 AM * */public class WeixInUtil {/** * Iniciar o solicitação de SetentMeTT @PendEn Solict (Get the Result * * @param solicitar o endereço * @ParamTet Solicitação (GET GET, GET, GET) * * @param request endereço * @paraming request Método (get, get,) * * @param solicitar endereço * @ParamTet Método (Get, Get,) do objeto json através de jsonObject.get (key)) */ public static string httprequest (string requesturl, string requestmethod, string outputsttr) {stringbuffer buffer = new stringBuffer (); tente {// crie objeto SSLContext e inicialize TrustManager [] tm = {new Myx509TrustManager ()}; SslContext sslContext = sslContext.getInstance ("ssl", "sunjsse"); sslContext.init (null, tm, New Java.Security.SecureRandom ()); // Obtenha o objeto SSLSocketFactory do objeto SSLContext acima SSLSocketFactory ssf = sslContext.getSocketFactory (); Url url = novo url (requesturl); HttpsurlConnection httpurlconn = (httpsurlConnection) url.openconnection (); httpurlconn.setslsocketFactory (SSF); httpurlconn.setdoOutput (true); httpurlconn.setdoinput (true); httpurlconn.setusecaches (false); // Definir método de solicitação (get/post) httpurlconn.setRequestMethod (requestMethod); if ("get" .equalsignorecase (requestmethod)) httpurlconn.connect (); // quando há dados que precisam ser enviados se (null! = OutputStream outputStream = httpurlconn.getOutputStream (); // preste atenção ao formato de codificação para impedir que o strort de strort de stringStram. httpurlconn.getInputStream (); bufferedReader.close(); inputStreamReader.close(); // Release the resource inputStream.close(); inputStream = null; httpUrlConn.disconnect(); return buffer.toString(); } catch (ConnectException ce) { ce.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return "";4. Nesse ponto, a função de compartilhamento foi desenvolvida, mas você encontrará muitos problemas ao gerar assinatura. Aqui estão alguns métodos de solução de problemas para falhas do WX.Config.
① Confirme se a assinatura gerada está correta no http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign fornecido pela WeChat para verificação
② Seja o não -restos, o registro de data e hora usado no wx.config é consistente com o não -restos e o timestamp correspondente usado para assinar ... como acima (1. Código do servidor)
(É possível que, devido ao problema da ordem de carregamento da página JS, a assinatura gerada pelo servidor, o não-CEST e o timestamp não tenham sido obtidos no WX.Config).
③ Confirme que o URL é o URL completo da página, incluindo a parte do parâmetro GET que precisa ser removida do seguinte #
④ O Appid na configuração é consistente com o Appid usado para obter JSAPI_TICKET?
⑤ Erro {Errmsg: config: ok} é o retorno normal do modo de depuração e desative o modo de depuração. OK
WX.config Debug: false,
Este artigo foi compilado no "Resumo do Tutorial de Desenvolvimento do Android WeChat" e "Java WeChat Development Tutorial Resumo" recebe todos para aprender e ler.
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.