python+Django微信网页扫码支付

views视图

import sys
import socket
import time
import random
import hashlib
import xmltodict
import urllib2
from django.utils import timezone


def WxPay(request):
    # 微信
    if request.is_secure():
        notify_url = "https://%s/xxxx/xxxx/" % request.get_host()  # 获取当前域名
    else:
        notify_url = "http://%s/xxxx/xxxx/" % request.get_host()
    wx_paytoolutil = WX_PayToolUtil(
        APP_ID='',   # 公众账号appid
        MCH_ID='',  # 商户号
        API_KEY='',  # key
        NOTIFY_URL=notify_url # 回调地址
    )
    data = request.GET
    money = data.get('money ')  # 获取前台传的订单金额和订单号
    total = data.get('total ') 
    code_url = wx_paytoolutil.getPayUrl(
        goodsName='',  # 微信 body,例如,小米科技有限公司 
        orderid=total,
        goodsPrice=money ,
    )
    return HttpResponse(json.dumps({"code_url": code_url}))  # 把url传给前台,前台生成二维码

工具包Utils

import json
import socket
import time
import random
import hashlib
import xmltodict
import urllib2
from django.utils import timezone

class WX_PayToolUtil():
    """ 微信支付工具 """

    def __init__(self, APP_ID, MCH_ID, API_KEY, NOTIFY_URL):
        # ========支付相关配置信息===========
        self._APP_ID = APP_ID  # 公众账号appid
        self._MCH_ID = MCH_ID  # 商户号
        self._API_KEY = API_KEY  # key设置路径:微信商户平台(pay.weixin.qq.com) -->账户设置 -->API安全 -->密钥设置
        # 有关url
        self._host_name = socket.gethostname()
        self._ip_address = socket.gethostbyname(self._host_name)
        self._CREATE_IP = self._ip_address  # 发起支付的ip
        self._UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"  # 接口链接
        # self._UFDODER_URL = "https://api.mch.weixin.qq.com/sandboxnew/pay/unifiedorder" # 测试链接
        self._NOTIFY_URL = NOTIFY_URL  # 异步通知
        # 其他参数
        self._time_start = timezone.now().strftime("%Y%m%d%H%M%S")

    def getPayUrl(self, orderid, goodsName, goodsPrice, **kwargs):
        """向微信支付端发出请求,获取url"""

        appid = self._APP_ID
        mch_id = self._MCH_ID
        key = self._API_KEY

        nonce_str = str(int(round(time.time() * 1000))) + str(random.randint(1, 999)) + "".join(random.sample(
            ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'], 5)).replace(" ", "")  # 生成随机字符串
        spbill_create_ip = self._CREATE_IP
        notify_url = self._NOTIFY_URL
        trade_type = "NATIVE"  # 扫码支付类型
        time_start = self._time_start

        params = {'appid': appid, 'mch_id': mch_id, 'nonce_str': nonce_str, 'out_trade_no': orderid, 'total_fee': goodsPrice, 'spbill_create_ip': spbill_create_ip,
                  'notify_url': notify_url, 'body': goodsName, 'trade_type': trade_type, 'time_start': time_start}

        # 生成签名
        ret = []
        for k in sorted(params.keys()):
            if (k != 'sign') and (k != '') and (params[k] is not None):
                ret.append('%s=%s' % (k, params[k]))
        params_str = '&'.join(ret)
        params_str = '%(params_str)s&key=%(partner_key)s' % {'params_str': params_str, 'partner_key': key}

        # # 这里需要设置系统编码为utf-8,否则下面md5加密会报参数错误
        reload(sys)
        sys.setdefaultencoding('utf8')

        # MD5加密
        params_str = hashlib.md5(params_str.encode('utf-8')).hexdigest()
        sign = params_str.upper()
        params['sign'] = sign

        # 拼接参数的xml字符串
        request_xml_str = '<xml>'
        for key, value in params.items():
            if isinstance(value, str):
                request_xml_str = '%s<%s><![CDATA[%s]]></%s>' % (request_xml_str, key, value, key,)
            else:
                request_xml_str = '%s<%s>%s</%s>' % (request_xml_str, key, value, key,)
        request_xml_str = '%s</xml>' % request_xml_str

        # 向微信支付发出请求,并提取回传数据
        res = urllib2.Request(self._UFDODER_URL, data=request_xml_str.encode("utf-8"))
        res_data = urllib2.urlopen(res)  # 打开响应流
        res_read = res_data.read()  # 读取响应流中数据
        doc = xmltodict.parse(res_read)  # 数据是xml格式的,转为dict
        return_code = doc['xml']['return_code']  # 根据dict的层级,从顶层开始逐级访问提取所需内容

        if return_code == "SUCCESS":
            result_code = doc['xml']['result_code']
            if result_code == "SUCCESS":
                code_url = doc['xml']['code_url']
                return code_url
            else:
                err_des = doc['xml']['err_code_des']
                print("errdes===========" + err_des)
        else:
            fail_des = doc['xml']['return_msg']
            print("fail des=============" + fail_des)

支付轮询

def WxStatus(request):
    # 支付轮询
    data = request.GET
    total = data.get('total_key') # 获取到前台的订单号
    if PayOrder.objects.filter(order_no=total ).count() == 1:  # 查询数据库
        return HttpResponse(json.dumps({"STATUS": "SUCCESS"}))
    else:
        return HttpResponse(json.dumps({"STATUS": "FAIL"}))
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值