阅读全文

关于python使用支付宝当面付报错的解决方案

支付宝当面付的示例代码中,没有python的接口联调。因此,将统一收单线下交易预创建(alipay.trade.precreate,即生成商家及时收款二维码)相关python代码记录如下:

import logging
import traceback
from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
from alipay.aop.api.domain.AlipayTradeCreateModel import AlipayTradeCreateModel
from alipay.aop.api.response.AlipayTradeCreateResponse import AlipayTradeCreateResponse
from alipay.aop.api.request.AlipayTradePrecreateRequest import (
    AlipayTradePrecreateRequest,
)

logging.basicConfig( 
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(message)s",
    filemode="a",
)
logger = logging.getLogger("")

if __name__ == "__main__":
    # 实例化客户端
    alipay_client_config = AlipayClientConfig()
    alipay_client_config.server_url = "https://openapi.alipay.com/gateway.do"
    alipay_client_config.app_id = "2021003126644838"
    alipay_client_config.app_private_key = "***"
    alipay_client_config.alipay_public_key = "***"
    client = DefaultAlipayClient(alipay_client_config, logger)

    # 构造请求参数对象
    model = AlipayTradeCreateModel()
    model.out_trade_no = "2115821010101001"
    model.total_amount = "88"
    model.subject = "Iphone6 16G"
    request = AlipayTradePrecreateRequest(biz_model=model)

    # 执行API调用
    response_content = False
    try:
        response_content = client.execute(request)
    except Exception as e:
        print(traceback.format_exc())

    if not response_content:
        print("failed execute")
    else:
        # 解析响应结果
        response = AlipayTradeCreateResponse()
        response.parse_response_content(response_content)

        # 响应成功的业务处理
        if response.is_success():
            # 如果业务成功,可以通过response属性获取需要的值
            result_code = response.code
            if not result_code:
                result_code = 0
            if int(result_code) == 10000:
                print("成功")
            else:
                print("失败")
        # 响应失败的业务处理
        else:
            # 如果业务失败,可以从错误码中可以得知错误情况,具体错误码信息可以查看接口文档
            print(
                f"{response.code}, {response.msg}, {response.sub_code}, {response.sub_msg}"
            )

运行上述代码报错如下:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/alipay/aop/api/DefaultAlipayClient.py", line 125, in __prepare_request_params
    sign = sign_with_rsa2(self.__config.app_private_key, sign_content, self.__config.charset)
  File "/usr/local/lib/python3.10/dist-packages/alipay/aop/api/util/SignatureUtils.py", line 49, in sign_with_rsa2
    signature = rsa.sign(sign_content, rsa.PrivateKey.load_pkcs1(private_key, format='PEM'), 'SHA-256')
  File "/usr/local/lib/python3.10/dist-packages/rsa/key.py", line 125, in load_pkcs1
    return method(keyfile)
  File "/usr/local/lib/python3.10/dist-packages/rsa/key.py", line 613, in _load_pkcs1_pem
    return cls._load_pkcs1_der(der)
  File "/usr/local/lib/python3.10/dist-packages/rsa/key.py", line 548, in _load_pkcs1_der
    key = cls(*as_ints)
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'Sequence'

支付宝开放平台-接口报错排查中,请求报文biz_content字段全部都不是预定字段。

此问题发生原因为,开放平台密钥工具生成的密码默认是PKCS8,而python的RSA库只能识别PKCS1版本。因此,把生成应用公钥并上传至支付宝后,还需要使用格式转换PKCS1,如下:

在上述程序的alipay_client_config.app_private_key字段使用输出部分内容即可。

阅读全文

备份hassos的备份

考虑到树莓派TF卡确实容易损坏,尽管superviewer提供了备份功能,但是其备份目录也是存储在该TF卡中。因此,亟待使用另一个设备对hassos产生的备份进行备份。

hassbian社区已有的备份方案我感觉过于复杂,借助resilio sync,仅需一行命令即可完成。

resilio sync简介:

Resilio Sync(曾经名为“BitTorrent Sync”)是由BitTorrent公司开发的专有的对等网络数据同步工具,可在Windows、OS X、Linux、Android、iOS和FreeBSD上使用。 其可在局域网、互联网上通过安全的、分布式的P2P技术在不同设备之间同步文件。

step1:

方法一:

对于没有翻墙的用户,执行命令行方便一点。请执行以下操作:

打开SSH & Web Terminal插件,需注意关闭保护模式。输入命令:

docker run -d --name sync \
           -e TZ=Asia/Shanghai \
           -p 8888:8888 \
           -p 55555:55555 \
           -v /mnt/data/supervisor/homeassistant/sync:/mnt/sync \
           -v /mnt/data/supervisor/backup:/mnt/sync/folders/backup \
           --restart unless-stopped \
           resilio/sync

方法二:

 对于已经翻墙的用户,通过加载项商店安装,这样supervisor不会出现兼容性提示:

 在加载项商店增加这个仓库:https://github.com/imwyh/hassos-addons 

然后再这个仓库安装resilio_sync_for_hassos。

因为不知道怎么制作多平台的docker镜像,所以只能编译安装,速度有些慢。

step2:

打开homeassistant.local:8888,设置用户名密码,许可选择 home use (完全够用),登陆进入主界面。在右上角的设置中可以更换到中文。

点左上角的+,标准文件夹,选择/sync/folders/backup并打开。选择中间的tab,复制只读秘钥。

step3:

前往官网:https://www.resilio.com/individuals/,下载桌面版,许可可用home use。安装完成左上角的+,输入秘钥或链接,粘贴上一步的秘钥,最后新建一个备份目的地文件夹即可。

resilio sync自带内网穿透功能,因此也可以将其用docker部署到VPS上,步骤同上。也可以使用自带套件部署到群晖上。

阅读全文

写了一个响应式可自定义的简洁导航

效果预览:

https://blog.fanmiao.site/nav/

已经放到了GitHub

https://github.com/imwyh/nav

使用方法

编辑bd.js中的json,添加自定义导航页面或者搜索页面。

最终JS根据bd内容生成完整网页。

技巧

1.输入框回车直接使用默认搜索。

2.输入内容后可用方向键上下选择搜索引擎。

3.点击默认搜索(如demo中谷歌)没有任何反应是为了兼容移动端无法区分click和hover。

4.双击输入框清空内容。

5.可以设置一个默认网页使click搜索引擎时直接前往。

6.鼠标或者触屏滑动中间div部分可左右切换页。

注意事项

1.编辑json时小心标点符号。

2.可以编辑index.html中最后一行script修改动态背景。

3.可以编辑include/style.css中:root修改配色。

4.可以编辑include/style.css最后的#background修改背景颜色。

5.到这个链接获取或者修改mdi图标:https://materialdesignicons.com/ (此网页加载较慢)。

6.没有合适mdi图标可以直接使用文字代替,bd.js有示范。

阅读全文

使用小爱同学语音控制home assistant

STEP1:https://bemfa.com/注册账号。

STEP2:打开控制台,选择MQTT设备云。

STEP3:记录下私钥

STEP4:右上角新建主题,根据文档:

  • 当主题名字后三位是001时为插座设备。
  • 当主题名字后三位是002时为灯泡设备。
  • 当主题名字后三位是003时为风扇设备。
  • 当主题名字后三位是004时为传感器设备。
  • 当主题名字后三位是005时为空调设备。

建议主题名字总不要长于十二个字符,要不然小爱识别不到(具体多少字符内我没试过,但是比如ZhuWoXiDingDeng002的话会出问题)。这里创建一个名为:ZWxdd002的主题。

进入更多设置

右上角更新小爱里你要控制的名字。这里建议使用房间名+灯名的形式。这样你喊比如“小爱同学,关主卧灯”这个灯也会被关闭。

STEP5:返回home assistant,到supervisor,安装Node-red插件。

STEP6:进Node-red配置页配置,以下部分需要修改:

1.credential_secret字段配置一个随机的字母或数字即可。

2.修改ssl行为false。

3.最后加入以下代码:

require_ssl: false

然后保存,之后启动addon。如果显示502: Bad Gateway,那就等半分钟再进addon。

STEP7:进Node-red,从左侧拉一个mqtt in。双击这个节点,新建MQTT服务器,如图配置。其中客户端ID为STEP3中私钥。

STEP8:从左边拉一个debug节点,然后两个连起来。单机部署。然后返回STEP4页面,推送一个“on”命令,看看HA中有什么反应。

STEP9:拖入一个switch节点和一个call service节点,如图配置,然后部署

STEP10:打开小爱同学APP,下方智能家居页,右上角+,其他平台设备,跳转到米家。找到巴法,绑定巴法云账号密码,同步设备。注意以后每次在巴法云新增设备都要到米家同步一次。

STEP11:喊小爱同学,打开主卧吸顶灯。

现在您已经学会了使用小爱同学控制灯和开关(谷歌、小度音响、天猫精灵同理)。其实巴法云还支持控制风扇、空调、传感器状态轮询,但是要对其发送的内容进行分割,再使用switch分流不同情况交由不同call service处理,会比较复杂。如果对编程和JS稍有了解,应该都可以参照说明文档自己编程了。

课后作业:使用巴法云控制风扇和空调设备。


参考答案:

阅读全文

当网页启用gzip压缩时,node-red GET请求乱码的解决方案

home assistant中node-RED流程如图,简单来说,通过node-red get一个url,网页默认启用了gzip压缩,返回的payload乱码。

解决这个问题很简单,右上角设置,控制板,安装,安装一个 node-red-contrib-gzip 。

然后在http request设置获取二进制数据,之后后插入gzip模块即可。