支付宝小程序对接国家医保接口,签名算法SM2(SM3withSM2)、加密算法SM4

903 阅读11分钟

已帮助多家医院对接国家医保,如有问题可私信评论

第1章 范围 本文档适用于两定机构调用接入医保移动支付中心服务,主要表述了电子凭证结算涉及 的接口出入参调用示例。 天津市医保移动支付本期建设包含支付宝小程序和国家医保局 APP 移动支付应用场景。 第2章 接口规则 2.1 协议规则 规则 规则描述 传输方式 为保证交易安全性,采用 HTTPS 传输 提交方式 采用 POST 方法提交 数据格式 提交和返回数据都为 JSON 格式 字符编码 统一采用 UTF-8 字符编码 签名算法 SM2 加密算法 SM4 签名要求 请求和接收数据均需要校验签名,详细方法请参考安全规范-签名算法 加密要求 请求和接收数据均需要校验签名,详细方法请参考安全规范-加密算法 判断逻辑 先判断协议字段返回,再判断业务返回,最后判断交易状态 2.2 格式规定 2.2.1 日期、时间格式 日期:YYYYMMDD; 14 时间: HHMMSS。 2.2.2 交易金额格式约定 以元为单位,具体根据接口示例约定保留位数。 2.3 安全规范 2.3.1 签名算法(SM2) 2.3.1.1 概述 根据 SM2 算法(Signature 的 algorithm 选择 SM3withSM2),签名报文。通过对报文数 据筛选、排序和拼接,组成待签名报文数据。 2.3.1.2 请求参数签名 2.3.1.2.1 筛选 获取所有请求参数,不包括字节类型参数,如文件、字节流,剔除 signData、encData、 extra 字段。 2.3.1.2.2 排序 将筛选的参数按照第一个字符的键值 ASCII 码递增排序(字母升序排序),如果遇到相 同字符则按照第二个字符的键值 ASCII 码递增排序,以此类推。 2.3.1.2.3 拼接 将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用&字符 连接起来,最后拼接上应用密钥 appSecret 在“…参数=参数值…”后,此时生成的字符串 为待签名字符串,将待签名字符串 SM2 运算,即是签名(signData)的值(“signData”、 “encData”、“extra”参数不参与签名)。 JOSN 对象签名规范(如 data):内部按字母顺序升序排列空值不参与签名 将整理好的 JSON 内容,输出 JSON 字符串后拼接参与签名,例如下面的示例请求报文,参数值都是示例, 开发者仅参考报文格式即可。 加签报文示例: 15 { "appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX", "data":{"appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX","appUserId":"o8z4C5avQXqC0aWFPf1Mzu6D7 WCQ_bd","idNo":"350181199011193519","idType":"01","phoneNumber":"13763873033","userName": "测试"}, "encType":"SM4", "signData":"URVQNdVNn5mz2EhKZhLTlXNwAWTSncFoSe8Ilx7jhn81eABJ46sdRRN1ZiAiQjPUTixG9bwqEhiJu pHRGmyO5w==", "signType":"SM2", "timestamp":"20200207175759", "version":"2.0.1" } 组成的待签名字符串: appId=43AF047BBA47FC8A1AE8EFB2XXXXXXXX&data={"appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX"," appUserId":"o8z4C5avQXqC0aWFPf1Mzu6D7WCQ_bd","idNo":"350181199011193519","idType":"01","p honeNumber":"13763873033","userName":"测试"} &encType=SM4&signType=SM2&timestamp=20200207175759&version=2.0.1&key=4117E877F5FA0A018889 1283E4B617D5 2.3.1.2.4 签名结果 使用各自语言对应的 SM2 签名函数,对拼接得出的待签名字符串使用私钥进行 SM2 签 名后,再将字节码进行 Base64 编码,即是签名结果,如签名结果。 签名结果示例: URVQNdVNn5mz2EhKZhLTlXNwAWTSncFoSe8Ilx7jhn81eABJ46sdRRN1ZiAiQjPUTixG9bwqEhiJupHRGmyO5w= 2.3.1.3 返回参数验签 2.3.1.3.1 筛选 获取所有请求参数,不包括字节类型参数,如文件、字节流,剔除 signData、encData、 extra 字段。 16 2.3.1.3.2 排序 将筛选的参数按照第一个字符的键值 ASCII 码递增排序(字母升序排序),如果遇到相 同字符则按照第二个字符的键值 ASCII 码递增排序,以此类推。 2.3.1.3.3 拼接 将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用&字符 连接起来,最后拼接上应用密钥 appSecret 在“…参数=参数值…”,此时生成的字符串为 待签名字符串,将待签名字符串 SM2 运算,即是签名(signData)的值(“signData”、 “encData”、“extra”参数不参与签名)。 请求报文示例: { "appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX", "data":{"appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX","appUserId":"o8z4C5avQXqC0aWFPf1Mzu6D7 WCQ_bd","idNo":"350181199011193519","idType":"01","phoneNumber":"13763873033","userName": "测试"}, "encType":"SM4", "signData":"URVQNdVNn5mz2EhKZhLTlXNwAWTSncFoSe8Ilx7jhn81eABJ46sdRRN1ZiAiQjPUTixG9bwqEhiJu pHRGmyO5w==", "signType":"SM2", "timestamp":"20200207175759", "version":"2.0.1" } 组成的待签名字符串: appId=43AF047BBA47FC8A1AE8EFB2XXXXXXXX&data={"appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX"," appUserId":"o8z4C5avQXqC0aWFPf1Mzu6D7WCQ_bd","idNo":"350181199011193519","idType":"01","p honeNumber":"13763873033","userName":"测试"} &encType=SM4&signType=SM2&timestamp=20200207175759&version=2.0.1&key=4117E877F5FA0A018889 1283E4B617D5 17 2.3.1.3.4 签名结果 使用对应的 SM2 验签函数,对拼接得出的待签名字符串使用公钥进行 SM2 进行验签,对 比验签内容的签名与返回报文里的 signData 字段比较是否验签通过。 2.3.2 加密算法(SM4) 2.3.2.1 概述 根据 SM4 加密算法,加密报文。通过对报文数据筛选、排序和拼接,组成待加密报文数 据。 2.3.2.2 请求报文加密 1、组装请求报文 根据 API 列表定义参数,整理请求报文; 加密报文示例: { "appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX", "data":{"appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX","appUserId":"o8z4C5avQXqC0aWFPf1Mzu6D7 WCQ_bd","idNo":"350181199011193519","idType":"01","phoneNumber":"13763873033","userName": "测试"}, "encType":"SM4", "signData":"URVQNdVNn5mz2EhKZhLTlXNwAWTSncFoSe8Ilx7jhn81eABJ46sdRRN1ZiAiQjPUTixG9bwqEhiJu pHRGmyO5w==", "signType":"SM2", "timestamp":"20200207175759", "version":"2.0.1" } 2、将 data 字段值,转换为字符串 jStr; 待加密串示例: {"appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX","appUserId":"o8z4C5avQXqC0aWFPf1Mzu6D7WCQ_bd" ,"idNo":"350181199011193519","idType":"01","phoneNumber":"13763873033","userName":"测试"} 18 3、根据 SM4 加密算法,先使用 appId(渠道 id)作为 Key 加密 appSecret(渠道秘钥) 生成新的秘钥串。(补充:传入 SM4 加密算法长度秘钥为 32 位,实际底层算法秘钥应用长 度为前 16 位); 4、使用 3 获得的报文加密密钥,截取新秘钥串的前 32 位作为 SM4 密钥,加密 jStr(data 字段值)字符串(补充:传入 SM4 加密算法秘钥长度为 32 位,实际底层算法秘钥应用长度 为前 16 位),并将加密结果转换为大写,获得加密密文 encData; 密文示例: 4470B6B96A8E0BADA051A318E6B6FBED66B9FC5AB2A4A3C66FDDD3C70BCADD6EF526AB57DC1DC916385CEF348 43AABFCBAF8F1FDEA9DC51A2A56AB3EA3E170201E4EDD3137D6D1BA6A4A773F6F4872A718F56742E5052AD1C0 4E99C91EA048990F06A96E6E1E534E40BD28DFDC204ACA03CAE0DFE0DE5229EDADBD27BBD32DD4C3F9ADC833C D3CF01CD012CE1799BB6F 5、将加密结果 encData,加入请求报文中,并清空报文的 data 字段; 加密请求报文示例: { "appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX", "encData":"64A9C5A7AB3AEA5FC01DE87025F999521C08D25DA13BD715D7E036A7D7C1DBCB6AB7914898A23A 99C97EBEFE5277247AD7D0DD9B18F4DCC71A2C280C5143F25B857C795E6BA9F399652C3A4264FC2CBBA7E06B0 8E151362301659FC3F3773480966E8D19AB082B64A4F9B9BDBABCE57DC2CA95C9975090885AB286BB736BA3BB 98F3540962552F40C8350926B93CD21CB7A624E6C4E41E349627E7B36B5C1B5F94604EDC42EA6034D63B2D387 A87F42130F0D47B9445F9D729566FE183F9A959", "encType":"SM4", "signData":"URVQNdVNn5mz2EhKZhLTlXNwAWTSncFoSe8Ilx7jhn81eABJ46sdRRN1ZiAiQjPUTixG9bwqEhiJu pHRGmyO5w==", "signType":"SM2", "timestamp":"20200207175759", "version":"2.0.1" } 6、返回报文解密; 19 响应报文示例: { "appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX", "encData":"64A9C5A7AB3AEA5FC01DE87025F999521C08D25DA13BD715D7E036A7D7C1DBCB6AB7914898A23A 99C97EBEFE5277247AD7D0DD9B18F4DCC71A2C280C5143F25B857C795E6BA9F399652C3A4264FC2CBBA7E06B0 8E151362301659FC3F3773480966E8D19AB082B64A4F9B9BDBABCE57DC2CA95C9975090885AB286BB736BA3BB 98F3540962552F40C8350926B93CD21CB7A624E6C4E41E349627E7B36B5C1B5F94604EDC42EA6034D63B2D387 A87F42130F0D47B9445F9D729566FE183F9A959", "encType": "SM4", "code": "0", "message": "成功", "signData": " OTk0MUYwREIyODk1RDhDRDQ5NjQzRTU1RENCN0ZGMzdCRUY4MzFFNDMxMTM1OTY0MEM1MDk3N0E4REE2Nzk2QQ==" , "signType": "SM2", "timestamp": "20161226093147927", "success": true, "version": "2.0.1" } 加密密文数据 enctData 示例: 64A9C5A7AB3AEA5FC01DE87025F999521C08D25DA13BD715D7E036A7D7C1DBCB6AB7914898A23A99C97EBEFE5 277247AD7D0DD9B18F4DCC71A2C280C5143F25B857C795E6BA9F399652C3A4264FC2CBBA7E06B08E151362301 659FC3F3773480966E8D19AB082B64A4F9B9BDBABCE57DC2CA95C9975090885AB286BB736BA3BB98F35409625 52F40C8350926B93CD21CB7A624E6C4E41E349627E7B36B5C1B5F94604EDC42EA6034D63B2D387A87F42130F0 D47B9445F9D729566FE183F9A959 7、根据 encType 声明加密算法,先使用 appId(渠道 id)作为 Key 加密 appSecret(渠 道秘钥)生成新的秘钥串。(补充:传入 SM4 加密算法长度秘钥为 32 位,实际底层算法秘 钥应用长度为前 16 位); 20 8、根据 encType 声明加密算法,使用 7 获取的报文解密密钥,解密 encData 获取明文 字符串 jStr 示例: {"appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX","appUserId":"o8z4C5avQXqC0aWFPf1Mzu6D7WCQ_bd" ,"idNo":"350181199011193519","idType":"01","phoneNumber":"13763873033","userName":"测试"} 9、将 jStr 转换为 JSON 赋值 data,获取解密后返回报文示例: { "appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX", "data":{"appId":"43AF047BBA47FC8A1AE8EFB2XXXXXXXX","appUserId":"o8z4C5avQXqC0aWFPf1Mzu6D7 WCQ_bd","idNo":"350181199011193519","idType":"01","phoneNumber":"13763873033","userName": "测试"}, "encType": "SM4", "code": "0", "message": "成功", "signData": " OTk0MUYwREIyODk1RDhDRDQ5NjQzRTU1RENCN0ZGMzdCRUY4MzFFNDMxMTM1OTY0MEM1MDk3N0E4REE2Nzk2QQ==" , "signType": "SM2", "timestamp": "20161226093147927", "success": true, "version": "2.0.1" } 2.3.3 报文公共参数 3.3.3.1 请求报文 参数 参数名称 类型 可空 参数说明 appId 渠道 id String(32) N version 版本号 String(6) N 2.0.1 timestamp 当前时间 String(32) N 时间戳 21 参数 参数名称 类型 可空 参数说明 encType 加密方式 String(6) N SM4 encData 加密数据 String(max) N signType 签名方式 String(6) N SM2 signData 签名串 String(200) N 3.3.3.2 返回报文 参数 参数名称 类型 可空 参数说明 code 响应状态码 int N appId 渠道 id String(32) N timestamp 当前时间 String(32) N 时间戳 encType 加密方式 String(6) N SM4 signType 签名方式 String(6) N SM2 signData 签名串 String(200) N encData 加密数据 String(max) N message 响应异常信息 String(max) Y success 响应标识 boolean Y version 版本号 String(6) N 2.0.1