微信开发回复空字符串_微信 字符串判断空 - CSDN
精华内容
参与话题
  • 微信开发中消息回复的代码Ste·ga·no·graph·y / stegəˈnägrəfi / (noun): the practice of concealing messages or information within other nonsecret text or data. 文字/名词:在其他非秘密文本或数据中...

    微信开发中消息回复的代码

    Ste·ga·no·graph·y / stegəˈnägrəfi / (noun): the practice of concealing messages or information within other nonsecret text or data.

    文字/名词:在其他非秘密文本或数据中隐藏消息或信息的做法。

    Synopsis: it’s possible to effectively conceal sensitive information inside language without raising eavesdropper suspicion using deep learning. This has important implications for secure communication.

    简介:可以通过深度学习有效地隐藏语言内部的敏感信息,而不会引起窃听者的怀疑。 这对安全通信具有重要意义。

    Edit 09/06/20: Check out the end of the article for a machine-generated summary! More to come in that direction soon. :)

    编辑09/06/20: 查阅本文结尾处的机器生成摘要! 不久将有更多的朝着这个方向发展。 :)

    Steganography has been used for ages to communicate information in a hidden manner. A natural question: how is this different from cryptography? Isn’t cryptography a very well-studied field in which two individuals aim to share information with each other without an eavesdropper being able to discover this information? Indeed, these two areas are very similar, but there’s an interesting property of steganography that takes information sharing to a whole different level: the information is shared without an eavesdropper even knowing that anything secret is being shared. What’s the use of, say, Shor’s algorithm (for breaking RSA encryption in polynomial time using a quantum computer) if you don’t even know what to decrypt?

    隐写术已经使用了很长时间,以隐藏​​的方式传达信息。 一个自然的问题:这与密码学有何不同? 密码学不是一个经过精心研究的领域,在这个领域中,两个人旨在彼此共享信息,而窃听者却无法发现这些信息吗? 的确,这两个领域非常相似,但是隐秘术的一个有趣特性将信息共享带到了一个完全不同的水平:即使不知道任何秘密都在共享,信息也无需窃听者即可共享。 如果您甚至不知道要解密什么,Shor的算法(用于使用量子计算机在多项式时间内打破RSA加密)的用途是什么?

    Steganography has long been associated with painting and visual art. Painters often hide signatures, self-portraits, and other secret messages within their works as an “inside joke”. One such example of this is Jackson Pollock’s “Mural”, wherein Pollock hid his entire name in plain sight in the curvatures of the work.

    隐写术长期以来与绘画和视觉艺术有关。 画家经常在自己的作品中隐藏签名,自画像和其他秘密信息,以此作为“内部笑话”。 杰克逊·波洛克(Jackson Pollock)的“壁画”就是一个这样的例子,其中波洛克在作品的曲折中清晰地隐藏了他的整个名字。

    Image for post
    Top: Mural (1943) by Jackson Pollock. Image licensed under Creative Commons CC BY-ND 2.0. Bottom: Analysis of signature by art historian Henry Adams.
    上图:杰克逊·波洛克(Jackson Pollock)的壁画(1943)。 图片根据Creative Commons CC BY-ND 2.0许可。 下:艺术史学家亨利·亚当斯 ( Henry Adams)的签名分析。

    Until recently, however, computational steganography methods for images (such as appending bits at the end of a .jpg file or applying mathematical functions to select RGB pixel values) have been easy to detect and uncover, and hand-crafted ones are difficult and not scalable.

    但是,直到最近,图像的计算隐写方法(例如,在.jpg文件末尾附加位或应用数学函数来选择RGB像素值)一直很容易检测和发现,而手工制作的方法则很困难,而且不是很容易做到。可扩展的。

    In 2017, Shumeet Baluja proposed the idea of using deep learning for image steganography in his paper “Hiding Images in Plain Sight: Deep Steganography” [1]. In this paper, a first neural network (the hiding network) takes in two images, a cover and a message. The aim of the hiding network is to create a third image, a container image, that is visually similar to the cover image and is able to be used by a second neural network (the revealing network) to reconstruct the message image via the revealed image (without any knowledge of either the original message or the original cover). The loss is defined by how similar the cover and container images are and how similar the message and revealed images are. The concept was expanded upon a few months later by Zhu et al. to allow for arbitrary data encoding into images [2]. The results were astounding: the network was able to create container images that looked very much like the cover yet allowed the revealing network to reconstruct the message very closely.

    2017年,Shumeet Baluja在他的论文“将图像隐藏在普通视域中:深度隐写术 ”中提出了使用深度学习进行图像隐写术的想法[1]。 在本文中,第一个神经网络( 隐藏网络)接收两个图像,一个是封面 ,另一个是消息 。 隐藏网络的目的是创建第三张图像,即容器图像,该图像在视觉上类似于封面图像,并且可以被第二神经网络( 显示网络)用来通过显示的图像重建消息图像。 (不了解原始邮件或原始封面)。 损失由封面和容器图像的相似程度以及消息和显示的图像的相似程度定义。 Zhu等人在几个月后扩展了这一概念。 以允许将任意数据编码为图像[2]。 结果是惊人的:网络能够创建看起来非常像封面的容器图像,但允许显示网络非常紧密地重建消息。

    Image for post
    Hiding Images in Plain Sight: Deep Steganography. 隐藏视域中隐藏图像:深度隐写术”中提出的体系结构的简化。 Image by author.图片由作者提供

    While this result was very interesting, we felt that the utility of steganography specifically for images is limited.

    尽管此结果非常有趣,但我们认为隐写术专门用于图像的用途有限。

    The question arises: what are the limits for this approach in other domains of information?

    随之而来的问题是:在其他信息领域中这种方法的局限性是什么?

    More specifically, the aim is to apply this approach to the domain of human language in the form of text and audio, which could be a stepping stone to implementing this procedure for general information.

    更具体地说,目的是将这种方法以文本音频的形式应用于人类语言领域,这可能是为通用信息实施此过程的垫脚石。

    用于文字和其他文本信息的深度隐写术 (Deep Steganography for written language and other textual information)

    Text is harder to perform steganography with: images are dense while text is sparse; images aren’t affected much by small changes in pixel values while text is greatly affected by small changes in token values. While various methods for conducting text-based steganalysis exist, they face substantial challenges: (1) classical heuristic-based approaches are often easy to decode, because they leverage fixed, easily reversible rules, and (2) current approaches do not exploit any of the structural properties of the text, resulting in hidden messages that are not semantically correct or coherent to humans.

    文本很难用以下方法进行隐写术:图像密集而文本稀疏; 图像不受像素值的微小变化的影响很大,而文本受令牌值的微小变化的影响很大。 尽管存在多种进行基于文本的隐写分析的方法,但它们都面临着严峻的挑战:(1)基于经典启发式的方法通常很容易解码,因为它们利用了固定且易于逆转的规则,并且(2)当前的方法不利用任何一种文本的结构属性,导致隐藏的消息在语义上不正确或与人类不一致。

    Recent deep learning approaches [3, 4, 5, 6] rely on using generative models to hide the “secret” text in meaningless groupings of words. Here, we want to propose using a transformer-based approach to address both problems at once. We explore using a transformer to combine the desired secret text with some human-readable, coherent cover text in order to generate a new container text that both properly encodes the hidden message inside of it and is nearly identical to the cover text, retaining the cover text’s original semantic structure and legibility. In addition to the transformer used for encoding, we leverage a second transformer model to decode the container text and recover the hidden message.

    最近的深度学习方法[3、4、5、6]依靠使用生成模型将“秘密”文本隐藏在无意义的单词组合中。 在这里,我们希望提出使用基于变压器的方法来立即解决这两个问题。 我们探索使用转换器将所需的秘密文本与一些人类可读的,连贯的封面文本结合在一起,以生成一个新的容器文本,该文本既可以正确编码其中的隐藏消息,又与封面文本几乎相同,从而保留了封面文本的原始语义结构和可读性。 除了用于编码的转换器之外,我们还利用第二个转换器模型来解码容器文本并恢复隐藏的消息。

    Image for post
    From “1D versus 2D CNN” by Nils Ackermann, which is licensed under Creative Commons CC BY-ND 4.0
    摘自Nils Ackermann的“一维vs二维CNN”,该协议获得了Creative Commons CC BY-ND 4.0的 许可

    Because transformers are big and bulky, we first tested our luck with a much simpler 1D-convolution character-based approach, CharCNN [7].

    因为变压器又大又笨,所以我们首先使用一种更简单的基于1D卷积特征的方法CharCNN [7]测试了运气。

    In this character-based approach, the idea is that a model would learn a statistical profile of character choices in a string of text and modify the characters in a way that sends a signal capturing the hidden message through character additions, substitutions, or removals.

    在这种基于字符的方法中,想法是模型将学习文本字符串中字符选择的统计信息,并以发送信号的方式通过添加,替换或删除字符捕获隐藏消息来修改字符。

    A trivial example in which the message is two bits is considered. To communicate the secret message, our function is the length of the container message modulo 4. More specifically, let l represent the number of characters in the container message. l ≡ 0 (mod 4) yields 00, l ≡ 1 (mod 4) yields 01, l ≡ 2 (mod 4) yields 10, and l ≡ 3 (mod 4) yields 11. The model would accordingly remove or add characters from the cover to communicate the secret message. In practice, we would ideally have our model be more robust, yielding much more complex secret messages through the container texts. This approach has given some recognizable results on both steganographic and reconstructive metrics.

    考虑一个简单的例子,其中消息是两位。 为了传达秘密消息,我们的功能是容器消息的模数为4。更具体地说,让l表示容器消息中的字符数。 l 0(mod 4)产生00, l 1(mod 4)产生01, l 2(mod 4)产生10, l 3(mod 4)产生11。模型将相应地从中删除或添加字符传达秘密信息的封面。 实际上,理想情况下,我们希望模型更加健壮,并通过容器文本产生更复杂的秘密消息。 这种方法在隐写和重建指标上都给出了一些可识别的结果。

    Cover: I can not believe my eyes, what I saw in the forest was far beyond the reaches of my imagination.

    封面 :我简直不敢相信自己的眼睛,在森林里看到的东西远远超出了我的想象。

    Secret: meet at river tomorrow at sunset.

    秘密 :明天日落时在河边碰面。

    Container: I mac now bleiave mye eey, waht I sa inn tee freost ws fara beymdo tee racheas of ym imaingaiton.

    容器 :我现在要面对面的挑战,因为我是来自ym imaingaiton的fare beymdo tee racheas的旅馆。

    Revealed Secret: eemt a th rivre tomowro tt snseht.

    揭露的秘密 :让您流连忘返。

    Surprisingly, this information is still somewhat decodable (even though it’s clear that the message has been modified).

    令人惊讶的是,此信息仍然有些可解码(即使很明显该消息已被修改)。

    An interesting (likely unsolved) information-theoretic question arises in this area: given an information domain (like images, text, etc.), how much secret information can a model hide in given cover information in the average case? We started to see that with larger secret message input sizes and a static cover message size, the model had an increasingly difficult time hiding the information and reconstructing the hidden message. How good it was at each depending on how we weighted the two tasks in the loss function.

    在这个领域中出现了一个有趣的(可能尚未解决的)信息理论问题:给定一个信息域(例如图像,文本等),在给定的封面信息中,模型平均可以隐藏多少秘密信息? 我们开始发现,随着秘密消息输入大小的增加和静态掩护消息大小的增加,模型隐藏信息和重构隐藏消息的时间越来越困难。 每个指标的优劣取决于我们对损失函数中两个任务的加权方式。

    Next, we decided to investigate a heftier model for performing steganography in text. The primary approach we propose to tackle the challenge of text-based steganography consists of leveraging two NMT (Neural Machine Translation) models: one transformer model to encode the hidden message and a second model to decode it. We hypothesize that this transformer-based approach can potentially succeed at encoding a secret text within a cover text to produce a container text that closely matches the semantic structure of the cover text. An additional nice thing about this is that no custom dataset is needed: any collection of sentences or phrases and random generation of secret messages will do.

    接下来,我们决定研究一种用于在文本中执行隐写术的更高级模型。 我们提出的解决基于文本的隐写技术挑战的主要方法包括利用两种NMT(神经机器翻译)模型:一种用于对隐藏消息进行编码的转换器模型,另一种用于对隐藏消息进行解码的模型。 我们假设这种基于转换器的方法可能会成功地对封面文本中的秘密文本进行编码,以生成与封面文本的语义结构紧密匹配的容器文本。 与此相关的另一个好处是,不需要自定义数据集:任何句子或短语集合以及随机生成的秘密消息都可以。

    What does “similarity” between cover and container in this case mean? We don’t have a simple metric anymore like edit distance or L2 norm between pixel values. In our new scheme, the sentence “Don’t eat, my friends!” and “Don’t eat my friends!” mean very different things, whereas “Don’t eat, my friends!” and “Please abstain from eating, ye for whom I truly care!” have similar meanings. For ascertaining a metric of similarity, we leverage BERT (Bidirectional Encoder Representations from Transformers [8]), a pre-trained language model that can represent a sentence as a real-valued vector (using the [SEP] token’s vector) where the cosine similarity between two vectors is a good indication of how similar the sentences are in meaning.

    在这种情况下,盖子与容器之间的“相似性”是什么意思? 我们再也没有一个简单的指标,例如像素值之间的编辑距离或L2范数。 在我们的新方案中,句子“不要吃,我的朋友们!” 和“别吃我的朋友们!” 意思是完全不同的,而“别吃了,我的朋友们!” 和“我真正关心的人,请不要进食!” 具有相似的含义。 为确定的度量相似性,我们杠杆BERT(B idirectionalËncoderT ransformersř对产权[8]),一个预训练的语言模型可以表示一个句子作为一个实值向量(使用[SEP]标记的矢量),两个向量之间的余弦相似度很好地表明了句子的含义如何相似。

    The results presented in Neural Linguistic Steganography [6], the work most closely related to our own, indicate that state-of-the-art transformer-based language models such as GPT-3 can be leveraged to generate convincing cover texts to hide secret messages. In our implementation, our first NMT transformer model reads in the concatenated secret message (four digits in base 10) and cover text and proceeds to translate them into a container text. Our second transformer reads in the container text and translates it into a reconstruction of the original secret message. Again, the loss function we use consists of a linear combination of the similarity functions between the cover text and the container text (using BERT to produce Loss_Stego), along with the edit distance between the reconstructed secret message and the original secret message. The loss function is (somewhat humorously) formulated as

    神经语言隐写术 [6](与我们的研究最相关)中的结果表明,可以利用基于变压器的最新语言模型(例如GPT-3)来生成令人信服的封面文字以隐藏秘密消息。 在我们的实现中,我们的第一个NMT转换器模型读取连接的秘密消息(以10为基数的四位数字)并覆盖文本,然后继续将其转换为容器文本。 我们的第二个转换器读取容器文本并将其转换为原始秘密消息的重构。 同样,我们使用的损失函数由封面文本和容器文本(使用BERT生成Loss_Stego)之间的相似度函数以及重构的秘密消息和原始秘密消息之间的编辑距离的线性组合组成。 损失函数(有点幽默)公式为

    Image for post

    where c is the cover instance, c′ is the container instance, s is the secret message, and s′ is the reconstructed message. α and β in our loss function are parameters we can set or have change as a function of the epoch or the loss rate of change. We define the similarity between stegotext (or container text) and cover text with respect to meaning to be the cosine similarity of the embedding of both sequences generated by a pre-trained BERT base model.

    其中c是封面实例, c '是容器实例, s是秘密消息, s '是重构消息。 损失函数中的αβ是我们可以根据时期或损失变化率设置或更改的参数。 我们将隐写文本(或容器文本)和封面文本之间的相似性定义为是预训练的BERT基本模型生成的两个序列的嵌入的余弦相似性。

    We found that the model that we used, an LSTM seq2seq model with attention for the hiding network and revealing network, was not powerful enough to generate good containers and was faulty in reconstructing the secret message. The loss converged quickly and at a fairly high loss. We additionally hypothesize that a low loss is likely the result of a generative adversarial model for BERT: finding sentences that are meaningless to humans but have small cosine similarity in their embeddings against cover texts as evaluated by BERT. Below is one output example:

    我们发现,我们使用的模型(一个关注隐藏网络和显示网络的LSTM seq2seq模型) 功能不强大,无法生成良好的容器,并且在重建秘密消息方面存在错误 。 损失Swift收敛,损失很高。 我们还假设,误码率低可能是BERT生成对抗模型的结果:找到对人类无意义的句子,但与BERT评估的掩盖文字相比,它们的嵌入余弦相似度小。 以下是一个输出示例:

    Cover: celebrate the opportunity you have to eat this.

    封面 :庆祝有机会吃这个的机会。

    Secret: 8 4 4 4.

    秘密 :8 4 4 4。

    Container: blessing pedals ampoule mbi mbi jharkhand ampoule coring substantive substantive tranquil steadfast murdoch cleverness germane obeng.

    容器 :祝福踏板安瓿mbi mbi贾坎德邦安瓿实质性实质性宁静坚定默多克聪明德意志。

    Revealed Secret: 8 4 1 4.

    揭秘秘密 :8 4 1 4。

    Despite this weak example, we also feel that with a sufficiently powerful NMT model and enough compute, we would start to observe useful natural language steganography on textual and general information. This technique could potentially revolutionize communication where there exist adversarial eavesdroppers, especially in the quantum era of fast decryption of common cryptographic protocols. This implementation is left as future work to folks who have an abundance of compute. (Code for the seq2seq model is viewable in this Colab.)

    尽管有这个薄弱的例子,我们也感到,有了足够强大的NMT模型和足够的计算能力,我们将开始在文本和一般信息上观察到有用的自然语言隐写术。 在存在对抗性窃听者的情况下,尤其是在快速解密通用密码协议的量子时代,该技术可能会彻底改变通信。 该实现留给有大量计算能力的人们作为未来的工作。 (可以在此Colab中查看seq2seq模型的代码。)

    用于语音和其他音频信息的深度隐写术 (Deep Steganography for speech and other audio information)

    While performing deep steganography for text may be a ways off, a similar approach for sonic information (sound files) is certainly within reach. The core differentiator for why text is so much more difficult to perform steganography with than images is because text is sparse: in a line of text, each word can be represented by a natural number, and there are typically no more than 100 words in a given sentence. However, images are dense: that is, an image is represented by a very large number of pixels, each having 16777216 possible values (for RGB images).

    虽然对文本执行深度隐写术可能是一种方法,但对于声音信息(声音文件)的类似方法肯定可以实现。 为什么文本比图像更难以进行隐写术的主要区别在于,因为文本稀疏:在一行文本中,每个单词都可以用自然数表示,而一个单词中通常不超过100个单词给定句子。 但是,图像很密集 :也就是说,图像由非常多的像素表示,每个像素都有16777216个可能值(对于RGB图像)。

    Sound waves are similarly dense, depending on how they’re represented. We’re going to look at two of the ways that sonic information can be represented: spectrograms and waveforms.

    声波的密度类似,取决于它们的表示方式。 我们将研究两种表示声音信息的方式: 频谱图波形

    1. A spectrogram is a visual representation of audio. Specifically, the spectrum of frequencies of a signal as it varies with time is represented in the spectrogram by colors and intensities of a time series heatmap. Below is a spectrogram of myself saying, “this is a secret message: my secret message”. For the sake of visuals in this article, we focus on spectrograms.

      频谱图是音频的视觉表示。 具体来说,信号随时间变化的频率频谱在频谱图中由时间序列热图的颜色和强度表示。 下面是我自己的频谱图,上面写着:“这是一条秘密信息:我的秘密信息”。 为了本文的视觉效果,我们将重点放在频谱图上。

    2. A waveform is the shape of the graph of a sonic signal as a function of time. Waveforms can be visualized with oscilloscopes to be analyzed for properties such as amplitude, frequency, rise time, time interval, distortion, and others.

      波形是声音信号随时间变化的图形形状。 可以使用示波器查看波形,以分析其属性,例如振幅频率上升时间 ,时间间隔, 失真等。

    Image for post
    Image by author.图片由作者提供。

    As was proposed by Hiding Images in Plain Sight: Deep Steganography [1], the spectrogram can be operated on as an image using its 2D feature map spectrogram, which can be linearly or logarithmically scaled. The secret message can be an image, text, or other audio data. There are three primary ways of extracting spectrograms from sound: 1) Short-Time Fourier Transform (STFT), with the filters distributed uniformly on the linear frequency axis; 2) Log STFT, same as 1) but with filters that are equally spaced on the logarithmic frequency axis, and 3) Random Matrix Transform (RMT); related to 1) and 2), but with a random matrix R in the place of the discrete Fourier transform matrix.

    正如隐藏在普通视域中的图像所提出的:深层隐写术 [1] 可以使用频谱图的2D特征图频谱图将其作为图像进行操作,该特征图可以进行线性或对数缩放。 秘密消息可以是图像,文本或其他音频数据。 从声音中提取频谱图的主要方法有三种:1)短时傅立叶变换(STFT),滤波器在线性频率轴上均匀分布; 2)对数STFT,与1)相同,但滤波器在对数频率轴上等距分布,以及3)随机矩阵变换(RMT); 与1)和2)有关,但是用随机矩阵R代替离散傅立叶变换矩阵。

    Here, we can use a 2D U-Net architecture [9] to learn steganography with the spectrogram.

    在这里,我们可以使用2D U-Net架构[9]来学习频谱图的隐写术。

    Image for post
    Image by author.图片由作者提供。

    We can also use a convolutional model to learn steganography with the raw audio waveform (STFT), as was proposed in July 2020 by Kreuk et al. in Hide and Speak: Towards Deep Neural Networks for Speech Steganography [10] with impressive results. In either case, the deep learning model training procedure is largely the same: a concealer network and revealer network must be trained in parallel in such a way that the concealer network is able to generate container audio data that is aurally similar to the cover audio it is given (in practice, this perturbed container audio has a tiny bit of “fuzzy” sound), which can then be used by the revealer network to reveal the secret audio it is also given.

    正如Kreuk等人在2020年7月提出的,我们还可以使用卷积模型来学习带有原始音频波形(STFT)的隐写术。 “ 捉迷藏和说话:走向语音隐写术的深度神经网络” [10]中的结果令人印象深刻。 在这两种情况下,深度学习模型的训练过程都基本相同:遮盖器网络和显示器网络必须并行进行训练,以使该遮盖器网络能够生成与听觉上相似的容器音频数据。给出(实际上,这种受干扰的容器音频具有一点“模糊”声音),然后可以由揭示者网络使用它来揭示也给出的秘密音频。

    End-to-end, a product created using this system can be used as illustrated after training the concealer and revealer networks:

    端对端,使用此系统创建的产品可以在训练遮瑕膏和揭露者网络之后如图所示使用:

    Image for post
    Image by author.图片由作者提供。

    As shown, Bob is trying to hide an image of me inside a spectrogram. The concealer model receives the spectrogram and secret message, yielding a resulting modified spectrogram with small perturbations. This spectrogram is sent across the internet to Alice, who uses the revealer model to convert the container spectrogram into a reconstructed (slightly modified) secret image. A similar process is achieved with a convolutional architecture on the audio STFT waveform.

    如图所示,Bob试图将我的图像隐藏在频谱图中。 隐藏器模型接收频谱图和秘密消息,从而产生具有较小扰动的最终修改后的频谱图。 该频谱图通过互联网发送给爱丽丝,爱丽丝使用揭示者模型将容器频谱图转换为重建的(略微修改的)秘密图像。 通过在音频STFT波形上使用卷积架构可以实现类似的过程。

    Image for post
    Image by author.图片由作者提供。

    结论…… (To conclude…)

    Deep steganography has important implications for secure communication as well as watermarking and service accountability for information machine learning cloud providers. These are only preliminary, unpublished results and have not been incorporated into any sort of product yet, but they provide a hopeful look into the potential that deep steganography offers to keep our information safe in the future.

    深度隐写术对于安全通信以及信息机器学习云提供商的水印和服务责任制具有重要意义。 这些只是初步的,尚未发布的结果,尚未被整合到任何产品中,但是它们为深度隐写术为保持我们的信息安全所提供的潜力提供了希望。

    Shoutouts to Mario Srouji, Dian Ang Yap, Michele Catasta, Brad Efron, Ashish Kundu, Mustafa Canim, and Christopher Manning for their involvement and contributions!

    向马里奥·斯鲁吉(Mario Srouji),滇安(Dian Ang Yap),米歇尔·卡斯塔斯塔(Michele Catasta),布拉德·埃夫隆(Brad Efron),阿什什·昆杜(Ashish Kundu),穆斯塔法·卡宁(Mustafa Canim)和克里斯托弗·曼宁(Christopher Manning)致以呐喊!

    I’m on LinkedIn, Medium, and Twitter.

    我在LinkedInMediumTwitter上

    机器生成的摘要 (Machine-Generated Summary)

    As promised, here is the machine-generated summary, minimally edited (replacing [UNK] tokens here and there, capitalizing words, removing extra spaces…not cherry-picked other than paragraph selection!). This is another project I’m working on…more to come soon. The original text is 2400+ words.

    如所承诺的,这是由机器生成的摘要,经过了最小程度的编辑(在此处和此处替换[UNK]标记,大写单词,删除多余的空格……除了段落选择以外,别无其他选择!)。 这是我正在研究的另一个项目,更多内容即将推出。 原始文本为2400多个字。

    摘要(473字): (Summary (473 words):)

    People have been using steganography for ages to communicate information in a hidden way. It has long been associated with painting and visual art. Baluja proposed the idea of using deep learning for image steganography in his paper. A first neural network takes in two images to create a third one that can be used by a second neural network to reveal the message via the revealed image. The concept was expanded upon by et a few months later to allow for arbitrary data encoding into images.

    人们多年来一直使用隐写术以隐藏的方式传达信息。 长期以来,它与绘画和视觉艺术有关。 Baluja在他的论文中提出了将深度学习用于图像隐写术的想法。 第一个神经网络接收两个图像以创建第三个神经网络,第二个神经网络可以使用第三个神经网络通过显示的图像显示消息。 几个月后,这一概念得到了扩展,以允许将任意数据编码成图像。

    For written language the idea is that a model would learn a statistical profile of character choices in a string of text and modify them in a way that sends a signal to the hidden message through character or character. The current approaches rely on using generative models to hide the hidden messages. The new approach uses a second model to combine the desired text with some coherent cover text to create a container text. L represents the number of characters in the container. The model would remove or add characters from the cover to communicate the secret. The approach has given some recognizable results but the information is still hidden.

    对于书面语言,想法是,模型将学习文本字符串中字符选择的统计信息,并以通过字符或字符向隐藏消息发送信号的方式修改它们。 当前的方法依赖于使用生成模型来隐藏隐藏的消息。 新方法使用第二种模型将所需文本与一些连贯的封面文本结合起来以创建容器文本。 L表示容器中的字符数。 该模型将从封面上删除或添加角色以传达秘密。 该方法已经给出了一些可识别的结果,但是信息仍然是隐藏的。

    The primary approach for performing a in-depth analysis of secret messages consists of two models: one reads in the hidden message and the second one translates it into a container text. The loss function consists of a linear combination of the similarity functions between the cover text and the container text to create a secret message. The model with attention for the hiding network was not powerful enough to generate good containers and was faulty in the secret. The low loss is probably the result of a generative adversarial model for finding sentences that have small similarity in their similarity. A sufficiently powerful and powerful model and enough people will start to observe useful natural language. The implementation is left as future work to people who have a lot of money.

    对秘密消息进行深入分析的主要方法包括两个模型:一个模型读取隐藏的消息,第二个模型将其转换为容器文本。 损失函数由封面文本和容器文本之间的相似度函数的线性组合组成,以创建秘密消息。 注意隐藏网络的模型不够强大,无法生成良好的容器,并且秘密存在错误。 低损失可能是生成对抗性模型的结果,该模型用于寻找相似度较小的句子。 一个足够强大的模型和足够多的人将开始观察有用的自然语言。 该实现留给有很多钱的人将来的工作。

    Text is more difficult to perform deep steganography for text than for images. Images are represented by a very large number of words. Waves are similarly represented. The deep learning model training procedure is largely the same: a concealer network and the revealer network. It is able to generate container audio data that is similar to the cover audio it is given. It can then be used by the network to reveal the secret audio. A product created using the system can be used as illustrated after training the concealer and when training the secret. A model is trying to hide an image of me inside a spectrogram concealer model. The model is sent across the internet to someone who uses the model to convert the container into a reconstructed spectrogram revealer secret.

    与文本相比,对文本执行深度隐写术更困难。 图像由大量单词表示。 波被类似地表示。 深度学习模型训练过程大致相同:遮瑕网和揭密网。 它能够生成与给定的封面音频相似的容器音频数据。 然后网络可以使用它来显示秘密音频。 如图所示,使用该系统创建的产品可以在训练遮瑕膏之后和训练秘密时使用。 模型正在尝试将我的图像隐藏在频谱图遮瑕模型中。 该模型通过Internet发送给使用该模型将容器转换为重构的频谱图显示者秘密的人员。

    Deep steganography offers to keep people’s information safe in the cloud.

    深度隐写术可以确保人们的信息在云中安全。

    [1] Baluja, S. (2017). Hiding images in plain sight: Deep steganography. In Advances in Neural Information Processing Systems (pp. 2069–2079).

    [1] Baluja,S.(2017年)。 隐藏清晰可见的图像:隐写术 。 《 神经信息处理系统进展》 (第2069-2079页)。

    [2] Zhu, J., Kaplan, R., Johnson, J., & Fei-Fei, L. (2018). Hidden: Hiding data with deep networks. In Proceedings of the European conference on computer vision (ECCV) (pp. 657–672).

    [2] Zhu,J.,Kaplan,R.,Johnson,J.,&Fei-Fei,L.(2018)。 隐藏:使用深层网络隐藏数据 。 在欧洲计算机视觉会议(ECCV)会议录中 (第657-672页)。

    [3] Yang, Z.L., Guo, X.Q., Chen, Z.M., Huang, Y.F., & Zhang, Y.J. (2018). RNN-stega: Linguistic steganography based on recurrent neural networks IEEE Transactions on Information Forensics and Security, 14(5), 1280–1295.

    [3]杨ZL,郭晓琴,陈ZM,黄艳芳,张玉杰(2018)。 RNN-stega:基于递归神经网络的语言隐写术 IEEE Transactions on Information Forensics and Security,14 (5),1280-1295。

    [4] Fang, T., Jaggi, M., & Argyraki, K. (2017). Generating steganographic text with LSTMs arXiv preprint arXiv:1705.10742.

    [4] Fang,T.,Jaggi,M.和Argyraki,K.(2017)。 使用LSTM arXiv预印本arXiv:1705.10742 生成隐写文字

    [5] Chang, C.Y., & Clark, S. (2010). Linguistic steganography using automatically generated paraphrases. In Human Language Technologies: The 2010 Annual Conference of the North American Chapter of the Association for Computational Linguistics (pp. 591–599).

    [5] Chang,CY,&Clark,S.(2010)。 语言隐写术使用自动生成的释义 。 在人类语言技术中:计算语言学协会北美分会2010年年会 (第591-599页)。

    [6] Ziegler, Z., Deng, Y., & Rush, A. (2019). Neural linguistic steganography arXiv preprint arXiv:1909.01496.

    [6] Ziegler,Z.,Deng,Y.,&Rush,A.(2019)。 神经语言隐写术 arXiv预印本arXiv:1909.01496

    [7] Zhang, X., Zhao, J., & LeCun, Y. (2015). Character-level convolutional networks for text classification. In Advances in neural information processing systems (pp. 649–657).

    [7] Zhang,X.,Zhao,J.,&LeCun,Y.(2015)。 用于文本分类的字符级卷积网络神经信息处理系统的进展 (第649–657页)。

    [8] Devlin, J., Chang, M. W., Lee, K., & Toutanova, K. (2018). Bert: Pre-training of deep bidirectional transformers for language understanding. arXiv preprint arXiv:1810.04805.

    [8] Devlin,J.,Chang,MW,Lee,K.,&Toutanova,K.(2018)。 伯特:为理解语言而对深度双向转换器进行的预训练arXiv预印本arXiv:1810.04805

    [9] Ronneberger, O., Fischer, P., & Brox, T. (2015, October). U-net: Convolutional networks for biomedical image segmentation. In International Conference on Medical image computing and computer-assisted intervention (pp. 234–241). Springer, Cham.

    [9] Ronneberger,O.,Fischer,P.和Brox,T.(2015年10月)。 U-net:用于生物医学图像分割的卷积网络 。 在国际医学图像计算和计算机辅助干预会议上 (第234-241页)。 湛史普林格。

    [10] Felix Kreuk, Yossi Adi, Bhiksha Raj, Rita Singh, & Joseph Keshet. (2020). Hide and Speak: Towards Deep Neural Networks for Speech Steganography.

    [10] Felix Kreuk,Yossi Adi,Bhiksha Raj,Rita Singh和Joseph Keshet。 (2020)。 《捉迷藏和说话:走向用于语音隐写的深层神经网络》

    翻译自: https://towardsdatascience.com/message-in-a-message-44b89090b3b8

    微信开发中消息回复的代码

    展开全文
  • 微信开发学习总结(三)——消息管理—接收普通消息—(2)图片消息

    上一节内容:
    微信开发学习总结(三)——消息管理(1)
    https://blog.csdn.net/qq_29914837/article/details/82903594


    消息管理具有的各个子模块功能,现在我们将一个详细介绍如何使用
    在这里插入图片描述

    一、接受普通消息接口介绍

    1.1、接受普通消息

    接收到的普通消息的消息类型目前有以下几种:
    ①文本消息
    ②图片消息
    ③语音消息
    ④视频消息
    ⑤小视频消息
    ⑥地理位置消息
    ⑦链接消息

    每一种消息类型都有其指定的XML数据格式,在官方文档上都有具体的格式定义和属性说明。
    当普通微信用户向公众账号发消息时,微信服务器会先接收到用户发送的消息,然后将用户消息按照指定的XML格式组装好数据,最后POST消息的XML数据包到开发者填写的URL上。
    接收消息的整个过程:就是获取post请求的这个xml,然后对这个xml进行分析的过程。post请求的入口还是之前提到的微信公众号接入的那个地址,整个公众号的所有请求都会走这个入口,只是接入时是get请求,其它情况下是post请求。

    二、被动回复用户消息接口介绍

    2.1、被动回复用户消息

    被动回复用户消息的消息类型目前有以下几种:
    ①回复文本消息
    ②回复图片消息
    ③回复语音消息
    ④回复视频消息
    ⑤回复音乐消息
    ⑥回复图文消息

    微信服务器在将用户的消息发给公众号的开发者服务器地址后,会等待开发者服务器回复响应消息。微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。
      假如服务器无法保证在五秒内处理并回复,必须做出下述回复,这样微信服务器才不会对此作任何处理,并且不会发起重试(这种情况下,可以使用客服消息接口进行异步回复),否则,将出现严重的错误提示。详见下面说明:
      1、(推荐方式)直接回复success
      2、直接回复空串(指字节长度为0的空字符串,而不是XML结构体中content字段的内容为空)

     一旦遇到以下情况,微信都会在公众号会话中,向用户下发系统提示“该公众号暂时无法提供服务,请稍后再试”
      1、开发者在5秒内未回复任何内容
      2、开发者回复了异常数据,比如JSON数据等

      另外,请注意,回复图片等多媒体消息时需要预先通过素材管理接口上传临时素材到微信服务器,可以使用素材管理中的临时素材,也可以使用永久素材。
      消息回复目前支持回复文本、图片、图文、语音、视频、音乐,每一种类型的消息都有特定的XML数据格式。

    三、微信公众号的普通消息的接收和回复的实现

    接收消息和被动回复消息这两个动作是不分家的,这本来就是一个交互场景,一般情况就是公众号通过分析接收到的消息,会给出对应的回复。
    3.1、微信公众号的普通消息的接收和回复的实现的开发流程思路
    (1)微信服务器发送post请求的xml数据到微信公众号服务器
    (2)微信公众号服务器需要解析xml格式的数据
    (3)根据微信公众号被动回复用户消息接口中回复消息的xml格式,构建回复消息的格式内容
    (4)返回构建的消息xml格式的消息内容到微信服务器,由微信服务器转发到微信公众号回复

    3.2、现在我将一个个步骤进行模拟代码实现:

    (1)当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。

    	/**
    	 * 处理微信服务器发post请求发来的xml格式消息
    	 */
        @Override
    	public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        	long startTime=System.currentTimeMillis();   //获取开始时间
            // TODO 接收、处理、响应由微信服务器转发的用户发送给公众帐号的消息
            // 将请求、响应的编码均设置为UTF-8(防止中文乱码)
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            System.out.println("微信的post请求进入了本地服务器了");
            String result = "";
            try {
                Map<String,String> map = WeiXinCheck.parseXml(request);
                System.out.println("微信公众号要开始发送消息");
                result =  WeiXinCheck.buildResponseMessage(map);
                
                if(result.equals("")){
                    result = "未正确响应";
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("发生异常:"+ e.getMessage());
            }
            
            response.getWriter().println(result);
            System.out.println( result) ;
            long endTime=System.currentTimeMillis(); //获取结束时间
            System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
        }
    

    (2)然后我们需要对这个xml数据进行解析处理,这样才可以得知微信服务器转发的消息内容。

        /**
         * 解析微信发来的请求(XML)并且转换为Map
         * @param request
         * @return map
         * @throws Exception
         */
    	public static Map<String,String> parseXml(HttpServletRequest request) throws Exception {
            // 将解析结果存储在HashMap中
            Map<String,String> map = new HashMap();
            // 从request中取得输入流
            InputStream inputStream = request.getInputStream();
            // 读取输入流
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素的所有子节点
            List<Element> elementList = root.elements();
    
            // 遍历所有子节点
            for (Element e : elementList) {
                System.out.println(e.getName() + "|" + e.getText());
                map.put(e.getName(), e.getText());
            }
    
            // 释放资源
            inputStream.close();
            return map;
        }
    
    

    这样我们就完成了post传递到URL的xml格式的消息的接收。
    (3)根据微信公众号被动回复用户消息接口中回复消息的xml格式,构建回复消息的格式内容

    代码结构图:
    在这里插入图片描述
    公共实体类

    package weixin.entity.message.common;
    /**
     * @所属类别:实体类
     * @用途:微信公众号开发中消息管理-公用消息实体类
     * @author yilei
     * @version:1.0
     */
    public class Common {
    
    	private String toUserName;//消息接收方
    	private String fromUserName;//消息发送方
    	private String createTime;//消息创建时间 (整型)
    	private String msgType;//消息类型
    	private String msgId;//消息id,64位整型
    	
    	public String getToUserName() {
    		return toUserName;
    	}
    	public void setToUserName(String toUserName) {
    		this.toUserName = toUserName;
    	}
    	public String getFromUserName() {
    		return fromUserName;
    	}
    	public void setFromUserName(String fromUserName) {
    		this.fromUserName = fromUserName;
    	}
    	public String getCreateTime() {
    		return createTime;
    	}
    	public void setCreateTime(String createTime) {
    		this.createTime = createTime;
    	}
    	public String getMsgType() {
    		return msgType;
    	}
    	public void setMsgType(String msgType) {
    		this.msgType = msgType;
    	}
    	public String getMsgId() {
    		return msgId;
    	}
    	public void setMsgId(String msgId) {
    		this.msgId = msgId;
    	}
    	public Common(String toUserName, String fromUserName, String createTime, String msgType, String msgId) {
    		this.toUserName = toUserName;
    		this.fromUserName = fromUserName;
    		this.createTime = createTime;
    		this.msgType = msgType;
    		this.msgId = msgId;
    	}
    	public Common(String toUserName, String fromUserName, String createTime ) {
    		this.toUserName = toUserName;
    		this.fromUserName = fromUserName;
    		this.createTime = createTime;
    	}
    	public Common(){
    		
    	}
    	
    }
    
    

    ①构造文本消息

    package weixin.entity.message.text;
    
    import weixin.entity.message.common.Common;
    
    /**
     * @所属类别:实体类
     * @用途:微信公众号开发中消息管理-文本消息
     * @author yilei
     * @version:1.0
     */
    public class Text {
    
    	private Common common;//公用消息实体类
    	
    	private String content;//文本消息内容
    	
    	public Common getCommon() {
    		return common;
    	}
    
    	public void setCommon(Common common) {
    		this.common = common;
    	}
    
    	public String getContent() {
    		return content;
    	}
    
    	public void setContent(String content) {
    		this.content = content;
    	}
    
    	public Text(){
    		
    	}
    
    	/**
    	 * @param common
    	 * @param content
    	 */
    	public Text(Common common, String content) {
    		this.common = common;
    		this.content = content;
    	}
    			
    }
    
    
        /**
         * 构造文本消息
         * @param text 封装了解析结果的Text对象
         * @return 文本消息XML字符串
         */
        private static String buildTextMessage(Text text) {
        	String result = "";
        	if(text!=null){
        		result=String.format(
                        "<xml>" +
                                "<ToUserName><![CDATA[%s]]></ToUserName>" +
                                "<FromUserName><![CDATA[%s]]></FromUserName>" +
                                "<CreateTime>%s</CreateTime>" +
                                "<MsgType><![CDATA[text]]></MsgType>" +
                                "<Content><![CDATA[%s]]></Content>" + "</xml>",
                                text.getCommon().getFromUserName(), text.getCommon().getToUserName(), text.getCommon().getCreateTime(), text.getContent());
                 }
            return result;
        	}
    

    ②构建图片消息

    package weixin.entity.message.image;
    
    import weixin.entity.message.common.Common;
    
    /**
     * @所属类别:实体类
     * @用途:微信公众号开发中消息管理-图片消息
     * @author yilei
     * @version:1.0
     */
    public class Image {
    
    	private Common common;//公用消息实体类
    		
    	private String mediaId;//图片消息媒体id,可以调用多媒体文件下载接口拉取数据。
    
    	public Common getCommon() {
    		return common;
    	}
    
    	public void setCommon(Common common) {
    		this.common = common;
    	}
    
    
    	public String getMediaId() {
    		return mediaId;
    	}
    
    	public void setMediaId(String mediaId) {
    		this.mediaId = mediaId;
    	}
    
    	/**
    	 * @param common
    	 * @param mediaId
    	 */
    	public Image(Common common, String mediaId) {
    		this.common = common;
    		this.mediaId = mediaId;
    	}
    	
    	public Image(){
    		
    	}
    }
    
    
        /**
         * 构造图片消息
         * @param image 封装了解析结果的Image对象
         * @return 图片消息XML字符串
         */
        public static String buildImageMessage(Image image) {
        	String result = "";
        	if(image!=null){
        		result= String.format(
                    "<xml>" +
                            "<ToUserName><![CDATA[%s]]></ToUserName>" +
                            "<FromUserName><![CDATA[%s]]></FromUserName>" +                       
                            "<CreateTime>%s</CreateTime>" +
                            "<MsgType><![CDATA[image]]></MsgType>" +
                            "<Image>"+
                            "    <MediaId><![CDATA[%s]]></MediaId>" +   
                            "</Image>"+
                            "</xml>",
                            image.getCommon().getFromUserName(), image.getCommon().getToUserName(),image.getCommon().getCreateTime(),image.getMediaId());
        	}
        	return result;
        }
    

    ③构建语言消息

    package weixin.entity.message.voice;
    
    import weixin.entity.message.common.Common;
    
    /**
     * @所属类别:实体类
     * @用途:微信公众号开发中消息管理-语音消息
     * @author yilei
     * @version:1.0
     */
    public class Voice {
    	
    	private Common common;//公用消息实体类
    	
    	private String mediaId;//语音消息媒体id,可以调用多媒体文件下载接口拉取数据。
    	
    	public Common getCommon() {
    		return common;
    	}
    
    	public void setCommon(Common common) {
    		this.common = common;
    	}
    
    	public String getMediaId() {
    		return mediaId;
    	}
    
    	public void setMediaId(String mediaId) {
    		this.mediaId = mediaId;
    	}
    
    	
    
    	/**
    	 * @param common
    	 * @param mediaId
    	 */
    	public Voice(Common common, String mediaId) {
    		this.common = common;
    		this.mediaId = mediaId;
    	}
    	
    	public Voice(){
    		
    	}
    }
    
    
       /**
         * 构造语音消息
         * @param voice 封装了解析结果的Voice对象
         * @return 视频消息XML字符串
         */
        public static String buildVoiceMessage(Voice voice) {
        	String result = "";
        	if(voice!=null){
        		result= String.format(
                    "<xml>" +
                            "<ToUserName><![CDATA[%s]]></ToUserName>" +
                            "<FromUserName><![CDATA[%s]]></FromUserName>" +
                            "<CreateTime>%s</CreateTime>" +
                            "<MsgType><![CDATA[voice]]></MsgType>" +
                            "<Voice>"+
                            "     <MediaId><![CDATA[%s]]></MediaId>" +
                            "</Voice>"+
                            "</xml>",
                            voice.getCommon().getFromUserName(), voice.getCommon().getToUserName(), voice.getCommon().getCreateTime(),voice.getMediaId());
            }
        	return result;
        }
    

    ④构建视频消息

    package weixin.entity.message.video;
    
    import weixin.entity.message.common.Common;
    
    /**
     * @所属类别:实体类
     * @用途:微信公众号开发中消息管理-视频消息
     * @author yilei
     * @version:1.0
     */
    public class Video {
    
    	private Common common;//公用消息实体类
    	
    	private String mediaId;//通过素材管理中的接口上传多媒体文件,得到的id
    
    	private String title;//视频消息的标题
    	
    	private String description;//视频消息的描述
    	
    	
    	/**
    	 * @param common
    	 * @param mediaId
    	 * @param title
    	 * @param description
    	 */
    	public Video(Common common, String mediaId, String title, String description) {
    		this.common = common;
    		this.mediaId = mediaId;
    		this.title = title;
    		this.description = description;
    	}
    
    	public Common getCommon() {
    		return common;
    	}
    
    	public void setCommon(Common common) {
    		this.common = common;
    	}
    
    	public String getMediaId() {
    		return mediaId;
    	}
    
    	public void setMediaId(String mediaId) {
    		this.mediaId = mediaId;
    	}
    
    	public String getTitle() {
    		return title;
    	}
    
    	public void setTitle(String title) {
    		this.title = title;
    	}
    
    	public String getDescription() {
    		return description;
    	}
    
    	public void setDescription(String description) {
    		this.description = description;
    	}
    
    
    	public Video(){
    		
    	}
    }
    
    
        /**
         * 构造视频消息
         * @param video 封装了解析结果的Video对象
         * @return 视频消息XML字符串
         */
        public static String buildVideoMessage(Video video) {
        	String result = "";
        	if(video!=null){
        		result= String.format(
                    "<xml>" +
                            "<ToUserName><![CDATA[%s]]></ToUserName>" +
                            "<FromUserName><![CDATA[%s]]></FromUserName>" +
                            "<CreateTime>%s</CreateTime>" +
                            "<MsgType><![CDATA[video]]></MsgType>" +
                            "<Video>" +
                            "  <MediaId><![CDATA[%s]]></MediaId>" +
                            "  <Title><![CDATA[%s]]></Title>" +
                            "  <Description><![CDATA[%s]]></Description>" +
                            "</Video>" +
                            "</xml>",
                    video.getCommon().getFromUserName(), video.getCommon().getToUserName(), video.getCommon().getCreateTime(),video.getMediaId(),video.getTitle(),video.getDescription());
            }
        	return result;
        }
    

    ⑤构建音乐消息

    package weixin.entity.message.music;
    import weixin.entity.message.common.Common;
    
    /**
     * @所属类别:实体类
     * @用途:微信公众号开发中消息管理-音乐消息
     * @author yilei
     * @version:1.0
     */
    public class Music {
    
    	private Common common;//公用消息实体类
    	
    	private String title;//音乐标题
    	
    	private String description;//音乐描述
    
    	private String musicURL;//音乐链接
    	
    	private String hQMusicUrl;//高质量音乐链接,WIFI环境优先使用该链接播放音乐
    	
    	private String thumbMediaId;//缩略图的媒体id,通过素材管理中的接口上传多媒体文件,得到的id
    
    	public Common getCommon() {
    		return common;
    	}
    
    	public void setCommon(Common common) {
    		this.common = common;
    	}
    
    	public String getTitle() {
    		return title;
    	}
    
    	public void setTitle(String title) {
    		this.title = title;
    	}
    
    	public String getDescription() {
    		return description;
    	}
    
    	public void setDescription(String description) {
    		this.description = description;
    	}
    
    	public String getMusicURL() {
    		return musicURL;
    	}
    
    	public void setMusicURL(String musicURL) {
    		this.musicURL = musicURL;
    	}
    
    	public String gethQMusicUrl() {
    		return hQMusicUrl;
    	}
    
    	public void sethQMusicUrl(String hQMusicUrl) {
    		this.hQMusicUrl = hQMusicUrl;
    	}
    
    	public String getThumbMediaId() {
    		return thumbMediaId;
    	}
    
    	public void setThumbMediaId(String thumbMediaId) {
    		this.thumbMediaId = thumbMediaId;
    	}
    
    	/**
    	 * @param common
    	 * @param title
    	 * @param description
    	 * @param musicURL
    	 * @param hQMusicUrl
    	 * @param thumbMediaId
    	 */
    	public Music(Common common, String title, String description, String musicURL, String hQMusicUrl,
    			String thumbMediaId) {
    		this.common = common;
    		this.title = title;
    		this.description = description;
    		this.musicURL = musicURL;
    		this.hQMusicUrl = hQMusicUrl;
    		this.thumbMediaId = thumbMediaId;
    	}
    	
    	
    	public Music(){
    		
    	}
    }
    
    
        /**
         * 构造音乐消息
         * @param music 封装了解析结果的Music对象
         * @return 音乐消息XML字符串
         */
        public static String buildMusicMessage(Music music) {
        	String result = "";
        	if(music!=null){
        		result= String.format(
                    "<xml>" +
                            "<ToUserName><![CDATA[%s]]></ToUserName>" +
                            "<FromUserName><![CDATA[%s]]></FromUserName>" +
                            "<CreateTime>%s</CreateTime>" +
                            "<MsgType><![CDATA[music]]></MsgType>" +
                            "<Music>"+
                            "  <Title><![CDATA[%s]]></Title>"+
                            "  <Description><![CDATA[%s]]></Description>"+
                            "  <MusicUrl><![CDATA[%s]]></MusicUrl>"+
                            "  <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>" +
                            "  <ThumbMediaId><![CDATA[%s]]></ThumbMediaId>" +
                            "</Music>"+
                            "</xml>",
                            music.getCommon().getFromUserName(), music.getCommon().getToUserName(), music.getCommon().getCreateTime(),music.getTitle(),music.getDescription(),music.getMusicURL(),music.gethQMusicUrl(),music.getThumbMediaId());
            }
        	return result;
        } 
    

    ⑥构建图文消息

    package weixin.entity.message.news;
    import weixin.entity.message.articles.Articles;
    import weixin.entity.message.common.Common;
    
    /**
     * @所属类别:实体类
     * @用途:微信公众号开发中消息管理-图文消息
     * @author yilei
     * @version:1.0
     */
    public class News {
    	
    	private Common common;//公用消息实体类
    	
    	private String articleCount;//图文消息个数,限制为1条以内
    	
    	private Articles articles;//图文消息信息,注意,如果图文数超过1,则将只发第1条
    	
    	private String articlesXml;//图文消息信息,注意,如果图文数超过1,则将只发第1条(xml格式)
    
    	
    	public String getArticlesXml() {
    		return articlesXml;
    	}
    
    	public void setArticlesXml(String articlesXml) {
    		this.articlesXml = articlesXml;
    	}
    
    	public Common getCommon() {
    		return common;
    	}
    
    	public void setCommon(Common common) {
    		this.common = common;
    	}
    
    	public String getArticleCount() {
    		return articleCount;
    	}
    
    	public void setArticleCount(String articleCount) {
    		this.articleCount = articleCount;
    	}
    
    	public Articles getArticles() {
    		return articles;
    	}
    
    	public void setArticles(Articles articles) {
    		this.articles = articles;
    	}
    
    	/**
    	 * @param common
    	 * @param articleCount
    	 * @param articles
    	 */
    	public News(Common common, String articleCount, Articles articles,String articlesXml) {
    		this.common = common;
    		this.articleCount = articleCount;
    		this.articles = articles;
    		this.articlesXml = articlesXml;
    	}
    	/**
    	 * @param common
    	 * @param articleCount
    	 * @param articlesXml
    	 */
    	public News(Common common, String articleCount,String articlesXml) {
    		this.common = common;
    		this.articleCount = articleCount;
    		this.articlesXml = articlesXml;
    	}	
    	public News(){
    		
    	}
    
    }
    
    
    package weixin.entity.message.articles;
    /**
     * @所属类别:实体类
     * @用途:微信公众号开发中消息管理-图文消息-文章试题类
     * @author yilei
     * @version:1.0
     */
    public class Articles {
    	
    	private String title;//图文消息标题
    	
    	private String description;//图文消息描述
    	
    	private String picUrl;//图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
    	
    	private String url;//点击图文消息跳转链接
    
    	public String getTitle() {
    		return title;
    	}
    
    	public void setTitle(String title) {
    		this.title = title;
    	}
    
    	public String getDescription() {
    		return description;
    	}
    
    	public void setDescription(String description) {
    		this.description = description;
    	}
    
    	public String getPicUrl() {
    		return picUrl;
    	}
    
    	public void setPicUrl(String picUrl) {
    		this.picUrl = picUrl;
    	}
    
    	public String getUrl() {
    		return url;
    	}
    
    	public void setUrl(String url) {
    		this.url = url;
    	}
    
    	/**
    	 * @param title
    	 * @param description
    	 * @param picUrl
    	 * @param url
    	 */
    	public Articles(String title, String description, String picUrl, String url) {
    		this.title = title;
    		this.description = description;
    		this.picUrl = picUrl;
    		this.url = url;
    	}
    	
    	public Articles(){
    		
    	}
    }
    
    
        /**
         * 构造图文消息
         * @param news 封装了解析结果的News对象
         * @return 图文消息XML字符串
         */
        public static String buildNewsMessage(News news) {
        	String result = "";
        	if(news!=null){
        		result= String.format(
                    "<xml>" +
                            "<ToUserName><![CDATA[%s]]></ToUserName>" +
                            "<FromUserName><![CDATA[%s]]></FromUserName>" +
                            "<CreateTime>%s</CreateTime>" +
                            "<MsgType><![CDATA[news]]></MsgType>" +
                            "<ArticleCount>%s</ArticleCount>" +
                            "<Articles>%s</Articles>" +
                            "</xml>",
                            news.getCommon().getFromUserName(), news.getCommon().getToUserName(), news.getCommon().getCreateTime(),news.getArticleCount(),news.getArticlesXml());
            }
        	return result;
        }
     
        /**
         * 构造图文消息-一条消息记录
         * @param news 封装了解析结果的News对象
         * @return 图文消息XML字符串
         */
        private static String buildArticlesMessage(Articles articles) {
           	String result = "";
        	if(articles!=null){
        		result= String.format("<item>\n" +
                    "<Title><![CDATA[%s]]></Title> \n" +
                    "<Description><![CDATA[%s]]></Description>\n" +
                    "<PicUrl><![CDATA[%s]]></PicUrl>\n" +
                    "<Url><![CDATA[%s]]></Url>\n" +
                    "</item>", articles.getTitle(), articles.getDescription(),articles.getPicUrl(),articles.getUrl());
            }
        	return result;
        }
    

    (4)返回构建的消息xml格式的消息内容到微信服务器,由微信服务器转发到微信公众号回复

    	/**
    	 * Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
    	 * 这里和你服务器配置-令牌(token)一致
    	 */
    	public static final String TOKEN  ="yilei";
    	
    	
    	/**
    	 * 第三方用户唯一凭证
    	 */
    	public static final String APPID="wxc931e30eb7da614b";
    	
    	/**
    	 * 第三方用户唯一凭证密钥,即appsecret
    	 */
    	public static final String APPSECRET="ae68f7583fda08460e116fc02780aab8";
    	
    	/**
    	 * 获取access_token的调用接口
    	 */
    	public static final String ACCESS_TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    
    	/**
    	 * 接收到的消息类型-文本消息
    	 */
    	public static final String  TEXT="TEXT";
    	
    	/**
    	 * 接收到的消息类型-图片消息
    	 */
    	public static final String  IMAGE="IMAGE";
    
    	/**
    	 * 接收到的消息类型-语音消息
    	 */
    	public static final String  VOICE="VOICE";
    	
    	/**
    	 * 接收到的消息类型-视频消息
    	 */
    	public static final String  VIDEO="VIDEO";
    	
    	/**
    	 * 接收到的消息类型-小视频消息
    	 */
    	public static final String  SHORTVIDEO="SHORTVIDEO";
    	
    	/**
    	 * 接收到的消息类型-地理位置消息
    	 */
    	public static final String  LOCATION="LOCATION";	
    	
    	/**
    	 * 接收到的消息类型-链接消息
    	 */
    	public static final String  LINK="LINK";
    	
    	/**
    	 * 事件类型-事件消息
    	 */
    	public static final String  EVENT="EVENT";
    	
    	/**
    	 * 素材你管理-新增临时素材接口
    	 */
    	public static final String New_Temporary_Material_Interface = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
    
    
    
        /**
         * 根据消息内容构造返回消息
         * @param map 封装了解析结果的Map
         * @return responseMessage(响应消息)
         */
        public static String buildResponseMessage(Map map) {
        	//响应消息
        	String responseMessage="";
        	//得到消息类型
        	String msgType = map.get("MsgType").toString().toUpperCase();
    
        	Common common = new Common(map.get("ToUserName").toString(), map.get("FromUserName").toString(), WeiXinCheck.getCreateTime());
        	if("TEXT".equals(msgType)){
            	// 消息内容
            	String content = map.get("Content").toString();
        		switch (content) {
    			case "文本":
    				//处理文本消息
    				Text text = new Text(common, "欢迎猪牧狼马蜂!");
    				responseMessage = WeiXinCheck.buildTextMessage(text);
    				break;
    			case "图片":
    				//处理图片消息
    				Image image = new Image(common, "f8nhXwittsvHHMxjRjLyIh969fQbsfIsNLhamifwxVqoZTyuEgMg8Il7WG0-1vZ_");
    				responseMessage = WeiXinCheck.buildImageMessage(image);
    				break;
    			case "语音":
    				//处理语音消息
    				Voice voice = new Voice(common, "zzefkVeuF0ZSGZ39B3rzbo9243uyksewR682A3leU9jNSoMrQG0ErkvO2qtptNnr");
    				responseMessage = WeiXinCheck.buildVoiceMessage(voice);
    				break;
    			case "视频":
    				//处理视频消息
    				Video video = new Video(common, "mQr8c5NqywVyLhwMT1j5mhi03jSvK19MvLTcqFRej_PoW8Uai5H-7lHMk8XL14B5", "《微信公众号开发学习视频》","本视频详细的介绍了微信公众号开发流程和步骤,可以更好帮助你快速的学会开发微信公众号。");
    				responseMessage = WeiXinCheck.buildVideoMessage(video);
    				break;
    			case "音乐":
    				//处理音乐消息
    				Music music = new Music(common, "音乐标题", "音乐描述", "http://www.ytmp3.cn/down/53421.mp3","http://www.ytmp3.cn/down/53420.mp3","f8nhXwittsvHHMxjRjLyIh969fQbsfIsNLhamifwxVqoZTyuEgMg8Il7WG0-1vZ_");
    				responseMessage = WeiXinCheck.buildMusicMessage(music);
    				break;
    			case "图文":
    				//处理音乐消息
    				Articles articles1 = new Articles("图文消息标题1", "图文消息描述","http://e5cd1621.ngrok.io/weixin/media/image/image.JPG", "https://www.baidu.com");
    				Articles articles2 = new Articles("图文消息标题1", "图文消息描述","http://e5cd1621.ngrok.io/weixin/media/image/image.JPG", "https://www.baidu.com");
    				Articles articles3 = new Articles("图文消息标题1", "图文消息描述","http://e5cd1621.ngrok.io/weixin/media/image/image.JPG", "https://www.baidu.com");
                    List<Articles> list = new ArrayList<Articles>();
                    list.add(articles1);list.add(articles2);list.add(articles3);
                    
    				StringBuffer articlesXml= new StringBuffer( );
    				for (Articles articles : list) {
    					articlesXml.append(WeiXinCheck.buildArticlesMessage(articles));				
    				}
    				
    				News news = new News(common,String.valueOf(list.size()),articlesXml.toString());
    				responseMessage = WeiXinCheck.buildNewsMessage(news);
    				break;
    			default:
    				//处理文本消息
    				Text text1 = new Text(common, "请回复如下关键词:\n文本\n图片\n语音\n视频\n音乐\n图文");			
    				responseMessage = WeiXinCheck.buildTextMessage(text1);
    				break;
    			}
        	}
        	//返回响应消息
        	return responseMessage;
        }
    

    四、项目运行结果

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    五、素材管理-新增临时素材

    上述中回复的图片、视频、语言等多媒体消息都需要media_id,而media_id可以调用素材管理接口来获取,本例中我使用的时新增临时素材接口

    具体调用方式请参考
    微信开发学习总结(五)——素材管理(1)—获取临时素材和新增永久素材
    https://blog.csdn.net/qq_29914837/article/details/82923132


    本节代码:
    微信开发学习总结(三)——消息管理(2)-接受普通消息和被动回复用户消息——项目源码
    下载地址:
    https://download.csdn.net/download/qq_29914837/10699782


    下一节内容:
    微信开发学习总结(三)——消息管理(3)-接收事件推送
    https://blog.csdn.net/qq_29914837/article/details/82925451


    展开全文
  • 微信开发中的被动回复消息

    千次阅读 2018-04-18 17:32:50
    被动回复用户消息 当用户发送消息给公众号时(或某些特定的用户操作引发的事件推送时...严格来说,发送被动响应消息其实并不是一种接口,而是对微信服务器发过来消息的一次回复。 假如服务器无法保证在五秒内处理...

    被动回复用户消息


            当用户发送消息给公众号时(或某些特定的用户操作引发的事件推送时),会产生一个POST请求,开发者可以在响应包(Get)中返回特定XML结构,来对该消息进行响应(现支持回复文本、图片、图文、语音、视频、音乐 [目前已学文本,图片、图文])。严格来说,发送被动响应消息其实并不是一种接口,而是对微信服务器发过来消息的一次回复。

            假如服务器无法保证在五秒内处理并回复,必须做出下述回复,这样微信服务器才不会对此作任何处理,并且不会发起重试(这种情况下,可以使用客服消息接口进行异步回复),否则,将出现严重的错误提示。详见下面说明: 1、直接回复success(推荐方式) 2、直接回复空串(指字节长度为0的空字符串,而不是XML结构体中content字段的内容为空)

            一旦遇到以下情况,微信都会在公众号会话中,向用户下发系统提示“该公众号暂时无法提供服务,请稍后再试”:1、开发者在5秒内未回复任何内容 2、开发者回复了异常数据,比如JSON数据等

    回复文本消息

    <xml> <ToUserName>< ![CDATA[toUser] ]></ToUserName> <FromUserName>< ![CDATA[fromUser] ]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType>< ![CDATA[text] ]></MsgType> <Content>< ![CDATA[你好] ]></Content> </xml>
    
    参数是否必须描述
    ToUserName接收方帐号(收到的OpenID)
    FromUserName开发者微信号
    CreateTime消息创建时间 (整型)
    MsgTypetext
    Content回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)

    回复图片消息

    <xml><ToUserName>< ![CDATA[toUser] ]></ToUserName><FromUserName>< ![CDATA[fromUser] ]></FromUserName><CreateTime>12345678</CreateTime><MsgType>< ![CDATA[image] ]></MsgType><Image><MediaId>< ![CDATA[media_id] ]></MediaId></Image></xml>
    
    参数是否必须说明
    ToUserName接收方帐号(收到的OpenID)
    FromUserName开发者微信号
    CreateTime消息创建时间 (整型)
    MsgTypeimage
    MediaId通过素材管理中的接口上传多媒体文件,得到的id。

    回复图文消息

    <xml><ToUserName>< ![CDATA[toUser] ]></ToUserName><FromUserName>< ![CDATA[fromUser] ]></FromUserName><CreateTime>12345678</CreateTime><MsgType>< ![CDATA[news] ]></MsgType><ArticleCount>2</ArticleCount><Articles><item><Title>< ![CDATA[title1] ]></Title> <Description>< ![CDATA[description1] ]></Description><PicUrl>< ![CDATA[picurl] ]></PicUrl><Url>< ![CDATA[url] ]></Url></item><item><Title>< ![CDATA[title] ]></Title><Description>< ![CDATA[description] ]></Description><PicUrl>< ![CDATA[picurl] ]></PicUrl><Url>< ![CDATA[url] ]></Url></item></Articles></xml>
    
    参数是否必须说明
    ToUserName接收方帐号(收到的OpenID)
    FromUserName开发者微信号
    CreateTime消息创建时间 (整型)
    MsgTypenews
    ArticleCount图文消息个数,限制为8条以内
    Articles多条图文消息信息,默认第一个item为大图,注意,如果图文数超过8,则将会无响应
    Title图文消息标题
    Description图文消息描述
    PicUrl图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
    Url点击图文消息跳转链接
    被动回复文本,代码如下:
    public function reply(){
    		$mp = $this->mp; //使用中的公众号id
                    //获取前台页面的数据
    		$content = I('post.content');
    		$keyword = I('post.keyword');
                    //追加数据到数据库
    		$text = M('reply_text');	
    		$str['content'] = $content;
    		$ret = $text->add($str);		
    		$rule = M('rule');	
    		$data['keyword'] = $keyword;
    		$data['type'] = 'text';
    		$data['mpid'] = $mp['id'];
    		$data['reply_id'] = $ret;
    		$ret = $rule->add($data);
    public static function text(&$request){
            //获取哪个公众号发过来的请求
            $mpid=$_GET['id'];
            $content=$request['content'];
            $where['mpid']=$mpid;
            $where['keyword']=$content;
            $data=M('rule')->where($where)->find();
            if($data){
                $reply_id=$data['reply_id'];
                $type=$data['type'];
                switch($type){
                    case 'text':
                       $reply=M('reply_text')->find($reply_id);
                       if($reply){
                        $reply_text=$reply['content'];
                       }else{
                        $reply_text="出错啦";
                       }
                       return ResponsePassive::text($request['fromusername'], $request['tousername'], $reply_text); 
                       break;}}
    


    展开全文
  • 微信消息处理

    2019-03-27 04:49:22
    首先登录微信公众平台 https://mp.weixin.qq.com,在开发->基本配置中填写服务器配置(接收处理微信消息的地址)保存好你的配置,在加解密时需要使用。 验证 开发者提交信息后,微信服务器将发送GET请求到填写的...
        

    配置

    首先登录微信公众平台 https://mp.weixin.qq.com,在开发->基本配置中填写服务器配置(接收处理微信消息的地址)
    图片描述
    保存好你的配置,在加解密时需要使用。

    验证

    开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数如下表所示:

    参数 描述
    signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
    timestamp 时间戳
    nonce 随机数
    echostr 随机字符串

    开发者通过检验 signature 对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回 echostr 参数内容,则接入生效,成为开发者成功,否则接入失败。

    加密/校验流程如下:

    1. tokentimestampnonce 三个参数进行字典序排序
    2. 将三个参数字符串拼接成一个字符串进行 sha1 加密
    3. 开发者获得加密后的字符串可与 signature 对比,标识该请求来源于微信
    public function validate() {
        $echoStr = Input::get('echostr');
        if (!empty($echoStr)) {
            $signature = Input::get('signature');
            $timestamp = Input::get('timestamp');
            $nonce = Input::get('nonce');
            $tmpArr = [
                '你配置的Token',
                $timestamp,
                $nonce
            ];
            sort($tmpArr);
            $tmpStr = implode('', $tmpArr);
            $tmpStr = sha1($tmpStr);
            if ($tmpStr == $signature) {
                echo $echoStr;
                exit;
            }
        }
    }

    PHP示例代码下载:下载

    消息加解密

    微信官方文档:加密解密技术方案

    首先获取微信发送的XML数据:

    $xmlString = file_get_contents("php://input");

    使用下载的示例代码解密消息:

    //提供提取消息格式中的密文 XmlParse类在xmlparse.php里
    $secretData = (new XmlParse())->extract($xmlString);
    //对密文进行解密 Prpcrypt类在pkcs7Encoder.php里
    $result = (new PrpCrypt('你配置的EncodingAESKey'))->decrypt($secretData[1]);

    之后就根据具体业务来实现了:

    $xmlFormatData = simplexml_load_string($result[1], 'SimpleXMLElement', LIBXML_NOCDATA);
    $event = (string)$xmlFormatData->Event;
    $eventKey = isset($xmlFormatData->EventKey) ? (string)$xmlFormatData->EventKey : '';
    $openId = (string)$xmlFormatData->FromUserName;
    $toUserName = (string)$xmlFormatData->ToUserName;
    
    //事件处理
    if ($event === 'VIEW' || $event == "CLICK") {
        //自定义菜单事件
    }
    if (!$eventKey && $event == "subscribe") {
        //扫描公众号二维码关注事件
    }
    if ($eventKey && $event == "subscribe") {
        //扫描二维码关注事件
    }
    if ($eventKey && $event == "SCAN") {
        //扫描生成的二维码
    }
    if ($event == "unsubscribe") {
        //取消关注事件
    }
    if ($event === 'card_pass_check' || $event === 'card_not_pass_check') {
        //卡券审核通过或审核未通过事件
    }
    if ($event === 'user_get_card') {
        //卡券领取事件
    }
    if ($event === 'user_consume_card') {
        //卡券核销事件
    }
    
    //其他事件不处理
    return false;

    需要发送加密消息时:

    $wxBizMsg = new WxBizMsgCrypt('你配置的Token', '你配置的EncodingAESKey', '你公众号的APPID');
    //加密后的消息,传引用
    $encryptMsg = '';
    //未加密的消息为XML格式的字符串
    echo $wxBizMsg->encryptMsg('未加密的消息', time(), str_random(16), $encryptMsg);

    假如服务器无法保证在五秒内处理并回复,必须做出下述回复,这样微信服务器才不会对此作任何处理,并且不会发起重试(这种情况下,可以使用客服消息接口进行异步回复),否则,将出现严重的错误提示。
    详见下面说明:

    1. 直接回复success(推荐方式)
    2. 直接回复空串(指字节长度为0的空字符串,而不是XML结构体中content字段的内容为空)

    一旦遇到以下情况,微信都会在公众号会话中,向用户下发系统提示“该公众号暂时无法提供服务,请稍后再试”:

    1. 开发者在5秒内未回复任何内容
    2. 开发者回复了异常数据,比如JSON数据等

    具体的各种XML格式见:被动回复用户消息

    展开全文
  • 在上篇《微信开发学习总结(二)——微信开发入门》我们介绍了微信公众平台的基本原理,如何接入微信公众号,如何保持access_token的长期有效性以及进行了简单的文本消息测试,本篇再来具体细说一如何实现微信公众号...
  • 微信公众号被动回复方案梳理

    千次阅读 2016-08-25 15:06:45
    微信公众号机器人客服回复方案预梳理 一、微信公众平台开发接入指南 接入微信公众平台开发,需要按照如下步骤完成: 1、填写服务器配置 登录微信公众平台官网后,在公众平台后台管理页面 - 开发者中心页,点击...
  • 微信开发之入门教程

    万次阅读 多人点赞 2016-01-12 10:55:26
    微信开发也是有了一定的认识。在此,小宝鸽再次无私地分享给大家啦。其实微信开发跟web开发没有多大的区别,只是经过了微信,然后再由浏览器打开。因为经过微信,因此你的web会附加一些微信平台所提供的一些功能,...
  • 它不仅仅是社交软件,还是手机支付工具,而且现在的公众号更是微信的一大特色,他可以对外宣传和介绍自己的产品,作为一名IT,我们不仅要会使用微信,还要进行微信的二次开发,接下来就给大家介绍一下微信开发的入门...
  • 因为年会需要用到公众号消息通知功能,和自定义菜单,所以开发了有关公众号的部分功能,期间遇到了很多的问题,特意记录一次。 其中微信公众号被动消息回复出现的问题最多,一直提示出现故障,不能使用。 出现这种...
  • 微信公众号开发之自动回复

    千次阅读 2019-07-29 17:58:30
    自动回复这块是比较麻烦的 一、后端回复管理 ...规则表中关键词和回复内容拼接id成字符串 存入表中 二、前端回复逻辑 $this->app->server->push(function($message){ switch ($message['Msg...
  • 微信开发,自动回复表情符号

    千次阅读 2018-09-20 22:38:11
    //表情符号 ... //将字符串组合成json格式 $emoji_str = '[&amp;amp;amp;quot;'.$emoji_str.'&amp;amp;amp;quot;]'; $emoji_arr = json_decode($emoji_str, true); if (c...
  • 微信公众号回复消息换行符处理

    千次阅读 2018-12-11 11:51:36
    一、直接回复字符串,处理换行符只需要把字符串使用双引号包含即可,这种方法基本上都会,没有什么难度 二、从数据库读取带有换行符的文本  这时,换行符会被当成字符串,而不是特殊字符。这样的话,微信回复的也...
  • 微信开发自动回复消息乱码问题

    千次阅读 2018-01-05 19:01:07
    最近开发微信服务号,遇到了一个问题,在编写自动回复消息的时候出现乱码,最后发现问题是由于spring mvc的@ResponseBody注解返回字符串时默认返回的是“ISO-8859-1”而不是utf-8。  虽然大家的项目里面可能都有...
  • 上一篇:接入指南这部分是实现简单的自动回复,当然也是很大一部分功能的实现基础,这里使用了图灵机器人的接口。效果图如下: 当然,这个机器人的效果如何不是我能管得了的事情了,类似图灵机器人,我们还可以实现...
  • 需求在公众号内的输入任意文字,文字相关的第三方网站链接实现简单后台设置我们在微信公众平台上,是可以进行简单的自定义消息回复的。这里的显然不能满足我们的需求。配置服务器配置域名略配置测试服务器略。和一般...
  • 今天跟大家分享一下微信自动回复功能开发,在这这次需要准备好自己的服务器(可以在外网上面访问的),以及在公众号上面进行服务器认证,并且开启服务器配置。 用户在给公众号发消息的时候,微信会把这些消息以xml...
  • 微信开发五之微信红包开发

    千次阅读 2018-01-18 10:20:24
    微信支付的开发,作为微信公众号开发的难点之一,另不少开发者颇为头痛。市面上微信支付开发成本动辄上万,也让刚创业的小公司无力负担。本次文章将详细介绍微信支付中微信原生红包的开发思路,并提供源代码。以供...
  • 微信公众号自动回复功能开发  本篇主要讲解 微信公众号自动回复功能开发,让我们自己去托管公众号回复的功能,这样可以更加灵活的根据公众号收到的信息来制定特定的回复信息,一起来了解吧!  1.注册公众号  &...
  • 上一篇《微信开发学习总结(一)——微信开发环境搭建》我们已经完成了微信开发的准备工作,准备工作完成之后,就要开始步入正题了。 一、微信公众平台的基本原理  在开始做之前,先简单介绍了微信公众平台的基本...
  • 微信公众号开发基本流程

    万次阅读 多人点赞 2019-04-26 09:40:21
    过年前后做了个微信公众号项目,已经过去一段时间了,抽空回忆总结下基本流程吧,不然很快估计自己就忘了。。 微信公众平台官网:https://mp.weixin.qq.com 文章目录一、注册公众号二、了解公众号管理页面三、必备...
1 2 3 4 5 ... 20
收藏数 6,965
精华内容 2,786
关键字:

微信开发回复空字符串