python微信公众支付


# 一、定义路由:
url('ic/order/(?P<order_id>.+)/payment/', views_front.PaymentView.as_view()), # 元器件微信支付
url('ic/wechatpay/', views_front.Wxpay_Result.as_view()), # 订单支付成功回调
 
# 二、定义两个函数用来转换文本类型

def trans_dict_to_xml(data_dict):
"""
定义字典转XML的函数
:param data_dict:
:return:
"""
data_xml = []
for k in sorted(data_dict.keys()): # 遍历字典排序后的key
v = data_dict.get(k) # 取出字典中key对应的value
if k == 'detail' and not v.startswith('<![CDATA['): # 添加XML标记
v = '<![CDATA[{}]]>'.format(v)
data_xml.append('<{key}>{value}</{key}>'.format(key=k, value=v))
return '<xml>{}</xml>'.format(''.join(data_xml)) # 返回XML


def trans_xml_to_dict(data_xml):
"""
定义XML转字典的函数
:param data_xml:
:return:
"""
soup = BeautifulSoup(data_xml, features='xml')
xml = soup.find('xml') # 解析XML
if not xml:
return {}
data_dict = dict([(item.name, item.text) for item in xml.find_all()])
return data_dict

# 三、后台传order_id与open_id给到前台
 
class PaymentView(APIView):
"""微信支付"""

def get(self, request, order_id):

open_id = request.query_params.get('openid')
try:
order = OrderInfo.objects.get(order_id=order_id,
pay_method=OrderInfo.PAY_METHODS_ENUM['WEXIN'],
status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'])
except OrderInfo.DoesNotExist:
return Response({'message': '订单信息有误', "enmessage": "Error"}, status=status.HTTP_400_BAD_REQUEST)
wechatpay = WeChatPay(
appid=settings.APPID,
# sub_appid=settings.sub_appid,
api_key=settings.API_KEY,
mch_id=settings.MCH_ID,
mch_cert=os.path.join(os.path.dirname(os.path.abspath(__file__)), "../keys/apiclient_cert.pem"),
mch_key=os.path.join(os.path.dirname(os.path.abspath(__file__)), "../keys/apiclient_key.pem"),
timeout=300,
# sandbox=True,
)
from math import floor
total_fee = floor(order.total_amount * 100)
from datetime import datetime, timedelta
from wechatpy.utils import timezone
now = datetime.fromtimestamp(time.time(), tz=timezone('Asia/Shanghai'))
hours_later = now + timedelta(seconds=60)
import random
import string
import json
pay_data = wechatpay.order.create(
trade_type="JSAPI",
body='魔方智能%s' % order_id,
total_fee=total_fee,
notify_url='http://www.baidu.com/ic/wechatpay/', # 微信支付成功后的回调地址,一定要能被外网访问到,注:“http://www.baidu.com” =》域名,“ic/wechatpay”=》接口。
user_id=open_id,
out_trade_no=order_id,
product_id=1,
time_expire=hours_later
)
timestamp = str(int(time.time()))
nonce_str = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15))
params = wechatpay.jsapi.get_jsapi_params(
prepay_id=pay_data['prepay_id'],
timestamp=timestamp,
nonce_str=nonce_str,
)
signature = wechatpay.jsapi.get_jsapi_signature(
prepay_id=pay_data['prepay_id'],
timestamp=timestamp,
nonce_str=nonce_str,
)
params['signature'] = signature

return Response(params)


class Wxpay_Result(APIView):
"""
微信支付结果回调通知路由
"""
def post(self, request, *args, **kwargs):
"""
微信支付成功后会自动回调
返回参数为:
{'mch_id': '',
'time_end': '',
'nonce_str': '',
'out_trade_no': '',
'trade_type': '',
'openid': '',
'return_code': '',
'sign': '',
'bank_type': '',
'appid': '',
'transaction_id': '',
'cash_fee': '',
'total_fee': '',
'fee_type': '', '
is_subscribe': '',
'result_code': 'SUCCESS'}

:param request:
:param args:
:param kwargs:
:return:
"""
a = request.body.decode('utf-8')
data_dict = trans_xml_to_dict(a) # 回调数据转字典

wechatpay = WeChatPay(
appid=settings.APPID,
api_key=settings.API_KEY,
mch_id=settings.MCH_ID,
mch_cert=os.path.join(os.path.dirname(os.path.abspath(__file__)), "../keys/apiclient_cert.pem"),
mch_key=os.path.join(os.path.dirname(os.path.abspath(__file__)), "../keys/apiclient_key.pem"),
timeout=300,
)
sign = wechatpay.check_signature(data_dict)
if data_dict['return_code'] == 'SUCCESS' and sign:
'''
检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。
'''
OrderInfo.objects.filter(order_id=data_dict['out_trade_no']).update(
status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'])
# 处理支付成功逻辑
# 返回接收结果给微信,否则微信会每隔8分钟发送post请求
return HttpResponse(trans_dict_to_xml({'return_code': 'SUCCESS', 'return_msg': 'OK'}))
return HttpResponse(trans_dict_to_xml({'return_code': 'FAIL', 'return_msg': 'SIGNERROR'}))
 
 
# 如有错误还请指出,感谢!!!!

猜你喜欢

转载自www.cnblogs.com/xiaohu1139168758/p/11314006.html