本代码示例基于gmssl-python实现。gmssl-python是GmSSL密码库 https://github.com/guanzhi/GmSSL 的Python语言封装.
使用前需要安装GmSSL密码库, 可以参考:https://github.com/guanzhi/GmSSL
安装依赖
如果你是通过uv管理的项目
uv add gmssl-python
uv add requests
如果你是通过pip管理的项目
pip install gmssl-python
pip install requests
银行卡核验接口SM2SM4加密请求示例
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
银行卡三要素核验(SM2+SM4加密版)- 聚合数据API调用示例
文档地址:https://www.juhe.cn/docs/api/id/207
本示例演示如何使用SM2和SM4加密算法调用银行卡三要素核验接口
加密流程:
1. 生成随机的SM4密钥和初始向量
2. 使用SM2公钥加密SM4密钥和初始向量
3. 使用SM4加密敏感业务参数
4. 发送加密后的数据到接口
"""
import base64
import os
from typing import Dict, Optional
from gmssl import Sm4Cbc, Sm2Key, DO_ENCRYPT
import requests
# ==================== 配置项 ====================
API_URL = "https://v.juhe.cn/verifybankcard3/queryEncrySm"
API_KEY = "15e304************" # 请替换为您自己的API Key
PUBLIC_KEY_FILE = "sm2_public_key.pem" # SM2公钥文件路径(联系聚合商务获取)
# ==================== 加密工具函数 ====================
def sm4_encrypt(sm4_key: bytes, sm4_iv: bytes, data: str) -> str:
"""
使用SM4算法加密数据
Args:
sm4_key: SM4密钥(16字节)
sm4_iv: SM4初始向量(16字节)
data: 待加密的明文数据
Returns:
Base64编码的加密数据
"""
sm4_enc = Sm4Cbc(sm4_key, sm4_iv, DO_ENCRYPT)
encrypted = sm4_enc.update(data.encode('utf-8'))
encrypted += sm4_enc.finish()
return base64.b64encode(encrypted).decode('utf-8')
def sm2_encrypt_key(public_key_path: str, data: bytes) -> str:
"""
使用SM2公钥加密数据
Args:
public_key_path: SM2公钥文件路径
data: 待加密的数据
Returns:
Base64编码的加密数据
"""
public_key = Sm2Key()
public_key.import_public_key_info_pem(public_key_path)
encrypted = public_key.encrypt(data)
return base64.b64encode(encrypted).decode('utf-8')
# ==================== 主要业务逻辑 ====================
def verify_bank_card(
realname: str,
idcard: str,
bankcard: str,
mobile: str,
api_key: str = API_KEY,
api_url: str = API_URL
) -> Optional[Dict]:
"""
银行卡三要素核验
Args:
realname: 真实姓名
idcard: 身份证号码
bankcard: 银行卡号
mobile: 手机号码
api_key: API密钥
api_url: API接口地址
Returns:
API响应的JSON数据,失败时返回None
"""
try:
# 步骤1: 生成随机的SM4密钥和初始向量(各16字节)
sm4_key = os.urandom(16)
sm4_iv = os.urandom(16)
print("=" * 60)
print("步骤1: 生成SM4密钥和初始向量")
print(f"SM4 Key (hex): {sm4_key.hex()}")
print(f"SM4 IV (hex): {sm4_iv.hex()}")
# 步骤2: 使用SM2公钥加密SM4密钥和初始向量
print("\n步骤2: 使用SM2公钥加密SM4密钥和初始向量")
encrypted_sm4_key = sm2_encrypt_key(PUBLIC_KEY_FILE, sm4_key)
encrypted_sm4_iv = sm2_encrypt_key(PUBLIC_KEY_FILE, sm4_iv)
print(f"加密后的SM4 Key: {encrypted_sm4_key[:50]}...")
print(f"加密后的SM4 IV: {encrypted_sm4_iv[:50]}...")
# 步骤3: 使用SM4加密敏感业务参数
print("\n步骤3: 使用SM4加密业务参数")
encrypted_realname = sm4_encrypt(sm4_key, sm4_iv, realname)
encrypted_idcard = sm4_encrypt(sm4_key, sm4_iv, idcard)
encrypted_bankcard = sm4_encrypt(sm4_key, sm4_iv, bankcard)
encrypted_mobile = sm4_encrypt(sm4_key, sm4_iv, mobile)
print(f"姓名已加密: {encrypted_realname}")
print(f"身份证已加密: {encrypted_idcard}")
print(f"银行卡已加密: {encrypted_bankcard}")
print(f"手机号已加密: {encrypted_mobile}")
# 步骤4: 构造请求参数
print("\n步骤4: 构造请求参数")
request_params = {
'key': api_key,
'realname': encrypted_realname,
'idcard': encrypted_idcard,
'bankcard': encrypted_bankcard,
'mobile': encrypted_mobile,
'sm4Key': encrypted_sm4_key,
'sm4Iv': encrypted_sm4_iv,
}
# 步骤5: 发送POST请求
print("\n步骤5: 发送请求到API")
print(f"请求地址: {api_url}")
response = requests.post(api_url, data=request_params, timeout=10)
response.raise_for_status()
# 步骤6: 解析响应
print("\n步骤6: 解析API响应")
print("=" * 60)
response_data = response.json()
if response_data.get('error_code') == 0:
print("✓ 请求成功")
print(f"响应结果: {response_data}")
else:
print("✗ 请求失败")
print(f"错误代码: {response_data.get('error_code')}")
print(f"错误原因: {response_data.get('reason')}")
print("=" * 60)
return response_data
except requests.exceptions.RequestException as e:
print(f"✗ 网络请求失败: {e}")
return None
except FileNotFoundError:
print(f"✗ 公钥文件不存在: {PUBLIC_KEY_FILE}")
print("提示: 请联系聚合商务获取SM2公钥文件")
return None
except Exception as e:
print(f"✗ 发生错误: {e}")
return None
def main():
"""
主函数 - 演示如何调用银行卡三要素核验接口
"""
print("\n银行卡三要素核验(SM2+SM4加密版)- 示例程序")
print("=" * 60)
# 示例数据(请替换为真实数据进行测试)
test_data = {
'realname': '董先生',
'idcard': '330329198901010202',
'bankcard': '6216606101012341234',
'mobile': '18913511234'
}
print("测试数据(明文):")
for key, value in test_data.items():
print(f" {key}: {value}")
print()
# 调用接口
result = verify_bank_card(**test_data)
if result:
print("\n接口调用完成!")
else:
print("\n接口调用失败,请检查配置和网络连接")
if __name__ == "__main__":
main()