Python實現微信支付(三種方式)


一、准備環境

###1、要有微信公眾號,商戶平台賬號

https://pay.weixin.qq.com/wiki/doc/api/index.html

2、支持的支付方式有

在這里插入圖片描述

3、備案域名

選擇掃碼支付,如果使用模式二則不需要域名,只需要可訪問的ip地址就行。

4、建一個Django項目。

一、掃碼支付

  • 點擊“掃碼支付”按官方文檔配置好回調url(具體如何配置看官網)
  • 先從公眾號上獲取APP_ID,APP_SECRECT,從商戶平台上獲取MCH_ID,API_KEY

###1、使用模式一生成支付二維碼

這個二維碼是沒有時間限制的。

####create_qrcode.html

創建二維碼頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>生成掃碼支付二維碼</title>
</head>
<body>

<form method="post" action="/wxpay/QRcode/" >
輸入手機號:<input name="phone"/>
<input id="submit" type="submit"  value="生成二維碼">
    <br>
    {% if img_url %}
        <img src="{{ img_url }}" style="width: 200px;height: 200px"/>
    {% endif %}
<br>
{{ url }}
</form>
</body>
</html>

pay_settings.py

#微信支付配置
# ========支付相關配置信息===========
import random
import time
import hashlib
from random import Random

import qrcode
from bs4 import BeautifulSoup

APP_ID = "xxx"  # 你公眾賬號上的appid
MCH_ID = "xxx"  # 你的商戶號
API_KEY = "xxx"  # 微信商戶平台(pay.weixin.qq.com) -->賬戶設置 -->API安全 -->密鑰設置,設置完成后把密鑰復制到這里
APP_SECRECT = "xxx"
UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"  # 該url是微信下單api

NOTIFY_URL = "http://xxx/"  # 微信支付結果回調接口,需要改為你的服務器上處理結果回調的方法路徑
CREATE_IP = 'xxx'  # 你服務器的IP


def random_str(randomlength=8):
    """
    生成隨機字符串
    :param randomlength: 字符串長度
    :return:
    """
    str = ''
    chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
    length = len(chars) - 1
    random = Random()
    for i in range(randomlength):
        str+=chars[random.randint(0, length)]
    return str


def order_num(phone):
    """
    生成掃碼付款訂單號
    :param phone: 手機號
    :return:
    """
    local_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
    result = phone + 'T' + local_time + random_str(5)
    return result


def get_sign(data_dict, key):
    # 簽名函數,參數為簽名的數據和密鑰
    params_list = sorted(data_dict.items(), key=lambda e: e[0], reverse=False)  # 參數字典倒排序為列表
    params_str = "&".join(u"{}={}".format(k, v) for k, v in params_list) + '&key=' + key
    # 組織參數字符串並在末尾添加商戶交易密鑰
    md5 = hashlib.md5()  # 使用MD5加密模式
    md5.update(params_str.encode('utf-8'))  # 將參數字符串傳入
    sign = md5.hexdigest().upper()  # 完成加密並轉為大寫
    return sign


def trans_dict_to_xml(data_dict):  # 定義字典轉XML的函數
    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)).encode('utf-8')  # 返回XML,並轉成utf-8,解決中文的問題


def trans_xml_to_dict(data_xml):
    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


def wx_pay_unifiedorde(detail):
    """
    訪問微信支付統一下單接口
    :param detail:
    :return:
    """
    detail['sign'] = get_sign(detail, API_KEY)
    # print(detail)
    xml = trans_dict_to_xml(detail)  # 轉換字典為XML
    response = requests.request('post', UFDODER_URL, data=xml)  # 以POST方式向微信公眾平台服務器發起請求
    # data_dict = trans_xml_to_dict(response.content)  # 將請求返回的數據轉為字典
    return response.content


def pay_fail(err_msg):
    """
    微信支付失敗
    :param err_msg: 失敗原因
    :return:
    """
    data_dict = {'return_msg': err_msg, 'return_code': 'FAIL'}
    return trans_dict_to_xml(data_dict)


def create_qrcode(phone,url):
    """
    生成掃碼支付二維碼
    :param phone: 手機號
    :param url: 支付路由
    :return:
    """
    img = qrcode.make(url)  # 創建支付二維碼片
    # 你存放二維碼的地址
    img_url = r'media/QRcode' + '/' + phone + '.png'
    img.save(img_url)
    return img_url
 

views.py

from django.shortcuts import render
from django.http import HttpResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from pay_settings.py import *

class Wxpay_QRccode(View):
    """
    生成微信支付二維碼
    """
    def get(self, request, *args, **kwargs):
        return render(request, 'create_qrcode.html')

    def post(self, request, *args, **kwargs):
        """
        # 生成可掃碼支付的二維碼
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        
        phone = request.data.get('phone', None)
        if not phone:
            return HttpResponse('手機號獲取失敗')
        paydict = {
            'appid': APP_ID,
            'mch_id': MCH_ID,
            'nonce_str': random_str(phone),
            'product_id': phone,  # 商品id,可自定義
            'time_stamp': int(time.time()),
        }
        paydict['sign'] = get_sign(paydict, API_KEY)
        url = "weixin://wxpay/bizpayurl?appid=%s&mch_id=%s&nonce_str=%s&product_id=%s&time_stamp=%s&sign=%s" \
              % (paydict['appid'], paydict['mch_id'], paydict['nonce_str'], paydict['product_id'], paydict['time_stamp'], paydict['sign'])
        
        # 可以直接在微信中點擊該url,如果有錯誤,微信會彈出提示框,如果是掃碼,如果失敗,什么提示都沒有,不利於調試
        print(url)
        # 創建二維碼
        img_url = create_qrcode(url)

        return render(request, 'create_qrcode.html', context={'img_url': img_url})


@method_decorator(csrf_exempt, name='dispatch')
class Wxpay_ModelOne_pay(View):
    """
    使用微信掃一掃掃描二維碼,微信系統會自動回調此路由,Post請求
    """

    def post(self, request, *args, **kwargs):
        """
        掃描二維碼后,微信系統回調的地址處理
        微信傳來的參數格式經trans_xml_to_dict()轉成字典
        {'openid': 'xxx',
         'is_subscribe': 'Y',
         'mch_id': 'xxx',
         'nonce_str': 'xxx',
         'sign': 'xxx',
         'product_id': 'xxx',
         'appid': 'xxx'}

        :param request:
        :param args:
        :param kwargs:
        :return:
        """

        data_dict = trans_xml_to_dict(request.body)  # 回調數據轉字典
        sign = data_dict.pop('sign')  # 取出簽名
        key = API_KEY  # 商戶交易密鑰
        back_sign = get_sign(data_dict, key)  # 計算簽名

        if sign == back_sign:  # 驗證簽名是否與回調簽名相同
            total_fee = 1  # 付款金額,單位是分,必須是整數

            params = {
                'appid': APP_ID,  # APPID
                'mch_id': MCH_ID,  # 商戶號
                'nonce_str': random_str(16),  # 隨機字符串
                'out_trade_no': order_num(data_dict['product_id']),  # 訂單編號
                'total_fee': total_fee,  # 訂單總金額
                'spbill_create_ip': CREATE_IP,  # 發送請求服務器的IP地址
                'notify_url': NOTIFY_URL,
                'body': 'xxx公司',   # 商品描述
                'detail': 'xxx商品',  # 商品詳情
                'trade_type': 'NATIVE',  # 掃碼支付類型
            }
            # 調用微信統一下單支付接口url
            notify_result = wx_pay_unifiedorde(params)
            #print(trans_xml_to_dict(notify_result))
            return HttpResponse(notify_result)

        return HttpResponse(pay_fail('交易信息有誤,請重新掃碼'))
 

2、使用模式二生成支付二維碼

這個二維碼是有時間限制的。

模式二與模式一相比,流程更為簡單,不依賴設置的回調支付URL。商戶后台系統先調用微信支付的統一下單接口,微信后台系統返回鏈接參數code_url,商戶后台系統將code_url值生成二維碼圖片,用戶使用微信客戶端掃碼后發起支付。注意:code_url有效期為2小時,過期后掃碼不能再發起支付。具體流程看微信公眾號

主體代碼:

####pay_settings.py

#微信支付配置
# ========支付相關配置信息===========
import random
import time
import hashlib
from random import Random
from bs4 import BeautifulSoup

APP_ID = "xxx"  # 你公眾賬號上的appid
MCH_ID = "xxx"  # 你的商戶號
API_KEY = "xxx"  # 微信商戶平台(pay.weixin.qq.com) -->賬戶設置 -->API安全 -->密鑰設置,設置完成后把密鑰復制到這里
APP_SECRECT = "xxx"
UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"  # 該url是微信下單api

NOTIFY_URL = "http://xxx/"  # 微信支付結果回調接口,需要改為你的服務器上處理結果回調的方法路徑
CREATE_IP = 'xxx'  # 你服務器的IP


def get_sign(data_dict, key):  
    """
    簽名函數
    :param data_dict: 需要簽名的參數,格式為字典
    :param key: 密鑰 ,即上面的API_KEY
    :return: 字符串
    """
    params_list = sorted(data_dict.items(), key=lambda e: e[0], reverse=False)  # 參數字典倒排序為列表
    params_str = "&".join(u"{}={}".format(k, v) for k, v in params_list) + '&key=' + key
    # 組織參數字符串並在末尾添加商戶交易密鑰
    md5 = hashlib.md5()  # 使用MD5加密模式
    md5.update(params_str.encode('utf-8'))  # 將參數字符串傳入
    sign = md5.hexdigest().upper()  # 完成加密並轉為大寫
    return sign


def order_num(phone):
    """
    生成掃碼付款訂單號
    :param phone: 手機號
    :return:
    """
    local_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
    result = phone + 'T' + local_time + random_str(5)
    return result


def random_str(randomlength=8):
    """
    生成隨機字符串
    :param randomlength: 字符串長度
    :return: 
    """
    strs = ''
    chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
    length = len(chars) - 1
    random = Random()
    for i in range(randomlength):
        strs += chars[random.randint(0, length)]
    return strs

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
 

####views.py

import qrcode
from django.shortcuts import render
from pay_settings import *
from django.http import HttpResponse
from django.views import View

class WXPayView(View):
    def get(self,request):
        # 在info.html有一個按鈕,點擊后跳轉到這個類的post()中,具體urls.py設置不詳述
        return render(request, 'info.html')

    def post(self,request):
        phone = request.POST.get('phone','')
        if not phone:
            return render(request, 'info.html', {'err_msg': '獲取手機號失敗'})
        data_dict = wxpay(phone)
        
        if data_dict.get('return_code') == 'SUCCESS':  # 如果請求成功
            qrcode_name = phone + '.png'  # 二維碼圖片名稱
            img = qrcode.make(data_dict.get('code_url'))  # 創建支付二維碼片
            img.save(r'static' + '/' + qrcode_name)  
            return render(request, 'qrcode.html', {'qrcode_img': qrcode_name})
        return render(request, 'info.html', {'err_msg': '獲取微信的code_url失敗'})


def wxpay(phone):
    nonce_str = random_str() # 拼接出隨機的字符串即可,我這里是用  時間+隨機數字+5個隨機字母

    total_fee = 1  # 付款金額,單位是分,必須是整數

    params = {
        'appid': APP_ID,  # APPID
        'mch_id': MCH_ID,  # 商戶號
        'nonce_str': nonce_str,    # 隨機字符串
        'out_trade_no': order_num(phone),  # 訂單編號,可自定義
        'total_fee': total_fee, # 訂單總金額
        'spbill_create_ip': CREATE_IP,  # 自己服務器的IP地址
        'notify_url': NOTIFY_URL,  # 回調地址,微信支付成功后會回調這個url,告知商戶支付結果
        'body': 'xxx公司',  # 商品描述
        'detail': 'xxx商品',  # 商品描述
        'trade_type': 'NATIVE',  # 掃碼支付類型
    }

    sign = get_sign(params,API_KEY)  # 獲取簽名
    params['sign'] = sign  # 添加簽名到參數字典
    # print(params)
    xml = trans_dict_to_xml(params)  # 轉換字典為XML
    response = requests.request('post', settings._UFDODER_URL, data=xml)  # 以POST方式向微信公眾平台服務器發起請求
    data_dict = trans_xml_to_dict(response.content)  # 將請求返回的數據轉為字典
    return data_dict


class Wxpay_Result(View):
    """
    微信支付結果回調通知路由
    """
    def get(self, request, *args, **kwargs):
        machine_code = request.GET.get('machine_code', '獲取機器編號失敗')
        # 返回支付成功頁面,可自定義
        return render(request, 'zfcg.html', {'machine': {'machine_code': machine_code}})

    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:
        """
        data_dict = trans_xml_to_dict(request.body)  # 回調數據轉字典
        # print('支付回調結果', data_dict)
        sign = data_dict.pop('sign')  # 取出簽名
        back_sign = get_sign(data_dict, API_KEY)  # 計算簽名
        # 驗證簽名是否與回調簽名相同
        if sign == back_sign and data_dict['return_code'] == 'SUCCESS':
            '''
            檢查對應業務數據的狀態,判斷該通知是否已經處理過,如果沒有處理過再進行處理,如果處理過直接返回結果成功。
            '''
            print('微信支付成功會回調!')
            # 處理支付成功邏輯
            # 返回接收結果給微信,否則微信會每隔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'}))
 

##二、使用JsAPI發起微信支付

微信公眾號中左下角 設置->公眾號設置->功能設置,把業務域名,js接口安全域名,網頁授權域名設置好。

用戶在微信中點擊一個路由Url(可把這個url封裝成二維碼).在后台中的views.py中的WxJsAPIPay類中使用get()函數處理用戶的請求,先獲取用戶的openid,然后調用微信統一下單接口,獲取prepay_id,具體看官網

####wx_js_pay.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" id="vp"/>
{#        <script type="text/javascript" src="/static/js/rem.js"></script>#}
{#        <link rel="stylesheet" type="text/css" href="/static/css/base.css" />#}
{#        <link rel="stylesheet" type="text/css" href="/static/css/index.css" />#}
    </head>
    <body>
        <div class="bigbox">
            <div class="top">
                <span>訂單詳情</span>
            </div>
            <div class="zhong">

            </div>

            <div class="zhifu">
                <button class="btn" type="button" onclick="javascript:callpay();return false;">立即支付</button>
            </div>

        </div>

<script src="https://cdn.bootcss.com/jquery/1.12.1/jquery.js"></script>
<script type="text/javascript">
    //調用微信JS api 支付
    function onBridgeReady() {
        WeixinJSBridge.invoke(
            'getBrandWCPayRequest',
            {
                appId: "{{ params.appid }}",        //公眾號名稱,由商戶傳入
                timeStamp: "{{ params.timeStamp }}", //時間戳,自1970年以來的秒數
                nonceStr: "{{ params.nonceStr }}",  //隨機串
                package: "prepay_id={{ params.prepay_id }}",  //預支付id
                signType: "MD5",  //微信簽名方式
                paySign: "{{ params.sign }}"     //微信簽名
            },
            function (res) {
                //支付成功后返回 get_brand_wcpay_request:ok
                if (res.err_msg == "get_brand_wcpay_request:ok") {
                    // 跳轉到支付成功的頁面
                    window.location.href = '#';
                    {#alert('支付成功');#}
                } else if (res.err_msg == "get_brand_wcpay_request:cancel") {
                    alert("您已取消支付!");
                    {#alert({{ params.machine_code }});#}
                    {#window.location.href = '';#}
                } else if (res.err_msg == "get_brand_wcpay_request:fail") {
                    $.each(res, function(key,value){
                        alert(value);
                        });
                    alert("支付失敗!");
                }
            }
        );
    }

    function callpay() {
        if (typeof WeixinJSBridge == "undefined") {
            if (document.addEventListener) {
                document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
            } else if (document.attachEvent) {
                document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
                document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
            }
        } else {
            onBridgeReady();
        }
    }

</script>
    </body>
</html>
 

pay_settings.py

# encoding: utf-8

import hashlib
import time
import requests
from collections import OrderedDict
from random import Random
from bs4 import BeautifulSoup


APP_ID = "xxx"  # 公眾賬號appid
MCH_ID = "xxx"  # 商戶號
API_KEY = "xxx"  # 微信商戶平台(pay.weixin.qq.com) -->賬戶設置 -->API安全 -->密鑰設置,設置完成后把密鑰復制到這里
APP_SECRECT = "xxx"
UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"  # url是微信下單api
NOTIFY_URL = "http://xxx/wxpay/pay_result/"  # 微信支付結果回調接口,需要你自定義
CREATE_IP = 'xxx'  # 你服務器上的ip


# 生成隨機字符串
def random_str(randomlength=8):
    """
    生成隨機字符串
    :param randomlength: 字符串長度
    :return:
    """
    str = ''
    chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
    length = len(chars) - 1
    random = Random()
    for i in range(randomlength):
        str+=chars[random.randint(0, length)]
    return str


def order_num(phone):
    """
    生成掃碼付款訂單,
    :param phone: 
    :return:
    """
    local_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
    result = phone + 'T' + local_time + random_str(5)
    return result


def get_sign(data_dict, key):
    # 簽名函數,參數為簽名的數據和密鑰
    params_list = sorted(data_dict.items(), key=lambda e: e[0], reverse=False)  # 參數字典倒排序為列表
    params_str = "&".join(u"{}={}".format(k, v) for k, v in params_list) + '&key=' + key
    # 組織參數字符串並在末尾添加商戶交易密鑰
    md5 = hashlib.md5()  # 使用MD5加密模式
    md5.update(params_str.encode('utf-8'))  # 將參數字符串傳入
    sign = md5.hexdigest().upper()  # 完成加密並轉為大寫
    return sign


def trans_dict_to_xml(data_dict):  # 定義字典轉XML的函數
    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)).encode('utf-8')  # 返回XML,並轉成utf-8,解決中文的問題


def trans_xml_to_dict(data_xml):
    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


def wx_pay_unifiedorde(detail):
    """
    訪問微信支付統一下單接口
    :param detail:
    :return:
    """
    detail['sign'] = get_sign(detail, API_KEY)
    # print(detail)
    xml = trans_dict_to_xml(detail)  # 轉換字典為XML
    response = requests.request('post', UFDODER_URL, data=xml)  # 以POST方式向微信公眾平台服務器發起請求
    # data_dict = trans_xml_to_dict(response.content)  # 將請求返回的數據轉為字典
    return response.content


def get_redirect_url():
    """
    獲取微信返回的重定向的url
    :return: url,其中攜帶code
    """
    WeChatcode = 'https://open.weixin.qq.com/connect/oauth2/authorize'
    urlinfo = OrderedDict()
    urlinfo['appid'] = APP_ID
    urlinfo['redirect_uri'] = 'http://xxx/wxjsapipay/?getInfo=yes'  # 設置重定向路由
    urlinfo['response_type'] = 'code'
    urlinfo['scope'] = 'snsapi_base'  # 只獲取基本信息
    urlinfo['state'] = 'mywxpay'   # 自定義的狀態碼

    info = requests.get(url=WeChatcode, params=urlinfo)
    return info.url


def get_openid(code,state):
    """
    獲取微信的openid
    :param code:
    :param state:
    :return:
    """

    if code and state and state == 'mywxpay':

        WeChatcode = 'https://api.weixin.qq.com/sns/oauth2/access_token'
        urlinfo = OrderedDict()
        urlinfo['appid'] = APP_ID
        urlinfo['secret'] = APP_SECRECT
        urlinfo['code'] = code
        urlinfo['grant_type'] = 'authorization_code'
        info = requests.get(url=WeChatcode, params=urlinfo)
        info_dict = eval(info.content.decode('utf-8'))

        return info_dict['openid']
    return None


def get_jsapi_params(openid):
    """
    獲取微信的Jsapi支付需要的參數
    :param openid: 用戶的openid
    :return:
    """

    total_fee = 1  # 付款金額,單位是分,必須是整數

    params = {
        'appid': APP_ID,  # APPID
        'mch_id': MCH_ID,  # 商戶號
        'nonce_str': random_str(16),  # 隨機字符串
        'out_trade_no': order_num('123'),  # 訂單編號,可自定義
        'total_fee': total_fee,  # 訂單總金額
        'spbill_create_ip': CREATE_IP,  # 發送請求服務器的IP地址
        'openid': openid,
        'notify_url': NOTIFY_URL,  # 支付成功后微信回調路由
        'body': 'xxx公司',  # 商品描述
        'trade_type': 'JSAPI',  # 公眾號支付類型
    }
    # print(params)
    # 調用微信統一下單支付接口url
    notify_result = wx_pay_unifiedorde(params)

    params['prepay_id'] = trans_xml_to_dict(notify_result)['prepay_id']
    params['timeStamp'] = int(time.time())
    params['nonceStr'] = random_str(16)
    params['sign'] = get_sign({'appId': APP_ID,
                               "timeStamp": params['timeStamp'],
                               'nonceStr': params['nonceStr'],
                               'package': 'prepay_id=' + params['prepay_id'],
                               'signType': 'MD5',
                               },
                              API_KEY)
    
    return params
 

views.py

from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
from django.views import View
from pay_settings import *


class WxJsAPIPay(View):
    def get(self, request, *args, **kwargs):
        """
        用戶點擊一個路由或者掃碼進入這個views.py中的函數,首先獲取用戶的openid,
        使用jsapi方式支付需要此參數
        :param self:
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        getInfo = request.GET.get('getInfo', None)
        openid = request.COOKIES.get('openid', '')
        if not openid:
            if getInfo != 'yes':
            # 構造一個url,攜帶一個重定向的路由參數,
            # 然后訪問微信的一個url,微信會回調你設置的重定向路由,並攜帶code參數
                return HttpResponseRedirect(get_redirect_url())
            elif getInfo == 'yes':
		    # 我設置的重定向路由還是回到這個函數中,其中設置了一個getInfo=yes的參數
            # 獲取用戶的openid
                openid = get_openid(request.GET.get('code'), request.GET.get('state', ''))
                if not openid:
                    return HttpResponse('獲取用戶openid失敗')
                response = render_to_response('wx_js_pay.html', context={'params': get_jsapi_params(openid)})
                response.set_cookie('openid', openid, expires=60 * 60 * 24 *30)
                return response

            else:
                return HttpResponse('獲取機器編碼失敗')
        else:
            return render(request, 'wx_js_pay.html', context={'params': get_jsapi_params(openid)})
 
 
預留:response = requests.request('post', UFDODER_URL, data=xml.encode('utf-8'), headers={'Content-Type': 'text/xml'}) # 以POST方式向微信公眾平台服務器發起請求 這里 data的值xml還需要再進行一次編碼才可以


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM