您的位置:首页 > 脚本大全 > > 正文

java怎么调用支付宝的扫码支付(python实现银联支付和支付宝支付接入)

更多 时间:2021-10-06 01:08:59 类别:脚本大全 浏览量:241

java怎么调用支付宝的扫码支付

python实现银联支付和支付宝支付接入

本文实例为大家分享了python银联支付和支付宝支付接入的具体代码,供大家参考,具体内容如下

前置条件:需要安装python的openssl模块,我使用的版本是16.1.0,可以使用pip install pyopenssl来安装

一、支付宝支付

1. 使用rsa公钥加密系统进行签名和签名验证,需要自己生成一个rsa私钥和对应的一个rsa公钥(在linux下可以使用ssh-keygen命令来生成),公钥需要上传至支付宝,供支付宝对开发者发送的请求做签名验证使用;而同时支付宝会提供一个rsa公钥给开发者,开发者使用这个公钥来验证支付宝的回调请求的合法性。

2. 整个接入过程最核心的工作就是构建一个合法的请求报文,这个可以参考支付宝的相关文档;其次是对请求报文的内容进行rsa签名,并将签名随请求报文一并发送。

核心的签名和报文构建代码如下:

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • import openssl
  • import json
  • import time
  • import urllib
  • import base64
  •  
  • from django.conf import settings
  •  
  • def build_sign(param_map, sign_type="rsa"):
  •  '''
  •  doc: https://doc.open.alipay.com/doc2/detail.htm?treeid=200&articleid=105351&doctype=1
  •  '''
  •  # 将筛选的参数按照第一个字符的键值ascii码递增排序(字母升序排序),如果遇到相同字符则按照第二个字符的键值ascii码递增排序,以此类推。
  •  sort_param = sorted([(key, unicode(value, settings.alipay_charset).encode(settings.alipay_charset)) for key, value in param_map.iteritems()], key=lambda x: x[0])
  •  # 将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用&字符连接起来,此时生成的字符串为待签名字符串。sdk中已封装签名方法,开发者可直接调用,详见sdk说明。
  •  # 如自己开发,则需将待签名字符串和私钥放入sha1 rsa算法中得出签名(sign)的值。
  •  content = '&'.join(['='.join(x) for x in sort_param])
  •  return base64.encodestring(openssl.crypto.sign(settings.alipay_app_private_key_obj, content, 'sha1'))
  •  
  • def build_params(out_trade_no, subject, body, total_amount):
  •  '''
  •  doc:https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.mvkrgo&treeid=193&articleid=105465&doctype=1
  •  将参数按照支付宝规定组织并签名之后,返回
  •  '''
  •  params = {}
  •  # 获取配置文件
  •  params['app_id']   = settings.alipay_appid
  •  params['method']   = settings.alipay_method
  •  params['format']   = settings.alipay_format
  •  params['charset']   = settings.alipay_charset
  •  params['sign_type']   = settings.alipay_sign_type
  •  params['sign_type']   = settings.alipay_sign_type
  •  params['timestamp']   = time.strftime('%y-%m-%d %h:%m:%s')
  •  params['version']   = settings.alipay_version
  •  params['notify_url'= settings.alipay_notify_url
  •  
  •  # 业务参数
  •  params['biz_content'] = {}
  •  params['biz_content']['body']    = body   # 订单描述、订单详细、订单备注,显示在支付宝收银台里的“商品描述”里
  •  params['biz_content']['subject']   = subject  # 商品的标题/交易标题/订单标题/订单关键字等。
  •  params['biz_content']['out_trade_no'= out_trade_no # 商户网站唯一订单号
  •  params['biz_content']['total_amount'= '%.2f' % (float(total_amount) / 100) # 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]
  •  params['biz_content']['product_code'= settings.alipay_app_product_code
  •  params['biz_content']      = json.dumps(params['biz_content'], separators=(',', ':'))
  •  
  •  params['sign'] = build_sign(params)
  •  
  •  return urllib.urlencode(params)
  •  
  • def check_sign(message, sign):
  •  '''doc: https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.ddrpek&treeid=204&articleid=105301&doctype=1'''
  •  try:
  •   openssl.crypto.verify(settings.alipay_public_key_obj, sign, message, 'sha1')
  •   return true
  •  except exception as _:
  •   return false
  • 在读取支付宝公钥的时候,由于openssl模块使用的是x509格式的证书,所以需要做以下的处理(用于对发起支付报文进行签名):

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • # 支付宝开发者公钥(支付宝生成)
  • alipay_public_key = os.path.join(base_dir, 'utils/paycenter/alipay/certs/alipay_public_key')
  • _alipay_public_key_obj_pub = openssl.crypto.load_publickey(openssl.crypto.filetype_pem, open(alipay_public_key).read())
  • _alipay_public_key_obj_x509 = openssl.crypto.x509()
  • _alipay_public_key_obj_x509.set_pubkey(_alipay_public_key_obj_pub)
  • alipay_public_key_obj = _alipay_public_key_obj_x509
  • 载入开发者生成的私钥的代码为(用于验证支付宝回调请求的合法性):

  • ?
  • 1
  • 2
  • 3
  • # 支付宝开发者应用私钥(接入方生成)
  • alipay_app_private_key = os.path.join(base_dir, 'utils/paycenter/alipay/certs/alipay_app_private_key')
  • alipay_app_private_key_obj = openssl.crypto.load_privatekey(openssl.crypto.filetype_pem, open(alipay_app_private_key).read(), none)
  • 二、银联支付

    1. 银联支付(网关支付)与支付宝支付基本上遵循了同样的流程,但是在发起支付的请求报文和签名、验证签名等方面存在细微的差别,特别是在签名和验证签名时,支付宝是直接对报文内容进行了rsa加密,但是银联却是首先对签名内容取sha1的摘要,继而对此摘要做rsa加密,这点在build_sign函数中就可以很明显地看出来。

    2. 银联支付的证书文件申请流程比较繁琐,并且其格式也和支付宝使用的不同,我们申请到的私钥证书文件是以pkcs12的格式保存的,并且需要注意在从指定位置下载此证书后,导出证书时一定要将密码设置为6位的整数数字,之后,还需要将pkcs12格式的证书文件上传至指定位置并启用才可以正常使用此证书。

    核心的签名和报文构建代码如下:

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • import time
  • import hashlib
  • import urllib, urllib2
  • import base64
  • import openssl
  • from django.conf import settings
  •  
  • def build_sign(param_map, sign_type="rsa"):
  •  '''构建签名'''
  •  # 将筛选的参数按照第一个字符的键值ascii码递增排序(字母升序排序),如果遇到相同字符则按照第二个字符的键值ascii码递增排序,以此类推。
  •  sort_param = sorted([(key, unicode(value, settings.unionpay_encoding).encode(settings.unionpay_encoding)) for key, value in param_map.iteritems()], key=lambda x: x[0])
  •  content = '&'.join(['='.join(x) for x in sort_param])
  •  message = hashlib.sha1(content).hexdigest()
  •  return base64.b64encode(openssl.crypto.sign(settings.unionpay_private_key_obj, message, 'sha1'))
  •  
  • def build_params(out_trade_no, total_amount):
  •  params = {}
  •  # 获取配置信息
  •  params['acctype'] = settings.unionpay_acc_type
  •  params['accesstype'] = settings.unionpay_access_type
  •  params['backurl'] = settings.unionpay_back_url
  •  params['fronturl'] = settings.unionpay_front_url
  •  params['biztype'] = settings.unionpay_biz_type
  •  params['certid'] = settings.unionpay_cert_id
  •  params['channeltype'] = settings.unionpay_channel_type
  •  params['currencycode'] = settings.unionpay_currency_code
  •  params['encoding'] = settings.unionpay_encoding
  •  params['merid'] = settings.unionpay_mer_id
  •  params['signmethod'] = settings.unionpay_sign_method
  •  params['txntype'] = settings.unionpay_txn_type
  •  params['txnsubtype'] = settings.unionpay_txn_subtype
  •  params['version'] = settings.unionpay_version
  •  
  •  params['orderid'] = out_trade_no
  •  params['txnamt'] = '%d' % int(total_amount) # 单位为分
  •  params['txntime'] = time.strftime('%y%m%d%h%m%s') #
  •  
  •  params['signature'] = build_sign(params)
  • #  return params
  •  return urllib.urlencode(params)
  •  
  • def check_sign(message, sign):
  •  try:
  •   openssl.crypto.verify(settings.unionpay_public_key_obj, sign, message, 'sha1')
  •   return true
  •  except exception as _:
  •   return false
  • 商户私钥证书的载入方法(用户对发起支付的报文进行签名):

  • ?
  • 1
  • 2
  • 3
  • 4
  • # 商户私钥证书
  • unionpay_app_private_key_cert = os.path.join(unionpay_certs_path, unionpay_app_private_key_cert_filename) # pkcs12 format
  • unionpay_private_keystore = openssl.crypto.load_pkcs12(open(unionpay_app_private_key_cert).read(), unionpay_app_private_key_cert_password)
  • unionpay_private_key_obj = unionpay_private_keystore.get_privatekey()
  • 银联公钥证书的载入方法(用于验证银联回调的合法性):

  • ?
  • 1
  • 2
  • 3
  • # 银联公钥证书
  • unionpay_public_key_cert = os.path.join(unionpay_certs_path, unionpay_public_key_cert_filename)
  • unionpay_public_key_obj = openssl.crypto.load_certificate(openssl.crypto.filetype_pem, open(unionpay_public_key_cert).read())
  • 后记:银联支付接入过程中,参考过其官方提供的一个python实现的接口,里面同时使用了python的rsa模块和openssl模块,并且对证书的格式做了各种处理,但是这些似乎是没有什么必要,只使用openssl模块就完全可以完成相关的工作。

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持开心学习网。

    原文链接:https://blog.csdn.net/cnweike/article/details/52669089

    您可能感兴趣