django2.0调用银联支付接口实现银联支付

article/2025/10/9 0:05:09

准备工作:

1.银联技术开放平台注册:https://open.unionpay.com/tjweb/acproduct/list?apiservId=448
2.点击网关支付 --> 我要测试 (按照提示下载密钥)
3.安装需要的模块 pip install pyOpenSSL

代码实现:

目录结构

在这里插入图片描述

pay.py 文件
import xxx  # 自行导入class UnionPay:"""银联支付接口(PC端)"""def __init__(self,version,mer_id,front_url,back_url,backend_url,cert_path,debug=False):self.version = versionself.mer_id = mer_idself.front_url = front_urlself.back_url = back_urlself.backend_url = backend_urlself.cert = {}self.cert_id = self.__get_cert_id(cert_path)if debug is True:# 支付网关self.gateway = "https://gateway.test.95516.com/gateway/api/frontTransReq.do"# 查询网关self.query_gateway = "https://gateway.test.95516.com/gateway/api/queryTrans.do"else:self.gateway = "https://gateway.95516.com/gateway/api/frontTransReq.do"self.query_gateway = "https://gateway.95516.com/gateway/api/queryTrans.do"def build_request_data(self, order_id, txn_amt, **kwargs):"""构建请求数据:param order_id: 商户订单号:param txn_amt: 交易金额(单位: 分):return:"""request_data = {"version": self.version,  # 版本"encoding": "utf-8",  # 编码"txnType": "01",  # 交易类型  01:消费"txnSubType": "01",  # 交易子类  01:自助消费"bizType": "000201",  # 产品类型  000201:B2C网关支付"frontUrl": self.front_url,  # 前台通知地址"backUrl": self.back_url,  # 后台通知地址 需外网"signMethod": "01",  # 签名方法  01:RSA签名"channelType": "07",  # 渠道类型  07:互联网"accessType": "0",  # 接入类型  0:普通商户直连接入"currencyCode": "156",  # 交易币种  156:人民币"merId": self.mer_id,  # 商户代码"txnAmt": txn_amt,  # 订单金额(单位: 分)"txnTime": datetime.now().strftime("%Y%m%d%H%M%S"),  # 订单发送时间"certId": self.cert_id,"orderId": order_id,"signature": ""}request_data.update(**kwargs)self.get_sign(request_data)return request_datadef pay_url(self, request_data):payment_url = "{}?{}".format(self.backend_url, parse.urlencode(request_data))return payment_urldef pay_html(self, request_data):result = """<html><head><meta http-equiv="Content-Type" content="text/html"charset="utf-8"/></head><body onload="pay_form.submit();"><form id="pay_form" name="pay_form" action="{}" method="post">""".format(self.gateway)for key, value in request_data.items():result += """<input type="hidden" name="{0}" id="{0}" value="{1}"/>""".format(key, value)result = result + """<!-- <input type="submit" type="hidden">--></form></body></html>"""return resultdef get_sign(self, data):"""获取签名:param data::return:"""sha256 = hashlib.sha256(self.build_sign_str(data).encode("utf-8")).hexdigest()private = OpenSSL.crypto.sign(self.cert["pkey"], sha256, "sha256")data["signature"] = str(base64.b64encode(private), encoding="utf-8")def verify_sign(self, data):"""银联回调签名校验"""signature = data.pop('signature')  # 获取签名link_string = self.build_sign_str(data)digest = hashlib.sha256(bytes(link_string, encoding="utf-8")).hexdigest()signature = base64.b64decode(signature)sign_pubkey_cert = data.get("signPubKeyCert", None)try:x509_ert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, sign_pubkey_cert)OpenSSL.crypto.verify(x509_ert, signature, digest, 'sha256')return Trueexcept Exception as exc:return Falsedef verify_query(self, order_num, txn_time):'''验证查询的交易状态:param order_num: 订单号:param txn_time: 交易时间:return: True or False'''request_data = {"version": self.version,"encoding": "utf-8","txnType": "00",  # 00:查询"txnSubType": "00","bizType": "000201","signMethod": "01",  # 签名方法  01:RSA签名"accessType": "0","merId": self.mer_id,"txnTime": txn_time,"orderId": order_num,"certId": self.cert_id,}self.get_sign(request_data)request_data['signature'] = parse.urlencode({'signature': request_data['signature']})[10:]req_string = self.build_sign_str(request_data)res = requests.post(url=self.query_gateway,data=req_string,headers={'content-type': 'application/x-www-form-urlencoded'})if res.status_code != requests.codes.ok:query_status = Falseelse:content = self.parse_arguments(res.content.decode('utf-8'))if content.get('origRespCode', '') == '00':query_status = Trueelse:query_status = Falsereturn query_statusdef __get_cert_id(self, cert_path):"""获取证书ID(签名KEY):param cert_path::return:"""with open(cert_path, "rb") as f:certs = OpenSSL.crypto.load_pkcs12(f.read(), UnionPayConfig.cert_password)x509data = certs.get_certificate()self.cert["certid"] = x509data.get_serial_number()self.cert["pkey"] = certs.get_privatekey()return self.cert["certid"]@staticmethoddef build_sign_str(data):"""排序:param data::return:"""req = []for key in sorted(data.keys()):if data[key] != '':req.append("%s=%s" % (key, data[key]))return '&'.join(req)@staticmethoddef parse_arguments(raw):""":param raw: raw data to parse argument:return:"""data = {}qs_params = parse.parse_qs(str(raw))for name in qs_params.keys():data[name] = qs_params.get(name)[-1]return data
views.py 文件
import xxx  # 自行导入# 充值页面
def pay_page(request):return render(request, 'user/pay_page.html')# 获取一个UnionPay对象    
def get_uni_object(uid):uni_pay = UnionPay(version=UnionPayConfig.version,mer_id=UnionPayConfig.mer_id,front_url=UnionPayConfig.front_url + uid + "/",back_url=UnionPayConfig.back_url + uid + "/",backend_url=UnionPayConfig.back_url,cert_path=UnionPayConfig.cert_path,debug=UnionPayConfig.debug,)return uni_pay# 生成订单号(自定义)
def order_num(package_num,uid):'''商品代码后两位+下单时间后十二位+用户id后四位+随机数四位:param package_num: 商品代码:return: 唯一的订单号'''local_time = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time()))[2:]result = str(package_num)[-2:] + local_time +uid[-4:]+str(random.randint(1000,9999))return result# 账户充值(银联)  # uid参数可不传入,此处用于生成订单号
def unipay(request,uid):money = float(request.POST.get('money'))unipay = get_uni_object(uid)query_params = unipay.build_request_data(order_id=order_num('xx',uid),  # 用户购买订单(每次不一样)txn_amt=int(float(money)*100)  # 交易金额 单位分)pay_html = unipay.pay_html(query_params)rsp = HttpResponse()rsp.content = pay_htmlreturn rsp# 充值成功后前台回调(银联)
def uni_back(request,uid):if request.method == "POST":params = request.POST.dict()unipay = get_uni_object(uid)res = unipay.verify_sign(params)if res:if unipay.verify_query(params['orderId'], params['txnTime']):  # 再次查询状态return HttpResponse('充值成功')else:return HttpResponse('充值失败')# 充值成功后后台回调(银联)
def uni_notify(request,uid):if request.method == "POST":params = request.POST.dict()unipay = get_uni_object(uid)res = unipay.verify_sign(params)if res:status = unipay.verify_query(params['orderId'], params['txnTime'])  # 再次查询状态if status:try:updata_data(uid,float(int(params['txnAmt']) / 100))return HttpResponse('ok')except User.DoesNotExist as e:raise eelse:return HttpResponse('')else:params = request.GET.dict()for k,v in params.items():print(k,v,'\n')return HttpResponse('failed')
urls.py 文件
from django.urls import path
from . import viewsapp_name = 'pay'urlpatterns = [path('pay_page/',views.pay_page,name='pay_page'),path('unipay/<str:uid>/',views.unipay,name='unipay'),path('uni_notify/<str:uid>/',views.uni_notify,name='uni_notify'),path('uni_back/<str:uid>/',views.uni_back,name='uni_back'),
]
sittings.py 文件
# 银联支付参数配置
class UnionPayConfig(object):# 银联版本号(固定)version = "5.1.0"# 商户ID(配置项)mer_id = "xxxxxxxxxxx"  # 你的商户id  (正式生产环境需修改)# 前台回调地址(支付成功回调成功)(配置项)(正式生产环境需修改)front_url = "http://127.0.0.1:8000/pay/uni_back/"  # http://公网IP/back/ # 后台回调地址(配置项)(正式生产环境需修改)back_url = "http://127.0.0.1:8000/pay/uni_notify/"  # http://公网IP/notify/ # 证书地址(配置项)(正式生产环境需修改)cert_path = "keys/acp_test_sign.p12" # 证书解密密码(根据实际去调配)(配置项) (正式生产环境需修改)cert_password = "000000"# 是否开启测试模式(默认False)(配置项)(正式生产环境为False)debug = True
效果图

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

代码参考:
1.https://blog.csdn.net/cnweike/article/details/52669089
2.https://blog.csdn.net/yulei_qq/article/details/49025045
3.https://github.com/jie/unionpay
以上代码仅供参考,如直接用于商用出现任何问题概不负责。


http://chatgpt.dhexx.cn/article/RajPGdpR.shtml

相关文章

小程序调银联支付接口

这几天接了一个需求&#xff0c;将之前的项目支付接口改成银联的支付接口&#xff0c;简单说一下&#xff0c;对于没有接触过支付的小伙伴可能会有那么一丢丢启发… 环境&#xff1a;微信小程序银联支付 文档&#xff1a;公司提供的开发文档银联官方文档 框架&#xff1a;Dub…

【java支付一 】java整合银联支付

1.注册银联账号后进入测试地址 传送门 2.下载源码 银联源码地址 3.根据需求&#xff08;这里我们肯定使用JAVA&#xff09;选择不同的开发包&#xff0c;导入到项目中 4.修改 Java Version SDK (通用版)\ACPSample_B2C\src 文件中acp_sdk.propertites 证书以及配置回调的地址…

银联网关支付demo

对接银联支付接口&#xff0c;通过一个例子向商家支付金额。 1.首先在银联开放平台下载支付Demo&#xff0c;点击链接 或者直接拿我修改好的demo,链接: https://pan.baidu.com/s/1FywgOf5j_EYj5NQYHPeGqg 提取码: d2hp 建议拿我的现成版demo(修改了一些问题),解压后按照下面…

银联支付流程

本文的前提是你已经申请好了银联的相关资料&#xff0c;即将进入集成阶段或者遇到坑了&#xff08;没错。我踩了 吐槽下 这东西真是渣&#xff09;&#xff0c;不bb了&#xff0c;直接开始吧 照着文档把相关的so jar data.bin文件拷贝到相应的文件夹&#xff0c;权限&#xff…

java银联支付

貌似最近银联出了什么活动,公司急需接入银联支付, 作为写代码的我们 , 只能服从命令,特地记录下接入银联的过程 ,后续还会说接入支付宝和微信的亲自体验历程.................................................................... 1.申请商户 首先得去银联那里开通商户,这个…

谈谈银联 js 支付

业务场景&#xff1a;银联 JS 支付指二维码为收单机构订单的 URL&#xff0c;用户扫描二维码后在 APP 浏览器中打开收单机构的 H5 页面&#xff0c;收单机构在确认支付后调用银联统一网关&#xff0c;由银联调用 APP 完成支付的场景。 银联 JS 支付为丰富 APP 受理范围&#x…

springboot整合银联支付B2C

springboot整合银联支付B2C 前期准备 需要注册银联&#xff0c;登录&#xff0c;下载相关的sdk 这里是整合B2C 注册&#xff0c;登录 注册登录地址 https://open.unionpay.com/tjweb/login 下载sdk sdk下载地址: https://open.unionpay.com/tjweb/acproduct/list?apiSvc…

银联支付接口申请流程-傲付宝

公司的业务主要是帮企业申请各种支付接口&#xff0c;申请得多就慢慢熟悉了一些门道&#xff0c;其实银联支付申请还是比较简单的&#xff08;不用上传app截图什么的&#xff09;&#xff0c;只是申请比较难&#xff0c;还有填写的资料比较多。下面我给大家介绍下银联支付接口中…

PHP对接银联电子支付接口开发

PHP对接银联电子支付接口开发 提示:https://service.chinapay.com/OSIWeb/plogin/toLogin.action#银联在线,注册用户,签约成为商户。成为商户后银联会发邮件到你的邮箱,内容有插件、企业门户控台证书申请、logo、cp.cer、商户接入手册,和商户号ID。 企业门户控台证书申请…

PHP银联支付接口

同事整理的银联支付接口&#xff1a; 链接&#xff1a;http://pan.baidu.com/s/1boMJ2z1 密码&#xff1a;qxcx 1.首先导入Api银联支付接口到项目的Aip目录下。 2.前端创建如下相对应页面 2-1 2-2 3.填写如上图2-2的真实个人信息数据。发form表单或者ajax到后台方法中。 如下图…

银联支付接口+支付宝接口统一支付功能

这个demo发出来已经比较久了&#xff0c;后面发现陆续还有同学找到我&#xff0c;我这里说下现在的情况。 这个接口中的银联支付接口实际也是走的支付宝接口&#xff0c;不需要单独申请银联了。但是&#xff01;支付宝的这个接口已经下架了&#xff0c;以前已经接入的此接口还可…

#DNS比较(北京联通宽带) @FDDLC

阿里&#xff1a;223.5.5.5 腾讯&#xff1a;119.29.29.29 百度&#xff1a;180.76.76.76 北京联通&#xff1a;202.106.46.151 北京联通&#xff1a;202.106.195.68

牛啊,全国DNS服务器IP地址都在这里了

各省公共DNS服务器IP大全 欢迎关注微信公众号【厦门微思网络】。www.xmws.cn专业IT认证培训19周年主要课程&#xff1a;思科、华为、红帽、ORACLE、VMware、CISP、PMP等认证培训及考证 名称各省公共DNS服务器IP大全114 DNS114.114.114.114114.114.115.115阿里 AliDNS223.5.5.52…

教育网系统服务器域名地址,北京教育网dns服务器地址

北京教育网dns服务器地址 内容精选 换一换 默认部署在VPC下的应用可以调用API。如果域名解析失败&#xff0c;则参考配置内网DNS&#xff0c;在当前终端节点上配置DNS服务器。配置完成后&#xff0c;部署在VPC下的应用可以调用API。配置DNS需要配置“/etc”目录下的resolv.conf…

全国DNS地址大全

电信DNS&#xff1a; 北京DNS地址&#xff1a; 202.96.199.133 202.96.0.133 202.106.0.20 202.106.148.1 202.97.16.195 上海DNS地址&#xff1a; 202.96.199.132 202.96.199.133 202.96.209.5 202.96.209.6 202.96.209.133 天津DNS地址&#xff1a; 202.99.96.68 10.10.64.68…

【EtherCAT】基础概念

一、定义 EtherCAT&#xff08;以太网控制自动化技术&#xff09;是最初由德国倍福&#xff08;Beckhoff&#xff09;公司开发的实时&#xff08;real—time&#xff09;工业以太网&#xff08;Ethernet&#xff09;技术&#xff0c;它是一种以以太网为基础的现场总线系统&…

EtherCAT是如何工作的

来源https://blog.csdn.net/u014311679/article/details/90713554 若有侵权&#xff0c;请联系删除。 这次讨论一下ETHERCAT是如何工作的&#xff1a; 应用层-数据链路层-物理层 物理层&#xff1a; RJ45标准连接器&#xff1b;TX to FX转换器&#xff1b;LVDS&#xff1a;低电…

IgH详解十、EtherCAT DC(1)理论

(Distributed Clocks) 分布式时钟 分布式时钟相当于每个节点都有一个时钟&#xff0c;在同一时刻&#xff0c;触发所有节点做给定的动作&#xff0c;要达到同一时刻触发就要求大家的时钟保持一致&#xff0c;也就是同步。 比如每个人都有手机&#xff0c;只要手机接入网络&…

EtherCAT 之邮箱

EtherCAT特点 由于工作需要&#xff0c; 最近在学习EtherCAT总线&#xff0c;对于主站和从站的通信&#xff0c;发表一下我个人的理解。 1. EtherCAT为保证低延迟高响应&#xff0c;不可能像MODBUS一样用软件解析数据包再转发的模式&#xff0c;而是采用“高速火车”不停车上下…

IgH详解八、EtherCAT SDO原理

主站通过使用 SDO对对象字典进行读取/写入操作,完成对从站设备进行参数设置&#xff64;状态监视等&#xff61; 从站SDO的读写是非实时的&#xff0c;所以需要多次访问来确保数据操作的正确性。 如下图写入操作&#xff0c;主站把数据发送到从站&#xff0c;从站返回WC确保数…