-
Notifications
You must be signed in to change notification settings - Fork 16
/
alipay.py
105 lines (83 loc) · 4.42 KB
/
alipay.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = "cenegd<[email protected]>"
import requests, time, hashlib, string, urllib, os
import re
from bs4 import BeautifulSoup
requests.packages.urllib3.disable_warnings()
# 通知 Web 服务器 URL
PUSH_STATE_URL = "http://pay.qiyichao.cn/api/pay.php?application={0}&apikey={1}&method=new_order".format(os.getenv('PAYMENT_APPLICATION_ID'), os.getenv('PAYMENT_APIKEY'))
# 通知 Web 服务器验签名加密参数,不参与明文传输
PUSH_STATE_KEY = os.getenv('PAYMENT_SECERT')
# 将输入的 Cookie 转换为字典类型
def cookie_string_to_dict(cookiestring):
cookie_dict = {}
for line in cookiestring.split(";"):
line_cache = line.split("=")
cookie_key = line_cache[0]
cookie_value = line_cache[1]
if cookie_key != '':
cookie_dict[cookie_key] = cookie_value
return cookie_dict
cookie = os.getenv('PAYMENT_COOKIE')
s = requests.Session()
# 已经成功通知服务器的订单列表
orderList = {}
def check_order():
localtime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print "staring get order", localtime
# 由于支付宝限制只刷新订单页面会导致 Cookie 失效
s.get("https://my.alipay.com/portal/i.htm", cookies=cookie_string_to_dict(cookie))
# 仅查看收入
r = s.get("https://consumeprod.alipay.com/record/advanced.htm?fundFlow=in&_input_charset=utf-8", cookies=cookie_string_to_dict(cookie))
ps = BeautifulSoup(r.text, "html5lib")
orderTable = ps.find("tbody")
for order in orderTable.find_all("tr"):
order_data = {}
# 请装作没看见以下写的乱七八糟解析网页的代码
# 订单产生时间
order_data["time"] = str(order.td.p.text).strip() + " "+ order.td.p.find_next("p").text.strip()
# 用户 id,没什么用,为了兼容 EasyPay 架构存在
order_data["userid"] = ""
# 订单名称,正则去掉支付宝页面的空白
try:
order_data["desc"] = re.sub('[ \n\t]*', '', order.td.find_next("td").find_next("td").p.string)
except:
order_data["desc"] = "get has error"
# 订单号
order_data["tradeNo"] = order.td.find_next("td").find_next("td").find_next("td").p.text.encode("utf-8").split("|")[0].split(":")[1].strip()
# 支付宝对方用户名
order_data["username"] = order.td.find_next("td").find_next("td").find_next("td").find_next("td").p.text.strip()
# 用户名为英文的话支付宝会用unicode编码,如用\u0062代替b
if order_data["username"].startswith('\u'):
order_data["username"].decode("unicode-escape")
# 转账金额,支出为负
order_data["amount"] = float(order.td.find_next("td").find_next("td").find_next("td").find_next("td").find_next("td").span.text[2:])
#print order_data["amount"]
# 订单状态,通常为交易成功
order_data["status"] = order.td.find_next("td").find_next("td").find_next("td").find_next("td").find_next("td").find_next("td").find_next("td").p.text
# 解析网页完成
if order_data["amount"] <= 0:
# 支出则不再通知服务器
print localtime, "tradeNo", order_data["tradeNo"], "amount <= 0"
else:
# 重复通知服务器完全没有问题,服务器不会更新订单状态,只是会让服务器执行较多的 SQL 查询
if order_data["tradeNo"] in orderList:
pass
else:
# 通知服务器
# sig 签名算法 md5(tradeNo|desc|time|username|userid|amount|status|key)
# 实现自己向服务器的推送算法
push_data = order_data
sig_format = '|'.join([order_data["tradeNo"], order_data["desc"], order_data["time"], order_data["username"], order_data["userid"], str(order_data["amount"]), order_data["status"], PUSH_STATE_KEY]).encode("utf-8")
push_data["sig"] = hashlib.new("md5", sig_format).hexdigest().upper()
response_text = requests.post(PUSH_STATE_URL, data=push_data).text
print "sending to server tradeNo", order_data["tradeNo"], response_text
if response_text == "success":
orderList[order_data["tradeNo"]] = order_data
else:
return False
if __name__ == "__main__":
while True:
check_order()
time.sleep(30)