python 微信支付 小程序红包 发放红包接口

python 微信支付 小程序红包 发放红包接口



前言

随着小程序的不断发展,需要给用户发送小程序红包来增加留存。

小程序红包是微信支付提供给商户在小程序场景下向用户发放红包的营销工具。区别于普通现金红包通过公众号消息推送红包的方式,小程序红包可以实现用户直接在小程序页面中领取红包,领取流程更加顺畅。

开通小程序红包要先开通应用场景,我这里的场景是企业内部福利


一、官方文档

产品说明
https://pay.weixin.qq.com/wiki/doc/api/tools/miniprogram_hb.php?chapter=18_4&index=1

二、使用步骤

1.引入,直接复制粘贴以下代码,新建wx_pay.py

这个项目的原地址,以下的代码是我修改过的,新增了发送小程序红包的函数
https://github.com/Jolly23/wx_pay_python

代码如下(示例):

# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import hashlib
import random
import string
import time
import urllib.request as urllib2
import urllib
import requests

try:
    from flask import request
except ImportError:
    request = None

try:
    from xml.etree import cElementTree as ETree
except ImportError:
    from xml.etree import ElementTree as ETree


class WxPayError(Exception):
    def __init__(self, msg):
        super(WxPayError, self).__init__(msg)


class WxPay(object):
    def __init__(self, wx_app_id, wx_mch_id, wx_mch_key, wx_notify_url):
        self.opener = urllib2.build_opener(urllib2.HTTPSHandler())
        self.WX_APP_ID = wx_app_id
        self.WX_MCH_ID = wx_mch_id
        self.WX_MCH_KEY = wx_mch_key
        self.WX_NOTIFY_URL = wx_notify_url

    @staticmethod
    def user_ip_address():
        return request.remote_addr if request else None

    @staticmethod
    def nonce_str(length=32):
        char = string.ascii_letters + string.digits
        return "".join(random.choice(char) for _ in range(length))

    @staticmethod
    def to_utf8(raw):
        return raw.encode("utf-8") if isinstance(raw, str) else raw

    @staticmethod
    def to_dict(content):
        raw = {}
        root = ETree.fromstring(content)
        for child in root:
            raw[child.tag] = child.text
        return raw

    @staticmethod
    def random_num(length):
        digit_list = list(string.digits)
        random.shuffle(digit_list)
        return ''.join(digit_list[:length])

    def sign(self, raw):
        """
        生成签名
        参考微信签名生成算法
        https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3
        """
        raw = [(k, str(raw[k]) if isinstance(raw[k], (int, float)) else raw[k]) for k in sorted(raw.keys())]
        s = "&".join("=".join(kv) for kv in raw if kv[1])
        s += "&key={0}".format(self.WX_MCH_KEY)
        return hashlib.md5(self.to_utf8(s)).hexdigest().upper()

    def check(self, raw):
        """
        验证签名是否正确
        """
        sign = raw.pop("sign")
        return sign == self.sign(raw)

    def to_xml(self, data):
        """
        将 dict 对象转换成微信支付交互所需的 XML 格式数据
        :param data: dict 对象
        :return: xml 格式数据
        """
        xml = []
        for k in sorted(data.keys()):
            v = data.get(k)
            if k == 'detail' and not v.startswith('<![CDATA['):
                v = '<![CDATA[{}]]>'.format(v)
            xml.append('<{key}>{value}</{key}>'.format(key=k, value=v))
        return '<xml>{}</xml>'.format(''.join(xml))

    def fetch(self, url, data):
        req = urllib2.Request(url, data=self.to_xml(data))
        try:
            resp = self.opener.open(req, timeout=20)
        except urllib.error.URLError as e:
            resp = e
        print(type(resp))
        re_info = resp.read()
        try:
            return self.to_dict(re_info)
        except ETree.ParseError:
            return re_info

    def fetch_with_ssl(self, url, data, api_client_cert_path, api_client_key_path):
        req = requests.post(url, data=(self.to_xml(data)).encode('utf-8'),
                            cert=(api_client_cert_path, api_client_key_path))
        return self.to_dict(req.content)

    def reply(self, msg, ok=True):
        code = "SUCCESS" if ok else "FAIL"
        return self.to_xml(dict(return_code=code, return_msg=msg))

    def unified_order(self, **data):
        """
        统一下单
        详细规则参考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

        :param data: out_trade_no, body, total_fee, trade_type
            out_trade_no: 商户订单号
            body: 商品描述
            total_fee: 标价金额, 整数, 单位 分
            trade_type: 交易类型
            user_ip 在flask框架下可以自动填写, 非flask框架需传入spbill_create_ip
        :return: 统一下单生成结果
        """
        url = "https://api.mch.weixin.qq.com/pay/unifiedorder"

        # 必填参数
        if "out_trade_no" not in data:
            raise WxPayError(u"缺少统一支付接口必填参数out_trade_no")
        if "body" not in data:
            raise WxPayError(u"缺少统一支付接口必填参数body")
        if "total_fee" not in data:
            raise WxPayError(u"缺少统一支付接口必填参数total_fee")
        if "trade_type" not in data:
            raise WxPayError(u"缺少统一支付接口必填参数trade_type")

        # 关联参数
        if data["trade_type"] == "JSAPI" and "openid" not in data:
            raise WxPayError(u"trade_type为JSAPI时,openid为必填参数")
        if data["trade_type"] == "NATIVE" and "product_id" not in data:
            raise WxPayError(u"trade_type为NATIVE时,product_id为必填参数")
        user_ip = self.user_ip_address()
        if not user_ip and "spbill_create_ip" not in data:
            raise WxPayError(u"当前未使用flask框架,缺少统一支付接口必填参数spbill_create_ip")

        data.setdefault("appid", self.WX_APP_ID)
        data.setdefault("mch_id", self.WX_MCH_ID)
        data.setdefault("notify_url", self.WX_NOTIFY_URL)
        data.setdefault("nonce_str", self.nonce_str())
        data.setdefault("spbill_create_ip", user_ip)
        data.setdefault("sign", self.sign(data))

        raw = self.fetch(url, data)
        if raw["return_code"] == "FAIL":
            raise WxPayError(raw["return_msg"])
        err_msg = raw.get("err_code_des")
        if err_msg:
            raise WxPayError(err_msg)
        return raw

    def js_pay_api(self, **kwargs):
        """
        生成给JavaScript调用的数据
        详细规则参考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6

        :param kwargs: openid, body, total_fee
            openid: 用户openid
            body: 商品名称
            total_fee: 标价金额, 整数, 单位 分
            out_trade_no: 商户订单号, 若未传入则自动生成
        :return: 生成微信JS接口支付所需的信息
        """
        kwargs.setdefault("trade_type", "JSAPI")
        if "out_trade_no" not in kwargs:
            kwargs.setdefault("out_trade_no", self.nonce_str())
        raw = self.unified_order(**kwargs)
        package = "prepay_id={0}".format(raw["prepay_id"])
        timestamp = int(time.time())
        nonce_str = self.nonce_str()
        raw = dict(appId=self.WX_APP_ID, timeStamp=timestamp,
                   nonceStr=nonce_str, package=package, signType="MD5")
        sign = self.sign(raw)
        return dict(package=package, appId=self.WX_APP_ID,
                    timeStamp=timestamp, nonceStr=nonce_str, sign=sign)

    def order_query(self, **data):
        """
        订单查询
        详细规则参考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2

        :param data: out_trade_no, transaction_id至少填一个
            out_trade_no: 商户订单号
            transaction_id: 微信订单号
        :return: 订单查询结果
        """
        url = "https://api.mch.weixin.qq.com/pay/orderquery"

        if "out_trade_no" not in data and "transaction_id" not in data:
            raise WxPayError(u"订单查询接口中,out_trade_no、transaction_id至少填一个")
        data.setdefault("appid", self.WX_APP_ID)
        data.setdefault("mch_id", self.WX_MCH_ID)
        data.setdefault("nonce_str", self.nonce_str())
        data.setdefault("sign", self.sign(data))

        raw = self.fetch(url, data)
        if raw["return_code"] == "FAIL":
            raise WxPayError(raw["return_msg"])
        return raw

    def close_order(self, out_trade_no):
        """
        关闭订单
        详细规则参考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3

        :param out_trade_no: 商户订单号
        :return: 申请关闭订单结果
        """
        url = "https://api.mch.weixin.qq.com/pay/closeorder"
        data = {
            'out_trade_no': out_trade_no,
            'appid': self.WX_APP_ID,
            'mch_id': self.WX_MCH_ID,
            'nonce_str': self.nonce_str(),
        }
        data["sign"] = self.sign(data)
        raw = self.fetch(url, data)
        if raw["return_code"] == "FAIL":
            raise WxPayError(raw["return_msg"])
        return raw

    def refund(self, api_cert_path, api_key_path, **data):
        """
        申请退款
        详细规则参考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4

        :param api_cert_path: 微信支付商户证书路径,此证书(apiclient_cert.pem)需要先到微信支付商户平台获取,下载后保存至服务器
        :param api_key_path: 微信支付商户证书路径,此证书(apiclient_key.pem)需要先到微信支付商户平台获取,下载后保存至服务器
        :param data: out_trade_no、transaction_id至少填一个, out_refund_no, total_fee, refund_fee
            out_trade_no: 商户订单号
            transaction_id: 微信订单号
            out_refund_no: 商户退款单号(若未传入则自动生成)
            total_fee: 订单金额
            refund_fee: 退款金额
        :return: 退款申请返回结果
        """
        url = "https://api.mch.weixin.qq.com/secapi/pay/refund"
        if "out_trade_no" not in data and "transaction_id" not in data:
            raise WxPayError(u"订单查询接口中,out_trade_no、transaction_id至少填一个")
        if "total_fee" not in data:
            raise WxPayError(u"退款申请接口中,缺少必填参数total_fee")
        if "refund_fee" not in data:
            raise WxPayError(u"退款申请接口中,缺少必填参数refund_fee")
        if "out_refund_no" not in data:
            data.setdefault("out_refund_no", self.nonce_str())

        data.setdefault("appid", self.WX_APP_ID)
        data.setdefault("mch_id", self.WX_MCH_ID)
        data.setdefault("op_user_id", self.WX_MCH_ID)
        data.setdefault("nonce_str", self.nonce_str())
        data.setdefault("sign", self.sign(data))

        raw = self.fetch_with_ssl(url, data, api_cert_path, api_key_path)
        if raw["return_code"] == "FAIL":
            raise WxPayError(raw["return_msg"])
        return raw

    def refund_query(self, **data):
        """
        查询退款
        提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,
        用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
        详细规则参考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5

        :param data: out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个
            out_refund_no: 商户退款单号
            out_trade_no: 商户订单号
            transaction_id: 微信订单号
            refund_id: 微信退款单号

        :return: 退款查询结果
        """
        url = "https://api.mch.weixin.qq.com/pay/refundquery"
        if "out_refund_no" not in data and "out_trade_no" not in data \
                and "transaction_id" not in data and "refund_id" not in data:
            raise WxPayError(u"退款查询接口中,out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个")

        data.setdefault("appid", self.WX_APP_ID)
        data.setdefault("mch_id", self.WX_MCH_ID)
        data.setdefault("nonce_str", self.nonce_str())
        data.setdefault("sign", self.sign(data))

        raw = self.fetch(url, data)
        if raw["return_code"] == "FAIL":
            raise WxPayError(raw["return_msg"])
        return raw

    def download_bill(self, bill_date, bill_type=None):
        """
        下载对账单
        详细规则参考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6

        :param bill_date: 对账单日期
        :param bill_type: 账单类型(ALL-当日所有订单信息,[默认]SUCCESS-当日成功支付的订单, REFUND-当日退款订单)

        :return: 数据流形式账单
        """
        url = "https://api.mch.weixin.qq.com/pay/downloadbill"
        data = {
            'bill_date': bill_date,
            'bill_type': bill_type if bill_type else 'SUCCESS',
            'appid': self.WX_APP_ID,
            'mch_id': self.WX_MCH_ID,
            'nonce_str': self.nonce_str()
        }
        data['sign'] = self.sign(data)
        raw = self.fetch(url, data)
        return raw

    def send_red_pack(self, api_cert_path, api_key_path, **data):
        """
        发给用户微信红包
        详细规则参考 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
        :param api_cert_path: 微信支付商户证书路径,此证书(apiclient_cert.pem)需要先到微信支付商户平台获取,下载后保存至服务器
        :param api_key_path: 微信支付商户证书路径,此证书(apiclient_key.pem)需要先到微信支付商户平台获取,下载后保存至服务器
        :param data: send_name, re_openid, total_amount, wishing, client_ip, act_name, remark
            send_name: 商户名称 例如: 天虹百货
            re_openid: 用户openid
            total_amount: 付款金额
            wishing: 红包祝福语 例如: 感谢您参加猜灯谜活动,祝您元宵节快乐!
            client_ip: 调用接口的机器Ip地址, 注:此地址为服务器地址
            act_name: 活动名称 例如: 猜灯谜抢红包活动
            remark: 备注 例如: 猜越多得越多,快来抢!
        :return: 红包发放结果
        """
        url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack"
        if "send_name" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数send_name")
        if "re_openid" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数re_openid")
        if "total_amount" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数total_amount")
        if "wishing" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数wishing")
        if "client_ip" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数client_ip")
        if "act_name" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数act_name")
        if "remark" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数remark")

        data.setdefault("wxappid", self.WX_APP_ID)
        data.setdefault("mch_id", self.WX_MCH_ID)
        data.setdefault("nonce_str", self.nonce_str())
        data.setdefault("mch_billno", u'{0}{1}{2}'.format(
            self.WX_MCH_ID, time.strftime('%Y%m%d', time.localtime(time.time())), self.random_num(10)
        ))
        data.setdefault("total_num", 1)
        data.setdefault("scene_id", 'PRODUCT_4')
        data.setdefault("sign", self.sign(data))

        raw = self.fetch_with_ssl(url, data, api_cert_path, api_key_path)
        if raw["return_code"] == "FAIL":
            raise WxPayError(raw["return_msg"])
        return raw

    def enterprise_payment(self, api_cert_path, api_key_path, **data):
        """
        使用企业对个人付款功能
        详细规则参考 https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2

        :param api_cert_path: 微信支付商户证书路径,此证书(apiclient_cert.pem)需要先到微信支付商户平台获取,下载后保存至服务器
        :param api_key_path: 微信支付商户证书路径,此证书(apiclient_key.pem)需要先到微信支付商户平台获取,下载后保存至服务器
        :param data: openid, check_name, re_user_name, amount, desc, spbill_create_ip
            openid: 用户openid
            check_name: 是否校验用户姓名
            re_user_name: 如果 check_name 为True,则填写,否则不带此参数
            amount: 金额: 企业付款金额,单位为分
            desc: 企业付款描述信息
            spbill_create_ip: 调用接口的机器Ip地址, 注:此地址为服务器地址
        :return: 企业转账结果
        """
        url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"
        if "openid" not in data:
            raise WxPayError(u"企业付款申请接口中,缺少必填参数openid")
        if "check_name" not in data:
            raise WxPayError(u"企业付款申请接口中,缺少必填参数check_name")
        if data['check_name'] and "re_user_name" not in data:
            raise WxPayError(u"企业付款申请接口中,缺少必填参数re_user_name")
        if "amount" not in data:
            raise WxPayError(u"企业付款申请接口中,缺少必填参数amount")
        if "desc" not in data:
            raise WxPayError(u"企业付款申请接口中,缺少必填参数desc")
        if "spbill_create_ip" not in data:
            raise WxPayError(u"企业付款申请接口中,缺少必填参数spbill_create_ip")

        data.setdefault("mch_appid", self.WX_APP_ID)
        data.setdefault("mchid", self.WX_MCH_ID)
        data.setdefault("nonce_str", self.nonce_str())
        data.setdefault("partner_trade_no", u'{0}{1}{2}'.format(
            self.WX_MCH_ID, time.strftime('%Y%m%d', time.localtime(time.time())), self.random_num(10)
        ))
        data['check_name'] = 'FORCE_CHECK' if data['check_name'] else 'NO_CHECK'
        data.setdefault("sign", self.sign(data))

        raw = self.fetch_with_ssl(url, data, api_cert_path, api_key_path)
        if raw["return_code"] == "FAIL":
            raise WxPayError(raw["return_msg"])
        return raw

    def swiping_card_payment(self, **data):
        """
        提交刷卡支付
        详细规则参考 https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1

        :param data: body, out_trade_no, total_fee, auth_code, (可选参数 device_info, detail, goods_tag, limit_pay)
            body: 商品描述
            *out_trade_no: 商户订单号
            total_fee: 标价金额, 整数, 单位 分
            auth_code: 微信支付二维码扫描结果
            *device_info: 终端设备号(商户自定义,如门店编号)
            user_ip 在flask框架下可以自动填写, 非flask框架需传入spbill_create_ip
        :return: 统一下单生成结果
        """
        url = "https://api.mch.weixin.qq.com/pay/micropay"

        # 必填参数
        if "body" not in data:
            raise WxPayError(u"缺少刷卡支付接口必填参数body")
        if "total_fee" not in data:
            raise WxPayError(u"缺少刷卡支付接口必填参数total_fee")
        if "out_trade_no" not in data:
            data.setdefault("out_trade_no", self.nonce_str())

        user_ip = self.user_ip_address()
        if not user_ip and "spbill_create_ip" not in data:
            raise WxPayError(u"当前未使用flask框架,缺少刷卡支付接口必填参数spbill_create_ip")

        data.setdefault("appid", self.WX_APP_ID)
        data.setdefault("mch_id", self.WX_MCH_ID)
        data.setdefault("nonce_str", self.nonce_str())
        data.setdefault("spbill_create_ip", user_ip)
        data.setdefault("sign", self.sign(data))

        raw = self.fetch(url, data)
        if raw["return_code"] == "FAIL":
            raise WxPayError(raw["return_msg"])
        err_msg = raw.get("err_code_des")
        if err_msg:
            raise WxPayError(err_msg)
        return raw

    def send_miniprogram_red_pack(self, api_cert_path, api_key_path, **data):
        """
        发给用户微信红包
        详细规则参考 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon_xcx.php?chapter=18_2&index=3

        :param api_cert_path: 微信支付商户证书路径,此证书(apiclient_cert.pem)需要先到微信支付商户平台获取,下载后保存至服务器
        :param api_key_path: 微信支付商户证书路径,此证书(apiclient_key.pem)需要先到微信支付商户平台获取,下载后保存至服务器
        :param data: send_name, re_openid, total_amount, wishing, act_name, remark
            send_name: 商户名称 例如: 天虹百货
            re_openid: 用户openid
            total_amount: 付款金额
            wishing: 红包祝福语 例如: 感谢您参加猜灯谜活动,祝您元宵节快乐!
            act_name: 活动名称 例如: 猜灯谜抢红包活动
            remark: 备注 例如: 猜越多得越多,快来抢!
        :return: 红包发放结果
        """
        url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendminiprogramhb"  # 小程序红包
        if "send_name" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数send_name")
        if "re_openid" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数re_openid")
        if "total_amount" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数total_amount")
        if "wishing" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数wishing")
        if "act_name" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数act_name")
        if "remark" not in data:
            raise WxPayError(u"向用户发送红包接口中,缺少必填参数remark")

        data.setdefault("wxappid", self.WX_APP_ID)
        data.setdefault("mch_id", self.WX_MCH_ID)
        data.setdefault("notify_way", 'MINI_PROGRAM_JSAPI')  # 小程序
        data.setdefault("nonce_str", self.nonce_str())
        data.setdefault("mch_billno", u'{0}{1}{2}'.format(
            self.WX_MCH_ID, time.strftime('%Y%m%d', time.localtime(time.time())), self.random_num(10)
        ))
        data.setdefault("total_num", 1)
        data.setdefault("scene_id", 'PRODUCT_4')
        data.setdefault("sign", self.sign(data))

        print(data)
        raw = self.fetch_with_ssl(url, data, api_cert_path, api_key_path)
        if raw["return_code"] == "FAIL":
            raise WxPayError(raw["return_msg"])
        return raw


2.使用,在同级目录下

代码如下(示例):

from .wx_pay import WxPay

wx_pay = WxPay(
    wx_app_id='WX_APP_ID',  # 微信平台appid
    wx_mch_id='WX_MCH_ID',  # 微信支付商户号
    wx_mch_key='WX_MCH_KEY',
    # wx_mch_key 微信支付重要密钥,请登录微信支付商户平台,在 账户中心-API安全-设置API密钥设置
    wx_notify_url='http://www.example.com/pay/weixin/notify'
    # wx_notify_url 接受微信付款消息通知地址(通常比自己把支付成功信号写在js里要安全得多,推荐使用这个来接收微信支付成功通知)
    # wx_notify_url 开发详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
)

wx_pay.send_miniprogram_red_pack(
    # 证书获取方法请阅读:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3
    # api_cert_path: 微信支付商户证书(apiclient_cert.pem)的本地保存路径
    api_cert_path='/home/xxx/SERVER/ext_file/apiclient_cert.pem',
    # api_cert_path: 微信支付商户证书(apiclient_key.pem)的本地保存路径
    api_key_path='/home/xxx/SERVER/ext_file/apiclient_key.pem',
    send_name=u'***公众号发送红包测试***',  # 红包名称
    re_openid=u'***to_user_openid***',  # 要接收红包的用户openid
    total_amount=100,  # total_fee 单位是 分, 100 = 1元, 最大499元
    wishing=u'***感谢参与测试***',  # 祝福语
    act_name=u'***微信支付测试系统***',  # 活动名称
    remark=u'***感谢参与***'  # 备注
)

该处使用的小程序发送红包接口。


总结

以上就是今天要讲的内容,本文仅仅简单介绍了python 微信支付 小程序红包 发放红包接口的使用,还有其他的函数和方法。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
微信小程序支付需要先在微信公众平台上完成开发者账号注册、小程序创建、商户账号注册等一系列步骤,才能获得相关信息(如appid、mch_id、key等)来进行支付接口开发。以下是简要的支付接口开发流程: 1. 获取预支付交易会话标识prepay_id,生成支付签名(注意,签名需要按照微信支付的规则进行签名,详情请参考微信支付官方文档),并将prepay_id、签名、时间戳等信息返回给小程序前端。 2. 小程序前端在收到支付相关信息后,可以调用微信支付API发起支付请求。 3. 微信支付后台会处理支付请求,并给小程序前端返回支付结果。 以下是一个使用Python进行微信小程序支付的示例代码: ```python import requests import hashlib import time import xml.etree.ElementTree as ET # 小程序appid和商户号 app_id = 'your_app_id' mch_id = 'your_mch_id' # 支付相关的接口地址 unified_order_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder' order_query_url = 'https://api.mch.weixin.qq.com/pay/orderquery' # 商户key key = 'your_key' # 生成签名 def generate_sign(params): sign = '' stringA = '&'.join(["{0}={1}".format(k, params.get(k)) for k in sorted(params)]) stringSignTemp = '{0}&key={1}'.format(stringA, key) sign = hashlib.md5(stringSignTemp.encode('utf-8')).hexdigest().upper() return sign # 生成随机字符串 def generate_nonce_str(): return hashlib.md5(str(time.time()).encode('utf-8')).hexdigest() # 获取预支付交易会话标识prepay_id def get_prepay_id(openid, total_fee): params = { 'appid': app_id, 'mch_id': mch_id, 'nonce_str': generate_nonce_str(), 'body': 'test', # 商品描述 'out_trade_no': 'your_order_id', # 商户订单号 'total_fee': total_fee, # 订单总金额,单位为分 'spbill_create_ip': 'your_client_ip', # 客户端ip 'notify_url': 'your_notify_url', # 支付结果回调地址 'trade_type': 'JSAPI', 'openid': openid } # 生成签名 sign = generate_sign(params) params['sign'] = sign # 将参数转换为xml格式 xml_data = ET.Element('xml') for k, v in params.items(): child = ET.SubElement(xml_data, k) child.text = str(v) xml_str = ET.tostring(xml_data, encoding='utf-8') # 发送请求 response = requests.post(unified_order_url, data=xml_str) # 解析返回的xml数据 result = {} for child in ET.fromstring(response.text): result[child.tag] = child.text prepay_id = result.get('prepay_id') return prepay_id # 查询订单状态 def query_order(out_trade_no): params = { 'appid': app_id, 'mch_id': mch_id, 'out_trade_no': out_trade_no, 'nonce_str': generate_nonce_str() } # 生成签名 sign = generate_sign(params) params['sign'] = sign # 将参数转换为xml格式 xml_data = ET.Element('xml') for k, v in params.items(): child = ET.SubElement(xml_data, k) child.text = str(v) xml_str = ET.tostring(xml_data, encoding='utf-8') # 发送请求 response = requests.post(order_query_url, data=xml_str) # 解析返回的xml数据 result = {} for child in ET.fromstring(response.text): result[child.tag] = child.text return result # 示例 openid = 'your_openid' total_fee = 1 prepay_id = get_prepay_id(openid, total_fee) print('prepay_id:', prepay_id) out_trade_no = 'your_order_id' order_result = query_order(out_trade_no) print('order_result:', order_result) ``` 注意,以上代码中的 `openid` 是用户的openid,`total_fee` 是订单总金额,`out_trade_no` 是商户订单号。在实际开发中,你需要将代码中的 `your_app_id`、`your_mch_id`、`your_key`、`your_order_id`、`your_client_ip`、`your_notify_url` 和 `your_openid` 等参数替换为你自己的参数。同时,你还需要在微信公众平台上设置支付回调地址,并根据实际情况修改代码中的 `unified_order_url` 和 `order_query_url` 等支付相关接口的地址。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

办法总比困难多多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值