Desarrollo de funciones de intercambio de WeChat
Después de un día, he desarrollado la función de enviar WeChat a amigos y compartirlo al círculo de mis amigos. Lo compartiré contigo aquí para evitar los desvíos.
1. Programa del lado del servidor
paquete com.wimedia.controller; import java.io.ioException; import java.security.messageGest; import java.security.nosuchalgorithmexception; import java.text.parseException; import java.text.sempledateformat; import java.util.atils; import java.atil.util. javax.servlet.http.httpservletRequest; import javax.servlet.http.httpservletResponse; import org.springframework.beanss.factory.annotation.aUtowired; import org.springfframework.stereotype.controller; import; org.springframework.web.bind.annotation.requestMapping; import com.google.gson.gson; import com.wimedia.model.ticket; import com.wimedia.service.articlesrSservice; import.wimedia.wiChicketrepository; com.wimedia.utils.getrandomstr; import com.wimedia.utils.signatureBean; import com.wimedia.utils.weixin.weixinutil;/** * * * <p> Project: mryl_phone_v2 </p> * * <p> paquete: com.wimedia.controller </p> * * <p> Descripción: Descripción: *<p>Company:Wimedia</p> * *@Athor:SongJia * *@Date:2016-7-15 09:34:10 am * */@Controller@RequestMapping("/WeixinshareController/Api/Inteface")public class WeixinshareController { @Autowired private TicketRepositorySolr ticketRepositorySolr; @RequestMapping ("/getSignature") cadena pública getSignature (httpservletRequest solicitud, respuesta httpservletreSponse) lanza ioexception, parseException {// get de la página de firma cadena url = request.getParameter ("url"); SimpleDateFormat Format = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); // Obtenga la etiqueta de la base de datos y verifique si la etiqueta expira. Ticket OldTicket = TicketRepositorySOlR.GetticketByid ("20160114wiimmediMrylsong1152"); if (oldTicket == null) {// La primera vez que accede, la etiqueta no existe. ejecutTicket (respuesta, "1", url, formato); regresar nulo; } else {// La etiqueta existe, determine si la etiqueta está programada para la cadena OldAcquiretime = OldTicket.GetAcQuiretime (); Long Difference = Format.Parse (Format.Format (New Date ())). GetTime ()-Format.Parse (OldAcquiretime) .GetTime (); if (diferencia> 71000000) {// El tiempo de espera de la etiqueta, vaya al servidor WeChat para solicitar el tiempo de espera de la etiqueta es de 7200 segundos (72000000 milisegundos) ExecutEticket (respuesta, "2", url, formato); regresar nulo; } else {// La etiqueta no ha programado tiempo/*** Notas* 1. La marca de tiempo sin cocos y la marca utilizada para la firma debe ser la misma que la marca de tiempo sin capas y el tiempo en wx.config. * 2. La URL utilizada para la firma debe ser la URL completa de la página que llama a la interfaz JS. * 3. Por razones de seguridad, los desarrolladores deben implementar la lógica de firma en el lado del servidor. ***** Es fácil cometer errores al configurar la firma de acuerdo con el punto 1. Debe pasar la marca de tiempo y la marca de tiempo que genera el ticket al cliente ****/ String Signature = Signature (OldTicket.getticket (), OldTicket.GetTimestamp (), OldTicket.getNoncestr (), url);; SignatureBean SignatureBean = new SignatureBean (); SignatureBean.SetNoncestr (OldTicket.getNoncestr ()); SignatureBean.SetSignature (firma); SignatureBean.SettimeStamp (OldTicket.GetTimestamp ()); SignatureBean.SetUrl (URL); respuesta.setContentType ("text/html; charset = utf-8"); Response.getWriter (). print (new Gson (). Tojson (SignatureBean)); regresar nulo; }}}/** * * <p> Proyecto: Mryl_Phone_V2 </p> * * <p>: mryl_phone_v2 </p> * * <p> Descripción: el método para actualizar y obtener boletos. Debido a que se usa el SOLR, la actualización es la misma que la nueva. Si no hay ID, se agregará. Si es responsable, actualice </p> * * <p> Compañía: Wiimedia </p> * *@Athor: SongJia * *@Fecha: 2016-7-15 09:45:00 am * */public void ExecutEticket (httpServletResponse Respuesta, String Flag, String Url, SimpledeFormat Format) tira IoException {// Get the Strand The Singrand The SiltstrArtRaN GetRandomStr (); Cadena noncestr = randomstr.getRandomString (15); // Obtenga la cadena de marca de tiempo de firma TimeStamp = Long.ToString (System.CurrentTimemillis ()); // Solicitar accesstoken string accessTokenurl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=your appid & secret = su clave"; Cadena tokenjson = weixinutil.httprequest (accessTokenurl, "get", null); Gson gson = new Gson (); ShareAccess_Token Token = Gson.FromJson (Tokenjson, ShareAccess_Token.Class); Cadena a = token.getAccess_token (); // Obtenga la cadena de etiqueta 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); Cadena t = ticket.getticket (); // string uuid = uuid.randomuuid (). ToString (). Trim (). ReplaceAll ("-", ""); // Mi ID de boleto es un tiempo de adquisición de cadena muerta = format.format (nueva fecha ()); Ticket.settid ("20160114wiimmediamrylsong1152"); Ticket.SetAcquiretime (adquiriendo tiempo); Ticket.settimestamp (marca de tiempo); Ticket.setNoncestr (no cuestr); // Debido a que se usa el SOLR, el método de actualización y adición es el mismo. Puede modificarlo de acuerdo con sus necesidades específicas. Este artículo ya no se postula. if (flag.equals ("2")) {ticketRepositorySolr.AddTicketTosolr (Ticket); } else {ticketRepositorySolr.AddTicketTosolr (Ticket); } /*** Notas* 1. La marca de tiempo sin cocción y el tiempo utilizada para la firma debe ser la misma que la marca de tiempo sin cocos y la marca de tiempo en wx.config. * 2. La URL utilizada para la firma debe ser la URL completa de la página que llama a la interfaz JS. * 3. Por razones de seguridad, los desarrolladores deben implementar la lógica de firma en el lado del servidor. * * Según el punto 1, es fácil cometer errores al configurar la firma. Debe pasar la marca de tiempo sin captura y tiempo que genera el ticket al cliente * */ String Signature = Signature (T, Timestamp, Non -Cestr, URL); SignatureBean SignatureBean = new SignatureBean (); SignatureBean.SetNoncestr (no cuell); SignatureBean.SetSignature (firma); SignatureBean.Settimestamp (marca de tiempo); SignatureBean.SetUrl (URL); respuesta.setContentType ("text/html; charset = utf-8"); Response.getWriter (). print (new Gson (). Tojson (SignatureBean)); } /** * *<p>Project:mryl_phone_v2</p> * *<p>:mryl_phone_v2</p> * *<p>Description:Signature based on tags, timestamps, keys, URLs</p> * *<p>Company:Wiimedia</p> * *@Athor:SongJia * *@Date:2016-7-15 09:37:13 am * */ String de cadena privada (String JSAPI_Ticket, String Timestamp, String Non -Cestr, String Url) {jsapi_ticket = "jsapi_ticket =" + jsapi_ticket; timestamp = "timestamp =" + timestamp; noncestr = "noncestr =" + Non -Cestr; url = "url =" + url; String [] arr = new String [] {jsapi_ticket, timestamp, non -coestr, url}; // clasificar el token del diccionario, la marca de tiempo, la matriz de parámetros de la URL, la URL.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 ("&"); }} MessageGest md = null; Cadena tmpStr = null; intente {md = messageDigest.getInstance ("sha-1"); // empalme tres cadenas de parámetros en una cadena para byte de cifrado Sha1 [] digest = md.digest (content.toString (). GetBytes ()); tmpStr = bytetoStr (digest); } Catch (nosuchalgorithMexception e) {E.PrintStackTrace (); } content = null; return tmpStr; } / ** * Convierta bytes a 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', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', '. 'E', 'f'}; char [] temparr = new Char [2]; temparr [0] = dígito [(mbyte >>> 4) y 0x0f]; temparr [1] = dígito [mbyte & 0x0f]; Cadena S = nueva cadena (temparr); regreso s; } / ** * Convertir la matriz de byte a una cadena hexadecimal * * @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; cadena privada expires_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 del cliente.
<script type = "text/javaScript"> var url = window.location.href; var articationId = ""; var sharetitle = "Información médica del mañana"; var shareMgurl = ""; var userInfo = localStorage.getItem ("_ UserInfo"); var timestamp de var; var no cuatr; firma var; // Obtenga la firma $ .AJAX ({type: "get", url: "weixInsharecontroller/api/inteface/getSignature", // data: {timestamp: timestamp, noncestr: noncestr, url: url}, data: {url: url}, éxito: function (data) {var objData = json.parse (data); Timestamp = objData.timestamp; función wxshare () {wx.config ({debug: false, // activar el modo de depuración, los valores de retorno de todas las API llamadas se alertarán en el cliente. Para ver los parámetros aprobados, puede abrirlos en el lado de la PC. La información del parámetro se imprimirá a través del registro y solo se imprimirá en el lado de la PC. Appid: 'Su appid', // es el mismo que se requerirá el Tarquio, el que se requerirá, el Tarqueo. de la marca de tiempo oficial de la cuenta: la marca de tiempo, // requerida, genere la marca de tiempo de la firma no encestrada: non -cestr, // requerida, genere la cadena aleatoria de firma firma: firma, // requerida, firmación, consulte el Apéndice 1 jsapilist: ['OnMenusharAppMessage'] // Se requiere la lista de js interfaces que se utilizarán y se utiliza la lista de todos los js. }); } wx.ready (function () {// Después de la verificación de información de configuración, se ejecutará el método listo. Se deben obtener todas las llamadas de interfaz después de que la interfaz de configuración obtenga el resultado. // config es una operación asíncrona de un cliente de un cliente. sin ponerlos en la función listo. El tipo es música o video, debe proporcionar un enlace de datos, el valor predeterminado es el éxito vacío: function () {// función de devolución de llamada ejecutada después de que el usuario confirme el intercambio, cancel: function () {// función de devolución de llamada ejecutada después del usuario cancela el intercambio}}); // ----------------------- "Compartir a Friends" wx.onmenusharetimeline ({title: 'Tomorrow Medical Information', // Compartir el enlace de título: '', // Compartir enlace imgurl: shareMgurl, // share icon éxito: function () {// función de devolución de llamada ejecutada después del usuario confirma compartir}, cancelar: function () {// Callback Función Ejecutada después del usuario puede Crops Ccelcels}); // --------------------------------------------------------------------------------------------------------------------------------------------------------------- compartir}, cancelar: function () {// La función de devolución de llamada ejecutada después del usuario cancela el intercambio}}); // --------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------3. Las herramientas y modelos requeridos por el servidor
① Boleto
paquete com.wimedia.model; ticket de clase pública {private string tid; boleto de cadena privada; String private Errcode; cadena privada errmsg; cadena privada expires_in; Tiempo de adquisición de cadenas privadas; cadena privada sin cocuración; marca de tiempo de cadena privada; Public Ticket (String Tid, String Ticket, String Errcode, String Errmsg, String ExpiratesIn, String AdquisitionTime, String Non -Cestr, String TimeStamp) {super (); this.tid = tid; this.ticket = ticket; this.errcode = errcode; this.errmsg = errmsg; expires_in = expiresin; this.acquiretime = adquiretime; this.noncestr = noncestr; this.timestamp = timestamp; } public String getTid () {return tid; } public void settid (string tid) {this.tid = tid; } public String getTicket () {Ticket de retorno; } public void setticket (ticket de cadena) {this.ticket = ticket; } public String getErRCode () {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) {expires_in = expiresIn; } public String getAcQuiretime () {return adquisitiontime; } public void setACQUIRETime (String adquirTime) {this.acquiretime = adquiretime; } public String getNonCestr () {return no cuestr; } public void setnoncestr (string non -coestr) {this.noncestr = non -coestr; } public String getTimestamp () {return timeStamp; } public void settimestamp (string timestamp) {this.timestamp = timestamp; }} ② El negocio agregado a la base de datos se implementa de acuerdo con sus necesidades.
③ Getrandomstr
paquete com.wiimedia.utils; import java.util.random; public class getRandomstr {/** * * <p> Project: mryl_phone_v2 </p> * * <p>: mryl_phone_v2 </p> * * * <p> Descripción: Generar una string instantil </p> * * * * <p> Company: wiimedia </p> *@p> * *@Fecha: 2016-7-14 11:14:46 am * */ public String getRandomString (int long) {string base = "abcdefghijklmnopqrstuvwxyz0123456789"; Aleatorio aleatorio = new Random (); StringBuffer sb = new StringBuffer (); for (int i = 0; i <longitud; i ++) {int number = random.nextint (base.length ()); sb.append (base.charat (número)); } return sb.ToString (); }}④ SignatureBean
paquete com.wimedia.utils; public class SignatureBean {private String no cuestr; URL de cadena privada; marca de tiempo de cadena privada; firma de cadena privada; public String getNonCestr () {return no cuestr; } public void setnoncestr (string non -coestr) {this.noncestr = non -coestr; } public String getUrl () {return url; } public void seturl (url de cadena) {this.url = url; } public String getTimestamp () {return timeStamp; } public void settimestamp (string timestamp) {this.timestamp = timestamp; } cadena pública getSignature () {return Signature; } public void setSignature (String Signature) {this.signature = Signature; }}⑤ weixinutil
paquete 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.httpsurlettion; javax.net.ssl.sslcontext; import javax.net.ssl.sslsocketfactory; import javax.net.ssl.trustmanager;/** * * * <p> Project: mryl_phone_v2 </p> * * <p>: mryl_phone_v2 </p> * * * <p>: descripción de la interfaz de plataforma pública </p> * * * * <p> Compañía: Wiimedia </p> * * @Athor: SongJia * * @fecha: 2016-7-15 09:37:13 am * */public class weixinutil {/** * Iniciar la solicitud Https y obtener el resultado * * @param Solicitud de solicitud * @Param Solicitud de solicitud de solicitud (get, post) * @param Data de salida * @@Param. del objeto json a través de jsonObject.get (key)) */ public static string httprequest (string requestUrl, string requitMethod, string outputStr) {StringBuffer buffer = new StringBuffer (); Pruebe {// cree el objeto SSLContext e inicialice TrustManager [] tm = {new MyX509TrustManager ()}; SslContext sslContext = sslContext.getInstance ("SSL", "SunJSse"); sslContext.init (NULL, TM, New Java.Security.SeCurerandom ()); // Obtenga el objeto SSLSocketFactory del objeto SSLContext anterior SSLSocketFactory ssf = sslContext.getSocketFactory (); Url url = nueva url (requestUrl); Httpsurlconnection httpurlconn = (httpsurlconnection) url.openconnection (); httpurlconn.setsslsocketFactory (SSF); httpurlconn.setDoOutput (true); httpurlconn.setDoInput (verdadero); httpurlconn.setUsecaches (falso); // Establecer el método de solicitud (get/post) httpurlconn.setRequestMethod (requestMethod); if ("get" .equalSignorecase (requestMethod)) httpurlconn.connect (); // Cuando hay datos que deben enviarse si (NULL! = OutputStream OutputStream = httpurlConn.getOutputStream (); // Preste atención al formato de codificación para evitar que el chino acumule la salida de la luz. httpurlconn.getInputStream (); InputStreamReader.CLOSE ();4. En este punto, se ha desarrollado la función de intercambio, pero encontrará muchos problemas al generar firma. Aquí hay algunos métodos de solución de problemas para fallas WX.Config.
① Confirme si la firma generada es correcta en http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign proporcionado por WeChat para verificación
② Si la marca de tiempo sin captura utilizada en wx.config es consistente con la marca no captura y la marca de tiempo utilizada para firmar ... como se indicó anteriormente (1. Código del servidor)
(Es posible que debido al problema del orden de carga de la página JS, la firma generada por el servidor, la no captura y la marca de tiempo no se obtuvieran en wx.config).
③ Confirme que la URL es la URL completa de la página, incluida la parte del parámetro GET que debe eliminarse del siguiente #
④ ¿El APPID en config es consistente con la aplicación utilizada para obtener jsapi_ticket?
⑤ Error {errmsg: config: ok} es la retorno normal del modo de depuración y apague el modo de depuración. DE ACUERDO
wx.config debug: falso,
Este artículo se ha compilado en "Resumen del tutorial de desarrollo de WeChat Android", y el "Tutorial de Desarrollo Java WeChat" dan la bienvenida a todos a aprender y leer.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.