Flask 与微信小程序对接

阅读: 评论:0

Flask 与微信小程序对接

Flask 与微信小程序对接

Flask 与微信小程序的对接

在 web/controllers/api中增建py文件,主要是给微信小程序使用的。

web/controllers/init.py

# -*- coding: utf-8 -*-
from flask import Blueprint
route_api = Blueprint( 'api_page',__name__ )@ute("/")
def index():return "Mina Api V1.0~~"

www.py

llers.api import route_api

如图所示api已经做好了

微信小程序mina

小程序简介 | 微信开放文档

mina/pages/index

mina/pages/index   /index.wxml

wxml中 屏蔽注释用 <!--       --!>

<!--start.wxml-->
<view class="container"><view class="remind-box" wx:if="{{remind}}"><image class="remind-img" src="/images/more/loading.gif"></image></view><block wx:else><image class="title" src="/images/more/title8.png"></image><view class="content"><view class="hd" style="transform:rotateZ({{angle}}deg);"><image class="logo" src="/images/more/logo.png"></image><image class="wave" src="/images/more/wave.png" mode="aspectFill"></image><image class="wave wave-bg" src="/images/more/wave.png" mode="aspectFill"></image></view><view class="bd"><image class="smalltitle" src="/images/more/confirm-word1.png"></image><view class="confirm-btn" bindtap='goToIndex'><text >走吧,订餐去</text></view><text class="copyright">@编程浪子 54php</text></view></view></block>
</view>

第一步: 设置小程序用户信息

avatar  

n.化身(印度教中化作人形或兽形的神);(人或思想的)化身,体现;(在电脑游戏或网络中代表使用者的)图标,头像;<正式>代表人物

这段代码中,使用了条件语句wx:if="{{canIUse}}"来判断是否支持该API。

如果支持      则显示一个按钮用于授权登录,点击按钮会触发bindgetuserinfo事件,可以在事件处理函数bindGetUserInfo中获取用户信息。

如果不支持   该API,则显示一条提示信息,请用户升级微信版本。


我们这里使用class="confirm-btn", 并去掉wx:if"{{canIUse}}"

<!--start.wxml-->
<view class="container"><view class="remind-box" wx:if="{{remind}}"><image class="remind-img" src="/images/more/loading.gif"></image></view><block wx:else><image class="title" src="/images/more/title8.png"></image><view class="content"><view class="hd" style="transform:rotateZ({{angle}}deg);"><image class="logo" src="/images/more/logo.png"></image><image class="wave" src="/images/more/wave.png" mode="aspectFill"></image><image class="wave wave-bg" src="/images/more/wave.png" mode="aspectFill"></image></view><view class="bd"><image class="smalltitle" src="/images/more/confirm-word1.png"></image>
<!--        <view class="confirm-btn" bindtap='goToIndex'>-->
<!--          <text >走吧,订餐去</text>-->
<!--        </view>--><button class="confirm-btn" open-type="getUserInfo" bindgetuserinfo="login">授权登录</button><text class="copyright">@编程浪子 54php</text></view></view></block></view>
问题1: 为什么wx:if 可以去掉?  wx:if的作用是什么呢?

没有使用<wx:if="{{canIUse}}">的原因是因为在data中没有定义canIUse这个属性。在data中定义了remind属性,用于控制是否显示加载中的提示框。因此,在wxml中使用了wx:if="{{remind}}"来判断是否显示加载中的提示框。

代码中,确实没有使用<wx:if="{{canIUse}}">

wx:if是一个条件渲染的指令,用于根据条件来决定是否渲染某个组件或元素。

canIUse是一个变量,用于存储一个布尔值,根据这个布尔值来决定是否渲染<wx:if>所在的组件或元素。

wx:if的作用是根据条件来动态渲染页面的不同部分。

        当条件为真时,渲染该组件或元素;

        当条件为假时,不渲染该组件或元素。

        这样可以根据不同的条件来显示不同的内容,提高页面的灵活性和交互性。

在给出的代码中,没有使用<wx:if="{{canIUse}}">,可能是因为canIUse变量的值在该代码段中没有被定义或赋值。所以,该代码段中没有使用<wx:if="{{canIUse}}">

其实上面代码已经使用wx:if="{{remind}}"做了相关判断。


按钮更改后展示图

问题2: open-type 有什么作用?

微信小程序中的open-type是一个属性,用于定义按钮的点击行为。根据提供的引用内容,有两种常见的open-type值可以使用。

  1. contact:该值用于直接打开客服对话功能。要使用此功能,需要在微信小程序的后台进行配置,并且只能通过真机调试来打开。具体的配置和使用方法可以参考微信小程序开发文档。

  2. launchApp:该值用于在小程序中直接打开其他应用程序。通过设置launchApp的open-type,可以实现在小程序中点击按钮后直接打开指定的应用程序。更多详细信息可以参考微信小程序开发文档中的相关章节。

请注意,open-type属性的具体使用方式和效果可能会因微信小程序的版本和配置而有所不同。建议在开发过程中参考官方文档并进行测试

这里使用了open-type="getUserInfo" 来定义这样一个属性,来获取用户信息

问题3: bindgetuserinfo="" 也是一个属性吗?这个属性起到什么作用?

在微信小程序中,bindgetuserinfo是一个用于   获取用户信息的事件  绑定  属性。

当用户点击 授权按钮 并允许小程序获取用户信息时,该事件会被触发,并将 用户信息  作为  参数  传递给  绑定的   事件处理函数

下面是一个示例代码,演示了如何在微信小程序中使用bindgetuserinfo属性:

<!-- index.wxml -->
<view class="container"><button bindgetuserinfo="getUserInfo">获取用户信息</button>
</view>
// index.js
Page({getUserInfo: function(e) {console.log(e.detail.userInfo);// 在这里可以对用户信息进行处理}
})

在上述示例中,当用户点击"获取用户信息"按钮时,会触发getUserInfo函数,并将用户信息传递给该函数的参数e。你可以在该函数中对用户信息进行处理,比如打印到控制台或者发送到服务器。


这里使用bindgetuserinfo="login",当用户点击这个授权登录按钮时,绑定login()方法

问题4: open-data 是什么?

open-data | 微信开放文档    用于展示微信开放的数据。

问题5: <block wx:else> </block> 中block是什么?

在给出的代码中,<block>是一个条件渲染的标签。它的作用是根据条件来决定是否渲染其中的内容。在这段代码中,<block>标签的wx:else属性表示如果remind为假,则渲染<block>标签内的内容。如果remind为真,则不渲染<block>标签内的内容。

条件渲染 | 微信开放文档

因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。

注意: <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。

问题6: <view></view>是什么?

view | 微信开放文档     视图容器

在给出的代码中,<view>是小程序中的一个组件,用于显示一个视图容器。它类似于HTML中的<div>标签,用于包裹其他元素或者作为一个独立的容器。在这段代码中,<view>标签被用来创建一个容器,其中包含了其他的视图元素,例如<image><text>

<view>标签有一些常用的属性,例如class用于指定样式类名,style用于指定内联样式,wx:if用于条件渲染,wx:else用于条件渲染的反向情况。

在这段代码中,<view>标签被用来创建一个容器,其中包含了一个条件渲染的逻辑。当remind为真时,显示一个带有loading图片的提醒框;否则显示一个包含图片、按钮和文本的内容框。


mina/pages/index    /index.js

//login.js
//获取应用实例
var app = getApp();
Page({data: {remind: '加载中',angle: 0,userInfo: {}},goToIndex:function(){wx.switchTab({url: '/pages/food/index',});},onLoad:function(){wx.setNavigationBarTitle({title: app.globalData.shopName})},onShow:function(){},onReady: function(){var that = this;setTimeout(function(){that.setData({remind: ''});}, 1000);wx.onAccelerometerChange(function(res) {var angle = -(res.x*30).toFixed(1);if(angle>14){ angle=14; }else if(angle<-14){ angle=-14; }if(that.data.angle !== angle){that.setData({angle: angle});}});},login:function(e){var that = this;if (!e.detail.userInfo){app.alert({ "content": "登陆失败,请在此点击~~"});return;}var data = e.detail.userInfo;wx.login({success:function(res){if (!de){app.alert({"content":"登陆失败,请再次点击~~"});return;}data['code'] = quest({url:app.buildUrl('/member/login'),RequestHeader(),method:'POST',data:data,success:function(res){if(de != 200){app.alert({'content':res.data.msg });return;}app.setCache("token", res.ken);ToIndex();}});}});}});
});

问题1: getApp() 是什么意思?

var app = getApp();:定义一个变量app,并将其赋值为getApp(),即获取小程序的实例。

AppObject getApp(Object object) | 微信开放文档

var app = getApp(); 是小程序中获取全局app对象的一种常见方式。通过这行代码,我们可以在页面中使用app对象中定义的全局数据和方法。

在小程序中,每个页面都有自己的js文件,而app.js是小程序的入口文件,它是全局的,可以在整个小程序中共享数据和方法。通过在页面中使用var app = getApp();我们可以获取到app.js中定义的全局app对象。

这个全局app对象中通常包含了一些全局的数据和方法,比如全局的用户信息、全局的网络请求方法等。通过获取app对象,我们可以在页面中直接使用这些全局数据和方法,而不需要重复定义或传递数据。

下面是一个示例,展示了如何使用var app = getApp();获取app对象并使用其中的全局数据和方法:

// app.js
App({globalData: {userInfo: null,apiUrl: ''},getUserInfo: function() {// 获取用户信息的方法}
})// page.js
var app = getApp();
console.log(app.globalData.userInfo); // 输出全局的用户信息
UserInfo(); // 调用全局的获取用户信息的方法

通过上述代码,我们可以看到,在page.js中使用var app = getApp();获取到了app对象,并可以通过app.globalData访问全局的数据,通过UserInfo()调用全局的方法。


该段代码是一个小程序的登录页面的代码。下面是各部分的作用:

  1. //获取应用实例:注释,说明下面的代码是获取小程序的实例。

  2. Page({ ... }):定义一个页面对象,包含了页面的  数据、事件处理函数和生命周期函数等。

  3. data: { ... }:定义页面的数据,包括remindangleuserInfo等。

  4. goToIndex: function() { ... }:定义了一个名为goToIndex的事件处理函数,用于跳转到首页。

  5. onLoad: function() { ... }:定义了一个名为onLoad的生命周期函数,在页面加载时执行,设置导航栏标题为全局变量app.globalData.shopName的值。

问题2: wx.switchTab({})函数起到了什么作用?

wx.switchTab(Object object) | 微信开放文档   跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面

在小程序中,可以使用wx.switchTab()函数来实现页面跳转到指定的tab页。

这段代码将会跳转到名为index的tab页,该tab页的路径为/pages/food/index

问题3: wx.setNavigationBarTitle({title: app.globalData.shopName})是什么函数?

这段代码是用于设置小程序页面的导航栏标题。 

wx.setNavigationBarTitle(Object object) | 微信开放文档  动态设置当前页面的标题

具体来说,它使用了wx.setNavigationBarTitle()函数,并传入一个对象作为参数。该对象包含一个title属性,其值为app.globalData.shopName

app.globalData.shopName是一个全局变量,用于存储商店的名称。通过将该变量的值赋给title属性,wx.setNavigationBarTitle()函数就可以将商店名称作为页面的导航栏标题进行显示。

需要注意的是,该代码需要在小程序的页面中使用,并且前提是在全局中定义了app对象,并且该对象中包含了globalData属性和shopName属性。


这里是调动了mina/app.js文件里的app里的globalData里的shopName  即“python3 + Flask 订餐全站系统”   作为 动态设置当前页面的标题的值。


问题3.1: shopName 是什么?

小程序商品推广 | 微信开放文档  

获取小程序商品推广素材

接口说明

通过该接口获取商品的推广素材,包括店铺appID、商品详情页Path、推广文案及推广短链、商品图片等

这里用的是已经封装好的js方法

login ...

该段代码是一个登录函数,用于处理用户登录的逻辑。具体介绍如下:

  1. 首先,函数接收一个事件对象e作为参数。
  2. 在函数内部,通过判断事件对象e中的用户信息是否存在来确定用户是否登录成功。如果用户信息不存在,则会弹出一个提示框提示登录失败,并返回。
  3. 如果用户信息存在,将用户信息赋值给变量data。
  4. 接着,调用wx.login()函数进行微信登录,获取登录凭证code。
  5. 如果登录凭证code不存在,则会弹出一个提示框提示登录失败,并返回。
  6. 如果登录凭证code存在,将code添加到data中。
  7. 然后,通过wx.request()函数向服务器发送登录请求,请求的URL为’/member/login’,请求头部包含RequestHeader()返回的请求头信息,请求方法为POST,请求数据为data。
  8. 如果服务器返回的状态码不等于200,则会弹出一个提示框显示返回的错误信息,并返回。
  9. 如果服务器返回的状态码等于200,则将返回的token存储到缓存中,键名为"token",键值为res.ken。
  10. 最后,调用goToIndex()函数进行页面跳转。
问题4: 概述一下setTimeout({})起到的功能?

number setTimeout(function callback, number delay, any rest) | 微信开放文档 设定一个定时器。在定时到期以后执行注册的回调函数

这段代码的作用是在1000毫秒(即1秒)后执行一个函数,将remind属性设置为空字符串。这通常用于在一定时间后执行某个操作,例如延迟显示或隐藏某个元素。

问题5: wx.onAccelerometerChange()代码有什么作用? 

accelerometer    美/əkˌseləˈrɑːmɪtər/     n.加速度计;(飞机、火箭的)加速器

根据提供的引用内容,这段代码是用于监听微信小程序的加速度计变化,并根据变化的角度来更新页面的数据。具体来说,代码中使用了函数来监听加速度计的变化,当加速度计的x轴变化时,会计算出对应的角度,并将角度更新到页面的angle数据中。

这段代码中,res.x表示加速度计在x轴上的变化值,乘以30后取负数,得到的就是角度值。然后通过判断角度是否超过了限制范围(-14到14之间),如果超过了,则将角度限制在这个范围内。最后,通过setData函数将更新后的角度值存储到页面的angle数据中,从而实现页面的更新。

toFixed(1)是一个用于保留小数位数的方法。它可以将一个数字四舍五入到指定的小数位数,并返回一个字符串表示该数字。

问题6:e.detail.userInfo的值是什么?

e.detail.userInfo是一个对象,包含用户的详细信息,例如用户的昵称、头像、性别等。在这个例子中,e.detail.userInfo是通过微信小程序的getUserInfo接口获取的用户信息。

问题7: wx.request({})方法 的作用是什么?

从前端js文件发送到后端

RequestTask | 微信开放文档  发起 HTTPS 网络请求。

文档里有其详细的各种属性。

wx.request({url:'192.168.10.10:8999/xxx/xxx',method:'POST',data:data,success:function(res){}})
问题8: wx.login 函数中的res是什么?

reswx.login方法的回调函数的参数,它包含了登录凭证code

wx.login(Object object) | 微信开放文档    

调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户在当前小程序的唯一标识(openid)、微信开放平台账号下的唯一标识(unionid,若当前小程序已绑定到微信开放平台账号)及本次登录的会话密钥(session_key)等。

用户数据的加解密通讯需要依赖会话密钥完成


知识点1: 小程序到微信公众平台需要进行相关request合法域名的设置

这里引入了一个新的 层面,域名。域名是做什么的呢?域名有什么作用呢?

通过这两三天的沉思琢磨,忍痛割爱般痛下决心,域名得买!买个最便宜的、最贱的。纵使是一年8块钱的花销,也要勇敢面对它。

当然了,这里编程浪子老师指出:在开发过程中有跳过request合法域名的设置选项,也就是说在程序开发好了以后再买也不迟。确实是这样,好钢用在刀刃上,刀不用,要刀以何?

步骤: 到小程序官网微信小程序开发设置,有个服务器域名。

问题8: 域名有什么作用呢?

域名有以下几个主要的作用:

  1. 建网站:注册域名最常见的用途就是建网站。域名可以直接用于访问网站,一个好的域名可以让网站在推广过程中更加省力,让用户更容易记住。

  2. 投资赚钱:除了建网站,还有很多人注册域名是为了投资。域名具有升值空间,因为注册一个域名就少一个,所以一个好的域名可以成为投资的对象,有一定的投资价值。

  3. 品牌保护:对于重视自身品牌的企业来说,他们通常会注册多个域名后缀来保护自己的品牌。除了以外的其他重要域名后缀也会被注册,以免被他人注册后造成不必要的损失。

以下是一个示例代码,演示如何使用Python获取域名的作用:

# 建网站
website_domain = &#ample"# 投资赚钱
investment_domain = "www.investmentdomain"# 品牌保护
brand_domains = [&#ample", &#ample"]print("网站域名:", website_domain)
print("投资域名:", investment_domain)
print("品牌保护域名:", brand_domains)
知识点2: 小程序开发工具 和 pycharm 怎么共同编辑同一个文件

小程序开发工具和PyCharm可以通过以下步骤共同编辑同一个文件:

  1. 打开小程序开发工具,创建一个新的小程序项目。
  2. 在PyCharm中打开同一个项目文件夹。
  3. 在小程序开发工具中,找到需要共同编辑的文件,右键点击选择“在资源管理器中打开”。
  4. 在资源管理器中,找到该文件的路径。
  5. 在PyCharm中,打开相同的文件。
  6. 现在你可以在PyCharm中进行编辑,并且小程序开发工具会自动检测到文件的更改并进行同步。

这样,你就可以在小程序开发工具和PyCharm中同时编辑同一个文件了。


 知识点3: 小程序路由在pycharm中的flask框架中的部署

如图:还没部署路由,在 微信开发者工具中DD报错

问题9: 微信小程序的路由如何在flask中部署呢?

common/libs/UrlManager.py  链接管理器中啥也没有

# -*- coding: utf-8 -*-
import time
from application import appclass UrlManager(object):def __init__(self):pass@staticmethoddef buildUrl( path ):return path
web/controllers/api/   此文件夹是专门给小程序配置用的

 web/controllers/api/  __init__.py 

# -*- coding: utf-8 -*-
from flask import Blueprint
route_api = Blueprint( 'api_page',__name__ )llers.api.Member import *@ute("/")
def index():return "Mina Api V1.0~~"

这段代码是一个使用Flask框架  为 微信小程序 创建API的示例代码。下面是对代码的解析:

  1. 首先,导入了Blueprint类和route_api对象。Blueprint是Flask框架中用于创建蓝图的类,蓝图可以将相关的视图函数、模板和静态文件组织在一起。route_api是一个蓝图对象,用于定义API的路由和视图函数。

  2. 接下来,导入了Member模块中的所有内容。这个模块可能包含了与会员相关的API视图函数和其他功能。

  3. 然后,使用ute("/")装饰器将index()函数注册为处理根路径(“/”)的视图函数。当用户访问根路径时,该函数将被调用。

  4. 最后,index()函数返回了一个字符串"Mini Api V1.0~~"作为响应。

这段代码的作用是创建一个名为api_page的蓝图,并定义了一个处理根路径的视图函数。当用户访问根路径时,将返回字符串"Mini Api V1.0~~"作为响应。

web/controllers/api       Member.py

# -*- coding: utf-8   -*-llers.api import route_api
from flask import request, jsonify@ute("/member/login",methods = [ "GET","POST" ])
def login():resp = { 'code':200 ,'msg':'操作成功~','data':{} }req = request.valuescode = req['code'] if 'code' in req else ''if not code or len( code ) < 1:resp['code'] = -1resp['msg'] = "需要code"return jsonify(resp)openid = WeChatOpenId( code )if openid is None:resp['code'] = -1resp['msg'] = "调用微信出错"return jsonify(resp)nickname = req['nickName'] if 'nickName' in req else ''sex = req['gender'] if 'gender' in req else 0avatar = req['avatarUrl'] if 'avatarUrl' in req else '''''判断是否已经测试过,注册了直接返回一些信息'''bind_info = OauthMemberBind.query.filter_by( openid = openid,type = 1 ).first()if not bind_info:model_member = Member()model_member.nickname = nicknamemodel_member.sex = sexmodel_member.avatar = avatarmodel_member.salt = Salt()model_member.updated_time = ated_time = getCurrentDate()db.session.add(model_member)db.sessionmit()model_bind = OauthMemberBind()ber_id = model_member.pe = 1model_bind.openid = a = ''model_bind.updated_time = ated_time = getCurrentDate()db.session.add(model_bind)db.sessionmit()bind_info = model_bindmember_info = Member.query.filter_by(id = ber_id).first()token = "%s#%s" % (AuthCode(member_info), member_info.id)resp['data'] = {'token': token}return jsonify( resp )

这段代码是一个基于Flask框架的API接口,主要实现了一个名为"login"的接口。下面是对代码的解析:

  1. 首先,导入了必要的模块和库:
  2. 定义了一个路由装饰器,将该接口绑定到"/member/login"的URL上:定义了一个路由/member/login,并指定了允许的请求方法为GET和POST。
  3. 定义了一个名为"login"的函数,用于处理登录请求:
  4. 初始化一个字典类型的变量"resp",创建了一个字典resp,用于存储接口返回的数据。
  5. 通过request.values获取请求参数,并从中获取code参数。
  6. 判断"code"参数是否存在,如果不存在或长度小于1,将resp中的code设置为-1,则返回错误msg信息"需要code",并返回resp的JSON格式
  7. 调用MemberService的getWeChatOpenId方法,传入"code"参数,获取微信的openid:
  8. 判断openid是否为空,如果为空,将resp中的code设置为-1,则返回错误信息msg:"调用微信出错",并返回resp的JSON格式。
  9. 从请求参数中获取nickNamegenderavatarUrl参数,并分别赋值给nicknamesexavatar变量。
  10. 判断是否已经存在与openid对应的OauthMemberBind记录,如果不存在,则表示用户是第一次登录,需要创建新的用户记录。
  11. 创建新的用户记录时,首先创建一个Member对象,并设置其属性值为nicknamesexavatar等参数值。
  12. 生成一个随机的盐值,并将其赋值给model_membersalt属性。
  13. 设置model_memberupdated_timecreated_time属性为当前时间。
  14. model_member添加到数据库会话中,并提交会话,完成用户记录的创建。
  15. 创建一个OauthMemberBind对象,并设置其属性值为model_memberid、1(表示微信登录)、openid等参数值。
  16. 设置model_bindupdated_timecreated_time属性为当前时间。
  17. model_bind添加到数据库会话中,并提交会话,完成OauthMemberBind记录的创建。
  18. bind_info赋值为model_bind,用于后续获取用户信息。
  19. 根据bind_info中的member_id查询Member表,获取用户信息。
  20. 生成用户的认证码,并将其与member_infoid拼接成一个字符串,赋值给token变量。
  21. token赋值给respdata字段。
  22. 返回resp的JSON格式作为接口的响应。

common/models/member/Member.py    数据库Member

# coding: utf-8
from sqlalchemy import Column, DateTime, Integer, String
from sqlalchemy.schema import FetchedValue
from application import db,appclass Member(db.Model):__tablename__ = 'member'id = db.Column(db.Integer, primary_key=True)nickname = db.Column(db.String(100), nullable=False, server_default=db.FetchedValue())mobile = db.Column(db.String(11), nullable=False, server_default=db.FetchedValue())sex = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())avatar = db.Column(db.String(200), nullable=False, server_default=db.FetchedValue())salt = db.Column(db.String(32), nullable=False, server_default=db.FetchedValue())reg_ip = db.Column(db.String(100), nullable=False, server_default=db.FetchedValue())status = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())@propertydef status_desc(self):fig['STATUS_MAPPING'][ str( self.status ) ]@propertydef sex_desc(self):sex_mapping = {"0":"未知","1":"男","2":"女"}return sex_mapping[str(self.sex)]

数据库配置相关信息

DROP TABLE IF EXISTS `member`;CREATE TABLE `member` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`nickname` varchar(100) NOT NULL DEFAULT '' COMMENT '会员名',`mobile` varchar(11) NOT NULL DEFAULT '' COMMENT '会员手机号码',`sex` tinyint(1) NOT NULL DEFAULT '0' COMMENT '性别 1:男 2:女',`avatar` varchar(200) NOT NULL DEFAULT '' COMMENT '会员头像',`salt` varchar(32) NOT NULL DEFAULT '' COMMENT '随机salt',`reg_ip` varchar(100) NOT NULL DEFAULT '' COMMENT '注册ip',`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态 1:有效 0:无效',`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后一次更新时间',`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员表';
flask-sqlacodegen 'mysql://root:root@127.0.0.1/food_db' --tables member --outfile "common/models/member/Member.py"  --flask


common/models/member/OauthMemberBind.py     OauthMemberBind数据库

# coding: utf-8
from sqlalchemy import Column, DateTime, Index, Integer, String, Text
from sqlalchemy.schema import FetchedValue
from application import dbclass OauthMemberBind(db.Model):__tablename__ = 'oauth_member_bind'__table_args__ = (db.Index('idx_type_openid', 'type', 'openid'),)id = db.Column(db.Integer, primary_key=True)member_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())client_type = db.Column(db.String(20), nullable=False, server_default=db.FetchedValue())type = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())openid = db.Column(db.String(80), nullable=False, server_default=db.FetchedValue())unionid = db.Column(db.String(100), nullable=False, server_default=db.FetchedValue())extra = db.Column(db.Text, nullable=False)updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
DROP TABLE IF EXISTS `oauth_member_bind`;CREATE TABLE `oauth_member_bind` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`member_id` int(11) NOT NULL DEFAULT '0' COMMENT '会员id',`client_type` varchar(20) NOT NULL DEFAULT '' COMMENT '客户端来源类型。qq,weibo,weixin',`type` tinyint(3) NOT NULL DEFAULT '0' COMMENT '类型 type 1:wechat ',`openid` varchar(80) NOT NULL DEFAULT '' COMMENT '第三方id',`unionid` varchar(100) NOT NULL DEFAULT '',`extra` text NOT NULL COMMENT '额外字段',`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后更新时间',`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',PRIMARY KEY (`id`),KEY `idx_type_openid` (`type`,`openid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='第三方登录绑定关系';
flask-sqlacodegen 'mysql://root:root@127.0.0.1/food_db' --tables oauth_member_bind --outfile "common/models/member/OauthMemberBind.py"  --flask

问题1: unionid 是什么?

UnionID是微信开放平台的一个标识符,用于唯一标识同一用户在不同应用(包括公众号、小程序、移动应用等)中的身份。它是一个  字符串 ,由微信开放平台生成并分配给每个用户。UnionID的作用是方便开发者在不同应用之间进行用户数据的关联和共享。通过UnionID,开发者可以获取用户在不同应用中的信息,实现跨应用的用户数据共享和个性化服务。

UnionID的获取方式有以下几种:

  1. 调用接口wx.getUserInfo,从解密数据中获取UnionID。需要用户授权。
  2. 如果开发者帐号下存在同主体的公众号,并且该用户已经关注了该公众号,可以通过wx.login + code2Session获取到该用户的UnionID,无需用户再次授权。
  3. 如果开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用,也可以通过wx.login + code2Session获取到该用户的UnionID,无需用户再次授权。
问题2:unionid 和 openid 有什么不同?

UnionId和OpenId是微信公众平台中的两个重要概念,它们之间有以下不同:

  1. UnionId(统一标识符)是同一主体下不同应用之间的唯一身份标识符。在同一主体的小程序、公众号等下面,一个UnionId只有一个,而一个UnionId可以对应多个wxopenid和多个小程序OpenId。

  2. OpenId(开放标识符)是用户在某个具体应用(如小程序、公众号)下的唯一身份标识符。在同一主体的不同应用之间,用户的OpenId是不同的。

  3. UnionId的覆盖范围更广,可以在用户关注公众号、逛公众号下的H5页面时获取UnionId和wxopenid;在逛小程序时,可以获取小程序UnionId和openid。无论在哪个应用下,都可以获取到UnionId。

  4. OpenId是应用级别的身份标识符,只能在特定的应用中使用,而UnionId是主体级别的身份标识符,可以在同一主体的不同应用之间共享使用。

总结起来,UnionId是同一主体下不同应用之间的唯一身份标识符,而OpenId是用户在某个具体应用下的唯一身份标识符。

common/libs/member/MemberService.py

# -*- coding: utf-8 -*-
import hashlib,requests,random,string,json
from application import  app
class MemberService():@staticmethoddef geneAuthCode( member_info = None ):m = hashlib.md5()str = "%s-%s-%s" % ( member_info.id, member_info.salt,member_info.status)m.de("utf-8"))return m.hexdigest()@staticmethoddef geneSalt( length = 16 ):keylist = [ random.choice( ( string.ascii_letters + string.digits ) ) for i in range( length ) ]return ( "".join( keylist ) )@staticmethoddef getWeChatOpenId( code ):url = "={0}&secret={1}&js_code={2}&grant_type=authorization_code" .fig['MINA_APP']['appid'], fig['MINA_APP']['appkey'], code)r = (url)res = json.)openid = Noneif 'openid' in res:openid = res['openid']return openid

是一个flask获取微信OpenID的静态方法的示例:

该方法使用了微信提供的API来通过code获取用户的OpenID。

问题0: 如何实现小程序登录?

小程序登录

小程序登录 | 微信开放文档    

接口英文名

code2Session

功能描述

登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程。更多使用方法详见小程序登录。


具体步骤如下:

  1. 构建请求URL,其中包括了小程序的appid、appkey和code。缺少就报错!其中url中使用{}来获取值,

  2. 发送GET请求到微信API,并获取返回结果。

  3. 解析返回结果,提取出OpenID。

  4. 返回OpenID。

问题1: 该段url中的作用是什么?

在Python中,反斜杠()被用作续行符,用于将一行代码分成多行书写。当一行代码太长时,可以使用反斜杠将其分成多行,以提高代码的可读性。

在给定的代码段中,反斜杠()的作用是将长的URL字符串分成多行,以便于阅读和理解。通过使用反斜杠,可以将长的URL字符串分成多行,使代码更加清晰易读。

问题2: format的作用是什么?

format()是一个字符串方法,用于将字符串中的占位符替换为指定的值。在这个例子中,format()方法用于替换url字符串中的占位符{0}、{1}和{2},分别为appid、appkey和code的值。通过使用format()方法,可以动态地将变量的值插入到字符串中,使得字符串具有动态性和可读性。

如在flask中设置所示

config/base_setting.py


MINA_APP = {'appid':'wx360d7b8ff0881fd3','appkey':'xxxxxxxxxxxxx换自己的','paykey':'xxxxxxxxxxxxxx换自己的','mch_id':'xxxxxxxxxxxx换自己的','callback_url':'/api/order/callback'
}

问题3:  requests 的作用是什么?

requests 用来发送请求

<发送get请求

r是返回的值

问题4: .text的作用是什么?

.text 是一个属性,用于获取 HTTP 响应的内容。在这个例子中,< 返回的是一个字符串,表示 HTTP 响应的内容。在这个例子中,< 是一个 JSON 格式的字符串,通过 json.loads() 方法将其转换为 Python 字典对象 res。然后,通过 res['openid'] 获取字典中的 openid 值,并将其返回。

知识点1: app.logger.info(res)

app.logger.info(res)是一个使用logger对象的info方法来记录res对象的日志信息的代码。具体的实现可能需要查看完整的代码,以确定logger对象是如何定义和配置的。

以下是一个示例,展示了如何使用logger对象的info方法记录res对象的日志信息

如图通过 app.logger.info(res)探索res的值的样式

如图openid返回的值是< 是一个 JSON 格式的字符串,通过 json.loads() 方法将其转换为 Python 字典对象 res。然后,通过 res['openid'] 获取字典中的 openid 值,并将其返回。


mina/app.js

//app.js
App({onLaunch: function () {},globalData: {userInfo: null,version: "1.0",shopName: "Python3 + Flask 订餐全栈系统",domain:"192.168.10.10:8999/api"},tip:function( params ){var that = this;var title = params.hasOwnProperty('title')?params['title']:'提示信息';var content = params.hasOwnProperty('content')?params['content']:'';wx.showModal({title: title,content: content,success: function(res) {if ( firm ) {//点击确定if( params.hasOwnProperty('cb_confirm') && typeof( params.cb_confirm ) == "function" ){params.cb_confirm();}}else{//点击否if( params.hasOwnProperty('cb_cancel') && typeof( params.cb_cancel ) == "function" ){params.cb_cancel();}}}})},alert:function( params ){var title = params.hasOwnProperty('title')?params['title']:'提示信息';var content = params.hasOwnProperty('content')?params['content']:'';wx.showModal({title: title,content: content,showCancel:false,success: function(res) {if (firm) {//用户点击确定if( params.hasOwnProperty('cb_confirm') && typeof( params.cb_confirm ) == "function" ){params.cb_confirm();}}else{if( params.hasOwnProperty('cb_cancel') && typeof( params.cb_cancel ) == "function" ){params.cb_cancel();}}}})},console:function( msg ){console.log( msg);},getRequestHeader:function(){return {'content-type': 'application/x-www-form-urlencoded'}},buildUrl:function (path,params) {var url = this.globalData.domain + path;var _paramUrl = "";if(params){_paramUrl = Object.keys(params).map(function(k){return [encodeURIComponent(k), encodeURIComponent(params[k])].join("=");}).join("&");_paramUrl ="?" + _paramUrl;}return url + _paramUrl;},});


App(Object object) | 微信开放文档    

注册小程序。接受一个 Object 参数,其指定小程序的生命周期回调等。

App() 必须在 app.js 中调用,必须调用且只能调用一次。不然会出现无法预期的后果。

  1. onShow: function() { ... }:定义了一个名为onShow的生命周期函数,在页面显示时执行。

  2. onReady: function() { ... }:定义了一个名为onReady的生命周期函数,在页面初次渲染完成时执行。

  3. setTimeout(function() { ... }, 1000);:使用setTimeout函数设置一个定时器,延迟1秒后执行回调函数,将remind的值设为空字符串,即隐藏加载中的提示。

  4. :监听加速度计数据变化的事件,当加速度计数据变化时执行回调函数。


问题@1: var title = params.hasOwnProperty('title')?params['title']:'提示信息'; 该段代码是什么意思?各部分元素的作用是什么? @代表对app.js文件内的提问

这段代码是一个条件表达式,用于  判断对象params中是否存在属性’title’。

 如果存在,则将该属性的值赋给变量title;

 如果不存在,则将字符串’提示信息’赋给变量title。

var title = params.hasOwnProperty('title') ? params['title'] : '提示信息';
  • params.hasOwnProperty('title'):这是一个判断对象params是否有属性’title’的方法。如果params对象中存在名为’title’的属性,则返回true;否则返回false。
  • ?:这是一个条件运算符,也称为三元运算符。它的作用是根据条件的真假来选择不同的值。
  • params['title']:如果params对象中存在名为’title’的属性,则返回该属性的值。
  • ::这是条件运算符的分隔符,用于分隔条件为真和条件为假时的两个值。
  • '提示信息':如果params对象中不存在名为’title’的属性,则返回字符串’提示信息’。

因此,这段代码的作用是判断对象params中是否存在属性’title’,如果存在则将其值赋给变量title,如果不存在则将字符串’提示信息’赋给变量title。


问题@2: wx.showModal({})是什么方法?
   wx.showModal({title: title,content: content,success: function(res) {if ( firm ) {//点击确定if( params.hasOwnProperty('cb_confirm') && typeof( params.cb_confirm ) == "function" ){params.cb_confirm();}}else{//点击否if( params.hasOwnProperty('cb_cancel') && typeof( params.cb_cancel ) == "function" ){params.cb_cancel();}}}})},

该段代码是一个使用  小程序框架  中的  wx.showModal方法  创建模态弹窗 的示例。

wx.showModal(Object object) | 微信开放文档   显示模态对话框

模态弹窗 是一种可以  阻止  用户继续操作的弹窗,需要用户进行  确认 或 取消   操作后才能关闭。

代码中的wx.showModal方法接受一个  对象  作为参数,该对象包含以下属性:

  • title:弹窗的标题。
  • content:弹窗的内容。
  • success:弹窗操作成功后的回调函数。

在回调函数中,可以根据用户的操作结果进行相应的处理。

如果用户点击了确定按钮,会执行success函数中的逻辑,

如果用户点击了  取消按钮,会执行else语句中的逻辑。

在该示例中,代码通过判断firm的值来确定用户点击的是确定按钮还是取消按钮。

如果firm为true,表示用户点击了确定按钮,会执行cb_confirm函数;

如果firm为false,表示用户点击了取消按钮,会执行cb_cancel函数。

该段代码的作用是创建一个模态弹窗,并根据用户的操作结果执行相应的回调函数。

问题@3: &&是什么?它的作用是什么?

在给定的代码中,&&是逻辑与运算符。它用于判断两个条件是否同时为真。如果两个条件都为真,则整个表达式的结果为真;否则,结果为假。

在给定的代码中,&&用于判断两个条件:

  1. params.hasOwnProperty('cb_confirm'):判断params对象是否具有名为cb_confirm的属性。
  2. typeof( params.cb_confirm ) == "function":判断params.cb_confirm的类型是否为函数。

只有当这两个条件都为真时,才会执行params.cb_confirm()函数。


mina/pages/my/addressSet.js

//获取应用实例
var commonCityData = require('../../utils/city.js');
var app = getApp();
Page({data: {provinces: [],citys: [],districts: [],selProvince: '请选择',selCity: '请选择',selDistrict: '请选择',selProvinceIndex: 0,selCityIndex: 0,selDistrictIndex: 0},onLoad: function (e) {var that = this;this.initCityData(1);},//初始化城市数据initCityData:function( level, obj ){if (level == 1) {var pinkArray = [];for (var i = 0; i < commonCityData.cityData.length; i++) {pinkArray.push(commonCityData.cityData[i].name);}this.setData({provinces: pinkArray});} else if (level == 2) {var pinkArray = [];var dataArray = obj.cityListfor (var i = 0; i < dataArray.length; i++) {pinkArray.push(dataArray[i].name);}this.setData({citys: pinkArray});} else if (level == 3) {var pinkArray = [];var dataArray = obj.districtListfor (var i = 0; i < dataArray.length; i++) {pinkArray.push(dataArray[i].name);}this.setData({districts: pinkArray});}},bindPickerProvinceChange: function (event) {var selIterm = commonCityData.cityData[event.detail.value];this.setData({selProvince: selIterm.name,selProvinceIndex: event.detail.value,selCity: '请选择',selCityIndex: 0,selDistrict: '请选择',selDistrictIndex: 0});this.initCityData(2, selIterm);},bindPickerCityChange: function (event) {var selIterm = commonCityData.cityData[this.data.selProvinceIndex].cityList[event.detail.value];this.setData({selCity: selIterm.name,selCityIndex: event.detail.value,selDistrict: '请选择',selDistrictIndex: 0});this.initCityData(3, selIterm);},bindPickerChange: function (event) {var selIterm = commonCityData.cityData[this.data.selProvinceIndex].cityList[this.data.selCityIndex].districtList[event.detail.value];if (selIterm && selIterm.name && event.detail.value) {this.setData({selDistrict: selIterm.name,selDistrictIndex: event.detail.value})}},bindCancel: function () {wx.navigateBack({});},bindSave: function (e) {},deleteAddress: function (e) {var that = this;var params={"content": "确定删除?","cb_confirm": function () {wx.request({url:app.buildUrl("/my/address/ops"),header: RequestHeader(),method:"POST",data:{id: that.data.id,act:'del'},success:function(res){var resp = res.data;app.alert({"":resp.msg});if (de == 200){// 跳转wx.navigateBack({});}}});}};app.tip(params);},
});

deleteAddress:function(){}  是一个小程序中的一个函数,用于删除地址信息。

下面是对代码的详细解释:

这段代码定义了一个名为deleteAddress的函数,用于删除地址信息。当用户点击删除按钮时,该函数会被调用。

首先,函数内部定义了一个变量that,并将其赋值为this,这是为了在后续的回调函数中能够访问到外部的this对象。

接下来,定义了一个名为params的对象,该对象包含两个属性:

  • content属性表示删除确认的提示内容,这里设置为"确定删除?"。
  • cb_confirm属性是一个回调函数,当用户点击确认删除时会执行该函数。

cb_confirm函数中,发起了一个请求,用于向服务器发送删除地址的请求。

RequestTask | 微信开放文档

具体的请求参数如下:

  • url属性指定了请求的URL,这里使用了小程序中的app.buildUrl函数来构建URL。
  • header属性设置了请求头,使用了小程序中的函数来获取请求头。
  • method属性指定了请求的方法,这里使用了POST方法。
  • data属性是一个对象,包含了要发送的数据。其中id表示要删除的地址的ID,act表示要执行的操作,这里设置为"del"表示删除操作。

在请求成功的回调函数中,首先解析了服务器返回的数据,并将其赋值给变量resp。然后使用app.alert函数弹出一个提示框,显示返回的消息内容。

如果服务器返回的状态码为200,表示删除成功,那么会执行以下操作:

  • 使用wx.navigateBack函数返回上一页。
  • wx.navigateBack(Object object) | 微信开放文档

本文发布于:2024-01-31 04:53:25,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170664800625664.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:程序   Flask   微信小
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23