From 07dc141b29a422180a8e0035cc3655f3db995c0b Mon Sep 17 00:00:00 2001 From: youngS Date: Sat, 17 Apr 2021 07:58:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E6=94=AF=E4=BB=98=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fir_ser/api/urls.py | 6 +- fir_ser/api/utils/pay/wx.py | 75 +++++++++ fir_ser/api/utils/wxpay/__init__.py | 141 +++++++++++++++++ fir_ser/api/utils/wxpay/wx.pay.py | 232 ++++++++++++++++++++++++++++ fir_ser/api/views/order.py | 31 +++- fir_ser/fir_ser/settings.py | 42 ++++- 6 files changed, 519 insertions(+), 8 deletions(-) create mode 100644 fir_ser/api/utils/pay/wx.py create mode 100644 fir_ser/api/utils/wxpay/__init__.py create mode 100644 fir_ser/api/utils/wxpay/wx.pay.py diff --git a/fir_ser/api/urls.py b/fir_ser/api/urls.py index cc32e0e..76c081d 100644 --- a/fir_ser/api/urls.py +++ b/fir_ser/api/urls.py @@ -23,7 +23,7 @@ from api.views.download import ShortDownloadView from api.views.uploads import AppAnalyseView, UploadView from api.views.storage import StorageView from api.views.receiveudids import IosUDIDView -from api.views.order import PriceView, OrderView, PaySuccess +from api.views.order import PriceView, OrderView, AliPaySuccess, WxPaySuccess from api.views.supersign import DeveloperView, SuperSignUsedView, AppUDIDUsedView # router=DefaultRouter() @@ -52,6 +52,8 @@ urlpatterns = [ re_path("^package_prices$", PriceView.as_view()), re_path("^orders$", OrderView.as_view()), re_path("^certification$", CertificationView.as_view()), - re_path("^pay_success$", PaySuccess.as_view()), + re_path("^ali_pay_success$", AliPaySuccess.as_view()), + re_path("^wx_pay_success$", WxPaySuccess.as_view()), + re_path("^pay_success$", WxPaySuccess.as_view()), ] diff --git a/fir_ser/api/utils/pay/wx.py b/fir_ser/api/utils/pay/wx.py new file mode 100644 index 0000000..e8ea8d4 --- /dev/null +++ b/fir_ser/api/utils/pay/wx.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# -*- coding:utf-8 -*- +# project: 3月 +# author: NinEveN +# date: 2021/3/18 +# pip install alipay-sdk-python==3.3.398 + +# !/usr/bin/env python +# -*- coding: utf-8 -*- + + +from api.utils.wxpay import WxPay +from fir_ser.settings import PAY_CONFIG +from datetime import datetime, timedelta +from api.utils.storage.caches import update_order_info +import json +import logging + +logger = logging.getLogger(__file__) + + +class Weixinpay(object): + def __init__(self): + self.ali_config = PAY_CONFIG.get("ALI") + self.alipay = self.__get_ali_pay() + + def __get_ali_pay(self): + return WxPay( + appid=self.ali_config.get("APP_ID"), + app_notify_url=self.ali_config.get("APP_NOTIFY_URL"), + app_private_key_string=self.ali_config.get("APP_PRIVATE_KEY"), + alipay_public_key_string=self.ali_config.get("ALI_PUBLIC_KEY"), + sign_type="RSA2", # RSA 或者 RSA2 + debug=False, # 默认False + verbose=True, # 输出调试数据 + config=AliPayConfig(timeout=15) # 可选, 请求超时时间 + ) + + def get_pay_pc_url(self, out_trade_no, total_amount, passback_params): + time_expire = (datetime.now() + timedelta(days=1)).strftime("%Y-%m-%d %H:%M:%S") + order_string = self.alipay.api_alipay_trade_page_pay( + out_trade_no=out_trade_no, + total_amount=total_amount, + subject=self.ali_config.get("SUBJECT"), + body="充值 %s 元" % total_amount, + time_expire=time_expire, + return_url=self.ali_config.get("RETURN_URL"), + notify_url=self.ali_config.get("APP_NOTIFY_URL"), + passback_params=json.dumps(passback_params) + ) + + return "https://openapi.alipay.com/gateway.do?%s" % order_string + + def valid_order(self, data): + signature = data.pop("sign") + success = self.alipay.verify(data, signature) + if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"): + logger.info("付款成功,等待下一步验证 %s" % data) + app_id = data.get("app_id", "") + if app_id == self.ali_config.get("APP_ID"): + out_trade_no = data.get("out_trade_no", "") # 服务器订单号 + passback_params = data.get("passback_params", "") + if passback_params: + ext_parms = json.loads(passback_params) + user_id = ext_parms.get("user_id") + payment_number = data.get("trade_no", "") + return update_order_info(user_id, out_trade_no, payment_number, 1) + else: + logger.error("passback_params %s user_id not exists" % passback_params) + else: + logger.error("APP_ID 校验失败 response: %s server: %s" % (app_id, self.ali_config.get("APP_ID"))) + return False + + def update_order_status(self, out_trade_no): + self.alipay.api_alipay_trade_query() diff --git a/fir_ser/api/utils/wxpay/__init__.py b/fir_ser/api/utils/wxpay/__init__.py new file mode 100644 index 0000000..c9800a7 --- /dev/null +++ b/fir_ser/api/utils/wxpay/__init__.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python +# -*- coding:utf-8 -*- +# project: 4月 +# author: NinEveN +# date: 2021/4/15 + +import socket +import time +import uuid +import hashlib +import xml.etree.ElementTree as ET +import requests + + +def get_nonce_str(): + """ + 获取随机字符串 + :return: + """ + return str(uuid.uuid4()).replace('-', '') + + +def dict_to_order_xml(dict_data): + """ + dict to order xml + ASCII码从小到大排序 + :param dict_data: + :return: + """ + xml = [""] + for k in sorted(dict_data): + xml.append("<{0}>{1}".format(k, dict_data.get(k))) + xml.append("") + return "".join(xml) + + +def dict_to_xml(dict_data): + xml = [""] + for k, v in dict_data.items(): + xml.append("<{0}>{1}".format(k, v)) + xml.append("") + return "".join(xml) + + +def xml_to_dict(xml_data): + """ + xml to dict + :param xml_data: + :return: + """ + xml_dict = {} + root = ET.fromstring(xml_data) + for child in root: + xml_dict[child.tag] = child.text + return xml_dict + + +class WxPay(object): + """ + https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_4&index=3 + """ + + def __init__(self, app_id, mch_id, notify_url, merchant_key): + self.url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/native' + self.app_id = app_id # 微信分配的小程序ID + self.mch_id = mch_id # 商户号 + self.notify_url = notify_url # 通知地址 + self.spbill_create_ip = socket.gethostbyname(socket.gethostname()) # 获取本机ip + self.merchant_key = merchant_key # 商户KEY,修改为自己的 + + def create_sign(self, pay_data): + """ + 生成签名 + https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3 + :param pay_data: + :return: + """ + + # 拼接stringA + string_a = '&'.join(["{0}={1}".format(k, pay_data.get(k)) for k in sorted(pay_data)]) + # 拼接key + string_sign_temp = '{0}&key={1}'.format(string_a, self.merchant_key).encode('utf-8') + # md5签名 + sign = hashlib.md5(string_sign_temp).hexdigest() + return sign.upper() + + def get_pay_info(self, pay_data): + """ + 支付统一下单 + :return: + """ + # 调用签名函数 + + post_data = { + 'appid': self.app_id, # 小程序ID + 'mch_id': self.mch_id, # 商户号 + 'description': pay_data.get('description'), # 商品描述 + 'out_trade_no': pay_data.get('out_trade_no'), # 商户订单号 + 'time_expire': pay_data.get('time_expire'), # 交易结束时间 示例值:2018-06-08T10:34:56+08:00 + 'attach': pay_data.get('attach'), # 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用 + 'notify_url': self.notify_url, # 通知地址 + 'amount': { + 'total': pay_data.get('total'), # 订单总金额,单位为分。示例值:100 + 'currency': 'CNY' + } + } + sign = self.create_sign(post_data) + post_data['sign'] = sign + + xml = dict_to_xml(post_data) + + # 统一下单接口请求 + r = requests.post(self.url, data=xml.encode("utf-8")) + r.encoding = "utf-8" + res = xml_to_dict(r.text) + err_code_des = res.get('err_code_des') + # 出错信息 + if err_code_des: + return {'code': 40001, 'msg': err_code_des} + prepay_id = res.get('prepay_id') + + return self.re_sign(post_data, prepay_id) + + def re_sign(self, post_data, prepay_id): + """ + 再次对返回的数据签名 + https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=3 + :param post_data: + :param prepay_id: + :return: + """ + pay_sign_data = { + 'appId': self.app_id, # 注意大小写与统一下单不一致 + 'timeStamp': post_data.get('out_trade_no'), + 'nonceStr': post_data.get('nonce_str'), + 'package': 'prepay_id={0}'.format(prepay_id), + 'signType': 'MD5', + } + pay_sign = self.create_sign(pay_sign_data) + pay_sign_data['paySign'] = pay_sign + return pay_sign_data diff --git a/fir_ser/api/utils/wxpay/wx.pay.py b/fir_ser/api/utils/wxpay/wx.pay.py new file mode 100644 index 0000000..a6d9b56 --- /dev/null +++ b/fir_ser/api/utils/wxpay/wx.pay.py @@ -0,0 +1,232 @@ +#!/usr/bin/env python +# -*- coding:utf-8 -*- +# project: 4月 +# author: NinEveN +# date: 2021/4/15 + +import time +import random +from Cryptodome.PublicKey import RSA +from Cryptodome.Signature import pkcs1_15 +from Cryptodome.Hash import SHA256 +from base64 import b64encode + +mchid = '1608486112' +app_id = 'wx390e5985fd3699e6' +serial_no = '27DADA4D2921CDD66B8B20A68276F09B90754922' +private_key = '''-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDbXhNoHljrkS8T +jXg3+tTkaoOol8FDt0jSGckhzX46gkS16CWYwTthBKurfFtynsJe4uDOphS1ge/r +QEU3+rWNxqa8o6gHSpp2UTYAz/1oYOlXuSa4NA1uD47lmVZJzad2ybWDSsoeRjFj +c+X6F0ZiE3FmdN1iHz8NmbP99foih4smv15X+wX5DrsuLuPVHNB4D0fqvY7P5PO3 +wUQXWQNezCYzpPoXX2H/UkyFEFZhWk6/9z3aAkYmqfd6IWPHewOqnVoQRKmo5bXb +yWbB+QIl/HcSfNtq869s5lLGR2Rl2UX8IFXCcXnRPhSAVIeWfXN26Pc9dz9N4VTU +yiZ8Y6AHAgMBAAECggEABdS0U1orJufPBogGIAbMzd1+7mZKPtCKYPtKe1mI92kr +BmLLTQol1+hV39MIYz2RERCaxSNo/YIcrHYi4OALH1+eYvk+qCL1hBuYgeEFbVbW +HPzQ6KiJitljBPtUbdXHk8K8zmaYhMF84pXcEQ+5UTYPF5gXoloORQBG5oM5SN2g +2GTgYw1cpDzzRRwnmpvYd1ZydYNj8m6k7I2L1pwzRS/6/whz1sScpfh+91w1IVM0 +WT+pPSdiVtQ7ktmvcTrWj7eNIbcsptZ1QgSV3UHkU0xzLG9N1TqJdHOquunXRS7V +iw/4NgXveXSTSQrmmZVS+Kdyc+z1iDqwOXmE7hjioQKBgQD7js+40NCAPLYXEfer +UFvZ6kem9mJIzAUdeTdK4BjYJrcU+UsXRmcWJIPI9HWSr31f/fSfu2SKyBa6+dFF +SeNHuHPPqQAXrsNuhFG1wcKoNybk7KrsQlXheK7br42565Tegz3UXOKMrnPPlukH +ZZdlYmwBFjEJvIr9jxJvJoW6qQKBgQDfPb697vR8ruLaecPmsq920iC3AQRanYFK +dW6U98JkCN9A/LXA1jGyDTEhtlja+5Ylp0M1EnlcZ079Jnvek5haSNnD0xb1nMy8 +P/o0/eWWArTgfjfiJeq1tSdrinGhNz0+Vty74wnbS+5P18H23I5jBlGX5hyNkU4L +axUfJM9jLwKBgCo/1xVkRNB04eRICT/FlFeqKHSbRvCRC37iv+2ca6/J+M/V+s2i +7mdipJuYqzKCtNztayt0rrM8Xczzbjlj6n8+NH05FiHkIUCriomrTEUyVh72vNJH +ZeMjgMK23mfOcEda5YSIQSh9mEfSQbsTTfUiLZ+VGZFYEEP7xo3Se31ZAoGBAJas +LPYytq8EtrYwowktJwJydoQt2otybRYdRmKjCn/MASrypZWeu/Hpt3SCh1xdnAyT +5OeILYMxcv2noMksIxMkwl3KNl/V0dVo9O4ZQ4DJGN3AMuWfI9g6iX2q9mCSUPKn +W9owNbHegN1AyXhdinjJhf6Y4EKohN1uC9Z2WMcfAoGAW90Z2LkqG2fen+R62syP +aaInnu9bitb9rVENCNGXQHdWmIYBMM5zrg8nX8xNJ+yeGQhgxE+YeSq4FOpe0JkA +daWIhg++OHN2MBRutj7oL/AFAxyu467YA5+itEJLHNATbOr/s13S66nePNXox/hr +bIX1aWjPxirQX9mzaL3oEQI= +-----END PRIVATE KEY-----''' +timestamp = str(int(time.time())) +import uuid + +wx_public_key = ''' + +''' + + +def get_nonce_str(): + """ + 获取随机字符串 + :return: + """ + return str(uuid.uuid4()).replace('-', '') + + +nonce_str = get_nonce_str() + + +def sign_str(method, url_path, request_body): + """ + 生成欲签名字符串 + """ + sign_list = [ + method, + url_path, + timestamp, + nonce_str, + request_body + ] + return '\n'.join(sign_list) + '\n' + +def sign_response_str(timestamp,nonce_str,request_body): + """ + 生成欲签名字符串 + """ + sign_list = [ + timestamp, + nonce_str, + request_body + ] + return '\n'.join(sign_list) + '\n' + +def sign(sign_str): + """ + 生成签名 + """ + rsa_key = RSA.importKey(private_key) + signer = pkcs1_15.new(rsa_key) + digest = SHA256.new(sign_str.encode('utf8')) + sign = b64encode(signer.sign(digest)).decode('utf8') + return sign + + +def authorization(method, url_path, request_body): + """ + 生成Authorization + """ + str = "" + if isinstance(request_body, dict): + str = json.dumps(request_body) + signstr = sign_str(method, url_path, str) + s = sign(signstr) + authorization = 'WECHATPAY2-SHA256-RSA2048 ' \ + 'mchid="{mchid}",' \ + 'nonce_str="{nonce_str}",' \ + 'signature="{sign}",' \ + 'timestamp="{timestamp}",' \ + 'serial_no="{serial_no}"'. \ + format(mchid=mchid, + nonce_str=nonce_str, + sign=s, + timestamp=timestamp, + serial_no=serial_no + ) + return authorization + + +from datetime import timezone + +import json + +post_data = { + 'appid': app_id, # 小程序ID + 'mchid': mchid, # 商户号 + 'description': '向 FLY分发平台 充值', # 商品描述 + 'out_trade_no': '12021415113114521722839155', # 商户订单号 + # 'time_expire': pay_data.get('time_expire'), # 交易结束时间 示例值:2018-06-08T10:34:56+08:00 + 'attach': json.dumps({'user_id': 11}), # 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用 + 'notify_url': 'https://app.hehelucky.cn/api/v1/fir/server/pay_success', # 通知地址 + 'amount': { + 'total': 10, # 订单总金额,单位为分。示例值:100 + 'currency': 'CNY' + } +} + + +def make_pay_pc(): + auth = authorization('POST', '/v3/pay/transactions/native', post_data) + print(auth) + import requests + headers = { + 'Authorization': auth + } + req = requests.post('https://api.mch.weixin.qq.com/v3/pay/transactions/native', json=post_data, headers=headers) + + print(req.text) + print(req.status_code) + + +def get_wx_cert(): + auth = authorization('GET', '/v3/certificates', '') + print(auth) + import requests + headers = { + 'Authorization': auth + } + req = requests.get('https://api.mch.weixin.qq.com/v3/certificates', headers=headers) + + print(req.text) + print(req.status_code) + + +from cryptography.hazmat.primitives.ciphers.aead import AESGCM +import base64 + +cert_info = {"data": [{"effective_time": "2021-04-15T14:08:03+08:00", + "encrypt_certificate": {"algorithm": "AEAD_AES_256_GCM", "associated_data": "certificate", + "ciphertext": "sOuR8QHOOh0QkLBtrsFdrsY6FohdN7JcI6saS7pb/YNowyLlzRQIFmge7C3dILt5DVJu8kzB7dPbqcQmP/J8INSyUqZtFOVVifszWulVyQo23vvC6kT9tHHp/IoPog/Z15rmpyWwmjtrNeWIWILHmmdeSruZKgop4C9L50vQoTBRS3z6JyrACX4OceYwgNR3ICZAu/TNofI6dp92vI9RwIylQxsV1dnzi+m9pYl9IvbF/OGzJazyBPurynFcdcHfq6G7BfKnlmGswh4u5uBqXBoSfzjF14T0clN+sLiZePL0wfyxVRNtAPFkFvsbtiy4ABIbkzwI7T+1Ne/RnLZizpq/4igkILfbtSzBEWO+KRSq2E3ejfKULMZA0uHe0NBVpaAf8f9jR3Bw/16c28hnxidJ+sjf/GMlhm+F3WgzrB7GRuDL97BTdjBKHV5Hm3Q/f94HUrZCUtmoMSihde/I2IE8bI0IPgnuFlOYGZm46yuXtj2aZcr2l9HaT8xCeNnUCPKzY3arVcVZKygKjnTu8Tyvsk4qV54SZTsiQ+hdQohim154401VnP7A2UsKvYQn14xvONkk3POwehe6SJrVwnjlODrKn9qdb2bo0w0yPyV8GkVqi3nn7Eh+Hnq1g6bJb0HXDOpkuf0JF/W0dceMBcTvFTvE0SDAsJgqoIVV1+B4nTCAEbTzmJ5mQKJFL2zzoSXxUZ9ORtWDNzq0Eo0mMnYuivm2fR2IvrjCYAxSXH9X54SmGiENg9usLLfmkp5l0wJqQ29PLB1LEbxI2YonOm0babMd8qfk2d3DVNhm/Uk6uqA+Trk8OtmCTHD6Yt7J4Iz4bqmL4q/1ea2FTIARkg3a+QKj2Yt2tDZeaBHeAsS9et8U82GdP0MQF61OTFhq/NknhyfGUXA6r4lgDN+tmZJyWGkwRhNphXqU6C57JWl8jU2CydPfmTORSlKTScr0fbAYsZQees0TnqnhAYAUFRNsGjdtmQ4fHQDSvXr9ner+e4bsQTqAXzGUYDwtgEjDh26Bn8jpHTkzfC9s491XIHKD5AueNv62JlM4fIDrqJ9o6q2a/skL2EWlegCWWena0eUh+fQdMYzuYg4VAmttk6fwr5S9h15PhyKcPugDyKuXjd3TGVF6oN+pGlyksDUJqrYYvcx16yNdpM4n+B+gf8uCXHpnRd6Ws/g37B0JZUdlIbx6BnXCVGzb8JTHkUOY6ZTQ0ArRn169Ta2DVPUmTIrxID7SZsvYiWiuKywXKfgCdEo3pBPZNthrtBp5GMsJg5dhjsFxsT28FSKolJRfxXViuEs36ybaI9Ks2g6rnBQ8AlpaV6RzWzR8QtTsF481rFK5mC/eaYXFGOGnNmyp12B4ER5UfEm88BBf4xiqk9ZZu8yem7EsomLrovPbF4szYSVyHY2SYalYyjKDZFdH21YUE9lvgQLsBt8LWfOG8PABuUQpEc3a/zVv5F5h+U/oHcdWGirOCIUgI+hk579hpiIdMpOO5YhSrpouuCqX8D+nYpkSbndBGQycfxlTtL2dx0f5DwKqHIPSsKd79F0tqKqodQuRm00KCuqINDNM6TcEwvN8liXy5mgHEbBtWGYlmg6a0Iufy3PvgJkB4hR/gqkEswp7YIJqR2BYoPWLVSROq+d8ExMNHPjihrFRaHDvUecKso7F8Sfq6N6VhScYM6QPk9ow+shc2nsbU+wBl3kHsgaYras+ku+5iHWT8QQk6vWG+RFrfiGfOFzJTXBslt/45ZUc5EdaSUOz9JK+3q8twIl0EBmUM8uThT3uM31/ShdH2ROYz5mdYANERt/23fXOzY4brQJ1gGJ+2wlqKPG/IBemT+1m6z3fGdvPvoQFk02OYmLYIoR0cNa5Y3/MUkGysggflg==", + "nonce": "1ef9f91582da"}, "expire_time": "2026-04-14T14:08:03+08:00", + "serial_no": "5091F0B7E805ACD1EDB2A3B7DD04B3A67D177F37"}]} + + +def decrypt_cert(nonce, ciphertext, associated_data): + key = "60DbP621a9C3162dDd4AB9c2O15a005L" + + key_bytes = str.encode(key) + nonce_bytes = str.encode(nonce) + ad_bytes = str.encode(associated_data) + data = base64.b64decode(ciphertext) + + aesgcm = AESGCM(key_bytes) + return aesgcm.decrypt(nonce_bytes, data, ad_bytes) + +# encrypt_certificate = cert_info['data'][0]['encrypt_certificate'] +# a=decrypt_cert(encrypt_certificate['nonce'],encrypt_certificate['ciphertext'],encrypt_certificate['associated_data']) +# print(a) +# # +# make_pay_pc() + +request_body={'id': '65cce1b4-bbb7-541c-b063-5f284f650196', 'create_time': '2021-04-16T18:12:19+08:00', 'resource_type': 'encrypt-resource', 'event_type': 'TRANSACTION.SUCCESS', 'summary': '支付成功', 'resource': {'original_type': 'transaction', 'algorithm': 'AEAD_AES_256_GCM', 'ciphertext': 'rx9sLCTnnrS3GH/WqSMr+eEJqBFNo75Lb9ZW1EnoOhJ/tbJhXYl3biIR+tj1OK7qhj6ctRFeDc/zwwZ9Y5gPuWMADHd7KhsGmFdhJj4ap+UNq6UFO8g2tF3mGRQ11Cj2BCj0F+31EF8n9UCjm9SE1f0vOSwZFM6tx3/pkEgWyBbHqienr2eWZVlv8qlmUqioYoZNdJbfGNLfD/Uo2OqJg2EtXeEmdglrcC6b5hTuqGD/NcBrj83OvgsaimEbtzhphTGWRWKw2/qJtLVGKTHTMFrJ7g990i6w35vEKALWbAKsDIpCtIwPxYXlxtfxMZsLI/CYLN3Oa0W0DeR7GF+TBYgFsbvMAeryq9plbQm50qMDLfuhXcxIc7XutWGREMAmoS8e8NFtMhhi39QA4BVxSiQvND7qPXQBEESAVL+VDyCDN/SlEU2bEu+E6XD1o5LL/hvOlBnXFtm7mXbKj4j2M1II9De2oYD5R25EOXUi5oB24opaPXgHubSr6QpApQrWl3DGVMsaHVsaB4tWHH8XRaJXZpdDjxzz9DtmmTu7ZCBQifWqmC5vb+78f2+9gEavkHbL4XisKf/IFGUxzW3bKi/042xHVB2Z/JM49+Y=', 'associated_data': 'transaction', 'nonce': 'BFK77WOGPp21'}} + +wx_headers = { + 'HTTP_WECHATPAY_NONCE': 's6pY4nneUbgFh9nJNiSYv1h9ZLC7ruSj', + 'HTTP_WECHATPAY_SERIAL': '5091F0B7E805ACD1EDB2A3B7DD04B3A67D177F37', + 'HTTP_WECHATPAY_SIGNATURE': 'T8oiVc5oFsEfNDpOSdTeTiVPyO6rbx9MDEV24EtB4myPZhVYmSsJWBrtPXbYemaEPFJTtkrlzGsc3Rm6PsZoOnxSvKVIbvy60So6y36nRSmgawolTK8ruRorm0qaeRJtUAAsJImmQrMlXSqy5YaZqW3GbbLci4r2UYYoDfaNwSTJiwgit3HFYiIL6rYrtUJ3ekwMW5oyT4Aio37ulGnxymC6Nnyqbos4zpo9y6Nc8upf8rStUJ5ya3d+rZxG6fsPkUOVNz9NwaaKQk2YdelpHjd8K/cfaVNJ1ot82x8ArbEWd0k/Iz02LtLLelfF1V0w//0zmukWxWaCV2K9I+ir6w==', + 'HTTP_WECHATPAY_TIMESTAMP': '1618567939', +} +HTTP_WECHATPAY_TIMESTAMP = wx_headers.get('HTTP_WECHATPAY_TIMESTAMP','') +HTTP_WECHATPAY_NONCE = wx_headers.get('HTTP_WECHATPAY_NONCE','') +HTTP_WECHATPAY_SIGNATURE = wx_headers.get('HTTP_WECHATPAY_SIGNATURE','') + +WX_CERT_KEY=b'-----BEGIN CERTIFICATE-----\nMIID3DCCAsSgAwIBAgIUUJHwt+gFrNHtsqO33QSzpn0XfzcwDQYJKoZIhvcNAQEL\nBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\nFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\nQ0EwHhcNMjEwNDE1MDYwODAzWhcNMjYwNDE0MDYwODAzWjBuMRgwFgYDVQQDDA9U\nZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl\nbnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpo\nZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDONPXG4eQktFWEVbzD\n7ev8eMK9EEL4BBMCcvQCn76PF3wgbvYSO2CLpp7qP1NNJhFDp5ItUOtvz68AD6u1\nPNWxkOMJqdWPXRpewdUo5nr8lZCR4i3XiY+OSO/cA8C8K8mDvVNsMT1wPMp75Vil\nBL2gK5lfjj/Kjoi/aJSU//gQDpuZ+4GHBFQcOK4QqmPY8rdqhX6z93cFEkFDGPUw\nLXE9jZvYGGf5xwKPFKLvjrrg8zX+znJOXOPQtpvKD/RBfHI9ebv/PxepiHw3prM9\nLoIf6FsVaqFqV1tTJZjAgPAgEhRqM53+8PxZTdxJZDCWv/vf4BvG3Bcfw0CSTlYO\npQpJAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBlBgNVHR8EXjBc\nMFqgWKBWhlRodHRwOi8vZXZjYS5pdHJ1cy5jb20uY24vcHVibGljL2l0cnVzY3Js\nP0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3NTQ5ODQ2QzAxQzNFOEVCRDIwDQYJ\nKoZIhvcNAQELBQADggEBAA508oXmLC0x0VdsW0ThOeN+BXzuqLsKec945BZz0qPm\n/fc3Wn2Ro5yb5tsh94aqyJGmOWgZsWo/nQk2XcE5BPLn7rX0q7uMGCMbJbxfFiuS\nNuJNDSXamYUCGRXgEsZn8mh8EwZ7MKefq2LxtX9VvJF3o1KsvOWaltr5Ra3DBh1F\nghxzyOOimiqn+duT9ZbbA0nfGJjSsLq61rzc/qBMuBsdJnqeYMFs/+AIDuGYNbOj\nFTcK0+fEFfU1H99RGCu4j9jQlOqnB6uXOnr7VSQPfMEpKd6xTmaa01YHWu9oAijO\nupWVgJZI0cC3/L5s5OzlUp8Bc84NOFxSN0yXAZtH1Bc=\n-----END CERTIFICATE-----' + +rsa_key = RSA.importKey(WX_CERT_KEY) +public_key=rsa_key.publickey().exportKey() + +Wechatpay_Signature = base64.b64decode(HTTP_WECHATPAY_SIGNATURE) + +res_sign_str = sign_response_str(HTTP_WECHATPAY_TIMESTAMP,HTTP_WECHATPAY_NONCE,json.dumps(request_body)) +print(res_sign_str) +print(Wechatpay_Signature) + +key = RSA.importKey(public_key) + +# 验证签名 +verifer = pkcs1_15.new(key) # 使用公钥创建校验对象 + +hasher = SHA256.new(Wechatpay_Signature)# 对收到的消息文本提取摘要 +#hasher.update(message.encode()) + +verifer.verify(hasher, res_sign_str.encode("utf-8")) # 校验摘要(本来的样子)和收到并解密的签名是否一致 + + +# rsa_key = RSA.importKey(private_key) +# signer = pkcs1_15.new(rsa_key) +# digest = SHA256.new(sign_str.encode('utf8')) +# sign = b64encode(signer.sign(digest)).decode('utf8') \ No newline at end of file diff --git a/fir_ser/api/views/order.py b/fir_ser/api/views/order.py index 3658d65..48832d4 100644 --- a/fir_ser/api/views/order.py +++ b/fir_ser/api/views/order.py @@ -135,12 +135,13 @@ class PriceView(APIView): return Response(res.dict) -class PaySuccess(APIView): +class AliPaySuccess(APIView): # authentication_classes = [ExpiringTokenAuthentication] def get(self, request): alipay = Alipay() - alipay.update_order_status('1202141610723105226256209') + # alipay.update_order_status('1202141610723105226256209') + print(request.META) return Response(111) # return HttpResponseRedirect(PAY_SUCCESS_URL) @@ -148,8 +149,30 @@ class PaySuccess(APIView): def post(self, request): alipay = Alipay() msg = 'failure' + logger.info("支付回调参数:%s" % request.data) + logger.info("----- %s" % request.META) data = request.data.copy().dict() - logger.info("支付回调参数:%s" % data) - if alipay.valid_order(request.data.copy().dict()): + if alipay.valid_order(data): msg = 'success' return Response(msg) + + +class WxPaySuccess(APIView): + # authentication_classes = [ExpiringTokenAuthentication] + + def get(self, request): + alipay = Alipay() + alipay.update_order_status('1202141610723105226256209') + return Response(111) + + # return HttpResponseRedirect(PAY_SUCCESS_URL) + + def post(self, request): + alipay = Alipay() + msg = 'failure' + logger.info("支付回调参数:%s" % request.data) + logger.info("----- %s" % request.META) + data = request.data.copy().dict() + if alipay.valid_order(data): + msg = 'success' + return Response(msg) \ No newline at end of file diff --git a/fir_ser/fir_ser/settings.py b/fir_ser/fir_ser/settings.py index 010a210..2033dd5 100644 --- a/fir_ser/fir_ser/settings.py +++ b/fir_ser/fir_ser/settings.py @@ -444,11 +444,49 @@ MIIEowIBAAKCAQEAhqf2mwftoxZDNpl4eWsQ6mEfXgMlNPr6jv72ecA4hbKWqChXQmGS1T+0VsRTSoOX 'ALI_PUBLIC_KEY': '''-----BEGIN CERTIFICATE----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkru1ulQV1v4q+q38nyzgkdd3evf7C1/Ipu6K+ZFb5FiuxJ7mildkBSuKz/8+TRd+tjgk2lfc2ehK5pja3cxDO/nb25sBoWiU09rtxgXLehLsgRRhatbICrlOnYxg5aiB5odAp3NMRqore4lnVYwfIyL9M49I0G/NbQzYjUQvAQJsnHwc6a6Kuqi1CwR1WXI0sDF9w7KXC4vRFFIUTwI4bVq4HQWI7NhbgEajHM/j6D6Bh/OMcTYnJJzCja0WmZRe5flfCsELlPESOCWUMbYoaNfBzpNvvyOpmRgs9jgy2WY9SeaB9hxwkpr8tOd2Sc7j3221JKCyDaFAX+4zPy7/fQIDAQAB -----END CERTIFICATE-----''', - 'APP_NOTIFY_URL': 'https://app.hehelucky.cn/api/v1/fir/server/pay_success', # 支付支付回调URL - # 'RETURN_URL': 'https://app.hehelucky.cn/api/v1/fir/server/pay_success', # 支付前端页面回调URL + 'APP_NOTIFY_URL': 'https://app.hehelucky.cn/api/v1/fir/server/ali_pay_success', # 支付支付回调URL + # 'RETURN_URL': 'https://app.hehelucky.cn/api/v1/fir/server/ali_pay_success', # 支付前端页面回调URL 'RETURN_URL': PAY_SUCCESS_URL, # 支付前端页面回调URL 'SUBJECT': '向 FLY分发平台 充值', }, 'WX': { + 'APP_ID': "wx390e5985fd3699e6", + 'MCH_ID': "1608486112", + 'SERIAL_NO': "27DADA4D2921CDD66B8B20A68276F09B90754922", + 'APP_PRIVATE_KEY': '''-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDbXhNoHljrkS8T +jXg3+tTkaoOol8FDt0jSGckhzX46gkS16CWYwTthBKurfFtynsJe4uDOphS1ge/r +QEU3+rWNxqa8o6gHSpp2UTYAz/1oYOlXuSa4NA1uD47lmVZJzad2ybWDSsoeRjFj +c+X6F0ZiE3FmdN1iHz8NmbP99foih4smv15X+wX5DrsuLuPVHNB4D0fqvY7P5PO3 +wUQXWQNezCYzpPoXX2H/UkyFEFZhWk6/9z3aAkYmqfd6IWPHewOqnVoQRKmo5bXb +yWbB+QIl/HcSfNtq869s5lLGR2Rl2UX8IFXCcXnRPhSAVIeWfXN26Pc9dz9N4VTU +yiZ8Y6AHAgMBAAECggEABdS0U1orJufPBogGIAbMzd1+7mZKPtCKYPtKe1mI92kr +BmLLTQol1+hV39MIYz2RERCaxSNo/YIcrHYi4OALH1+eYvk+qCL1hBuYgeEFbVbW +HPzQ6KiJitljBPtUbdXHk8K8zmaYhMF84pXcEQ+5UTYPF5gXoloORQBG5oM5SN2g +2GTgYw1cpDzzRRwnmpvYd1ZydYNj8m6k7I2L1pwzRS/6/whz1sScpfh+91w1IVM0 +WT+pPSdiVtQ7ktmvcTrWj7eNIbcsptZ1QgSV3UHkU0xzLG9N1TqJdHOquunXRS7V +iw/4NgXveXSTSQrmmZVS+Kdyc+z1iDqwOXmE7hjioQKBgQD7js+40NCAPLYXEfer +UFvZ6kem9mJIzAUdeTdK4BjYJrcU+UsXRmcWJIPI9HWSr31f/fSfu2SKyBa6+dFF +SeNHuHPPqQAXrsNuhFG1wcKoNybk7KrsQlXheK7br42565Tegz3UXOKMrnPPlukH +ZZdlYmwBFjEJvIr9jxJvJoW6qQKBgQDfPb697vR8ruLaecPmsq920iC3AQRanYFK +dW6U98JkCN9A/LXA1jGyDTEhtlja+5Ylp0M1EnlcZ079Jnvek5haSNnD0xb1nMy8 +P/o0/eWWArTgfjfiJeq1tSdrinGhNz0+Vty74wnbS+5P18H23I5jBlGX5hyNkU4L +axUfJM9jLwKBgCo/1xVkRNB04eRICT/FlFeqKHSbRvCRC37iv+2ca6/J+M/V+s2i +7mdipJuYqzKCtNztayt0rrM8Xczzbjlj6n8+NH05FiHkIUCriomrTEUyVh72vNJH +ZeMjgMK23mfOcEda5YSIQSh9mEfSQbsTTfUiLZ+VGZFYEEP7xo3Se31ZAoGBAJas +LPYytq8EtrYwowktJwJydoQt2otybRYdRmKjCn/MASrypZWeu/Hpt3SCh1xdnAyT +5OeILYMxcv2noMksIxMkwl3KNl/V0dVo9O4ZQ4DJGN3AMuWfI9g6iX2q9mCSUPKn +W9owNbHegN1AyXhdinjJhf6Y4EKohN1uC9Z2WMcfAoGAW90Z2LkqG2fen+R62syP +aaInnu9bitb9rVENCNGXQHdWmIYBMM5zrg8nX8xNJ+yeGQhgxE+YeSq4FOpe0JkA +daWIhg++OHN2MBRutj7oL/AFAxyu467YA5+itEJLHNATbOr/s13S66nePNXox/hr +bIX1aWjPxirQX9mzaL3oEQI= +-----END PRIVATE KEY-----''', + 'ALI_PUBLIC_KEY': '''-----BEGIN CERTIFICATE----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkru1ulQV1v4q+q38nyzgkdd3evf7C1/Ipu6K+ZFb5FiuxJ7mildkBSuKz/8+TRd+tjgk2lfc2ehK5pja3cxDO/nb25sBoWiU09rtxgXLehLsgRRhatbICrlOnYxg5aiB5odAp3NMRqore4lnVYwfIyL9M49I0G/NbQzYjUQvAQJsnHwc6a6Kuqi1CwR1WXI0sDF9w7KXC4vRFFIUTwI4bVq4HQWI7NhbgEajHM/j6D6Bh/OMcTYnJJzCja0WmZRe5flfCsELlPESOCWUMbYoaNfBzpNvvyOpmRgs9jgy2WY9SeaB9hxwkpr8tOd2Sc7j3221JKCyDaFAX+4zPy7/fQIDAQAB +-----END CERTIFICATE-----''', + 'APP_NOTIFY_URL': 'https://app.hehelucky.cn/api/v1/fir/server/ali_pay_success', # 支付支付回调URL + # 'RETURN_URL': 'https://app.hehelucky.cn/api/v1/fir/server/ali_pay_success', # 支付前端页面回调URL + 'RETURN_URL': PAY_SUCCESS_URL, # 支付前端页面回调URL + 'SUBJECT': '向 FLY分发平台 充值', } }