利用python+服务器简单实现微信公众号获取优惠券

目录

前言

一、前期准备

1.1 注册微信公众号

1.2 申请云服务器

1.3 获取淘宝客接口

二、微信公众号连接服务器

2.1 安装nginx

2.2 配置python环境

2.3 连接服务器

三、利用淘宝官方接口进行代码编写

3.1 获取官方SDK

3.2 编写接口函数

3.3 调用接口实现功能

总结


前言

本篇文章为自己动手实践后做的总结,利用阿里云服务器和python2进行实现的,python3原理相同,部分代码不同,最后也会作相应说明。

注:本方案只能实现简单的微信公众号获取优惠券的功能,不能实现返利等操作。

一、前期准备

1.1 注册微信公众号

微信公众号注册网址:微信公众平台

右上角点击立即注册即可

注:个人只能注册订阅号,且无法进行认证,所拥有的权限较低,但在本篇文章中够用,本篇文章也是在订阅号上进行的。有条件的可以注册服务号及进行认证(需要营业执照等信息)。注册时一个邮箱只能绑定一个微信公众号或小程序,若提示已注册,请使用别的邮箱进行注册。

注册完毕后可以根据个人喜好,对公众号进行简单的配置,完善公众号信息。找到左下角的设置与开发->基本配置,里面有一个AppID和Appsecret,如果没有就生成一个。这个秘钥可以自己存储到一个地方。

下面的服务器配置暂时不用开启,因为配置服务器还需要有一台云服务器。接下来就是申请一台云服务器进行使用

1.2 申请云服务器

学生认证可以在阿里云免费领取一个月的云服务器,最高可以免费续领六个月的云服务器,地址 https://developer.aliyun.com/adc/student/ 如果活动没有了,也可以去阿里云上租一台,配置最低就可以了。具体的申请流程可以参考之前写过的文章

记录一次服务器跑数据的全过程_如何使用服务器跑程序_Saulstone的博客-CSDN博客记录一次服务器跑数据的全过程远程连接软件:Xshell(用于命令窗口进行操作)Xftp_如何使用服务器跑程序https://blog.csdn.net/Stonesaul/article/details/124387226

注:阿里云高校计划申请的云服务器默认没有提供账号密码,需要按照下面的步骤进行重置。

拥有服务器后需要使用远程连接工具对服务器进行连接,也可以参考上面说的之前写的文档,里面有具体的操作步骤。

1.3 获取淘宝客接口

进入淘宝联盟官网,注册淘宝客账号,免费注册

淘宝联盟.生态伙伴链接入口:https://pub.alimama.com

有了媒体后还需要创建推广位,填写资料即可,名称为自己想要的。然后还需要进行APPKEY申请

申请完之后就可以获得淘宝客给的API,根据需要选择使用,本篇文章主要使用以下三个接口

注:订阅号申请后是没有这三个接口的权限的,需要自己申请,点击立即申请,填写足够字数的理由就能直接获取。

至此,前期所需要的东西就准备完成了,接下来就是进行代码的编写

二、微信公众号连接服务器

首先,云服务器的使用环境需要准备好,包括nginx、python等

2.1 安装nginx

本篇文章使用的云服务器是centos系统,通过以下命令即可直接安装nginx

yum install nginx -y  #centos
apt-get install nginx -y  #ubuntu

下载完nginx后需要对nginx配置文件进行相应的配置,因为nginx默认端口为80,所以对微信公众号收到消息的端口进行转发,使用8000端口,使用以下代码进行

vim /etc/nginx/nginx.conf

2.2 配置python环境

安装完nginx后就需要安装python环境,本篇文章使用的是python2版本,如果需要使用python3版本请先自行寻找如何下载(阿里云服务器低配版默认没有python3),也可以参考下面的内容

centos下安装python3详细教程_centos python-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/t8116189520/article/details/81976755

因为使用的是flask框架进行微信公众号的通信,所以需要先安装flask框架,使用以下命令即可安装

pip install flask

注:安装完python3之后记得将pip版本更改为python3版本,上面的文章也有说明。且安装完python3之后,使用pip2(python2版本的pip)命令会报错,如仍需使用pip2,参考以下文章

安装完python3后pip2无法使用icon-default.png?t=N7T8https://blog.csdn.net/xiaojun1288/article/details/121357721至此,所有准备都准备完成,接下来就是微信公众号连接代码编写的时刻

2.3 连接服务器

在公众号管理界面找到如下位置,配置服务器配置

接下来就是编程实现微信公众号和云服务器之间的通信。

token是微信公众号和云服务器之间连接的证明,只有验证成功后,微信公众号才能和云服务器之间进行通信。所以这里要确保token的正确性,就需要使用刚刚安装的flask框架来写一个简单的接收数据并验证的程序。具体代码可以百度搜索 “flask微信公众号验证token”,有很多教程可以参考。

微信公众号有自己的一套消息回复接口,官方文档地址:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html
关键就是看消息回复的被动回复用户消息。用户给公众号发送的消息都是发送到微信服务器上,然后微信服务器再根据我们填写的地址,转发到我们的服务器上,处理完以后,我们把我们要发送的消息,交给微信服务器,微信服务器再发送给客户。所以我们要做的事情就只有两件,先接受微信服务器发送过来的消息,然后处理以后,再把我们要发送的消息返回过去。

参考了大佬的代码,实现通信的功能,具体的代码如下:

注:以下代码来源制作淘宝客微信公众号(一)_淘客公众号-CSDN博客

# coding:utf-8
from flask import Flask, request, abort, render_template
import hashlib
import xmltodict
import requests
import time
# 用它可以访问http请求地址
import urllib3.request as urllib2
import urllib3
import urllib
import re
import json
import io
import sys
sys.setdefaultencoding('utf8')   #python2版本
#sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')  #python3版本


# 微信的token令牌
WECHAT_TOKEN = '你的token'
app = Flask(__name__)

@app.route("/zhuanfa", methods=["GET", "POST"])
def wechat():
    """验证服务器地址的有效性"""
    # 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带四个参数:
    # signature:微信加密, signature结合了开发者填写的token参数和请求中的timestamp参数 nonce参数
    # timestamp:时间戳(chuo这是拼音)
    # nonce: 随机数
    # echostr: 随机字符串
    # 接收微信服务器发送参数
    signature = request.args.get("signature")
    timestamp = request.args.get("timestamp")
    nonce = request.args.get("nonce")

    # 校验参数
    # 校验流程:
    # 将token、timestamp、nonce三个参数进行字典序排序
    # 将三个参数字符串拼接成一个字符串进行sha1加密
    # 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
    if not all([signature, timestamp, nonce]):
        # 抛出400错误
        abort(400)

    # 按照微信的流程计算签名
    li = [WECHAT_TOKEN, timestamp, nonce]
    # 排序
    li.sort()
    # 拼接字符串
    tmp_str = "".join(li)
    tmp_str = tmp_str.encode('utf-8')

    # 进行sha1加密, 得到正确的签名值
    sign = hashlib.sha1(tmp_str).hexdigest()

    # 将自己计算的签名值, 与请求的签名参数进行对比, 如果相同, 则证明请求来自微信
    if signature != sign:
        # 代表请求不是来自微信
        # 弹出报错信息, 身份有问题
        abort(403)
    else:
        # 表示是微信发送的请求
        if request.method == "GET":
            # 表示第一次接入微信服务器的验证
            echostr = request.args.get("echostr")
            # 校验echostr
            if not echostr:
                abort(400)
            return echostr

        elif request.method == "POST":
            # 表示微信服务器转发消息过来
            # 拿去xml的请求数据
            xml_str = request.data

            # 当xml_str为空时
            if not xml_str:
                abort(400)

            # 对xml字符串进行解析成字典
            xml_dict = xmltodict.parse(xml_str)

            xml_dict = xml_dict.get("xml")

            # MsgType是消息类型 这里是提取消息类型
            msg_type = xml_dict.get("MsgType")

            if msg_type == "text":
                # 表示发送文本消息
                # 够造返回值, 经由微信服务器回复给用户的消息内容
                # 回复消息
                # ToUsername: (必须传) 接收方账号(收到的OpenID)
                # FromUserName: (必须传) 开发者微信号
                # CreateTime: (必须传) 消息创建时间(整形)
                # MsgType: (必须传) 消息类型
                # Content: (必须传) 回复消息的内容(换行:在Content中能够换行, 微信客户端就支持换行显示)
                resp_dict = {
                    "xml": {
                        "ToUserName": xml_dict.get("FromUserName"),
                        "FromUserName": xml_dict.get("ToUserName"),
                        "CreateTime": int(time.time()),
                        "MsgType": "image",
                        "Content": "用户发送的是文字"
                    }
                }
            elif msg_type == "image":
                resp_dict = {
                    "xml": {
                        "ToUserName": xml_dict.get("FromUserName"),
                        "FromUserName": xml_dict.get("ToUserName"),
                        "CreateTime": int(time.time()),
                        "MsgType": "image",
                        "Content": "用户发送的是图片"
                    }
                }
            elif msg_type == "voice":
                resp_dict = {
                    "xml": {
                        "ToUserName": xml_dict.get("FromUserName"),
                        "FromUserName": xml_dict.get("ToUserName"),
                        "CreateTime": int(time.time()),
                        "MsgType": "text",
                        "Content": "用户发送的是语音"
                    }
                }
            elif msg_type == "link":
                resp_dict = {
                    "xml": {
                        "ToUserName": xml_dict.get("FromUserName"),
                        "FromUserName": xml_dict.get("ToUserName"),
                        "CreateTime": int(time.time()),
                        "MsgType": "text",
                        "Content": "用户发送的是链接"
                    }
                }
            elif msg_type == "vedio":
                resp_dict = {
                    "xml": {
                        "ToUserName": xml_dict.get("FromUserName"),
                        "FromUserName": xml_dict.get("ToUserName"),
                        "CreateTime": int(time.time()),
                        "MsgType": "text",
                        "Content": "用户发送的是视频"
                    }
                }
            elif msg_type == "event":
                if xml_dict.get('Event') == 'subscribe':
                    msg = '用户初次关注发送消息'
                    resp_dict = {
                    "xml": {
                        "ToUserName": xml_dict.get("FromUserName"),
                        "FromUserName": xml_dict.get("ToUserName"),
                        "CreateTime": int(time.time()),
                        "MsgType": "text",
                        "Content": msg
                    }
                }    
            # 将字典转换为xml字符串
            resp_xml_str = xmltodict.unparse(resp_dict)
            # 返回消息数据给微信服务器
            return resp_xml_str


if __name__ == '__main__':
    app.run(port=8000, debug=True)

在云服务器上编写完代码后,使用python xxx.py(xxx为实际的python代码文件名)运行文件,在微信公众号管理界面进行token连通性测试。

只有当token验证成功后才能进行以下步骤,否则一切都是没有意义的

三、利用淘宝官方接口进行代码编写

3.1 获取官方SDK

首先,需要先获取淘宝官方提供的sdk,否则无法编译成功

下载下来应该是个压缩包,解压后(解压后应该还有一个压缩包)利用远程连接工具上传至云服务器(解压后应该还有一个zip压缩包),根据以下步骤设置sdk

yum install unzip -y  #刚申请的阿里云服务器应该是没有unzip命令的
make /usr/local/sdk   #创建存放sdk的路径,根据自己选择
unzip xxxxx.zip -d /usr/local/sdk  #将压缩包解压到指定目录
echo "export PYTHONPATH=/usr/local/sdk" >> ~/.bashrc  #将sdk路径写入环境变量
##注:这里最好用vim ~/.bashrc检查一下文件是否出问题
source ~/.bashrc  #刷新环境变量

好了,至此所有环境变量全部设置完毕,接下来只需要编写代码就可以实现公众号自动获取优惠券链接的功能了

3.2 编写接口函数

首先编写所用到的函数,具体的命令和参数参考淘宝提供的接口文档


加个前提,需要先获取你的Appkey、Appsecret、PID的最后一段


以下是三个接口函数的代码(python2版本)

# -*- coding: utf-8 -*-
import top.api
from decimal import *
import re


appkey = '你的Appkey'
secret = '你的secret'
adzone_id = '你的pid的最后一段'

def TbkDgMaterialOptional(title): #查找商品的详细信息
    #连接淘宝api
    req = top.api.TbkDgMaterialOptionalRequest(domain='gw.api.taobao.com',port=80)
    req.set_app_info(top.appinfo(appkey, secret))

    #设置需要的参数
    req.adzone_id = adzone_id #必须有的参数
    req.platform = 2
    req.q = title
    try:
        resp = req.getResponse()
        return resp
    except Exception as e:
        print(e)


def TbkCouponGet(item_id,activity_id): #查找商品有无对应的优惠券
    req = top.api.TbkCouponGetRequest(domain='gw.api.taobao.com',port=80)
    req.set_app_info(top.appinfo(appkey, secret))

    req.item_id = str(item_id)
    req.activity_id = str(activity_id)
    try:
        resp = req.getResponse()
        return resp
    except Exception as e:
        print(e)


def TbkTpwdCreate(title,url): #有对应的优惠券的商品生成短链接
    req = top.api.TbkTpwdCreateRequest(domain='gw.api.taobao.com',port=80)
    req.set_app_info(top.appinfo(appkey, secret))

    req.text = title
    req.url = url
    try:
        resp = req.getResponse()
        return resp
    except Exception as e:
        print(e)

python3版本

# -*- coding: utf-8 -*-
from datetime import datetime
from topsdk.client import TopApiClient,TopException
from topsdk.ability370.ability370 import Ability370
from topsdk.ability371.ability371 import Ability371
from topsdk.ability375.ability375 import Ability375
from topsdk.ability370.request.taobao_tbk_dg_material_optional_request import *
from topsdk.ability371.request.taobao_tbk_coupon_get_request import *
from topsdk.ability375.request.taobao_tbk_tpwd_create_request import *

from decimal import *
import re


appkey = '你的Appkey'
secret = '你的Appsecret'
adzone_id = '你的pid最后一段'

def TbkDgMaterialOptional(title): #查找商品的详细信息
    #create Client
    client = TopApiClient(appkey=appkey, app_sercet=secret, top_gateway_url='gw.api.taobao.com', verify_ssl=False)
    ability = Ability370(client=client)

    #create request
    request = TaobaoTbkDgMaterialOptionalRequest()
    request.adzone_id = adzone_id #必须有的参数
    request.platform = 2
    request.q = title
    try:
        response = ability.taobao_tbk_dg_material_optional(request)
        return response
    except Exception as e:
        print(e)


def TbkCouponGet(item_id,activity_id): #查找商品有无对应的优惠券
    #create Client
    client = TopApiClient(appkey=appkey, app_sercet=secret, top_gateway_url='gw.api.taobao.com', verify_ssl=False)
    ability = Ability371(client=client)

    #create request
    request = TaobaoTbkCouponGetRequest()
    request.item_id = str(item_id)
    request.activity_id = str(activity_id)
    try:
        response = alibity.taobao_tbk_coupon_get(request)
        return response
    except Exception as e:
        print(e)


def TbkTpwdCreate(title,url): #有对应的优惠券的商品生成短链接
    #create Client
    client = TopApiClient(appkey=appkey, app_sercet=secret, top_gateway_url='gw.api.taobao.com', verify_ssl=False)
    ability = Ability375(client=client)

    #create request
    request = TaobaoTbkTpwdCreateRequest()
    request.text = title
    request.url = url
    try:
        response = ability.taobao_tbk_tpwd_create(request)
        return response
    except Exception as e:
        print(e)

注:python3版本没有实际进行测试,可能会出现问题,有任何问题欢迎留言和私信

3.3 调用接口实现功能

函数编写完成后就是需要进行调用,调用函数在之前flask验证代码的基础上进行修改

# -*- coding: utf-8 -*-
from flask import Flask, request, abort, render_template
from decimal import *
import hashlib
import xmltodict
import requests
import time
# 用它可以访问http请求地址
import urllib3.request as urllib2
import urllib3
import urllib
import re
import json
import io
import sys
reload(sys)
sys.setdefaultencoding('utf8')   #python2版本
#sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')  #python3版本
import taobao_    #为刚才编写的函数的python文件,如果不想分开写也可以写在一起

appkey = ''
secret = ''
adzone_id = ''


# 微信的token令牌
WECHAT_TOKEN = '你的token'
app = Flask(__name__)

@app.route("/zhuanfa", methods=["GET", "POST"])
def wechat():
    """验证服务器地址的有效性"""
    # 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带四个参数:
    # signature:微信加密, signature结合了开发者填写的token参数和请求中的timestamp参数 nonce参数
    # timestamp:时间戳(chuo这是拼音)
    # nonce: 随机数
    # echostr: 随机字符串
    # 接收微信服务器发送参数
    signature = request.args.get("signature")
    timestamp = request.args.get("timestamp")
    nonce = request.args.get("nonce")

    # 校验参数
    # 校验流程:
    # 将token、timestamp、nonce三个参数进行字典序排序
    # 将三个参数字符串拼接成一个字符串进行sha1加密
    # 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
    if not all([signature, timestamp, nonce]):
        # 抛出400错误
        abort(400)

    # 按照微信的流程计算签名
    li = [WECHAT_TOKEN, timestamp, nonce]
    # 排序
    li.sort()
    # 拼接字符串
    tmp_str = "".join(li)
    tmp_str = tmp_str.encode('utf-8')

    # 进行sha1加密, 得到正确的签名值
    sign = hashlib.sha1(tmp_str).hexdigest()

    # 将自己计算的签名值, 与请求的签名参数进行对比, 如果相同, 则证明请求来自微信
    if signature != sign:
        # 代表请求不是来自微信
        # 弹出报错信息, 身份有问题
        abort(403)
    else:
        # 表示是微信发送的请求
        if request.method == "GET":
            # 表示第一次接入微信服务器的验证
            echostr = request.args.get("echostr")
            # 校验echostr
            if not echostr:
                abort(400)
            return echostr

        elif request.method == "POST":
            # 表示微信服务器转发消息过来
            # 拿去xml的请求数据
            xml_str = request.data

            # 当xml_str为空时
            if not xml_str:
                abort(400)

            # 对xml字符串进行解析成字典
            xml_dict = xmltodict.parse(xml_str)

            xml_dict = xml_dict.get("xml")

            # MsgType是消息类型 这里是提取消息类型
            msg_type = xml_dict.get("MsgType")

            if msg_type == "text":
                # 表示发送文本消息
                # 够造返回值, 经由微信服务器回复给用户的消息内容
                # 回复消息
                # ToUsername: (必须传) 接收方账号(收到的OpenID)
                # FromUserName: (必须传) 开发者微信号
                # CreateTime: (必须传) 消息创建时间(整形)
                # MsgType: (必须传) 消息类型
                # Content: (必须传) 回复消息的内容(换行:在Content中能够换行, 微信客户端就支持换行显示)

                text = xml_dict.get("Content")
                #pattern = "؋<200e>฿₿¢₡₵$₫֏€₲₾₴₭₺₼₥₦₱£﷼<200e>៛₽₨௹₹৲৳૱₪₸₮₩¥₳₠₢₯₣₤₶₧₰₷"
                #pattern = "([" + pattern + "])" + "(\\w+)\\1"
                #result = re.compile(pattern).findall(text)
                #try:
                #    result = result[0][0] + result[0][1] + result[0][0]  # 取匹配到的第一个
                #except IndexError:
                #    result = ""

                #查找商品信息
                response = taobao_.TbkDgMaterialOptional(text)
                #获取信息页第一条数据
                map_data = response['tbk_dg_material_optional_response']['result_list']['map_data'][0]
                if map_data.get('coupon_share_url') is None:
                    message = "没有发现优惠券"
                else:
                    title = map_data.get('title')  #得到商品的名称
                    itemid = map_data.get('item_id')  #得到商品的id
                    activityid = map_data.get('coupon_id')  #得到优惠券的id
                    share_url = "https:" + map_data.get('coupon_share_url')

                    priceresponse = taobao_.TbkCouponGet(itemid,activityid)
                    price = priceresponse['tbk_coupon_get_response']['data']
                    discount = price.get('coupon_amount')#商品的优惠券额度
                    onsale= price.get('coupon_start_fee') #商品的原始价格
                    difference = str(float(Decimal(onsale) - Decimal(discount)))  #优惠后的价格

                    #生成淘口令
                    Shortlink = taobao_.TbkTpwdCreate(title,share_url)
                    link = Shortlink['tbk_tpwd_create_response']['data']['model'] #得到短链接
                    #linkterm = re.compile(r'(.*?)【.*')
                    #truelink = re.findall(linkterm,link) #优化为自己比较习惯的语言逻辑

                    message = title + "【在售价】" + onsale + "【券后价】" + difference + " " + link


                    resp_dict = {
                    "xml":{
                        "ToUserName":xml_dict.get("FromUserName"),
                        "FromUserName":xml_dict.get("ToUserName"),
                        "CreateTime":int(time.time()),
                        "MsgType":"text",
                        "Content": message
                        }
                    }
            # 将字典转换为xml字符串
            resp_xml_str = xmltodict.unparse(resp_dict)
            # 返回消息数据给微信服务器
            return resp_xml_str


if __name__ == '__main__':
    #pdb.set_trace()
    app.run(port=8000, debug=True)

至此,一个简单的微信公众号获取淘宝优惠券的功能就实现了,该功能没有做太多的内容,只是简单的进行优惠券的获取,感兴趣的可以在此基础上进行优化。

总结

总的来说整个流程并不复杂,涉及到的代码量也不是很多,感兴趣的可以自动动手实践一下。在整个python代码编写完成后,记得让代码在后台运行,否则是无法正常使用的(后台运行的原因是不需要一直前台远程连接,否则远程连接一旦断开,程序也会结束运行,也就没办法正常使用功能了)。具体的后台运行代码如下:

nohup python -u xxxxx.py >> /tmp/xxxlog.log 2>&1 &

1. 最后一个“&”表示后台运行程序
2. “nohup” 表示程序不被挂起
3. “python”表示执行python代码
4. “-u”表示不启用缓存,实时输出打印信息到日志文件(如果不加-u,则会导致日志文件不会实时      刷新代码中的print函数的信息)
5. “xxxxx.py”表示python的源代码文件(根据自己的文件修改)
6. “xxxlog.log”表示输出的日志文件(根据自己的选择自己取名字)
7. “>”表示将打印信息重定向到日志文件
8. “2>&1”表示将标准错误输出转变化标准输出,可以将错误信息也输出到日志文件中(0-> stdin,       1->stdout, 2->stderr)
注:此接口查询商品优惠券使用的是关键词搜索,并且只能获取淘宝客推广平台拥有的优惠券,所以可能在搜索的时候得到的优惠券并不是准备匹配的优惠券,会有部分的差异。

如果想要查看具体的实现效果,欢迎关注公众号“优来惠去”进行查看,目前也还在改造升级中,后续也有可能会实现完整的功能,方便自己的同时也方便大家。

如果在实际的操作过程中有任何问题,或者有任何不明白的地方,以及有任何好的建议都可以在留言或私信。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Saulstone

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值