百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

微信支付现在普及了!我用Python写个微信小程序支付功能!无敌

toyiye 2024-06-21 12:32 14 浏览 0 评论

由于最近自己在做小程序的支付,就在这里简单介绍一下讲一下用python做小程序支付这个流程。当然在进行开发之前还是建议读一下具体的流程,清楚支付的过程。

1.支付交互流程

私信小编007即可获取数十套PDF以及大量的学习教程呢!

当然具体的参数配置可以参考官方文档 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1

2.获取openid(微信用户标识)

 1 import requests
 2 
 3 from config import APPID, SECRET
 4 
 5 
 6 class OpenidUtils(object):
 7 
 8 def __init__(self, jscode):
 9 self.url = "https://api.weixin.qq.com/sns/jscode2session"
10 self.appid = APPID # 小程序id
11 self.secret = SECRET # 不要跟后面支付的key搞混
12 self.jscode = jscode # 前端传回的动态jscode
13 
14 def get_openid(self):
15 # url一定要拼接,不可用传参方式
16 url = self.url + "?appid=" + self.appid + "&secret=" + self.secret + "&js_code=" + self.jscode + "&grant_type=authorization_code"
17 r = requests.get(url)
18 print(r.json())
19 openid = r.json()['openid']
20 
21 return openid

3.支付请求

 1 # -*- coding:utf-8 -*-
 2 import requests
 3 import hashlib
 4 import xmltodict
 5 import time
 6 import random
 7 import string
 8 import urllib2
 9 import sys
 10 
 11 
 12 class WX_PayToolUtil():
 13 """ 微信支付工具 """
 14 
 15 def __init__(self, APP_ID, MCH_ID, API_KEY, NOTIFY_URL):
 16 self._APP_ID = APP_ID # 小程序ID
 17 self._MCH_ID = MCH_ID # # 商户号
 18 self._API_KEY = API_KEY
 19 self._UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder" # 接口链接
 20 self._NOTIFY_URL = NOTIFY_URL # 异步通知
 21 
 22 def generate_sign(self, param):
 23 '''生成签名'''
 24 stringA = ''
 25 ks = sorted(param.keys())
 26 # 参数排序
 27 for k in ks:
 28 stringA += (k + '=' + param[k] + '&')
 29 # 拼接商户KEY
 30 stringSignTemp = stringA + "key=" + self._API_KEY
 31 # md5加密,也可以用其他方式
 32 hash_md5 = hashlib.md5(stringSignTemp.encode('utf8'))
 33 sign = hash_md5.hexdigest().upper()
 34 return sign
 35 
 36 '''
 37 # python2另外一种实现方法
 38 def generate_sign(self, params):
 39 ret = []
 40 for k in sorted(params.keys()):
 41 if (k != 'sign') and (k != '') and (params[k] is not None):
 42 ret.append('%s=%s' % (k, params[k]))
 43 params_str = '&'.join(ret)
 44 params_str = '%(params_str)s&key=%(partner_key)s' % {'params_str': params_str, 'partner_key': key}
 45 
 46 reload(sys)
 47 sys.setdefaultencoding('utf8')
 48 
 49 params_str = hashlib.md5(params_str.encode('utf-8')).hexdigest()
 50 sign = params_str.upper()
 51 return sign
 52 '''
 53 
 54 def getPayUrl(self, orderid, openid, goodsPrice, **kwargs):
 55 """向微信支付端发出请求,获取url"""
 56 key = self._API_KEY
 57 nonce_str = ''.join(random.sample(string.letters + string.digits, 30)) # 生成随机字符串,小于32位
 58 params = {
 59 'appid': self._APP_ID, # 小程序ID
 60 'mch_id': self._MCH_ID, # 商户号
 61 'nonce_str': nonce_str, # 随机字符串
 62 "body": '测试订单', # 支付说明
 63 'out_trade_no': orderid, # 生成的订单号
 64 'total_fee': str(goodsPrice), # 标价金额
 65 'spbill_create_ip': "127.0.0.1", # 小程序不能获取客户ip,web用socekt实现
 66 'notify_url': self._NOTIFY_URL,
 67 'trade_type': "JSAPI", # 支付类型
 68 "openid": openid, # 用户id
 69 }
 70 # 生成签名
 71 params['sign'] = self.generate_sign(params)
 72 
 73 # python3一种写法
 74 param = {'root': params}
 75 xml = xmltodict.unparse(param)
 76 response = requests.post(self._UFDODER_URL, data=xml.encode('utf-8'), headers={'Content-Type': 'text/xml'})
 77 # xml 2 dict
 78 msg = response.text
 79 xmlmsg = xmltodict.parse(msg)
 80 # 4. 获取prepay_id
 81 if xmlmsg['xml']['return_code'] == 'SUCCESS':
 82 if xmlmsg['xml']['result_code'] == 'SUCCESS':
 83 prepay_id = xmlmsg['xml']['prepay_id']
 84 # 时间戳
 85 timeStamp = str(int(time.time()))
 86 # 5. 五个参数
 87 data = {
 88 "appId": self._APP_ID,
 89 "nonceStr": nonce_str,
 90 "package": "prepay_id=" + prepay_id,
 91 "signType": 'MD5',
 92 "timeStamp": timeStamp,
 93 }
 94 # 6. paySign签名
 95 paySign = self.generate_sign(data)
 96 data["paySign"] = paySign # 加入签名
 97 # 7. 传给前端的签名后的参数
 98 return data
 99 
100 # python2一种写法
101 '''
102 request_xml_str = '<xml>'
103 for key, value in params.items():
104 if isinstance(value, str):
105 request_xml_str = '%s<%s><![CDATA[%s]]></%s>' % (request_xml_str, key, value, key,)
106 else:
107 request_xml_str = '%s<%s>%s</%s>' % (request_xml_str, key, value, key,)
108 request_xml_str = '%s</xml>' % request_xml_str
109 
110 # 向微信支付发出请求,并提取回传数据
111 res = urllib2.Request(self._UFDODER_URL, data=request_xml_str.encode("utf-8"))
112 res_data = urllib2.urlopen(res)
113 res_read = res_data.read()
114 doc = xmltodict.parse(res_read)
115 return_code = doc['xml']['return_code']
116 if return_code == "SUCCESS":
117 result_code = doc['xml']['result_code']
118 if result_code == "SUCCESS":
119 doc = doc['xml']
120 data = {
121 "appId": self._APP_ID,
122 "nonceStr": nonce_str,
123 "package": "prepay_id=" + doc["prepay_id"],
124 "signType": 'MD5',
125 "timeStamp": str(int(time.time())),
126 }
127 # paySign签名
128 paySign = self.generate_sign(data)
129 data["paySign"] = paySign # 加入签名
130 return data
131 else:
132 err_des = doc['xml']['err_code_des']
133 return err_des 
134 else:
135 fail_des = doc['xml']['return_msg']
136 return fail_des
137 '''

当然你可能会遇到的错误有签名错误,一般的情况是你的appSecret和商户号的API密钥两个弄错了,当然如果不是还有可能是其他问题,解决方案链接 https://www.cnblogs.com/wanghuijie/p/wxpay_sign_error.html 。

其他的支付方式获取用户的ip地址可以通过 socket.gethostbyname(socket.gethostname()) 方法来获取。

4.支付回调

 1 # 统一下单回调处理
 2 
 3 import xmltodict
 4 
 5 from django.http import HttpResponse
 6 
 7 def payback(request):
 8 msg = request.body.decode('utf-8')
 9 xmlmsg = xmltodict.parse(msg)
10 
11 return_code = xmlmsg['xml']['return_code']
12 
13 if return_code == 'FAIL':
14 # 官方发出错误
15 return HttpResponse("""<xml><return_code><![CDATA[FAIL]]></return_code>
16 <return_msg><![CDATA[Signature_Error]]></return_msg></xml>""",
17 content_type='text/xml', status=200)
18 elif return_code == 'SUCCESS':
19 # 拿到这次支付的订单号
20 out_trade_no = xmlmsg['xml']['out_trade_no']
21 
22 # 根据需要处理业务逻辑
23 
24 return HttpResponse("""<xml><return_code><![CDATA[SUCCESS]]></return_code>
25 <return_msg><![CDATA[OK]]></return_msg></xml>""",
26 content_type='text/xml', status=200)

当然微信回调的参数有很多详细可以参考 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8

5.安全问题

在使用的过程中 商户系统对于支付结果通知的内容一定要做 签名验证,并校验返回的订单金额是否与商户侧的订单金额一致 ,防止数据泄漏导致出现“假通知”,造成资金损失。

我在开发过程中的解决方式是在向微信支付端发起请求的时候, 把订单号,金额,签名等存入数据库,然后在回调函数那里进行校验判断 。在确认跟前面订单情况一样的情况下,才进行后续一系列的操作。

最后送给大家一段祝福

# _oo8oo_
# o8888888o
# 88" . "88
# (| -_- |)
# 0\ = /0
# ___/'==='\___
# .' \\| |# '.
# / \\||| : |||# \
# / _||||| -:- |||||_ \
# | | \\\ - #/ | |
# | \_| ''\---/'' |_/ |
# \ .-\__ '-' __/-. /
# ___'. .' /--.--\ '. .'___
# ."" '< '.___\_<|>_/___.' >' "".
# | | : `- \`.:`\ _ /`:.`/ -` : | |
# \ \ `-. \_ __\ /__ _/ .-` / /
# =====`-.____`.___ \_____/ ___.`____.-`=====
# `=---=`
#
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# 强大爷保佑 永不宕机/永无bug
啦啦啦

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码