2019-03-07 11:59:35 qq_43068569 阅读数 1665
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27801 人正在学习 去看看 秦子恒

本项目已经上传到github上面:https://github.com/wangqifan/WeChatAnalyse

这个Demo是利用HttpWebRequest和HttpWebResponse来爬取微信好友列表,讲信息存入数据库,并对信息进行分析,用图标画出来。

如何获得微信好友列表信息

 首先前往https://wx.qq.com/登录自己的微信账号,打开浏览器的开发者控制台

获取微信好友列表
获取微信好友列表

微信给后台发送了几十个请求,我翻遍了所有请求,终于找到了想要的url

借助浏览器我们可以获取这个请求的信息

微信好友列表获取

我们可以把这个数据交给程序让程序帮我们取请求,并把数据保存下来

前期准备新建一个名为WeChatAnalyse的项目

借助nuget安装Entity Framwork和Json.net我们待会要使用这两个框架,顺便修改下配置文件

<connectionStrings>
        <add name="WeChartContex" connectionString="server=.;database=WeChat;uid=sa;pwd=000000"
          providerName="System.Data.SqlClient" />
    </connectionStrings>

创建model

我们再次回到浏览器控制台,分析服务器返回的数据

根据返回数据,我们可以建类 Friend

[Key]
        public int Id { get; set; }
        public int Uin { get; set; }
        public string UserName { get; set; }
        public string NickName { get; set; }
        public string HeadImgUrl { get; set; }
        public int ContactFlag { get; set; }
        public int MemberCount { get; set; }
        public List<Friend> MemberList { get; set; }
        public string RemarkName { get; set; }
        public int HideInputBarFlag { get; set; }
        public int Sex { get; set; }
        public string Signature { get; set; }
        public int VerifyFlag { get; set; }
        public int OwnerUin { get; set; }
        public string PYInitial { get; set; }
        public string PYQuanPin { get; set; }
        public int StarFriend { get; set; }
        public int AppAccountFlag { get; set; }
        public int Statues { get; set; }
        public int AttrStatus { get; set; }
        public string Province { get; set; }
        public string City { get; set; }
        public string Alias { get; set; }
        public int SnsFlag { get; set; }
        public int UniFriend { get; set; }
        public string DisplayName { get; set; }
        public int ChatRoomId { get; set; }
        public string KeyWord { get; set; }
        public string EncryChatRoomId { get; set; }

类BaseResponse

public class BaseResponse
   {
       //"Ret": 0, "ErrMsg": ""
       public int Ret { get; set; }
       public string ErrMsg { get; set; }
   }

类Respone

public class Respone
    {
        public BaseResponse respoen { get; set; }
        public int MemberCount { get; set; }
        public List<Friend> MemberList { get; set; }
    }

创建数据库上下文

public class WeChartContex:DbContext
    {
        public    DbSet<Friend> Fridens { get; set; }
    }

创建控制器Sprider

  给他添加一个数据库上下文对象

WeChartContex context = new WeChartContex();

这种强耦合的代码是不被推荐的,由于我们的Demo特别小,这里暂时这样写

public ActionResult GetFridendInformation()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?r=1480564845349&seq=0&skey=@crypt_20089e09_d38ecc170f273d2db91833e793677276");
            request.Method = "get";
            request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0";
            request.Referer = "https://wx.qq.com/";
            // CookieContainer contain = new CookieContainer();

  
            request.Headers.Add("Cookie", "pgv_pvi=1499432960; pt2gguin=o1694675518; RK=; /=s7972417536; wxsid=tjF6UrJ2RcvNH76H; wxloadtime=1480564533_expired);

           using(Stream dataStream = response.GetResponseStream())
          {
           using( StreamReader reader = new StreamReader(dataStream))
            {
            // Read the content.
            string responseFromServer = reader.ReadToEnd();
            Respone   responsefronserver = JsonHelper.DeserializeToObject<Respone>(responseFromServer);
            foreach (var item in responsefronserver.MemberList)
            {
                if(item.VerifyFlag==0) context.Fridens.Add(item);
            } 
              }
         }

    request.Abort();
if (context.SaveChanges()>0) { return Content("ok"); }


            return Content("fail");
        }

基本思路是根据URL来创建一个HttpWebRequest对象,它是用http协议来请求的,我们来设置UserAgent,cookie,这里的cookie我做了删除,cookie应该即时取浏览器提取,保证它是新鲜的

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?r=1480564845349&seq=0&skey=@crypt_20089e09_d38ecc170f273d2db91833e793677276");
            request.Method = "get";
            request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0";
            request.Referer = "https://wx.qq.com/";
             request.Headers.Add("Cookie", "pgv_pvi=149943")

接下来创建HttpWebResponse对象来获取数据,并进行反序列化

首先创建一个jsonhelp

public class JsonHelper
    {
        /// <summary>
        /// 对数据进行序列化
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string SerializeToString(object value)
        {
            return JsonConvert.SerializeObject(value);
        }
        /// <summary>
        /// 反序列化操作
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="str"></param>
        /// <returns></returns>
        public static T DeserializeToObject<T>(string str)
        {
            return JsonConvert.DeserializeObject<T>(str);
        }
}

接下来对返回的数据进行反序列化

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream dataStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(dataStream);
            // Read the content.
            string responseFromServer = reader.ReadToEnd();
            Respone   responsefronserver = JsonHelper.DeserializeToObject<Respone>(responseFromServer);

接下来保存到数据库中,我们只要朋友的信息

foreach (var item in responsefronserver.MemberList)
            {
                if(item.VerifyFlag==0) context.Fridens.Add(item);
            } 
            if (context.SaveChanges()>0)
            {
                return Content("ok");
            }

            return Content("fail");

VerifyFlag为0就是个人账号,公众号不为0

运行程序,进入Sprider/GetFridendInformation,返回OK执行成功

微信好友列表获取
微信好友列表获取

我一共有116个微信好友。这样就用爬虫实现:获取微信好友列表爬取进行好友分析。

更多关于微信好友列表获取交流可加q群:753876674  一起交流学习。

2018-08-09 20:37:26 yw8886484 阅读数 6040
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27801 人正在学习 去看看 秦子恒

先贴出完整源代码。

代码中:使用二维码登录网页版微信,并下载好友头像,并将好友资料数据存入csv文件,待进一步处理。

笔者使用的环境为python3.5。来实现:强制获取微信好友列表信息开发(一)提取微信好友数据

import os
import requests
import re
import time
import xml.dom.minidom
import json
import csv
import codecs
import sys
import math
import subprocess
import ssl
import threading
import urllib.request, urllib.parse, urllib.error, urllib.request, urllib.error, urllib.parse
 
DEBUG = False  # 测试时候 可以改为True,输出测试的json数据
 
MAX_GROUP_NUM = 2  # 每组人数
INTERFACE_CALLING_INTERVAL = 5  # 接口调用时间间隔, 间隔太短容易出现"操作太频繁", 会被限制操作半小时左右
MAX_PROGRESS_LEN = 50
 
QRImagePath = os.path.join(os.getcwd(), 'qrcode.jpg')  # 存放登录二维码的位置,不需要改
 
tip = 0
uuid = ''
 
base_uri = ''
redirect_uri = ''
push_uri = ''
 
skey = ''
wxsid = ''
wxuin = ''
pass_ticket = ''
deviceId = 'e000000000000000'
 
BaseRequest = {}
 
ContactList = []
My = []
SyncKey = []
 
try:
    xrange
    range = xrange
except:
    # python 3
    pass
 
 
def responseState(func, BaseResponse):
    ErrMsg = BaseResponse['ErrMsg']
    Ret = BaseResponse['Ret']
    if DEBUG or Ret != 0:
        print('func: %s, Ret: %d, ErrMsg: %s' % (func, Ret, ErrMsg))
 
    if Ret != 0:
        return False
 
    return True
 
 
def getUUID():
    global uuid
 
    url = 'https://login.weixin.qq.com/jslogin'
    params = {
        'appid': 'wx782c26e4c19acffb',
        'fun': 'new',
        'lang': 'zh_CN',
        '_': int(time.time()),
    }
 
    r = myRequests.get(url=url, params=params)
    r.encoding = 'utf-8'
    data = r.text
 
    # print(data)
 
    # window.QRLogin.code = 200; window.QRLogin.uuid = "oZwt_bFfRg==";
    regx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)"'
    pm = re.search(regx, data)
 
    code = pm.group(1)
    uuid = pm.group(2)
 
    if code == '200':
        return True
 
    return False
 
 
def showQRImage():
    global tip
 
    url = 'https://login.weixin.qq.com/qrcode/' + uuid
    params = {
        't': 'webwx',
        '_': int(time.time()),
    }
 
    r = myRequests.get(url=url, params=params)
 
    tip = 1
 
    f = open(QRImagePath, 'wb')
    f.write(r.content)
    f.close()
    time.sleep(1)
 
    if sys.platform.find('darwin') >= 0:  # 'darwin'
        subprocess.call(['open', QRImagePath])
    elif sys.platform.find('linux') >= 0:
        subprocess.call(['xdg-open', QRImagePath])
    else:
        os.startfile(QRImagePath)
 
    print('请使用微信扫描二维码以登录')
 
 
def waitForLogin():
    global tip, base_uri, redirect_uri, push_uri
 
    url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s' % (
        tip, uuid, int(time.time()))
 
    r = myRequests.get(url=url)
    r.encoding = 'utf-8'
    data = r.text
 
    # print(data)
 
    # window.code=500;
    regx = r'window.code=(\d+);'
    pm = re.search(regx, data)
 
    code = pm.group(1)
 
    if code == '201':  # 已扫描
        print('成功扫描,请在手机上点击确认以登录')
        tip = 0
    elif code == '200':  # 已登录
        print('正在登录...')
        regx = r'window.redirect_uri="(\S+?)";'
        pm = re.search(regx, data)
        redirect_uri = pm.group(1) + '&fun=new'
        base_uri = redirect_uri[:redirect_uri.rfind('/')]
 
        # push_uri与base_uri对应关系(排名分先后)(就是这么奇葩..)
        services = [
            ('wx2.qq.com', 'webpush2.weixin.qq.com'),
            ('qq.com', 'webpush.weixin.qq.com'),
            ('web1.wechat.com', 'webpush1.wechat.com'),
            ('web2.wechat.com', 'webpush2.wechat.com'),
            ('wechat.com', 'webpush.wechat.com'),
            ('web1.wechatapp.com', 'webpush1.wechatapp.com'),
        ]
        push_uri = base_uri
        for (searchUrl, pushUrl) in services:
            if base_uri.find(searchUrl) >= 0:
                push_uri = 'https://%s/cgi-bin/mmwebwx-bin' % pushUrl
                break
 
        # closeQRImage
        if sys.platform.find('darwin') >= 0:  # for OSX with Preview
            os.system("osascript -e 'quit app \"Preview\"'")
    elif code == '408':  # 超时
        pass
    # elif code == '400' or code == '500':
 
    return code
 
 
def login():
    global skey, wxsid, wxuin, pass_ticket, BaseRequest
 
    r = myRequests.get(url=redirect_uri)
    r.encoding = 'utf-8'
    data = r.text
 
    # print(data)
 
    doc = xml.dom.minidom.parseString(data)
    root = doc.documentElement
 
    for node in root.childNodes:
        if node.nodeName == 'skey':
            skey = node.childNodes[0].data
        elif node.nodeName == 'wxsid':
            wxsid = node.childNodes[0].data
        elif node.nodeName == 'wxuin':
            wxuin = node.childNodes[0].data
        elif node.nodeName == 'pass_ticket':
            pass_ticket = node.childNodes[0].data
 
    # print('skey: %s, wxsid: %s, wxuin: %s, pass_ticket: %s' % (skey, wxsid,
    # wxuin, pass_ticket))
 
    if not all((skey, wxsid, wxuin, pass_ticket)):
        return False
 
    BaseRequest = {
        'Uin': int(wxuin),
        'Sid': wxsid,
        'Skey': skey,
        'DeviceID': deviceId,
    }
 
    return True
 
 
def webwxinit():
    url = (base_uri +
           '/webwxinit?pass_ticket=%s&skey=%s&r=%s' % (
               pass_ticket, skey, int(time.time())))
    params = {'BaseRequest': BaseRequest}
    headers = {'content-type': 'application/json; charset=UTF-8'}
 
    r = myRequests.post(url=url, data=json.dumps(params), headers=headers)
    r.encoding = 'utf-8'
    data = r.json()
 
    if DEBUG:
        f = open(os.path.join(os.getcwd(), 'webwxinit.json'), 'wb')
        f.write(r.content)
        f.close()
 
    # print(data)
 
    global ContactList, My, SyncKey
    dic = data
    ContactList = dic['ContactList']
    My = dic['User']
    SyncKey = dic['SyncKey']
 
    state = responseState('webwxinit', dic['BaseResponse'])
    return state
 
 
def webwxgetcontact():
    url = (base_uri +
           '/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s' % (
               pass_ticket, skey, int(time.time())))
    headers = {'content-type': 'application/json; charset=UTF-8'}
 
    r = myRequests.post(url=url, headers=headers)
    r.encoding = 'utf-8'
    data = r.json()
 
    if DEBUG:
        f = open(os.path.join(os.getcwd(), 'webwxgetcontact.json'), 'wb')
        f.write(r.content)
        f.close()
 
    dic = data
    MemberList = dic['MemberList']
 
    # 倒序遍历,不然删除的时候出问题..
    SpecialUsers = ["newsapp", "fmessage", "filehelper", "weibo", "qqmail", "tmessage", "qmessage", "qqsync",
                    "floatbottle", "lbsapp", "shakeapp", "medianote", "qqfriend", "readerapp", "blogapp", "facebookapp",
                    "masssendapp",
                    "meishiapp", "feedsapp", "voip", "blogappweixin", "weixin", "brandsessionholder", "weixinreminder",
                    "wxid_novlwrv3lqwv11", "gh_22b87fa7cb3c", "officialaccounts", "notification_messages", "wxitil",
                    "userexperience_alarm"]
    for i in range(len(MemberList) - 1, -1, -1):
        Member = MemberList[i]
        if Member['VerifyFlag'] & 8 != 0:  # 公众号/服务号
            MemberList.remove(Member)
        elif Member['UserName'] in SpecialUsers:  # 特殊账号
            MemberList.remove(Member)
        elif Member['UserName'].find('@@') != -1:  # 群聊
            MemberList.remove(Member)
        elif Member['UserName'] == My['UserName']:  # 自己
            MemberList.remove(Member)
 
    return MemberList
 
 
def syncKey():
    SyncKeyItems = ['%s_%s' % (item['Key'], item['Val'])
                    for item in SyncKey['List']]
    SyncKeyStr = '|'.join(SyncKeyItems)
    return SyncKeyStr
 
 
def syncCheck():
    url = push_uri + '/synccheck?'
    params = {
        'skey': BaseRequest['Skey'],
        'sid': BaseRequest['Sid'],
        'uin': BaseRequest['Uin'],
        'deviceId': BaseRequest['DeviceID'],
        'synckey': syncKey(),
        'r': int(time.time()),
    }
 
    r = myRequests.get(url=url, params=params)
    r.encoding = 'utf-8'
    data = r.text
 
    # print(data)
 
    # window.synccheck={retcode:"0",selector:"2"}
    regx = r'window.synccheck={retcode:"(\d+)",selector:"(\d+)"}'
    pm = re.search(regx, data)
 
    retcode = pm.group(1)
    selector = pm.group(2)
 
    return selector
 
 
def webwxsync():
    global SyncKey
 
    url = base_uri + '/webwxsync?lang=zh_CN&skey=%s&sid=%s&pass_ticket=%s' % (
        BaseRequest['Skey'], BaseRequest['Sid'], urllib.parse.quote_plus(pass_ticket))
    params = {
        'BaseRequest': BaseRequest,
        'SyncKey': SyncKey,
        'rr': ~int(time.time()),
    }
    headers = {'content-type': 'application/json; charset=UTF-8'}
 
    r = myRequests.post(url=url, data=json.dumps(params))
    r.encoding = 'utf-8'
    data = r.json()
 
    # print(data)
 
    dic = data
    SyncKey = dic['SyncKey']
 
    state = responseState('webwxsync', dic['BaseResponse'])
    return state
 
 
def heartBeatLoop():
    while True:
        selector = syncCheck()
        if selector != '0':
            webwxsync()
        time.sleep(1)
 
 
def main():
    global myRequests
 
    if hasattr(ssl, '_create_unverified_context'):
        ssl._create_default_https_context = ssl._create_unverified_context
 
    headers = {
        'User-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36'}
    myRequests = requests.Session()
    myRequests.headers.update(headers)
 
    if not getUUID():
        print('获取uuid失败')
        return
 
    print('正在获取二维码图片...')
    showQRImage()
 
    while waitForLogin() != '200':
        pass
 
    os.remove(QRImagePath)
 
    if not login():
        print('登录失败')
        return
 
    if not webwxinit():
        print('初始化失败')
        return
 
    MemberList = webwxgetcontact()
 
    threading.Thread(target=heartBeatLoop)
 
    MemberCount = len(MemberList)
    print('通讯录共%s位好友' % MemberCount)
    print(MemberList)
 
    d = {}
    imageIndex = 0
    # 写入csv
    csvfile = open('friend2.csv', 'w', newline='') 
    # csvfile.write(codecs.BOM_UTF8)
    writer = csv.writer(csvfile)
    writer.writerow(['name', 'city', 'male', 'star', 'signature', 'remark', 'alias', 'nick'])
    for Member in MemberList:
        global writer
        imageIndex = imageIndex + 1
        name = 'D:\\Python\\Demo\\image\\image' + str(imageIndex) + '.jpg'
        imageUrl = 'https://wx.qq.com' + Member['HeadImgUrl']
        r = myRequests.get(url=imageUrl, headers=headers)
        imageContent = (r.content)
        fileImage = open(name, 'wb')
        fileImage.write(imageContent)
        fileImage.close()
        print('正在下载第:' + str(imageIndex) + '位好友头像')
        d[Member['UserName']] = (Member['NickName'], Member['RemarkName'])
        city = Member['City']
        city = 'nocity' if city == '' else  city
        name = Member['NickName']
        name = 'noname' if name == '' else  name
        sign = Member['Signature']
        sign = 'nosign' if sign == '' else  sign
        remark = Member['RemarkName']
        remark = 'noremark' if remark == '' else remark
        alias = Member['Alias']
        alias = 'noalias' if alias == '' else alias
        nick = Member['NickName']
        nick = 'nonick' if nick == '' else nick
        print(name, '  ^+*+^  ', city, '  ^+*+^  ', Member['Sex'], ' ^+*+^ ', Member['StarFriend'], ' ^+*+^ ', sign,
              ' ^+*+^ ', remark, ' ^+*+^ ', alias, ' ^+*+^ ', nick)
        # 写入csv
        writer.writerow([name.encode('gbk', 'ignore').decode('gbk'), city.encode('gbk', 'ignore').decode('gbk'),
                         Member['Sex'],
                         Member['StarFriend'], sign.encode('gbk', 'ignore').decode('gbk'),
                         remark.encode('gbk', 'ignore').decode('gbk'),
                         alias.encode('gbk', 'ignore').decode('gbk'),
                         nick.encode('gbk', 'ignore').decode('gbk')])
    csvfile.close()
 
if __name__ == '__main__':
    main()
    print('程序已安全退出...')

简单讲几点:

一、写入csv文件编码问题

      在上一篇文章中以及解释了。

二、登录出现问题

      没有找到系统,在120行左右:

    if sys.platform.find('darwin') >= 0:  # 'darwin'
        subprocess.call(['open', QRImagePath])
    elif sys.platform.find('linux') >= 0:
        subprocess.call(['xdg-open', QRImagePath])
    else:
        os.startfile(QRImagePath)

最后的else分句不可少。

若有在提取微信好友数据中遇到其他问题欢迎留言。笔者也开发过qq好友列表获取类。

 

 

2019-11-25 15:06:28 weixin_38746522 阅读数 39
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27801 人正在学习 去看看 秦子恒

文档地址:wkteam.gitbook.io

微信个人号二次开发,个人微信开发API

好友管理:

  • 添加好友、
  • 删除好友、
  • 修改备注、
  • 创建标签、
  • 获取好友列表、
  • 检测僵尸粉

消息管理:

  • 发文本消息、
  • 图片消息、
  • 名片消息、
  • 动图表情、
  • 小程序、
  • 发文件、
  • 发送视频、
  • 发送URL链接
  • 入群消息

群管理:

  • 自动创群、
  • 修改群名称、
  • 邀请新成员、
  • 踢群成员、
  • 获取群列表、
  • 发送邀请链接、
  • 获取群聊。

朋友圈:

  • 发送朋友圈、
  • 朋友圈点赞、
  • 获取朋友圈列表、
  • 转发朋友圈、
  • 同步朋友圈,
  • 批量发送朋友圈
  • 在这里插入图片描述
  • 在这里插入图片描述

各种知名SCRM系统、客服平台都是根据此API二次开发的。

文档地址:wkteam.gitbook.io

2016-01-14 13:55:49 HinstenyHisoka 阅读数 5925
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27801 人正在学习 去看看 秦子恒

当我们进行微信平台相关内容开发时,如果想做一些针对微信用户进行一些信息获取及消息推送,那我们第一步先要拿到微信用户的OPENID(用户唯一标识,建立在一个公众号与一个微信用户之间,即针对一个公众号,所有的微信用户都享有一个独立不变的标识);


1 . 如果微信用户已经关注自己的公众号, 那可以通过微信接口里面的用户管理模板直接获取到对应公众号的所有已关注用户OPENID的列表;
1). 在调用所有的微信接口之前,我们先要请求授权,拿到access_token

    @Getter
    @Config("wechat.appid")
    private static String WECHATAPPID;

    @Getter
    @Config("wechat.appsecret")
    private static String WECHATAPPSECRET;

    public static final String ACCESS_TOKEN = "access_token";
    public final static String WECHATACCESSTOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=";
        /**
     * <p>
     * 成功: {"access_token":"ACCESS_TOKEN","expires_in":7200}
     * </p>
     * <p>
     * 失败: {"errcode":40013,"errmsg":"invalid appid"}
     * </p>
     * @return 如果没有获取到有效的凭据,就返回 null
     */
    private static Map getWechatAPPAccessTokenFromWeChat() {
        StringBuilder accessTokenUrl = new StringBuilder().append(WECHATACCESSTOKEN).append(WECHATAPPID)
                        .append("&secret=").append(WECHATAPPSECRET);
        Map result = HttpClientUtil.readHttpContent(accessTokenUrl.toString());
        if (result != null && result.get(ACCESS_TOKEN) != null)
            return result;
        return null;
    }

    //HttpClientUtil.class static method
    /**
     * get json content and transform to Map from the urlStr
     * If occuer one error just return null.
     * @param urlStr
     * @return
     */
    public static Map<String,Object> readHttpContent(String urlStr){
        Map<String, Object> result = null;
        HttpEntity httpEntity = null;
        try {
            HttpResponse response = Request.Get(urlStr).execute().returnResponse();
            httpEntity = response.getEntity();
        }catch (IOException e) {
            logger.error("Get resouse from {} had occurred an error: {}", urlStr, e.toString());
            return result;
        }
        try (
            InputStream in = httpEntity.getContent();
        ){
            ObjectMapper mapper = new ObjectMapper();
            result = mapper.readValue(in, HashMap.class);
        }catch (IOException e) {
            logger.error("Get json content from {} had occurred an error: {}", urlStr, e.toString());
            return result;
        }
        return result;
    }

2). 使用前面得到的access_token获取公众号的微信关注用户列表

    public static final String ERRMSG = "errmsg";
    public final static String WECHATUSERLISTURL = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=";
    /**
     *<p>
     * 获取成功:{
     *  "total":23000,
     *  "count":10000,
     *  "data":{"
     *    openid":[
     *      "OPENID1",
     *      "OPENID2",
     *      ...,
     *      "OPENID10000"
     *    ]
     *  },
     *  "next_openid":"OPENID10000"
     *  }
     *</p>
     *
     *<p>
     * 获取失败:{"errcode":40013,"errmsg":"invalid appid"}
     *</p>
     *
     *
     * 获取微信公众帐号的关注者列表(wechat user openID),每次最多10000个
     *
     * @param accessToken
     * @param next_openid: 没有此参数,则默认从关注列表的第一个开始获取
     * @return
     */
    public static Map getWechatUserOpenIDList(String accessToken, String next_openid) {
        StringBuilder urlB = new StringBuilder().append(WECHATUSERLISTURL).append(accessToken);
        if (!Strings.isBlank(next_openid))
            urlB.append("&next_openid=").append(next_openid);
        Map result = HttpClientUtil.readHttpContent(urlB.toString());
        if (result != null && result.get(ERRMSG) == null)
            return result;
        return null;
    }
采用方法一,到此便得到了用户openID列表,可以进行后面获取微信用户信息及向用户推送模板消息等;

2 . 无论微信用户是否关注自己的公众号, 当微信用户访问我们的web站点时(通过微信内置浏览器),我们可以通过页面授权的方式拿到微信用户的OpendID(页面授权需要跳转到微信服务器拿到oauth_code然后再换取access_token及OpendID);
1). 为我们的web站点服务添加一个filter,拦截来自微信浏览器的请求,进行302跳转到微信站点,拿到授权码再回调回来;

public class WechatFilter implements Filter {

    private static final Logger logger             = LoggerFactory.getLogger(WechatFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;

        if (response.isCommitted()) {
            chain.doFilter(request, response);
            return;
        }
        //判断请求是否来自微信浏览器
        if (!WebUtil.isWechatRequest(httpRequest)) {
            chain.doFilter(request, response);
            return;
        }
        String requestURL = WebUtil.getRequsetUrl(httpRequest, true, true);
        logger.debug("Request from wechat client:{}", requestURL);
        HttpSession session = httpRequest.getSession();
        String weChatOpenId = (String) session.getAttribute(WeChatManager.WECHATOPENID);
        if (weChatOpenId == null) {
            if (httpRequest.getParameter(WeChatManager.CODE) == null) {
                StringBuilder url = new StringBuilder("http://").append(WebUtil.getRequsetUrl(httpRequest, true, true));
                response.reset();
                ((HttpServletResponse) response).sendRedirect(url.toString());
                return;
            } else {
                String oauthCode = httpRequest.getParameter(WeChatManager.CODE);
                if (!Strings.isBlank(oauthCode)) {
                    Map<String, Object> oauth_data = WeChatPageInterface.getWechatPageAccessToken(oauthCode);
                    weChatOpenId = oauthCode != null && oauth_data.get(WeChatManager.OPENID) != null ? (String) oauth_data.get(WeChatManager.OPENID) : null;
                    session.setAttribute(WeChatManager.WECHATOPENID, weChatOpenId);
                } else {
                    logger.warn("The oauth_code is empty!");
                }
            }
        }
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }

}
    //WeChatPageInterface.class static method
    /**
     * <p>
     * 微信获取授权成功:{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN",
     * "openid":"OPENID", "scope":"SCOPE", "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
     * </p>
     * <p>
     * 微信获取授权失败:{"errcode":40029,"errmsg":"invalid code"}
     * </p>
     *
     * 请求微信公众号的网页授权,得到用户OpenID和access_token
     * 微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证( 网页授权access_token),
     * 通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息;
     *
     * @return 如果没有获取到有效的凭据,就返回 null
     */
    public static Map<String, Object> getWechatPageAccessToken(String oauthCode) {
        StringBuilder accessTokenUrl = new StringBuilder().append(WeChatManager.weChatAuthAccessTokenPage).append(WeChatManager.getWECHATAPPID())
                        .append("&secret=").append(WeChatManager.getWECHATAPPSECRET()).append("&code=")
                        .append(oauthCode).append("&grant_type=").append("authorization_code");
        Map<String, Object> accessToken = HttpClientUtil.readHttpContent(accessTokenUrl.toString());
        if (accessToken != null && accessToken.get(WeChatManager.ACCESS_TOKEN) != null) {
            return accessToken;
        }
        return null;
    }

至此,我们通过两种方式都可以获取微信用户的OpenID了,至于采用哪一种可以根据实际业务环境;

PS: OpenID是介于微信用户与公众账号之间恒定不变的,所以可以进行三方持久化存储;

2019-11-26 09:27:30 weixin_38746522 阅读数 16
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27801 人正在学习 去看看 秦子恒

文档测试地址:wkteam.gitbook.io

可开发的功能包括但不限于:

好友管理:添加好友、删除好友、修改备注、创建标签、获取好友列表、检测僵尸粉
消息管理:发文本消息、图片消息、名片消息、动图表情、小程序、发文件、发送视频、发送URL链接
群管理:自动创群、修改群名称、邀请新成员、踢群成员、获取群列表、发送邀请链接、获取群聊。
朋友圈:发送朋友圈、朋友圈点赞、获取朋友圈列表、转发朋友圈、同步朋友圈,批量发送朋友圈
基于API您可以创造更多有趣的功能…

目前微信社区特别火,大部分社区客户在寻找解决方案,苦思许久,我司专业提供微信小程序接入功能(包含小程序发送功能 分享 自动分享 关键字触发),客户都可以根据自己需求研发,有需要的话可以看文档沟通。
在这里插入图片描述

  • 在这里插入图片描述

各种知名SCRM系统、客服平台都是根据此API二次开发的。

文档地址:wkteam.gitbook.io

没有更多推荐了,返回首页