标签 微信开发 下的文章

微信小程序的抽红包组件,小编一共是做了两种,第一种呢用了很长时间了,可能是时间长了,觉得不是那么霸气了,就重新又制作了一个,第一个当时使用了大量的图片,这也导致了加载的时候很慢,这里面的主要样式还是参考的别人的代码,总而言之效果还是不错的,不过现在呢,小编又自己写了个抽红包的组件,这回看上去比较好看了,首先我们先看下2.0代码吧。因为是放在具体项目里面的,有些细节性的东西大家可以改改:
首先是wxml,大部分的样式也写在了这里面:

<view style="position: fixed; top: 0; left: 0; display: flex; flex-direction: row; justify-content: center; align-items: center; width: 100%; height: 100vh; z-index: 100000000000000000000; background: rgba(0, 0, 0, 0.4);">
    <view class="{{open ? 'red-packet-open' : ''}}" style="background: #ff3d32; border-radius: 30rpx; border-bottom-right-radius: 100% 120px; border-bottom-left-radius: 100% 120px; box-shadow: 0px 3px 5px 1px #e92c27; width: 590rpx; height: 700rpx; position: absolute; top: 80rpx; z-index: 101;">
        <view wx:if="{{name}}" style="color: #F5B37B; text-align: center; font-size: 40rpx; padding-top:100rpx;">{{name}}的红包</view>
        <view wx:if="{{text}}" style="color: #F5B37B; text-align: center; font-size: 30rpx; padding-top:60rpx;">{{text}}</view>
        <view style="position: absolute; bottom: -80rpx; left: 220rpx; background: #E8bF7B; width: 150rpx; height: 150rpx; line-height: 150rpx; text-align: center; border-radius: 75rpx; font-size: 60rpx;" bindtap="handleOpen">抽</view>
    </view>
    <view class="{{open ? 'red-packet-open' : ''}}" style="background: #ff3328; border-radius: 30rpx; border-top-right-radius: -120px; border-top-left-radius: -120px; width: 590rpx; height: 464rpx; position: absolute; top: 500rpx; z-index: 100;"></view>
    <view style="width: 590rpx; height: 883rpx; position: absolute; top: 80rpx; z-index: 90; background: #FFFFFF; border-radius: 30rpx;">
        <view style="height: 260rpx; border-radius: 30rpx; border-bottom-right-radius: 100% 120px; border-bottom-left-radius: 100% 120px; background: #ff3d32; display: flex; flex-direction: column; justify-content: center; align-items: center;text-align: center;">
            <image mode="aspectFill" src="{{user?user.avatar : ''}}" style="width: 130rpx; height: 130rpx; min-width: 130rpx; min-height: 130rpx; border-radius: 65rpx; position: absolute; top: 180rpx;" />
            <view style="position: absolute; top: 0; right: 20rpx; color: #FFFFFF; font-size: 56rpx;" bind:tap="close">X</view>
        </view>
        <view style="display: flex; flex-direction: column; justify-content: center; align-items: center;text-align: center; font-size: 26rpx; margin: 60rpx;">
            <text style="color: #f33035; font-size: 40rpx;">{{title}}</text>
            <text style="padding: 10rpx; color: #f33035; font-size: 50rpx;">{{msg}}</text>
            <view style="text-align: center; font-size: 30rpx; margin: 20rpx;">{{tips}}</view>
            <view wx:if="{{balance}}" bind:tap="toBalance" style="text-align: center; font-size: 30rpx; margin: 20rpx; color: #f33035; padding-top: 60rpx;"><text wx:if="{{balance_name}}">{{balance_name}}</text>余额:{{balance}}>>
            </view>
        </view>
    </view>
</view>

在wxss里面实现了一个动画:

.red-packet-open {
    animation: open-up 0.2s ease-in-out 0.2s 1 normal;
    animation-fill-mode: forwards;
    display: none;
}

在js里面就是相关的逻辑了

const audio = wx.createInnerAudioContext()
audio.src = 'https://audiosrc.shangpo.net/sources/coin.mp3'
let g = getApp().globalData;

Component({
    properties: {
        title: {
            type: String,
            value: null
        },
        msg: {
            type: String,
            value: null
        },
        tips: {
            type: String,
            value: null
        },
        bind: {
            type: Boolean,
            value: true,
        },
        open: {
            type: Boolean,
            value: false
        },
        amount_ui: {
            type: String,
            value: null
        },
        name: {
            type: String,
            value: null
        },
        text: {
            type: String,
            value: null
        },
        user: {
            type: Object,
            value: g.user
        }, 
        balance: {
            type: String,
            value: null
        },
        balance_name: {
            type: String,
            value: null
        }
    },
    data: {

    },
    methods: {
        handleOpen() {
            var that = this
            if (that.data.bind) {
                that.setData({
                    title: that.data.title,
                    msg: that.data.msg,
                    bind: false,
                    // 以下两项为测试页面使用
                    // tips: that.data.tips,
                    // open: true,
                })
                audio.play()
                this.triggerEvent('choujiang', {})
            }
        },
        close() {
            this.triggerEvent('close_redpacket', {})
        },
        toBalance(){
            this.triggerEvent('toBalance', {})
        }
    }
})

1.0版本的基本上就是样式上的不一样,小编在这里就不列出来了,有需要的可以单独联系小编。

微信小程序在用户发布内容的时候往往需要检查发布内容是否违规,是否有敏感词汇,或者图片等有木有问题等等吧。检查这些内容当然可以使用手工进行检测,人工进行审核,但是那样是不是就太麻烦了。所以微信官方也给我们提供了免费的查询接口,记住是免费的。不过目前只能是微信才能使用。下面小编使用python封装的两个方法。

msg_sec_check文本内容检查

import requests
from flask import json, jsonify

def msg_sec_check(content=None, access_token=None):
    '''文字内容检查'''
    if content == None:
        return True
    url = 'https://api.weixin.qq.com/wxa/msg_sec_check?access_token=%s' % access_token
    req = {
        'content': content
    }
    req = json.dumps(req, ensure_ascii=False).encode('utf-8')
    rs = requests.post(url, data=req)
    if json.loads(rs.content).get("errcode")!=0:
        return False
    return True

参数说明:

  • content:要检测的内容
  • access_token:access_token

msg_sec_check图片检测

import requests
from flask import json, jsonify

def msg_sec_check(media=None, access_token=None):
    '''图片检查'''
    if content == None:
        return True
    url = 'POST https://api.weixin.qq.com/wxa/img_sec_check?access_token=%s' % access_token
    req = {
        'media': media
    }
    req = json.dumps(req, ensure_ascii=False).encode('utf-8')
    rs = requests.post(url, data=req)
    if json.loads(rs.content).get("errcode")!=0:
        return False
    return True

参数说明:

  • media:要检测的图片,格式支持PNG、JPEG、JPG、GIF,图片尺寸不超过 750px x 1334px
  • access_token:access_token

微信小程序也是可以引导用户关注公众号的,不过呢使用场景很严格,大家使用的时候注意一下哦。该组件限定最小宽度为300px,高度为定值84px。

代码片段:

<official-account></official-account>

使用前提:

  • 小程序和公众号必须同一主体。
  • 小程序打开的场景值:扫小程序码场景(场景值1047,场景值1124),从聊天顶部场景(场景值1089)中的「最近使用」内打开,从其他小程序返回小程序(场景值1038)时,若小程序之前未被销毁,则该组件保持上一次打开小程序时的状态,扫二维码(场景值 1011)打开 体验版小程序打开,总之场景值有(1011, 1124, 1047, 1089, 1038)
  • 用户未关注公证号。
  • 每个页面只能使用一次。
  • 公众号关注组件,场景值为1089(从聊天顶部)不显示

测试环境使用方法

在开发者工具中,编译的时候选择通过二维码编译,选择小程序二维码,进入就可以了。小编发现通过改变场景值是不管用的。

timg.jpeg

1 第一步:用户同意授权,获取code

2 第二步:通过code换取网页授权access_token

3 第三步:刷新access_token(如果需要)

4 第四步:拉取用户信息(需scope为 snsapi_userinfo)

简单网页授权

//简单授权
    function getBaseInfo(){
        //1.获取到code
        $appid = "wxde8d3eacc9f91cae";
        $redirect_uri = urlencode("http://wx.sunxiaoning.com/index.php/Wx/index/getUserOpenId");
        $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=snsapi_base&state=123#wechat_redirect";
        header('location:'.$url);
        
    }
    function getUserOpenId(){
        //2.获取到网页授权的access_token
        $appid = "wxde8d3eacc9f91cae";
        $appsecret = "3ae10c48de0ec193a7cc695f098c2817";
        $code = $_GET['code'];
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$appid."&secret=".$appsecret."&code=".$code."&grant_type=authorization_code";
        //3.拉取用户的openid
        $res = $this->http_curl($url,'get');
        var_dump($res);

    }

详细授权

    function getUserDetail(){
        //1.获取到code
        $appid = "wxde8d3eacc9f91cae";
        $redirect_uri = urlencode("http://wx.sunxiaoning.com/index.php/Wx/index/getUserInfo");
        $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect";
        header('location:'.$url);
    }
    function getUserInfo(){
        //2.获取到网页授权的access_token
        $appid = "wxde8d3eacc9f91cae";
        $appsecret = "3ae10c48de0ec193a7cc695f098c2817";
        $code = $_GET['code'];
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$appid."&secret=".$appsecret."&code=".$code."&grant_type=authorization_code";
        //3.拉取用户的openid
        $res = $this->http_curl($url,'get');
        $access_token = $res['access_token'];
        $openid = $res['openid'];
        //4.拉取用户的详细信息
        $url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";
        $res = $this->http_curl($url);
        var_dump($res);

    }

自定义菜单的创建

自定义菜单基本要求:
1.自定义菜单最多包含3个一级菜单,每个一级菜单最多包含5个二级菜单。
2.一级菜单最多4个汉字,二级菜单最多包含7个汉字,多出来的部分以"..."的形式来展现。
3.在创建自定义菜单后,微信不会立即生效,为了更快的看到效果,可以取消关注后,重新进行关注。

接口调用请求说明:
http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

下面简单介绍两种常用的请求:
click和view的请求示例

 {
     "button":[
     {    
          "type":"click",
          "name":"今日歌曲",
          "key":"V1001_TODAY_MUSIC"
      },
      {
           "name":"菜单",
           "sub_button":[
           {    
               "type":"view",
               "name":"搜索",
               "url":"http://www.soso.com/"
            },
            {
                 "type":"miniprogram",
                 "name":"wxa",
                 "url":"http://mp.weixin.qq.com",
                 "appid":"wx286b93c14bbf93aa",
                 "pagepath":"pages/lunar/index"
             },
            {
               "type":"click",
               "name":"赞一下我们",
               "key":"V1001_GOOD"
            }]
       }]
 }

参数说明

参数是否必须说明
button一级菜单数组,个数应为1~3个
sub_button二级菜单数组,个数应为1~5个
type菜单的响应动作类型,view表示网页类型,click表示点击类型,miniprogram表示小程序类型
name菜单标题,不超过16个字节,子菜单不超过60个字节
keyclick等点击类型必须菜单KEY值,用于消息接口推送,不超过128字节
urlview、miniprogram类型必须网页 链接,用户点击菜单可打开链接,不超过1024字节。 type为miniprogram时,不支持小程序的老版本客户端将打开本url。
media_idmedia_id类型和view_limited类型必须调用新增永久素材接口返回的合法media_id
appidminiprogram类型必须小程序的appid(仅认证公众号可配置)
pagepathminiprogram类型必须小程序的页面路径

返回结果:

  • 正确时的返回JSON数据包如下:

    {"errcode":0,"errmsg":"ok"}

  • 错误时的返回JSON数据包如下(示例为无效菜单名长度):

    {"errcode":40018,"errmsg":"invalid button name size"}

示例代码:(thinkphp3.2.3)

  /**
     * 创建自定义菜单
     * @return [type]
     */
    public function defineditem(){
        //创建微信菜单
        //目前微信接口的调用都是通过curl  post/get
        header('content-type:text/html;charset=utf-8');
        $access_token = $this->getWxAccessToken();
        $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token;
        $postArr = array(
                'button'=>array(
                    array(
                        'name'=>urlencode('菜单一'),
                        'type'=>'click',
                        'key'=>'item1',
                    ),//第一个一级菜单
                    array(
                        'name'=>urlencode('菜单二'),
                        'sub_button'=>array(
                            array(
                                'name'=>urlencode('二级菜单一'),
                                'type'=>'click',
                                'key'=>'songs',
                            ),//第一个二级菜单
                            array(
                                'name'=>urlencode('二级出菜单二'),
                                'type'=>'view',
                                'url'=>'http://www.sunxiaoning.com',
                            )//第一个二级菜单
                        )
                    ),//第二个一级菜单
                    array(
                        'name'=>urlencode('菜单三'),
                        'type'=>'view',
                        'url'=>'http://bbs.sunxiaoning.com',
                    )//第三个一级菜单
                )
            
        );
        $postJson = urldecode(json_encode($postArr));
        //echo "$postJson"."<br>";
        $res = $this->http_curl($url,'post','json',$postJson);
        //var_dump($res);
    }
    /**
     * 返回access_token
     * @return [type] [description]
     */
    public function getWxAccessToken(){
        //将access_token存在session/cookie中
        if($_SESSION['access_token']&&$_SESSION['expire_time']>time()){
            //如果access_token在session并未过期
            return $_SESSION['access_token'];
        }else{
            //如果access_token不存在或者已经过期,重新获取access_token
            $appid = 'wxde8d3eacc9f91cae';
            $appsecret = '3ae10c48de0ec193a7cc695f098c2817';
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret;
            $res = $this->http_curl($url,'get','json');
            $access_token = $res['access_token'];
            //将创新获取的access_token存到session
            $_SESSION['access_token'] = $access_token;
            $_SESSION['expire_time'] = time()+7000;
            return $access_token;
        }
    }
/**
     * @param  url
     * @param  获取方式
     * @param  获取到的格式
     * @param  string
     * @return [type]
     */
    function http_curl($url,$type='get',$res='json',$arr=''){
        //1.初始化curl
        $ch = curl_init();
        //2.设置curl的参数
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        if($type == 'post'){
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $arr);
        }
        //3.采集
        $output = curl_exec($ch);
        //4.关闭
        if($res == 'json'){
            if(curl_errno($ch)){
                return curl_error($ch);
            }else{
                return json_decode($output,true);
            }
        }
        curl_close($output);
    }

自定义菜单事件消息回复

点击菜单拉取消息时的事件推送

推送XML数据包示例:

<xml>
    <ToUserName>< ![CDATA[toUser] ]></ToUserName>
    <FromUserName>< ![CDATA[FromUser] ]></FromUserName>  
    <CreateTime>123456789</CreateTime>
    <MsgType>< ![CDATA[event] ]></MsgType>
    <Event>< ![CDATA[CLICK] ]></Event>
    <EventKey>< ![CDATA[EVENTKEY] ]></EventKey>
</xml>

参数说明:

参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgType消息类型,event
Event事件类型,CLICK
EventKey事件KEY值,与自定义菜单接口中KEY值对应

点击菜单跳转链接时的事件推送

推送XML数据包示例:

<xml>
   <ToUserName>< ![CDATA[toUser] ]></ToUserName>
   <FromUserName>< ![CDATA[FromUser] ]></FromUserName>
   <CreateTime>123456789</CreateTime>
   <MsgType>< ![CDATA[event] ]></MsgType>
   <Event>< ![CDATA[VIEW] ]></Event>
   <EventKey>< ![CDATA[www.qq.com] ]></EventKey>
</xml> 

参数说明:

参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgType消息类型,event
Event事件类型,VIEW
EventKey事件KEY值,设置的跳转URL

示例代码(thinkphp3.2.3)

  public function reponseMsg(){
    if (strtolower($postObj->Event)=='click') {
        //如果是自定义菜单中的event -> click
        if(strtolower($postObj->EventKey)=='item1'){
             $content  = "您点击了自定义菜单item1";
        }
        if(strtolower($postObj->EventKey)=='songs'){
             $content  = "您点击了自定义菜单songs";
        }
            $toUser   = $postObj->FromUserName;
            $fromUser = $postObj->ToUserName;
            $time     = time();
            $msgType  =  'text';
            $template = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <Content><![CDATA[%s]]></Content>
                            </xml>";
             $info     = sprintf($template, $toUser, $fromUser, $time, $msgType, $content);
             echo $info;
    }
}

在微信开发的过程中,调用接口的时候都需使用公众号的全局唯一接口调用凭据access_token,在使用之前我们需要获取它。目前Access_token的有效期通过返回的expire_in来传达,目前是7200秒之内的值。中控服务器需要根据这个有效时间提前去刷新新access_token。在刷新过程中,中控服务器可对外继续输出的老access_token,此时公众平台后台会保证在5分钟内,新老access_token都可用,这保证了第三方业务的平滑过渡。
接口调用请求说明
https请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

参数说明

参数是否必须说明
grant_type获取access_token填写client_credential
appid第三方用户唯一凭证
secret第三方用户唯一凭证密钥,即appsecret

返回说明

正常情况下,微信会返回下述JSON数据包给公众号:

{"access_token":"ACCESS_TOKEN","expires_in":7200}

参数说明

参数说明
access_token获取到的凭证
expires_in凭证有效时间,单位:秒

错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):
{"errcode":40013,"errmsg":"invalid appid"}

返回码说明

返回码说明
-1系统繁忙,此时请开发者稍候再试
0请求成功
40001AppSecret错误或者AppSecret不属于这个公众号,请开发者确认AppSecret的正确性
40002请确保grant_type字段值为client_credential
40164调用接口的IP地址不在白名单中,请在接口IP白名单中进行设置。(小程序及小游戏调用不要求IP地址在白名单内。)

以上的信息均来源于微信公众平台的开发者文档。但不保证是最新的,使用者可以自己上官网查看。
由于access_token的存活时间有时间上的限制,而且目前每天只能调用2000次,所有我们必须对access_token进行有效的利用,我们可以把它保存在session中,并设置有效的时间,如果有效,我们直接返回,无需重新获取。
示例代码:(thinkphp3.2.3)

    /**
     * 返回access_token
     * @return [type] [description]
     */
    public function getWxAccessToken(){
        //将access_token存在session/cookie中
        if($_SESSION['access_token']&&$_SESSION['expire_time']>time()){
            //如果access_token在session并未过期
            return $_SESSION['access_token'];
        }else{
            //如果access_token不存在或者已经过期,重新获取access_token
            $appid = 'wxde8d3eacc9f91cae';
            $appsecret = '3ae10c48de0ec193a7cc695f098c2817';
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret;
            $res = $this->http_curl($url,'get','json');
            $access_token = $res['access_token'];
            //将创新获取的access_token存到session
            $_SESSION['access_token'] = $access_token;
            $_SESSION['expire_time'] = time()+7000;
            return $access_token;
        }
    }


    /**
     * @param  url
     * @param  获取方式
     * @param  获取到的格式
     * @param  string
     * @return [type]
     */
    function http_curl($url,$type='get',$res='json',$arr=''){
        //1.初始化curl
        $ch = curl_init();
        //2.设置curl的参数
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        if($type == 'post'){
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $arr);
        }
        //3.采集
        $output = curl_exec($ch);
        //4.关闭
        if($res == 'json'){
            if(curl_errno($ch)){
                return curl_error($ch);
            }else{
                return json_decode($output,true);
            }
        }
        curl_close($output);
    }

当用户输入一个地名的时候,回复该地区的当前天气预报。使用的api接口为https://www.sojson.com/open/api/weather/json.shtml?city=北京返回的数据为json。自己提取相关的信息,为了方便演示,我只是回复了天气情况,有需要的可以自己添加相关的功能。
实例代码:

<?php
namespace Wx\Controller;
use Think\Controller;
class IndexController extends Controller {
    public function index(){
        //获得参数 signature nonce token timestamp echostr
        $nonce     = $_GET['nonce'];
        $token     = 'xxxx';
        $timestamp = $_GET['timestamp'];
        $echostr   = $_GET['echostr'];
        $signature = $_GET['signature'];
        //形成数组,然后按字典序排序
        $array = array();
        $array = array($nonce, $timestamp, $token);
        sort($array);
        //拼接成字符串,sha1加密 ,然后与signature进行校验
        $str = sha1( implode( $array ) );
        if( $str  == $signature && $echostr ){
            //第一次接入weixin api接口的时候
            echo  $echostr;
            exit;
        }else{
            $this->reponseMsg();
        }
    }
    public function reponseMsg(){
        //1.获取到微信推送过来post数据(xml格式)
        $postArr = $GLOBALS['HTTP_RAW_POST_DATA'];
        //2.处理消息类型,并设置回复类型和内容
        $postObj = simplexml_load_string( $postArr );//xml转换成对象
        //判断是否是用户回复过来的消息
        //用户发送过来消息后回复图文消息或者是单文本消息
        if( strtolower($postObj->MsgType) == 'text' ){
            $toUser = $postObj->FromUserName;
            $fromUser = $postObj->ToUserName;
            $content = $this->weather($postObj->Content);
            $toUser   = $postObj->FromUserName;
            $fromUser = $postObj->ToUserName;
            $time     = time();
            $msgType  =  'text';
            $template = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <Content><![CDATA[%s]]></Content>
                            </xml>";
             $info     = sprintf($template, $toUser, $fromUser, $time, $msgType, $content);
             echo $info;
    }
}
     public function weather($city){
        //1.初始化curl
        $ch = curl_init();
        $url = 'https://www.sojson.com/open/api/weather/json.shtml?city='.$city;
        //2.设置curl的参数
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //3.采集
        $output = curl_exec($ch);
        //4.关闭
        curl_close($ch);
        $wt = (array) json_decode($output,true);
        $wet = $wt["data"]["forecast"][0]["type"];
        return $wet;
    }
}

以下的格式和参数说明均参考的开发手册

回复纯文本

格式:

<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[news] ]></MsgType>
   <ArticleCount>1</ArticleCount>
   <Articles>
      <item>
         <Title>< ![CDATA[title1] ]></Title> 
         <Description>< ![CDATA[description1] ]></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格式,较好的效果为大图360200,小图200200
Url点击图文消息跳转链接

示例代码:(ThinkPHP3.2.3)

<?php
<?php
namespace Wx\Controller;
use Think\Controller;
class IndexController extends Controller {
    public function index(){
        //获得参数 signature nonce token timestamp echostr
        $nonce     = $_GET['nonce'];
        $token     = 'xxxx';
        $timestamp = $_GET['timestamp'];
        $echostr   = $_GET['echostr'];
        $signature = $_GET['signature'];
        //形成数组,然后按字典序排序
        $array = array();
        $array = array($nonce, $timestamp, $token);
        sort($array);
        //拼接成字符串,sha1加密 ,然后与signature进行校验
        $str = sha1( implode( $array ) );
        if( $str  == $signature && $echostr ){
            //第一次接入weixin api接口的时候
            echo  $echostr;
            exit;
        }else{
            $this->reponseMsg();
        }
    }
    public function reponseMsg(){
        //1.获取到微信推送过来post数据(xml格式)
        $postArr = $GLOBALS['HTTP_RAW_POST_DATA'];
        //2.处理消息类型,并设置回复类型和内容
        $postObj = simplexml_load_string( $postArr );//xml转换成对象
        //判断是否是用户回复过来的消息
        //用户发送过来消息后回复图文消息或者是单文本消息
        if( strtolower($postObj->MsgType) == 'text' && trim($postObj->Content)=='孙肖宁' ){
            $toUser = $postObj->FromUserName;
            $fromUser = $postObj->ToUserName;
            $arr = array(
                //注意:进行多图文发送时,子图文个数不能超过8个
                array(
                    'title'=>'孙肖宁',
                    'description'=>"孙肖宁的个人博客",
                    'picUrl'=>'http://www.sunxiaoning.com/usr/themes/handsome/usr/img/aaa.jpg',
                    'url'=>'http://www.sunxiaoning.com',
                ),
                array(
                    'title'=>'小宁博客',
                    'description'=>"孙肖宁的个人博客",
                    'picUrl'=>'http://www.sunxiaoning.com/usr/themes/handsome/usr/img/aaa.jpg',
                    'url'=>'http://www.sunxiaoning.com',
                ),
                array(
                    'title'=>'孙肖宁的个人博客',
                    'description'=>"孙肖宁的个人博客",
                    'picUrl'=>'http://www.sunxiaoning.com/usr/themes/handsome/usr/img/aaa.jpg',
                    'url'=>'http://www.sunxiaoning.com',
                ),
            );
            $template = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[%s]]></MsgType>
                        <ArticleCount>".count($arr)."</ArticleCount>
                        <Articles>";
            foreach($arr as $k=>$v){
                $template .="<item>
                            <Title><![CDATA[".$v['title']."]]></Title> 
                            <Description><![CDATA[".$v['description']."]]></Description>
                            <PicUrl><![CDATA[".$v['picUrl']."]]></PicUrl>
                            <Url><![CDATA[".$v['url']."]]></Url>
                            </item>";
            }
            
            $template .="</Articles>
                        </xml> ";
            echo sprintf($template, $toUser, $fromUser, time(), 'news');
        }else{
            switch( trim($postObj->Content) ){
                case 1:
                    $content = '您输入的数字是1';
                break;
                case 2:
                    $content = '您输入的数字是2';
                break;
                case 3:
                    $content = '您输入的数字是3';
                break;
                case '博客':
                    $content = "<a href='http://www.sunxiaoning.com'>小宁博客</a>";
                break;
                default:
                    $content = '暂无选项';

            }    
            $toUser   = $postObj->FromUserName;
            $fromUser = $postObj->ToUserName;
            $time     = time();
            $msgType  =  'text';
            $template = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <Content><![CDATA[%s]]></Content>
                            </xml>";
             $info     = sprintf($template, $toUser, $fromUser, $time, $msgType, $content);
             echo $info;
        }
    }
}

微信公众号开发之自动回复。
首先看下文档,用户关注公众号之后,会发送一段xml格式的文本给服务器。

<xml> 
    <ToUserName>< ![CDATA[toUser] ]></ToUserName>  
    <FromUserName>< ![CDATA[fromUser] ]></FromUserName>  
    <CreateTime>1348831860</CreateTime>  
    <MsgType>< ![CDATA[text] ]></MsgType>  
    <Content>< ![CDATA[this is a test] ]></Content>  
    <MsgId>1234567890123456</MsgId>  
</xml>
参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgTypetext
Content文本消息内容
MsgId消息id,64位整型

回复消息给用户同样也是一段xml

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

示例代码(thinkphp3.2.3)

<?php
namespace Wx\Controller;
use Think\Controller;
class IndexController extends Controller {
    public function index(){
        //获得参数 signature nonce token timestamp echostr
        $nonce     = $_GET['nonce'];
        $token     = 'xxxx';
        $timestamp = $_GET['timestamp'];
        $echostr   = $_GET['echostr'];
        $signature = $_GET['signature'];
        //形成数组,然后按字典序排序
        $array = array();
        $array = array($nonce, $timestamp, $token);
        sort($array);
        //拼接成字符串,sha1加密 ,然后与signature进行校验
        $str = sha1( implode( $array ) );
        if( $str  == $signature && $echostr ){
            //第一次接入weixin api接口的时候
            echo  $echostr;
            exit;
        }else{
            $this->reponseMsg();
        }
    }
    public function reponseMsg(){
        //1.获取到微信推送过来post数据(xml格式)
        $postArr = $GLOBALS['HTTP_RAW_POST_DATA'];
        //2.处理消息类型,并设置回复类型和内容
        $postObj = simplexml_load_string( $postArr );//xml转换成对象
        //$postObj->ToUserName
        //判断该数据包是否是订阅的事件推送
        if( strtolower( $postObj->MsgType) == 'event'){
            //如果是关注 subscribe 事件
            if( strtolower($postObj->Event == 'subscribe') ){
                //回复用户消息(纯文本格式)    
                $toUser   = $postObj->FromUserName;
                $fromUser = $postObj->ToUserName;
                $time     = time();
                $msgType  =  'text';
                $content  = '欢迎关注我们的微信公众账号';
                $template = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <Content><![CDATA[%s]]></Content>
                            </xml>";
                $info     = sprintf($template, $toUser, $fromUser, $time, $msgType, $content);
                echo $info;
            }
        }
    }
}

第一步:拥有自己的公众号以及服务器(及域名)。
第二步:申请测试账号,一定记住开发者密码(AppSecret),不然就只能重置了。
第三步:进入微信公共平台,点击开发->基本配置->服务器配置->修改规则
填入以下信息
1.png

URL:就是你的服务器的URL(要能响应TOKEN验证,还要能在外网访问到这个服务器)

TOKEN:这个算是自己设置的一个验证码,要自己在代码里面设置的(并且当微信服务器器把GET请求发到你的服务器的时候,能返回这个值)

注:微信服务器的GET请求会带四个参数signature,token,timestamp,echostr;POST请求会带三个参数除了刚才的echostr

  • 获得参数 signature nonce token timestamp echostr
  • 形成数组,然后按字典序排序
  • 拼接成字符串,sha1加密 ,然后与signature进行校验
    实例代码:

    <?php
    /**
    * wechat php test
    */
    
    //define your token;TOKEN一定和你自己的对应起来
    define("TOKEN", "weixin");
    $wechatObj = new wechatCallbackapiTest();
    $wechatObj->valid();
    
    class wechatCallbackapiTest
    {
      public function valid()
      {
          $echoStr = $_GET["echostr"];
    
          //valid signature , option
          if($this->checkSignature()){
              echo $echoStr;
              exit;
          }
      }
    
      public function responseMsg()
      {
          //get post data, May be due to the different environments
          $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
    
            //extract post data
          if (!empty($postStr)){
                  /* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
                     the best way is to check the validity of xml by yourself */
                  libxml_disable_entity_loader(true);
                    $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
                  $fromUsername = $postObj->FromUserName;
                  $toUsername = $postObj->ToUserName;
                  $keyword = trim($postObj->Content);
                  $time = time();
                  $textTpl = "<xml>
                              <ToUserName><![CDATA[%s]]></ToUserName>
                              <FromUserName><![CDATA[%s]]></FromUserName>
                              <CreateTime>%s</CreateTime>
                              <MsgType><![CDATA[%s]]></MsgType>
                              <Content><![CDATA[%s]]></Content>
                              <FuncFlag>0</FuncFlag>
                              </xml>";             
                  if(!empty( $keyword ))
                  {
                        $msgType = "text";
                      $contentStr = "Welcome to wechat world!";
                      $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
                      echo $resultStr;
                  }else{
                      echo "Input something...";
                  }
    
          }else {
              echo "";
              exit;
          }
      }
          
      private function checkSignature()
      {
          // you must define TOKEN by yourself
          if (!defined("TOKEN")) {
              throw new Exception('TOKEN is not defined!');
          }
          
          $signature = $_GET["signature"];
          $timestamp = $_GET["timestamp"];
          $nonce = $_GET["nonce"];
                  
          $token = TOKEN;
          $tmpArr = array($token, $timestamp, $nonce);
          // use SORT_STRING rule
          sort($tmpArr, SORT_STRING);
          $tmpStr = implode( $tmpArr );
          $tmpStr = sha1( $tmpStr );
          
          if( $tmpStr == $signature ){
              return true;
          }else{
              return false;
          }
      }
    }
    
    ?>

EncodingAeskey:直接点击随机生成就好了。

提交之后,会提醒你配置成功。