web第三方支付
微信支付
github 支付客户端: https://github.com/zwczou/weixin-python
开发文档:https://pay.weixin.qq.com/wiki/doc/api/index.html
微信支付的企业付款到零钱开通:https://jingyan.baidu.com/article/fec7a1e5989fc01191b4e74e.html
微信支付-证书安装+使用+CentOS+Python+Tornado
版权声明:本文为CSDN博主「Victor.Zhang」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013538542/article/details/99695955
使用微信支付的API证书下载

证书下载后,可以看到三个证书如图

在CentOS服务器上安装证书程序
教程:https://manuals.gfi.com/en/kerio/connect/content/server-configuration/ssl-certificates/adding-trusted-root-certificates-to-the-server-1605.html
在Linux上的CentOS 6安装ca-certificates包:
$ yum install ca-certificates
启用动态CA配置特性
$ update-ca-trust force-enable
把从微信商户平台下载的三个证书的其中两个(apiclient_cert.pem 和apiclient_key.pem)拷贝到这个目录下
$ /etc/pki/ca-trust/source/anchors/
从本地把证书拷贝到服务器上很简单的,使用scp命令就行
$ scp /User/victor/Desktop/apiclient_cert.pem root@你的服务器IP:/etc/pki/ca-trust/source/anchors/ $ scp /User/victor/Desktop/apiclient_key.pem root@你的服务器IP:/etc/pki/ca-trust/source/anchors/
Python的代码编写:企业付款到零钱
# 请求接口 general_url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers" # 服务端生产环境 server_root_ca_filepath = "/etc/pki/tls/certs/ca-bundle.crt" # 看文章底部解释 cert_ca_filepath ='/etc/pki/ca-trust/source/anchors/apiclient_cert.pem' key_ca_filepath = '/etc/pki/ca-trust/source/anchors/apiclient_key.pem' # 本地测试环境 # server_root_ca_filepath = "/Users/victor/Desktop/1535260341_20190816_cert/cacert.pem" # cert_ca_filepath = "/Users/victor/Desktop/1535260341_20190816_cert/apiclient_cert.pem" # key_ca_filepath = "/Users/victor/Desktop/1535260341_20190816_cert/apiclient_key.pem" # https://stackoverflow.com/questions/23954120/using-certificates-in-urllib3 # 重点关注这里!!! httpreq = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', cert_file=cert_ca_filepath, key_file=key_ca_filepath, ca_certs=server_root_ca_filepath) resp = httpreq.request("POST", general_url, headers={ 'Content-Type' : 'application/xml' }, body=xml_parameters.encode("utf-8")) resp_data = str(resp.data, encoding="utf-8")
证书配置错误时提示
{ 'return_code': 'SUCCESS', 'return_msg': '证书出错,请登录微信支付商户平台下载证书', 'mch_appid': 'wx54611105e8382140', 'mchid': '1535260341', 'result_code': 'FAIL', 'err_code': 'CA_ERROR', 'err_code_des': '证书出错,请登录微信支付商户平台下载证书' }
证书配置正确,没有开通企业付款到零钱的功能时提示
{ 'return_code': 'SUCCESS', 'return_msg': 'NO_AUTH', 'mch_appid': 'wx54611105e8382140', 'mchid': '1535260341', 'result_code': 'FAIL', 'err_code': 'NO_AUTH', 'err_code_des': '产品权限验证失败,请查看您当前是否具有该产品的权限' }
证书配置正确,已经开通企业付款到零钱的功能时提示:
该功能需要满足公众号90天,且最近30天连续有交易才能开通,所以,我在等
服务器根证书: /etc/pki/tls/certs/ca-bundle.crt 来自你在CentOS下安装完后就能找到这个目录了
本地的根证书来自:/Users/victor/Desktop/1535260341_20190816_cert/cacert.pem来自 https://curl.haxx.se/ca/cacert.pem
微信文档有解释,文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=23_4
支付宝支付
二维码API
草料二维码: https://cli.im/
安装SDK
win10安装出错,查看错误日志,应该是pycrypto没有安装成功,Ubuntu18.04可以正常安装
pip install alipay-sdk-python
沙箱测试
开放平台-->文档中心-->沙箱环境

Demo
import logging import traceback import json from . import globalSettings from alipay.aop.api.AlipayClientConfig import AlipayClientConfig from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient from alipay.aop.api.request.AlipayTradeQueryRequest import AlipayTradeQueryRequest from alipay.aop.api.request.AlipayTradeCloseRequest import AlipayTradeCloseRequest from alipay.aop.api.request.AlipayTradeRefundRequest import AlipayTradeRefundRequest from alipay.aop.api.request.AlipayTradeFastpayRefundQueryRequest import AlipayTradeFastpayRefundQueryRequest from alipay.aop.api.request.AlipayDataDataserviceBillDownloadurlQueryRequest import AlipayDataDataserviceBillDownloadurlQueryRequest from alipay.aop.api.request.AlipayTradeWapPayRequest import AlipayTradeWapPayRequest from alipay.aop.api.response.AlipayTradePayResponse import AlipayTradePayResponse from alipay.aop.api.response.AlipayTradeCloseResponse import AlipayTradeCloseResponse from alipay.aop.api.response.AlipayTradeFastpayRefundQueryResponse import AlipayTradeFastpayRefundQueryResponse from alipay.aop.api.response.AlipayDataDataserviceBillDownloadurlQueryResponse import AlipayDataDataserviceBillDownloadurlQueryResponse from alipay.aop.api.domain.AlipayTradeCloseModel import AlipayTradeCloseModel from alipay.aop.api.domain.AlipayTradeQueryModel import AlipayTradeQueryModel from alipay.aop.api.domain.AlipayTradeWapPayModel import AlipayTradeWapPayModel from alipay.aop.api.domain.AlipayTradeRefundModel import AlipayTradeRefundModel from alipay.aop.api.domain.AlipayTradeFastpayRefundQueryModel import AlipayTradeFastpayRefundQueryModel from alipay.aop.api.domain.AlipayDataDataserviceBillDownloadurlQueryModel import AlipayDataDataserviceBillDownloadurlQueryModel logging.basicConfig( level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s', filemode='a', ) logger = logging.getLogger('') def get_alipay_client(): """ 设置配置,包括支付宝网关地址、app_id、应用私钥、支付宝公钥等,其他配置值可以查看AlipayClientConfig的定义。 """ alipay_client_config = AlipayClientConfig() alipay_client_config.server_url = globalSettings.server_url # 支付宝网关 alipay_client_config.app_id = globalSettings.app_id # 支付宝分配给开发者的应用ID alipay_client_config.app_private_key = globalSettings.app_private_key # 应用私钥 alipay_client_config.alipay_public_key = globalSettings.alipay_public_key # 支付宝公钥 """ 得到客户端对象。 注意,一个alipay_client_config对象对应一个DefaultAlipayClient,定义DefaultAlipayClient对象后,alipay_client_config不得修改,如果想使用不同的配置,请定义不同的DefaultAlipayClient。 logger参数用于打印日志,不传则不打印,建议传递。 """ client = DefaultAlipayClient(alipay_client_config=alipay_client_config, logger=logger) return client default_alipay_client = get_alipay_client() def get_alipay_page(out_trade_no, total_amount, subject, body=None, timeout_express=None, product_code="QUICK_WAP_PAY"): """ 功能:支付宝手机网站支付接口(alipay.trade.wap.pay)接口调试入口页面 对于页面跳转类API,SDK不会也无法像系统调用类API一样自动请求支付宝并获得结果,而是在接受request请求对象后, 为开发者生成前台页面请求需要的完整form表单的html(包含自动提交脚本),商户直接将这个表单的String输出到http response中即可。 :param out_trade_no : 商户订单号,商户网站订单系统中唯一订单号,必填 :param total_amount : 付款金额,必填 :param subject : 订单名称,必填 :param body : 超时时间 可空 :param timeout_express : 超时时间 可空 :param product_code : 销售产品码,商家和支付宝签约的产品码。该产品请填写固定值:QUICK_WAP_WAY,必填 :return form: """ model = AlipayTradeWapPayModel() model.out_trade_no = out_trade_no model.subject = subject model.total_amount = total_amount model.timeout_express = timeout_express model.body = body alipay_request = AlipayTradeWapPayRequest(biz_model=model) alipay_request.return_url = globalSettings.return_url alipay_request.notify_url = globalSettings.notify_url form = "" try: form = default_alipay_client.page_execute(alipay_request) except Exception as e: print(e) return form def get_alipay_query(out_trade_no, trade_no): """ 交易查询接口 :param out_trade_no: 商户订单号,商户网站订单系统中唯一订单号,必填 :param trade_no: 支付宝交易号 :return trade_no: 支付宝28位交易号 :return out_trade_no: 支付时传入的商户订单号 :return trade_status: 交易当前状态 """ model = AlipayTradeQueryModel() model.out_trade_no = out_trade_no model.trade_no = trade_no request = AlipayTradeQueryRequest(biz_model=model) # 创建API对应的request类 response = default_alipay_client.execute(request) print(response) return response def alipay_refund(out_trade_no, trade_no, out_request_no, refund_amount): """ 交易退款接口,trade_no、out_trade_no如果同时存在优先取trade_no :param out_trade_no: 商户订单号,和支付宝交易号二选一 :param trade_no: 支付宝交易号,和商户订单号二选一 :param out_request_no: 本次退款请求流水号,部分退款时必传 :param refund_amount: 退款金额,不能大于订单总金额 :param refund_amount: 退款的原因说明 :return refund_fee: 该笔交易已退款的总金额 """ model = AlipayTradeRefundModel() model.out_trade_no = out_trade_no model.trade_no = trade_no model.refund_amount = refund_amount model.refund_reason = refund_amount model.out_request_no = out_request_no request = AlipayTradeRefundRequest(biz_model=model) response = default_alipay_client.execute(request) print(response) return response def alipay_refund_query(out_trade_no, trade_no, out_request_no): """ 交易退款查询接口 商户订单号和支付宝交易号不能同时为空。 trade_no、 out_trade_no如果同时存在优先取trade_no :param out_trade_no: 商户订单号,和支付宝交易号二选一 :param trade_no: 支付宝交易号,和商户订单号二选一 :param out_request_no: 请求退款接口时,传入的退款请求号,如果在退款请求时未传入,则该值为创建交易时的外部交易号 :return refund_fee: 该笔交易已退款的总金额 """ model = AlipayTradeFastpayRefundQueryModel() model.out_trade_no = out_trade_no model.trade_no = trade_no model.out_request_no = out_request_no alipay_request = AlipayTradeFastpayRefundQueryRequest(biz_model=model) response = default_alipay_client.execute(alipay_request) print(response) return response def get_bill_downloadurl(bill_date, bill_type="trade"): """ 功能:支付宝手机网站alipay.data.dataservice.bill.downloadurl.query (查询对账单下载地址)接口调试入口页面 :param bill_type: 固定传入trade :param bill_date: 需要下载的账单日期,最晚是当期日期的前一天 :return bill_download_url:账单文件下载地址,30秒有效 """ model = AlipayDataDataserviceBillDownloadurlQueryModel() model.bill_type = bill_type model.bill_date = bill_date alipay_request = AlipayDataDataserviceBillDownloadurlQueryRequest(biz_model=model) return _execute_request(alipay_request, AlipayDataDataserviceBillDownloadurlQueryResponse()) def async_alipay_notify(): """ 异步通知验签 :return: """ def close_alipay_trade(out_trade_no, trade_no): """ 功能:支付宝手机网站alipay.trade.close (统一收单交易关闭接口)调试入口页面 :param out_trade_no: 商户订单号,和支付宝交易号二选一 :param trade_no: 支付宝交易号,和商户订单号二选一 :return: """ close_model = AlipayTradeCloseModel() close_model.out_trade_no = out_trade_no close_model.trade_no = trade_no alipay_request = AlipayTradeCloseRequest(biz_model=close_model) is_success, response = _execute_request(alipay_request, AlipayTradeCloseResponse()) if is_success: # 如果业务成功,则通过respnse属性获取需要的值 return {"success": True, "trade_no": response.trade_no, "out_trade_no": response.out_trade_no} else: return {"success": False, "msg": response} def _execute_request(request, response): response_content = None try: response_content = default_alipay_client.execute(request) except Exception as e: print(traceback.format_exc()) if not response_content: return False, "failed execute" else: # 解析响应结果 response.parse_response_content(response_content) print(response.body) if response.is_success(): # 如果业务成功,则通过respnse属性获取需要的值 return True, response else: # 如果业务失败,则从错误码中可以得知错误情况,具体错误码信息可以查看接口文档 print(response.code + "," + response.msg + "," + response.sub_code + "," + response.sub_msg) return False, "failed execute" if __name__ == '__main__': get_bill_downloadurl(bill_date="2016-04-05")
手机网站支付产品
手机网站支付产品流程:https://docs.open.alipay.com/203/105288/
API接口调用流程:https://docs.open.alipay.com/203/105285/
安全分析:
API调用分析
步骤一:用户下单-->商户系统生成订单,生成并发送支付请求-->支付宝接收请求
存在商户系统(或黑客)修改订单的风险,如:用户本想支付1元,被修改为100元。
步骤二:支付宝生成订单进行确认,并对订单签名,让商户系统转交给用户--->商户系统接收form,转交给用户-->用户接收form
1、为了防止商户系统(或黑客等)修改订单,支付宝生成订单向用户确认。
2、为了防止确认订单在中途被修改,支付宝对订单进行签名
加密、解密、签名、验签介绍:https://www.cnblogs.com/pcheng/p/9629621.html
手机网站支付产品流程分析:
支付宝确认订单是一个自动提交的form表单,会尝试唤起支付宝APP,否则在一定的时间后会自动进入网页支付流程。
1、唤起APP后,用户确认订单,完成支付,支付宝通知商户系统
网页支付流程
DNS劫持:https://baike.baidu.com/item/DNS%E5%8A%AB%E6%8C%81
问题汇总
pip3 install alipay-sdk-python
src/MD2.c:31:20: fatal error: Python.h: No such file or directory
compilation terminated.
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
----------------------------------------
ERROR: Failed building wheel for pycrypto
sudo apt-get install python3-dev

浙公网安备 33010602011771号