Browse Source

迁移:修改中融爱签实盘BUG db03e261f3

deng.yinping 1 năm trước cách đây
mục cha
commit
fa4d77d43f

+ 2 - 2
config/config.xml

@@ -56,8 +56,8 @@
   </Tencent>
   <Asign>
     <Url value="https://oapi.asign.cn"/>
-    <AppId value="832360903"/>
-    <PrivateKey value="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCl+o3JA7u724TabBVR+cBuxbIaNOlW54fFDLqE6Kxm0Ym/2y3yZDVkcY9WTxXnvb1wRAzpyIneatZQ6hgqCVRsMZn3MZ9/6qpPApKufEN5TilCZ8+Og++fOLPODNQFDLfWHMKjZxmqWK8vOtEmneWn/JFwy1he2EBmXOYqyzu5FIKutOgLeEHoocdaNwtiaBhCulxEonze818q58TxLe1kcOBf9Dmk1BUOqDYxAY5FbqnDDVTKVTL9G8rw9XUJ0NO0hoqKKAciMgcV9epEN0/AQuir3rBrh1vXCf6mwVfYKFpqw+LJLv4WkOjai21xuiMYdU7Vibv95h862Aj8ovAfAgMBAAECggEBAIxrdgqrGueqpzH3IO5ygkf0/2HGg+afCLE/vIj3I+v0uDpVXwDjoHwyytZ1IA4n6x4QpHAg1esSrfBUrE7cB81lBWIpXExnJuCjR59Qx/DXnHZuxx1GJ7Kn0Q6wsar4AIunV0/QyNjiIIuvkgS+ru248v7fOgs7nvg6/gsUV5mTDppV6kf4lI14Mvpa7MIwKK2bB1zzLsWA7X9IuBS/QNxv+rRykc/uhZofDhWvaXbwGKxFf6unY2HwC3IFQONOdD6LlXyMdNT2pjMdPGdVu79eOC6wn2HBiIp7lXs08NqiL3oJ9Hh8+lqO0HVz5OMkpdaofXa7wDvZtdxGwsAlBokCgYEA5tgZWo/zK/u9GHCZrtwk9mP057BFy/83tl/c8ZmUT1CkyGx3/czVCvPZSjl6FBYWw6Bj1opwIBcQis83Kd7FHbVMgNDgg7Tyew+OAMUnM8GmWFHNQ/jA8Xe251yFOmoPwT/2MbGgwqmJjEtxD0zKPo8OVaK1odPZXN1g+KAjXjUCgYEAuBDkgrhpd8NrEa5OrxtiSipdgj8bmC7ET9xJVzFtoHFYybFCexQUA0z2NouA0GGw8qahOCx/a/CIP/hL1X3tZFUwuGjq3iSxBwhaM4aUPmDY1ratCCIxEQsl5eosGi54ltIVDE1yAgut3wMFP0YKM5ht/uBssPHrP7/gqdsGL4MCgYBcB0S8TO0F2Ns+9gzeoBcAP0MwZp68v+dnBnqfurlckWrQGCYSAWnhbutuYtGfVlsG7FdA/XnL4UYQAKIeSBhPSqrQI/WNrEKK+t2CwxZo1MfLJ/lsIqxQ14gMXl8itYvIYAZ3MzhCwrH6Q000a0mpfQCa9T3x4PIjyoHRPI49DQKBgBtZlzq9QB6lkOE9rz9hqEcw6FgUHHuOZ2keaF9mXs26SeEeT6yOHTMoWmVccTWFbo9/pvD726skQHqQ4GPGpGGGLwkXvd5oQU20NgL1+k0SguXUmv1cZ0ILEASLuSXixdRTPwFm+IvJRHqgrkTqmVV1TtLSchQQvk3oqu9SNicVAoGAYWga1T1D8MW0v7q2d05hJ3JqgHbAYZmKVxlR2Moh33fzV8CmusY3FhnbPQi8Lorj/CexjfXgvG+rZfa713qtJYLHWmJ7hQKwBQH9J0QPO3ffQyFAM1RjJyIvB9BPt8zN2QbujR4O6wXFee1zjKYgnuBAt7dBmE3O3nNdXAMa1g4="/>
+    <AppId value="964764021"/>
+    <PrivateKey value="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCS/rJCcUMRiWehBmmr1E2nAs6vB5YHb9BhmjxgyGZH2JcEIwtz7Qi46GL2iJlHVzPT0sB/Y5r7ssukCFP3PIIwdjO03i+QkuEHqNAzWmjbX7yr48pNFAxafA7bkctAMOd8bO3AAQrznRnFBn5rkv/FBPth1H393p0h+SNce9s6Sdntc//GFkQcT4qQLqi6H/prQ7tMO3HAEpRUORVWBAGpARg9cLmm6X1g6SE6YoGsr0pfhzn/clQ3xTDvnTTaipfl2bnHRnbUfC8j4zq1IYfD21oRxaY4bFWYdnquhsmv1U7jGR7G/WtCh76tNz4OlYl1DHWX498MvDmN/8++tWDjAgMBAAECggEAe3gEM1r/gtNvgAnq6LHDJ+1rvgkZM9Xvqovq+0BY6TA8aPUmwZDwKqDHv1ytowbUObBkkJwRqilcc8OrA5iHoj0m4V1fhohZDB34A6qFOP8Jczg6zNNyLO7XbAbiOmDZj+HPMd+uW0IySxRRS/qFa+/rVxktWviJ8+dYlG5UjngDvfVZbUHNdJWxk+cxU5YkaBKEfpJqs2sVIfFx0aQs0A+UmgAUwszmNAmtvu7y/kT0U9f1lbrze1Ndgg6S/JLjOmORFsbAgCm7NhAWG6yAMViyZ6R9dewqUwOJ214KDAeRREPp6mzvbPLbUg1imBEP5QU3YcEeCP01f3qpxukowQKBgQDJjHVxLRC/ynR3pXF/nYGY/aaNdLAKvWwQFLg/Xs1/Jes8GJ96/9A5VLq4h5pt5EhO0zsVy9S7D0FLSseswVKnRIfjahhiYLRiN9Of4Vgm81vQDduQyweFDh9yiorTerrrKcfFGuOwRKWZOdoxgjSUkRVq1c1G3jJGDmMniibSRwKBgQC6tS6EBQvwxs9mgbVvYISsN2AuPwN9mmpa9y99l5Iv+V+TjToXUJeH+j/i8pB8VrUZRS5MGE4zFCuIru9A1qIoctuMzQ2Ho/yAsTnsZd/LTVApPxLfZWMtLpFhzpoNmVwtuSUWCxZfnDZpb8Bcn3wKjVSgZaJe1z5Sm2cKV4POhQKBgE3TGL484ozMRjC1B6B5V0OWHivc9OUQw5tqBMMjfkIsiCrKbzp1cRfSKc97PRxV273kPppp/JjGiTXjiDqi46GHCtm7a/MA2GZcnDDOONXBfqBV2YSNgTfVfjsiV/zVFTwdA/COM4Eq4K7L8f7QAjGj3BtGt184CT2X7J2l8NudAoGADk6f9+HjHlo9vl8mJhjBUekUZ7bQb6mLiNj0PK2GuEJlvorN7sdwNS1KA/wOcli6m+sfNxmNtIBRLbIqB0/rMSpMBKgZ51D7omjyRVkxIwUTpXV93ryIMwgkf9gzGeOsmpxbaSsEVeNEkCPOG8rk2HIoD/p5zMa1seLSrIo0QXkCgYEAxme+IEcMPzQ/B9ZLdz5zj1W+p7FTK157CZrDlBrg2f+okf1dhItimB4uU7VPOPtH6aI21m7k0BSnuz1fGe8nf6oceMVowV7dXgjNcrPvWpYEY1Dp/w4YGeB7RpJBExUl6oOz6QOrezSBWEfCzy8TKBFFIDnahwken6aHyUTn3Rg="/>
     <NotifyUrl value="http://218.17.158.45:15105/api/Asign/HandleASignCompleted"/>
     <OpenApiUrl value="http://192.168.31.134:5015/mtp2-onlineopen"/>
   </Asign>

+ 38 - 1
config/readme.md

@@ -5,6 +5,7 @@
 开发文档:https://qian.tencent.com/developers/company/overview
 Enabled="1" 表示启用腾讯电子签功能,如不需要则改为"0"
 SecretId 和 SecretKey 是腾讯电子签密钥信息,使用公司账号登录(SaaS控制台) https://qian.tencent.com/console/ 获取 (微信扫码登录 测试环境:https://beta.qian.tencent.cn/console/)
+SecretId 和 SecretKey 实际上使用的是公司腾讯云的KEY,所以目前所有的正式环境都是一样的
 EndPoint 腾讯电子签API接入地址,测试环境填 "essbasic.test.ess.tencent.cn" ,生产环境填 "essbasic.tencentcloudapi.com"
 AppId 子客第三方应用ID,使用公司账号登录 https://qian.tencent.com/console/ 设置和获取
 创建子客通过我方接口来完成:Tencent/CreateConsoleLoginUrl (实盘环境初始化时要求使用公司法人微信扫码登录,并要求法人在控制台网站添加企业电子印章和法人章(法人章非必要)) 
@@ -13,6 +14,7 @@ ProxyOrganizationOpenId 子客企业ID,与子客企业名称一一对应,由
 ProxyOperatorOpenId 子客企业管理员ID,生产环境应要求客户使用对方身份进行认证,TJMD_ADMIN TJMD_LEGAL
 SignToken 腾讯电子签密回调通知Token,用于验签,使用公司账号登录 https://qian.tencent.com/console/ 设置和获取
 SignKey 腾讯电子签密回调通知密钥,用于解密,使用公司账号登录 https://qian.tencent.com/console/ 设置和获取
+指定回调地址样式:http://218.17.158.45:15160/api/Tencent/QianNotice
 
 ### 多元测试环境
 ```xml
@@ -59,6 +61,21 @@ SignKey 腾讯电子签密回调通知密钥,用于解密,使用公司账号
   <SignKey value="E7C6EA231F454BF1A5CF8C223D45C422"/>
 </Tencent>
 ```
+### 南海国际(海南丹农)正式环境
+```xml
+<Tencent>
+  <Enabled value="1"/>
+  <SecretId value="AKIDPktwvneP2WqxvmWFsMclmfLLKDyrbAXp"/>
+  <SecretKey value="GNH9tX8c6Wls02vhNzUvdLuGMYfeVErM"/>
+  <EndPoint value="essbasic.tencentcloudapi.com"/>
+  <AppId value="yDCWqUUg63lbs0UENeS7LSsrPRep9bLP"/>
+  <ProxyOrganizationName value="海南丹农商业管理有限公司"/>
+  <ProxyOrganizationOpenId value="NHGJ"/>
+  <ProxyOperatorOpenId value="NHGJ_LEGAL"/>
+  <SignToken value="1DB4705B05654E978D0A3108CA64BA91"/>
+  <SignKey value="4B223CB5F60146248D0A54B9974DF66A"/>
+</Tencent>
+```
 ---
 ## 爱签配置说明
 爱签官网:https://www.asign.cn
@@ -76,6 +93,9 @@ SignKey 腾讯电子签密回调通知密钥,用于解密,使用公司账号
 4、在“印章管理”中新增交易所默认印章;
 5、在“应用管理”中“签章权限”查看“无感知签章权限”是否已开通,如未开通则让交易所与爱签协商开通。
 
+注意事项:
+1、合同里的填充项一定要注意设置是“发起方填写”还是“接收方填写”;
+
 ### 多元测试环境
 ```xml
 <Asign>
@@ -93,7 +113,6 @@ zhou.xiaoning@muchinfo.cn
 Aa123456
 
 ### 中融测试环境
-爱签正式环境 zrwyt2023@163.com 密码 Zrwyt20231101
 爱签测试环境 zrwyt202302@163.com 密码 Zrwyt20231101
 ```xml
 <Asign>
@@ -105,6 +124,24 @@ Aa123456
 </Asign>
 ```
 
+### 中融生产环境
+爱签正式环境 zrwyt2023@163.com 密码 Zrwyt20231101
+# 公钥
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkv6yQnFDEYlnoQZpq9RNpwLOrweWB2/QYZo8YMhmR9iXBCMLc+0IuOhi9oiZR1cz09LAf2Oa+7LLpAhT9zyCMHYztN4vkJLhB6jQM1po21+8q+PKTRQMWnwO25HLQDDnfGztwAEK850ZxQZ+a5L/xQT7YdR9/d6dIfkjXHvbOknZ7XP/xhZEHE+KkC6ouh/6a0O7TDtxwBKUVDkVVgQBqQEYPXC5pul9YOkhOmKBrK9KX4c5/3JUN8Uw75002oqX5dm5x0Z21HwvI+M6tSGHw9taEcWmOGxVmHZ6robJr9VO4xkexv1rQoe+rTc+DpWJdQx1l+PfDLw5jf/PvrVg4wIDAQAB
+
+# 私钥
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCS/rJCcUMRiWehBmmr1E2nAs6vB5YHb9BhmjxgyGZH2JcEIwtz7Qi46GL2iJlHVzPT0sB/Y5r7ssukCFP3PIIwdjO03i+QkuEHqNAzWmjbX7yr48pNFAxafA7bkctAMOd8bO3AAQrznRnFBn5rkv/FBPth1H393p0h+SNce9s6Sdntc//GFkQcT4qQLqi6H/prQ7tMO3HAEpRUORVWBAGpARg9cLmm6X1g6SE6YoGsr0pfhzn/clQ3xTDvnTTaipfl2bnHRnbUfC8j4zq1IYfD21oRxaY4bFWYdnquhsmv1U7jGR7G/WtCh76tNz4OlYl1DHWX498MvDmN/8++tWDjAgMBAAECggEAe3gEM1r/gtNvgAnq6LHDJ+1rvgkZM9Xvqovq+0BY6TA8aPUmwZDwKqDHv1ytowbUObBkkJwRqilcc8OrA5iHoj0m4V1fhohZDB34A6qFOP8Jczg6zNNyLO7XbAbiOmDZj+HPMd+uW0IySxRRS/qFa+/rVxktWviJ8+dYlG5UjngDvfVZbUHNdJWxk+cxU5YkaBKEfpJqs2sVIfFx0aQs0A+UmgAUwszmNAmtvu7y/kT0U9f1lbrze1Ndgg6S/JLjOmORFsbAgCm7NhAWG6yAMViyZ6R9dewqUwOJ214KDAeRREPp6mzvbPLbUg1imBEP5QU3YcEeCP01f3qpxukowQKBgQDJjHVxLRC/ynR3pXF/nYGY/aaNdLAKvWwQFLg/Xs1/Jes8GJ96/9A5VLq4h5pt5EhO0zsVy9S7D0FLSseswVKnRIfjahhiYLRiN9Of4Vgm81vQDduQyweFDh9yiorTerrrKcfFGuOwRKWZOdoxgjSUkRVq1c1G3jJGDmMniibSRwKBgQC6tS6EBQvwxs9mgbVvYISsN2AuPwN9mmpa9y99l5Iv+V+TjToXUJeH+j/i8pB8VrUZRS5MGE4zFCuIru9A1qIoctuMzQ2Ho/yAsTnsZd/LTVApPxLfZWMtLpFhzpoNmVwtuSUWCxZfnDZpb8Bcn3wKjVSgZaJe1z5Sm2cKV4POhQKBgE3TGL484ozMRjC1B6B5V0OWHivc9OUQw5tqBMMjfkIsiCrKbzp1cRfSKc97PRxV273kPppp/JjGiTXjiDqi46GHCtm7a/MA2GZcnDDOONXBfqBV2YSNgTfVfjsiV/zVFTwdA/COM4Eq4K7L8f7QAjGj3BtGt184CT2X7J2l8NudAoGADk6f9+HjHlo9vl8mJhjBUekUZ7bQb6mLiNj0PK2GuEJlvorN7sdwNS1KA/wOcli6m+sfNxmNtIBRLbIqB0/rMSpMBKgZ51D7omjyRVkxIwUTpXV93ryIMwgkf9gzGeOsmpxbaSsEVeNEkCPOG8rk2HIoD/p5zMa1seLSrIo0QXkCgYEAxme+IEcMPzQ/B9ZLdz5zj1W+p7FTK157CZrDlBrg2f+okf1dhItimB4uU7VPOPtH6aI21m7k0BSnuz1fGe8nf6oceMVowV7dXgjNcrPvWpYEY1Dp/w4YGeB7RpJBExUl6oOz6QOrezSBWEfCzy8TKBFFIDnahwken6aHyUTn3Rg=
+```
+实盘配置
+```xml
+<Asign>
+  <Url value="https://oapi.asign.cn"/>
+  <AppId value="964764021"/>
+  <PrivateKey value="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCS/rJCcUMRiWehBmmr1E2nAs6vB5YHb9BhmjxgyGZH2JcEIwtz7Qi46GL2iJlHVzPT0sB/Y5r7ssukCFP3PIIwdjO03i+QkuEHqNAzWmjbX7yr48pNFAxafA7bkctAMOd8bO3AAQrznRnFBn5rkv/FBPth1H393p0h+SNce9s6Sdntc//GFkQcT4qQLqi6H/prQ7tMO3HAEpRUORVWBAGpARg9cLmm6X1g6SE6YoGsr0pfhzn/clQ3xTDvnTTaipfl2bnHRnbUfC8j4zq1IYfD21oRxaY4bFWYdnquhsmv1U7jGR7G/WtCh76tNz4OlYl1DHWX498MvDmN/8++tWDjAgMBAAECggEAe3gEM1r/gtNvgAnq6LHDJ+1rvgkZM9Xvqovq+0BY6TA8aPUmwZDwKqDHv1ytowbUObBkkJwRqilcc8OrA5iHoj0m4V1fhohZDB34A6qFOP8Jczg6zNNyLO7XbAbiOmDZj+HPMd+uW0IySxRRS/qFa+/rVxktWviJ8+dYlG5UjngDvfVZbUHNdJWxk+cxU5YkaBKEfpJqs2sVIfFx0aQs0A+UmgAUwszmNAmtvu7y/kT0U9f1lbrze1Ndgg6S/JLjOmORFsbAgCm7NhAWG6yAMViyZ6R9dewqUwOJ214KDAeRREPp6mzvbPLbUg1imBEP5QU3YcEeCP01f3qpxukowQKBgQDJjHVxLRC/ynR3pXF/nYGY/aaNdLAKvWwQFLg/Xs1/Jes8GJ96/9A5VLq4h5pt5EhO0zsVy9S7D0FLSseswVKnRIfjahhiYLRiN9Of4Vgm81vQDduQyweFDh9yiorTerrrKcfFGuOwRKWZOdoxgjSUkRVq1c1G3jJGDmMniibSRwKBgQC6tS6EBQvwxs9mgbVvYISsN2AuPwN9mmpa9y99l5Iv+V+TjToXUJeH+j/i8pB8VrUZRS5MGE4zFCuIru9A1qIoctuMzQ2Ho/yAsTnsZd/LTVApPxLfZWMtLpFhzpoNmVwtuSUWCxZfnDZpb8Bcn3wKjVSgZaJe1z5Sm2cKV4POhQKBgE3TGL484ozMRjC1B6B5V0OWHivc9OUQw5tqBMMjfkIsiCrKbzp1cRfSKc97PRxV273kPppp/JjGiTXjiDqi46GHCtm7a/MA2GZcnDDOONXBfqBV2YSNgTfVfjsiV/zVFTwdA/COM4Eq4K7L8f7QAjGj3BtGt184CT2X7J2l8NudAoGADk6f9+HjHlo9vl8mJhjBUekUZ7bQb6mLiNj0PK2GuEJlvorN7sdwNS1KA/wOcli6m+sfNxmNtIBRLbIqB0/rMSpMBKgZ51D7omjyRVkxIwUTpXV93ryIMwgkf9gzGeOsmpxbaSsEVeNEkCPOG8rk2HIoD/p5zMa1seLSrIo0QXkCgYEAxme+IEcMPzQ/B9ZLdz5zj1W+p7FTK157CZrDlBrg2f+okf1dhItimB4uU7VPOPtH6aI21m7k0BSnuz1fGe8nf6oceMVowV7dXgjNcrPvWpYEY1Dp/w4YGeB7RpJBExUl6oOz6QOrezSBWEfCzy8TKBFFIDnahwken6aHyUTn3Rg="/>
+  <NotifyUrl value="http://218.17.158.45:15105/api/Asign/HandleASignCompleted"/>
+  <OpenApiUrl value="http://192.168.31.134:5015/mtp2-onlineopen"/>
+</Asign>
+
 ### 贵茶2测试环境
 爱签测试环境地址:https://preweb.asign.cn/platform/openlogin    登陆帐号 : 155065880@qq.com   密码:Lv123456
 ```xml

+ 68 - 8
controllers/asign/test.go

@@ -1,6 +1,7 @@
 package asign
 
 import (
+	"io"
 	"mtp2_if/global/app"
 	"mtp2_if/global/e"
 	"mtp2_if/logger"
@@ -126,13 +127,13 @@ func TestAddEnterpriseUser(c *gin.Context) {
 
 // TestGetUser 获取用户信息(测试)
 // @Summary 获取用户信息(测试)
-// @Produce     json
-// @accept      application/json
+// @Produce json
+// @accept  application/json
 // @Param   data body     asignService.APIGetUserReq true "入参"
 // @Success 200  {object} asignService.APIGetUserReq
-// @Failure     500  {object} app.Response
+// @Failure 500  {object} app.Response
 // @Router  /Asign/TestGetUser [post]
-// @Tags        爱签
+// @Tags    爱签
 func TestGetUser(c *gin.Context) {
 	appG := app.Gin{C: c}
 
@@ -158,13 +159,13 @@ func TestGetUser(c *gin.Context) {
 
 // GetUserSeals 查询印章(测试)
 // @Summary 查询印章(测试)
-// @Produce     json
-// @accept      application/json
+// @Produce json
+// @accept  application/json
 // @Param   data body     asignService.APIGetUserSealsReq true "入参"
 // @Success 200  {object} asignService.APIGetUserSealsRsp
-// @Failure     500  {object} app.Response
+// @Failure 500  {object} app.Response
 // @Router  /Asign/GetUserSeals [post]
-// @Tags        爱签
+// @Tags    爱签
 func GetUserSeals(c *gin.Context) {
 	appG := app.Gin{C: c}
 
@@ -187,3 +188,62 @@ func GetUserSeals(c *gin.Context) {
 
 	appG.Response(http.StatusOK, e.SUCCESS, apiRsp)
 }
+
+// TestCreateContract 上传待签署文件(测试)
+// @Summary 上传待签署文件(测试)
+// @Produce     json
+// @accept      application/json
+// @Param   data body     asignService.APICreateContractReq true "入参"
+// @Success 200  {object} asignService.APICreateContractRsp
+// @Failure     500  {object} app.Response
+// @Router  /Asign/TestCreateContract [post]
+// @Tags        爱签
+func TestCreateContract(c *gin.Context) {
+	appG := app.Gin{C: c}
+
+	// 获取请求参数
+	var req asignService.APICreateContractReq
+	if err := appG.C.ShouldBindJSON(&req); err != nil {
+		logger.GetLogger().Errorf(err.Error())
+		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
+		return
+	}
+
+	r := asignService.APIReq[asignService.APICreateContractReq]{
+		Data: req,
+	}
+	apiRsp, err := asignService.APIPost[asignService.APICreateContractReq, asignService.APICreateContractRsp](r, asignService.APIURL_CreateContract)
+	if err != nil {
+		appG.ResponseByMsg(http.StatusBadRequest, e.ERROR, err.Error(), nil)
+		return
+	}
+
+	appG.Response(http.StatusOK, e.SUCCESS, apiRsp)
+}
+
+// TestAPI 文本入参(测试)
+// @Summary 文本入参(测试)
+// @Produce     json
+// @accept      application/json
+// @Param   data body     string true "入参"
+// @Success 200  {object} string
+// @Failure     500  {object} app.Response
+// @Router  /Asign/TestAPI [post]
+// @Tags        爱签
+func TestAPI(c *gin.Context) {
+	appG := app.Gin{C: c}
+
+	b, err := io.ReadAll(appG.C.Request.Body)
+	if err != nil {
+		appG.ResponseByMsg(http.StatusBadRequest, e.ERROR, err.Error(), nil)
+		return
+	}
+	req := string(b)
+	rspBody, err := asignService.TestAPI(req)
+	if err != nil {
+		appG.ResponseByMsg(http.StatusBadRequest, e.ERROR, err.Error(), nil)
+		return
+	}
+
+	appG.Response(http.StatusOK, e.SUCCESS, string(rspBody))
+}

+ 290 - 0
docs/docs.go

@@ -388,6 +388,45 @@ const docTemplate = `{
                 }
             }
         },
+        "/Asign/TestAPI": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "爱签"
+                ],
+                "summary": "文本入参(测试)",
+                "parameters": [
+                    {
+                        "description": "入参",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "string"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
         "/Asign/TestAddEnterpriseUser": {
             "post": {
                 "consumes": [
@@ -546,6 +585,45 @@ const docTemplate = `{
                 }
             }
         },
+        "/Asign/TestCreateContract": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "爱签"
+                ],
+                "summary": "上传待签署文件(测试)",
+                "parameters": [
+                    {
+                        "description": "入参",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/asign.APICreateContractReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/asign.APICreateContractRsp"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
         "/Asign/TestGetUser": {
             "post": {
                 "consumes": [
@@ -23637,6 +23715,164 @@ const docTemplate = `{
                 }
             }
         },
+        "asign.APIComponentData": {
+            "type": "object",
+            "required": [
+                "keyword",
+                "type"
+            ],
+            "properties": {
+                "defaultValue": {
+                    "description": "当填充类型为勾选(type=3)时填写: Yes:选中 Off:不选中",
+                    "type": "string"
+                },
+                "imageByte": {
+                    "description": "图片资源",
+                    "type": "array",
+                    "items": {
+                        "type": "integer"
+                    }
+                },
+                "keyword": {
+                    "description": "参数名称",
+                    "type": "string"
+                },
+                "options": {
+                    "description": "选项内容",
+                    "type": "object",
+                    "additionalProperties": true
+                },
+                "type": {
+                    "description": "组件类型: 2:单选 3:勾选 9:复选 11:图片",
+                    "type": "integer"
+                }
+            }
+        },
+        "asign.APICreateContractReq": {
+            "type": "object",
+            "required": [
+                "contractName",
+                "contractNo",
+                "signOrder"
+            ],
+            "properties": {
+                "autoContinue": {
+                    "description": "当前签署人签署完成自动跳转至下一签署人签署开关(仅对顺序签合同生效): 1 - 开启,0 - 关闭(默认)",
+                    "type": "integer"
+                },
+                "autoExpand": {
+                    "description": "多文件时,是否自动展开文件列表 1 - 展开, 0 - 不展开(默认)",
+                    "type": "integer"
+                },
+                "callbackUrl": {
+                    "description": "合同拒签或过期后(合同状态 status=3/4)回调通知地址,响应【\"ok\"】表示接收回调成功。",
+                    "type": "string"
+                },
+                "contractFiles": {
+                    "description": "合同附件(与合同模板必传其一)(支持多文件上传)",
+                    "type": "array",
+                    "items": {}
+                },
+                "contractName": {
+                    "description": "合同名称",
+                    "type": "string"
+                },
+                "contractNo": {
+                    "description": "合同ID,合同唯一编号",
+                    "type": "string"
+                },
+                "needAgree": {
+                    "description": "同意协议开关:(开启后表示必须同意协议才可签署合同) 1 - 开,0 - 关(默认)",
+                    "type": "integer"
+                },
+                "notifyUrl": {
+                    "description": "合同签署完成后(合同状态 status=2)回调通知地址,响应【\"ok\"】表示接收回调成功。",
+                    "type": "string"
+                },
+                "readSeconds": {
+                    "description": "强制阅读时间(秒)",
+                    "type": "integer"
+                },
+                "readType": {
+                    "description": "强制阅读设置 1:倒计时读秒方式 2:必须滑动到文件最底部(有多个文件务必逐个阅读) 3:必须点击打开查看(有多个文件务必逐个打开查看)【注】当readType不传值,仅readSeconds传值时,倒计时读秒是针对整体合同(不强制每个文件逐个阅读)。当readType传值1时,readSeconds也传值时,倒计时(要求每个文件逐个阅读)。当readType传值2或3时,readSeconds也传值时,倒计时读秒是针对整体合同(不强制每个文件逐个阅读)。",
+                    "type": "integer"
+                },
+                "redirectCompletedUrl": {
+                    "description": "合同发起页面完成后跳转url 若不为空,可以跳转业务方自己的前端过渡页面,实现业务方自己的逻辑。",
+                    "type": "string"
+                },
+                "redirectReturnUrl": {
+                    "description": "合同发起页面返回按钮跳转url 若不为空,可以跳转业务方自己的前端页面。",
+                    "type": "string"
+                },
+                "redirectUrl": {
+                    "description": "合同签署完成后同步回调地址: redirectUrl 若不为空,可以跳转业务方自己的前端过渡页面,实现业务方自己的逻辑。redirectUrl 为空,签署成功后,会回调小程序或app的方法。具体调用方法参考如下。",
+                    "type": "string"
+                },
+                "refuseOn": {
+                    "description": "合同签署页退回按钮开关: 1 - 开启,0 - 关闭(默认)",
+                    "type": "integer"
+                },
+                "signOrder": {
+                    "description": "签约方式 1:无序签约(默认) 2:顺序签约",
+                    "type": "integer"
+                },
+                "templates": {
+                    "description": "合同模板列表(与合同附件必传其一)",
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/asign.APITemplate"
+                    }
+                },
+                "userNotifyUrl": {
+                    "description": "某个用户签署完成(用户签署状态 signStatus=2,参考 查询合同信息接口)之后回调地址,响应【\"ok\"】表示接收回调成功。",
+                    "type": "string"
+                },
+                "validityDate": {
+                    "description": "合同有效截止日期(在此日期之前可以签署合同,格式要求:yyyyMMddHHmmss),【注】与合同有效天数必传其一,【例】传值“20231207190000” 为:2023年12月07日19时00分00秒",
+                    "type": "string"
+                },
+                "validityTime": {
+                    "description": "合同签署剩余天数(系统当前时间+该天数=在此日期之前可以签署合同日期),【注】与合同有效截止日期必传其一,【例】可传剩余天数:15",
+                    "type": "integer"
+                },
+                "viewFlg": {
+                    "description": "合同签署完是否允许可以通过链接查看合同内容: 1:不允许查看 不传值:可以查看(默认)",
+                    "type": "integer"
+                }
+            }
+        },
+        "asign.APICreateContractRsp": {
+            "type": "object",
+            "properties": {
+                "contractFiles": {
+                    "description": "合同文件信息(文件名称,附件编号,页数)",
+                    "type": "array",
+                    "items": {}
+                },
+                "previewUrl": {
+                    "description": "合同预览链接(预览链接3小时内有效,过期后可通过查询合同信息接口重新获取)",
+                    "type": "string"
+                }
+            }
+        },
+        "asign.APIFillData": {
+            "type": "object",
+            "required": [
+                "dataKey",
+                "value"
+            ],
+            "properties": {
+                "dataKey": {
+                    "description": "参数名称",
+                    "type": "string"
+                },
+                "value": {
+                    "description": "填充值",
+                    "type": "string"
+                }
+            }
+        },
         "asign.APIGetUserReq": {
             "type": "object",
             "properties": {
@@ -23723,6 +23959,60 @@ const docTemplate = `{
                 }
             }
         },
+        "asign.APITemplate": {
+            "type": "object",
+            "required": [
+                "templateNo"
+            ],
+            "properties": {
+                "componentData": {
+                    "description": "单选、复选、勾选、图片类型参数填充",
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/asign.APIComponentData"
+                    }
+                },
+                "contractNo": {
+                    "description": "合同编号(此处可传已完成签署的合同编号,实现追加签章的场景)",
+                    "type": "string"
+                },
+                "fillData": {
+                    "description": "单行文本、多行文本、日期、身份证类型参数填充。",
+                    "$ref": "#/definitions/asign.APIFillData"
+                },
+                "tableDatas": {
+                    "description": "表格填充数据",
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/asign.APItableData"
+                    }
+                },
+                "templateNo": {
+                    "description": "合同模板编号",
+                    "type": "string"
+                }
+            }
+        },
+        "asign.APItableData": {
+            "type": "object",
+            "required": [
+                "keyword"
+            ],
+            "properties": {
+                "keyword": {
+                    "description": "表名称",
+                    "type": "string"
+                },
+                "rowValues": {
+                    "description": "表格填充值",
+                    "type": "array",
+                    "items": {
+                        "type": "object",
+                        "additionalProperties": true
+                    }
+                }
+            }
+        },
         "asign.BankCard4Req": {
             "type": "object",
             "required": [

+ 290 - 0
docs/swagger.json

@@ -379,6 +379,45 @@
                 }
             }
         },
+        "/Asign/TestAPI": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "爱签"
+                ],
+                "summary": "文本入参(测试)",
+                "parameters": [
+                    {
+                        "description": "入参",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "string"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
         "/Asign/TestAddEnterpriseUser": {
             "post": {
                 "consumes": [
@@ -537,6 +576,45 @@
                 }
             }
         },
+        "/Asign/TestCreateContract": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "爱签"
+                ],
+                "summary": "上传待签署文件(测试)",
+                "parameters": [
+                    {
+                        "description": "入参",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/asign.APICreateContractReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/asign.APICreateContractRsp"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
         "/Asign/TestGetUser": {
             "post": {
                 "consumes": [
@@ -23628,6 +23706,164 @@
                 }
             }
         },
+        "asign.APIComponentData": {
+            "type": "object",
+            "required": [
+                "keyword",
+                "type"
+            ],
+            "properties": {
+                "defaultValue": {
+                    "description": "当填充类型为勾选(type=3)时填写: Yes:选中 Off:不选中",
+                    "type": "string"
+                },
+                "imageByte": {
+                    "description": "图片资源",
+                    "type": "array",
+                    "items": {
+                        "type": "integer"
+                    }
+                },
+                "keyword": {
+                    "description": "参数名称",
+                    "type": "string"
+                },
+                "options": {
+                    "description": "选项内容",
+                    "type": "object",
+                    "additionalProperties": true
+                },
+                "type": {
+                    "description": "组件类型: 2:单选 3:勾选 9:复选 11:图片",
+                    "type": "integer"
+                }
+            }
+        },
+        "asign.APICreateContractReq": {
+            "type": "object",
+            "required": [
+                "contractName",
+                "contractNo",
+                "signOrder"
+            ],
+            "properties": {
+                "autoContinue": {
+                    "description": "当前签署人签署完成自动跳转至下一签署人签署开关(仅对顺序签合同生效): 1 - 开启,0 - 关闭(默认)",
+                    "type": "integer"
+                },
+                "autoExpand": {
+                    "description": "多文件时,是否自动展开文件列表 1 - 展开, 0 - 不展开(默认)",
+                    "type": "integer"
+                },
+                "callbackUrl": {
+                    "description": "合同拒签或过期后(合同状态 status=3/4)回调通知地址,响应【\"ok\"】表示接收回调成功。",
+                    "type": "string"
+                },
+                "contractFiles": {
+                    "description": "合同附件(与合同模板必传其一)(支持多文件上传)",
+                    "type": "array",
+                    "items": {}
+                },
+                "contractName": {
+                    "description": "合同名称",
+                    "type": "string"
+                },
+                "contractNo": {
+                    "description": "合同ID,合同唯一编号",
+                    "type": "string"
+                },
+                "needAgree": {
+                    "description": "同意协议开关:(开启后表示必须同意协议才可签署合同) 1 - 开,0 - 关(默认)",
+                    "type": "integer"
+                },
+                "notifyUrl": {
+                    "description": "合同签署完成后(合同状态 status=2)回调通知地址,响应【\"ok\"】表示接收回调成功。",
+                    "type": "string"
+                },
+                "readSeconds": {
+                    "description": "强制阅读时间(秒)",
+                    "type": "integer"
+                },
+                "readType": {
+                    "description": "强制阅读设置 1:倒计时读秒方式 2:必须滑动到文件最底部(有多个文件务必逐个阅读) 3:必须点击打开查看(有多个文件务必逐个打开查看)【注】当readType不传值,仅readSeconds传值时,倒计时读秒是针对整体合同(不强制每个文件逐个阅读)。当readType传值1时,readSeconds也传值时,倒计时(要求每个文件逐个阅读)。当readType传值2或3时,readSeconds也传值时,倒计时读秒是针对整体合同(不强制每个文件逐个阅读)。",
+                    "type": "integer"
+                },
+                "redirectCompletedUrl": {
+                    "description": "合同发起页面完成后跳转url 若不为空,可以跳转业务方自己的前端过渡页面,实现业务方自己的逻辑。",
+                    "type": "string"
+                },
+                "redirectReturnUrl": {
+                    "description": "合同发起页面返回按钮跳转url 若不为空,可以跳转业务方自己的前端页面。",
+                    "type": "string"
+                },
+                "redirectUrl": {
+                    "description": "合同签署完成后同步回调地址: redirectUrl 若不为空,可以跳转业务方自己的前端过渡页面,实现业务方自己的逻辑。redirectUrl 为空,签署成功后,会回调小程序或app的方法。具体调用方法参考如下。",
+                    "type": "string"
+                },
+                "refuseOn": {
+                    "description": "合同签署页退回按钮开关: 1 - 开启,0 - 关闭(默认)",
+                    "type": "integer"
+                },
+                "signOrder": {
+                    "description": "签约方式 1:无序签约(默认) 2:顺序签约",
+                    "type": "integer"
+                },
+                "templates": {
+                    "description": "合同模板列表(与合同附件必传其一)",
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/asign.APITemplate"
+                    }
+                },
+                "userNotifyUrl": {
+                    "description": "某个用户签署完成(用户签署状态 signStatus=2,参考 查询合同信息接口)之后回调地址,响应【\"ok\"】表示接收回调成功。",
+                    "type": "string"
+                },
+                "validityDate": {
+                    "description": "合同有效截止日期(在此日期之前可以签署合同,格式要求:yyyyMMddHHmmss),【注】与合同有效天数必传其一,【例】传值“20231207190000” 为:2023年12月07日19时00分00秒",
+                    "type": "string"
+                },
+                "validityTime": {
+                    "description": "合同签署剩余天数(系统当前时间+该天数=在此日期之前可以签署合同日期),【注】与合同有效截止日期必传其一,【例】可传剩余天数:15",
+                    "type": "integer"
+                },
+                "viewFlg": {
+                    "description": "合同签署完是否允许可以通过链接查看合同内容: 1:不允许查看 不传值:可以查看(默认)",
+                    "type": "integer"
+                }
+            }
+        },
+        "asign.APICreateContractRsp": {
+            "type": "object",
+            "properties": {
+                "contractFiles": {
+                    "description": "合同文件信息(文件名称,附件编号,页数)",
+                    "type": "array",
+                    "items": {}
+                },
+                "previewUrl": {
+                    "description": "合同预览链接(预览链接3小时内有效,过期后可通过查询合同信息接口重新获取)",
+                    "type": "string"
+                }
+            }
+        },
+        "asign.APIFillData": {
+            "type": "object",
+            "required": [
+                "dataKey",
+                "value"
+            ],
+            "properties": {
+                "dataKey": {
+                    "description": "参数名称",
+                    "type": "string"
+                },
+                "value": {
+                    "description": "填充值",
+                    "type": "string"
+                }
+            }
+        },
         "asign.APIGetUserReq": {
             "type": "object",
             "properties": {
@@ -23714,6 +23950,60 @@
                 }
             }
         },
+        "asign.APITemplate": {
+            "type": "object",
+            "required": [
+                "templateNo"
+            ],
+            "properties": {
+                "componentData": {
+                    "description": "单选、复选、勾选、图片类型参数填充",
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/asign.APIComponentData"
+                    }
+                },
+                "contractNo": {
+                    "description": "合同编号(此处可传已完成签署的合同编号,实现追加签章的场景)",
+                    "type": "string"
+                },
+                "fillData": {
+                    "description": "单行文本、多行文本、日期、身份证类型参数填充。",
+                    "$ref": "#/definitions/asign.APIFillData"
+                },
+                "tableDatas": {
+                    "description": "表格填充数据",
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/asign.APItableData"
+                    }
+                },
+                "templateNo": {
+                    "description": "合同模板编号",
+                    "type": "string"
+                }
+            }
+        },
+        "asign.APItableData": {
+            "type": "object",
+            "required": [
+                "keyword"
+            ],
+            "properties": {
+                "keyword": {
+                    "description": "表名称",
+                    "type": "string"
+                },
+                "rowValues": {
+                    "description": "表格填充值",
+                    "type": "array",
+                    "items": {
+                        "type": "object",
+                        "additionalProperties": true
+                    }
+                }
+            }
+        },
         "asign.BankCard4Req": {
             "type": "object",
             "required": [

+ 206 - 0
docs/swagger.yaml

@@ -143,6 +143,124 @@ definitions:
     - mobile
     - realName
     type: object
+  asign.APIComponentData:
+    properties:
+      defaultValue:
+        description: 当填充类型为勾选(type=3)时填写: Yes:选中 Off:不选中
+        type: string
+      imageByte:
+        description: 图片资源
+        items:
+          type: integer
+        type: array
+      keyword:
+        description: 参数名称
+        type: string
+      options:
+        additionalProperties: true
+        description: 选项内容
+        type: object
+      type:
+        description: 组件类型: 2:单选 3:勾选 9:复选 11:图片
+        type: integer
+    required:
+    - keyword
+    - type
+    type: object
+  asign.APICreateContractReq:
+    properties:
+      autoContinue:
+        description: '当前签署人签署完成自动跳转至下一签署人签署开关(仅对顺序签合同生效): 1 - 开启,0 - 关闭(默认)'
+        type: integer
+      autoExpand:
+        description: 多文件时,是否自动展开文件列表 1 - 展开, 0 - 不展开(默认)
+        type: integer
+      callbackUrl:
+        description: 合同拒签或过期后(合同状态 status=3/4)回调通知地址,响应【"ok"】表示接收回调成功。
+        type: string
+      contractFiles:
+        description: 合同附件(与合同模板必传其一)(支持多文件上传)
+        items: {}
+        type: array
+      contractName:
+        description: 合同名称
+        type: string
+      contractNo:
+        description: 合同ID,合同唯一编号
+        type: string
+      needAgree:
+        description: 同意协议开关:(开启后表示必须同意协议才可签署合同) 1 - 开,0 - 关(默认)
+        type: integer
+      notifyUrl:
+        description: 合同签署完成后(合同状态 status=2)回调通知地址,响应【"ok"】表示接收回调成功。
+        type: string
+      readSeconds:
+        description: 强制阅读时间(秒)
+        type: integer
+      readType:
+        description: 强制阅读设置 1:倒计时读秒方式 2:必须滑动到文件最底部(有多个文件务必逐个阅读) 3:必须点击打开查看(有多个文件务必逐个打开查看)【注】当readType不传值,仅readSeconds传值时,倒计时读秒是针对整体合同(不强制每个文件逐个阅读)。当readType传值1时,readSeconds也传值时,倒计时(要求每个文件逐个阅读)。当readType传值2或3时,readSeconds也传值时,倒计时读秒是针对整体合同(不强制每个文件逐个阅读)。
+        type: integer
+      redirectCompletedUrl:
+        description: 合同发起页面完成后跳转url 若不为空,可以跳转业务方自己的前端过渡页面,实现业务方自己的逻辑。
+        type: string
+      redirectReturnUrl:
+        description: 合同发起页面返回按钮跳转url 若不为空,可以跳转业务方自己的前端页面。
+        type: string
+      redirectUrl:
+        description: 合同签署完成后同步回调地址: redirectUrl 若不为空,可以跳转业务方自己的前端过渡页面,实现业务方自己的逻辑。redirectUrl
+          为空,签署成功后,会回调小程序或app的方法。具体调用方法参考如下。
+        type: string
+      refuseOn:
+        description: 合同签署页退回按钮开关: 1 - 开启,0 - 关闭(默认)
+        type: integer
+      signOrder:
+        description: 签约方式 1:无序签约(默认) 2:顺序签约
+        type: integer
+      templates:
+        description: 合同模板列表(与合同附件必传其一)
+        items:
+          $ref: '#/definitions/asign.APITemplate'
+        type: array
+      userNotifyUrl:
+        description: 某个用户签署完成(用户签署状态 signStatus=2,参考 查询合同信息接口)之后回调地址,响应【"ok"】表示接收回调成功。
+        type: string
+      validityDate:
+        description: 合同有效截止日期(在此日期之前可以签署合同,格式要求:yyyyMMddHHmmss),【注】与合同有效天数必传其一,【例】传值“20231207190000”
+          为:2023年12月07日19时00分00秒
+        type: string
+      validityTime:
+        description: 合同签署剩余天数(系统当前时间+该天数=在此日期之前可以签署合同日期),【注】与合同有效截止日期必传其一,【例】可传剩余天数:15
+        type: integer
+      viewFlg:
+        description: '合同签署完是否允许可以通过链接查看合同内容: 1:不允许查看 不传值:可以查看(默认)'
+        type: integer
+    required:
+    - contractName
+    - contractNo
+    - signOrder
+    type: object
+  asign.APICreateContractRsp:
+    properties:
+      contractFiles:
+        description: 合同文件信息(文件名称,附件编号,页数)
+        items: {}
+        type: array
+      previewUrl:
+        description: 合同预览链接(预览链接3小时内有效,过期后可通过查询合同信息接口重新获取)
+        type: string
+    type: object
+  asign.APIFillData:
+    properties:
+      dataKey:
+        description: 参数名称
+        type: string
+      value:
+        description: 填充值
+        type: string
+    required:
+    - dataKey
+    - value
+    type: object
   asign.APIGetUserReq:
     properties:
       account:
@@ -204,6 +322,44 @@ definitions:
         description: 印章图片访问地址(当印章还在做成中时,此值为空)
         type: string
     type: object
+  asign.APITemplate:
+    properties:
+      componentData:
+        description: 单选、复选、勾选、图片类型参数填充
+        items:
+          $ref: '#/definitions/asign.APIComponentData'
+        type: array
+      contractNo:
+        description: 合同编号(此处可传已完成签署的合同编号,实现追加签章的场景)
+        type: string
+      fillData:
+        $ref: '#/definitions/asign.APIFillData'
+        description: 单行文本、多行文本、日期、身份证类型参数填充。
+      tableDatas:
+        description: 表格填充数据
+        items:
+          $ref: '#/definitions/asign.APItableData'
+        type: array
+      templateNo:
+        description: 合同模板编号
+        type: string
+    required:
+    - templateNo
+    type: object
+  asign.APItableData:
+    properties:
+      keyword:
+        description: 表名称
+        type: string
+      rowValues:
+        description: 表格填充值
+        items:
+          additionalProperties: true
+          type: object
+        type: array
+    required:
+    - keyword
+    type: object
   asign.BankCard4Req:
     properties:
       company:
@@ -31489,6 +31645,31 @@ paths:
       summary: 同步合同状态
       tags:
       - 爱签
+  /Asign/TestAPI:
+    post:
+      consumes:
+      - application/json
+      parameters:
+      - description: 入参
+        in: body
+        name: data
+        required: true
+        schema:
+          type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            type: string
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/app.Response'
+      summary: 文本入参(测试)
+      tags:
+      - 爱签
   /Asign/TestAddEnterpriseUser:
     post:
       consumes:
@@ -31591,6 +31772,31 @@ paths:
       summary: 认证验证码校验(测试)
       tags:
       - 爱签
+  /Asign/TestCreateContract:
+    post:
+      consumes:
+      - application/json
+      parameters:
+      - description: 入参
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/asign.APICreateContractReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/asign.APICreateContractRsp'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/app.Response'
+      summary: 上传待签署文件(测试)
+      tags:
+      - 爱签
   /Asign/TestGetUser:
     post:
       consumes:

+ 12 - 7
routers/router.go

@@ -855,13 +855,18 @@ func InitRouter() *gin.Engine {
 		asignR.Use().POST("SyncContractStatus", asign.SyncContractStatus)
 		asignR.Use().POST("HandleASignCompleted", asign.HandleASignCompleted)
 
-		asignR.Use().POST("TestBankCard4", asign.TestBankCard4)
-		asignR.Use().POST("TestCaptcaResend", asign.TestCaptcaResend)
-		asignR.Use().POST("TestCaptchaVerify", asign.TestCaptchaVerify)
-		asignR.Use().POST("TestAddEnterpriseUser", asign.TestAddEnterpriseUser)
-		asignR.Use().POST("TestGetUser", asign.TestGetUser)
-		asignR.Use().POST("CreateSeal", asign.CreateSeal)
-		asignR.Use().POST("GetUserSeals", asign.GetUserSeals)
+		if config.SerCfg.GetDebugMode() {
+			asignR.Use().POST("CreateSeal", asign.CreateSeal)
+			asignR.Use().POST("GetUserSeals", asign.GetUserSeals)
+			asignR.Use().POST("TestBankCard4", asign.TestBankCard4)
+			asignR.Use().POST("TestCaptcaResend", asign.TestCaptcaResend)
+			asignR.Use().POST("TestCaptchaVerify", asign.TestCaptchaVerify)
+			asignR.Use().POST("TestAddEnterpriseUser", asign.TestAddEnterpriseUser)
+			asignR.Use().POST("TestGetUser", asign.TestGetUser)
+			asignR.Use().POST("TestCreateContract", asign.TestCreateContract)
+
+			asignR.Use().POST("TestAPI", asign.TestAPI)
+		}
 
 		asignR.Use(token.Auth()).POST("BankCard4", asign.BankCard4)
 		asignR.Use(token.Auth()).POST("CaptcaResend", asign.CaptcaResend)

+ 29 - 24
services/asign/api.go

@@ -31,8 +31,30 @@ import (
 func APIPost[T_REQ APIReqData, T_RSP APIRspData](req APIReq[T_REQ], apiPort APIURL) (rsp *APIRsp[T_RSP], err error) {
 	apiUrl := config.SerCfg.AsignCfg.Url + string(apiPort)
 
+	// 排序key
+	// var b []byte
+	var sortedData string
+	if len(req.Datas) == 0 {
+		sortedData = SortMapByKey(structs.Map(req.Data))
+	} else {
+		sortedData = "["
+		for i, item := range req.Datas {
+			if i > 0 {
+				sortedData += ","
+			}
+			sortedData += SortMapByKey(structs.Map(item))
+		}
+		sortedData += "]"
+	}
+	logger.GetLogger().Debug("sortedData: " + sortedData)
+	if err != nil {
+		logger.GetLogger().Errorf("处理入参排序失败:" + err.Error())
+		return
+	}
+
+	// 调用接口
 	var rspBody []byte
-	rspBody, err = httpPost(apiUrl, req.Data)
+	rspBody, err = httpPost(apiUrl, sortedData)
 	if err != nil {
 		return
 	}
@@ -48,35 +70,18 @@ func APIPost[T_REQ APIReqData, T_RSP APIRspData](req APIReq[T_REQ], apiPort APIU
 	return
 }
 
-func httpPost(apiUrl string, bizData ...interface{}) (rspBody []byte, err error) {
+func TestHttpPost(apiUrl string, sortedData string) (rspBody []byte, err error) {
+	apiUrl = config.SerCfg.AsignCfg.Url + string(apiUrl)
+	return httpPost(apiUrl, sortedData)
+}
+
+func httpPost(apiUrl string, sortedData string) (rspBody []byte, err error) {
 	appId := config.SerCfg.AsignCfg.AppId
 	privateKey := fmt.Sprintf("-----BEGIN PRIVATE KEY-----\n%s\n-----END PRIVATE KEY-----", config.SerCfg.AsignCfg.PrivateKey)
 
 	// fuck asign dev.
 	timestamp := strconv.Itoa(int(time.Now().UnixMilli() + 10000*60))
 
-	// 排序key
-	// var b []byte
-	var sortedData string
-	if len(bizData) == 1 {
-		// b, err = encoder.Encode(bizData[0], encoder.SortMapKeys)
-		sortedData = SortMapByKey(structs.Map(bizData[0]))
-	} else {
-		// b, err = encoder.Encode(bizData, encoder.SortMapKeys)
-		sortedData := "["
-		for i, item := range bizData {
-			if i > 0 {
-				sortedData += ","
-			}
-			sortedData += SortMapByKey(structs.Map(item))
-		}
-		sortedData += "]"
-	}
-	if err != nil {
-		logger.GetLogger().Errorf("处理入参排序失败:" + err.Error())
-		return
-	}
-	// sortedData := string(b)
 	// 签名
 	signature, err := getSignature(sortedData, appId, timestamp, privateKey)
 	if err != nil {

+ 57 - 57
services/asign/apiModels.go

@@ -1,8 +1,7 @@
 package asign
 
 type APIReqData interface {
-	interface{} |
-		APIPersonBankCard4Req |
+	APIPersonBankCard4Req |
 		APICompanyBankCard4Req |
 		APICaptchaResendReq |
 		APICaptchaVerifyReq |
@@ -20,7 +19,8 @@ type APIReqData interface {
 }
 
 type APIReq[T APIReqData] struct {
-	Data T // 请求数据
+	Data  T   // 请求数据
+	Datas []T // 请求数据,切片类型
 }
 
 type APIRspData interface {
@@ -210,26 +210,26 @@ type APITemplate struct {
 //
 // 参数说明:https://preweb.asign.cn/platform/openDoc/docDetail?mid=createContract
 type APICreateContractReq struct {
-	ContractNo           string        `json:"contractNo" binding:"required"`             // 合同ID,合同唯一编号
-	ContractName         string        `json:"contractName" binding:"required"`           // 合同名称
-	ValidityTime         int           `json:"validityTime" structs:",omitempty"`         // 合同签署剩余天数(系统当前时间+该天数=在此日期之前可以签署合同日期),【注】与合同有效截止日期必传其一,【例】可传剩余天数:15
-	ValidityDate         string        `json:"validityDate" structs:",omitempty"`         // 合同有效截止日期(在此日期之前可以签署合同,格式要求:yyyyMMddHHmmss),【注】与合同有效天数必传其一,【例】传值“20231207190000” 为:2023年12月07日19时00分00秒
-	SignOrder            int           `json:"signOrder" binding:"required"`              // 签约方式 1:无序签约(默认) 2:顺序签约
-	ReadSeconds          int           `json:"readSeconds" structs:",omitempty"`          // 强制阅读时间(秒)
-	ReadType             int           `json:"readType" structs:",omitempty"`             // 强制阅读设置 1:倒计时读秒方式 2:必须滑动到文件最底部(有多个文件务必逐个阅读) 3:必须点击打开查看(有多个文件务必逐个打开查看)【注】当readType不传值,仅readSeconds传值时,倒计时读秒是针对整体合同(不强制每个文件逐个阅读)。当readType传值1时,readSeconds也传值时,倒计时(要求每个文件逐个阅读)。当readType传值2或3时,readSeconds也传值时,倒计时读秒是针对整体合同(不强制每个文件逐个阅读)。
-	NeedAgree            int           `json:"needAgree" structs:",omitempty"`            // 同意协议开关:(开启后表示必须同意协议才可签署合同) 1 - 开,0 - 关(默认)
-	AutoExpand           int           `json:"autoExpand" structs:",omitempty"`           // 多文件时,是否自动展开文件列表 1 - 展开, 0 - 不展开(默认)
-	NotifyUrl            string        `json:"notifyUrl" structs:",omitempty"`            // 合同签署完成后(合同状态 status=2)回调通知地址,响应【"ok"】表示接收回调成功。
-	CallbackUrl          string        `json:"callbackUrl" structs:",omitempty"`          // 合同拒签或过期后(合同状态 status=3/4)回调通知地址,响应【"ok"】表示接收回调成功。
-	UserNotifyUrl        string        `json:"userNotifyUrl" structs:",omitempty"`        // 某个用户签署完成(用户签署状态 signStatus=2,参考 查询合同信息接口)之后回调地址,响应【"ok"】表示接收回调成功。
-	RedirectUrl          string        `json:"redirectUrl" structs:",omitempty"`          // 合同签署完成后同步回调地址: redirectUrl 若不为空,可以跳转业务方自己的前端过渡页面,实现业务方自己的逻辑。redirectUrl 为空,签署成功后,会回调小程序或app的方法。具体调用方法参考如下。
-	RefuseOn             int           `json:"refuseOn" structs:",omitempty"`             // 合同签署页退回按钮开关: 1 - 开启,0 - 关闭(默认)
-	AutoContinue         int           `json:"autoContinue" structs:",omitempty"`         // 当前签署人签署完成自动跳转至下一签署人签署开关(仅对顺序签合同生效): 1 - 开启,0 - 关闭(默认)
-	ViewFlg              int           `json:"viewFlg" structs:",omitempty"`              // 合同签署完是否允许可以通过链接查看合同内容: 1:不允许查看 不传值:可以查看(默认)
-	RedirectReturnUrl    string        `json:"redirectReturnUrl" structs:",omitempty"`    // 合同发起页面返回按钮跳转url 若不为空,可以跳转业务方自己的前端页面。
-	RedirectCompletedUrl string        `json:"redirectCompletedUrl" structs:",omitempty"` // 合同发起页面完成后跳转url 若不为空,可以跳转业务方自己的前端过渡页面,实现业务方自己的逻辑。
-	ContractFiles        []interface{} `json:"contractFiles" structs:",omitempty"`        // 合同附件(与合同模板必传其一)(支持多文件上传)
-	Templates            []APITemplate `json:"templates" structs:",omitempty"`            // 合同模板列表(与合同附件必传其一)
+	ContractNo           string        `json:"contractNo" structs:"contractNo" binding:"required"`            // 合同ID,合同唯一编号
+	ContractName         string        `json:"contractName" structs:"contractName" binding:"required"`        // 合同名称
+	ValidityTime         int           `json:"validityTime" structs:"validityTime,omitempty"`                 // 合同签署剩余天数(系统当前时间+该天数=在此日期之前可以签署合同日期),【注】与合同有效截止日期必传其一,【例】可传剩余天数:15
+	ValidityDate         string        `json:"validityDate" structs:"validityDate,omitempty"`                 // 合同有效截止日期(在此日期之前可以签署合同,格式要求:yyyyMMddHHmmss),【注】与合同有效天数必传其一,【例】传值“20231207190000” 为:2023年12月07日19时00分00秒
+	SignOrder            int           `json:"signOrder" structs:"signOrder" binding:"required"`              // 签约方式 1:无序签约(默认) 2:顺序签约
+	ReadSeconds          int           `json:"readSeconds" structs:"readSeconds,omitempty"`                   // 强制阅读时间(秒)
+	ReadType             int           `json:"readType" structs:"readType,omitempty"`                         // 强制阅读设置 1:倒计时读秒方式 2:必须滑动到文件最底部(有多个文件务必逐个阅读) 3:必须点击打开查看(有多个文件务必逐个打开查看)【注】当readType不传值,仅readSeconds传值时,倒计时读秒是针对整体合同(不强制每个文件逐个阅读)。当readType传值1时,readSeconds也传值时,倒计时(要求每个文件逐个阅读)。当readType传值2或3时,readSeconds也传值时,倒计时读秒是针对整体合同(不强制每个文件逐个阅读)。
+	NeedAgree            int           `json:"needAgree" structs:"needAgree,omitempty"`                       // 同意协议开关:(开启后表示必须同意协议才可签署合同) 1 - 开,0 - 关(默认)
+	AutoExpand           int           `json:"autoExpand" structs:"autoExpand,omitempty"`                     // 多文件时,是否自动展开文件列表 1 - 展开, 0 - 不展开(默认)
+	NotifyUrl            string        `json:"notifyUrl" structs:"notifyUrl,omitempty"`                       // 合同签署完成后(合同状态 status=2)回调通知地址,响应【"ok"】表示接收回调成功。
+	CallbackUrl          string        `json:"callbackUrl" structs:"callbackUrl,omitempty"`                   // 合同拒签或过期后(合同状态 status=3/4)回调通知地址,响应【"ok"】表示接收回调成功。
+	UserNotifyUrl        string        `json:"userNotifyUrl" structs:"userNotifyUrl,omitempty"`               // 某个用户签署完成(用户签署状态 signStatus=2,参考 查询合同信息接口)之后回调地址,响应【"ok"】表示接收回调成功。
+	RedirectUrl          string        `json:"redirectUrl" structs:"redirectUrl,omitempty"`                   // 合同签署完成后同步回调地址: redirectUrl 若不为空,可以跳转业务方自己的前端过渡页面,实现业务方自己的逻辑。redirectUrl 为空,签署成功后,会回调小程序或app的方法。具体调用方法参考如下。
+	RefuseOn             int           `json:"refuseOn" structs:"refuseOn,omitempty"`                         // 合同签署页退回按钮开关: 1 - 开启,0 - 关闭(默认)
+	AutoContinue         int           `json:"autoContinue" structs:"autoContinue,omitempty"`                 // 当前签署人签署完成自动跳转至下一签署人签署开关(仅对顺序签合同生效): 1 - 开启,0 - 关闭(默认)
+	ViewFlg              int           `json:"viewFlg" structs:"viewFlg,omitempty"`                           // 合同签署完是否允许可以通过链接查看合同内容: 1:不允许查看 不传值:可以查看(默认)
+	RedirectReturnUrl    string        `json:"redirectReturnUrl" structs:"redirectReturnUrl,omitempty"`       // 合同发起页面返回按钮跳转url 若不为空,可以跳转业务方自己的前端页面。
+	RedirectCompletedUrl string        `json:"redirectCompletedUrl" structs:"redirectCompletedUrl,omitempty"` // 合同发起页面完成后跳转url 若不为空,可以跳转业务方自己的前端过渡页面,实现业务方自己的逻辑。
+	ContractFiles        []interface{} `json:"contractFiles" structs:"contractFiles,omitempty"`               // 合同附件(与合同模板必传其一)(支持多文件上传)
+	Templates            []APITemplate `json:"templates" structs:"templates,omitempty"`                       // 合同模板列表(与合同附件必传其一)
 }
 
 // APICreateContractRsp 上传待签署文件出参
@@ -240,16 +240,16 @@ type APICreateContractRsp struct {
 
 // APISignStrategy 签章策略
 type APISignStrategy struct {
-	AttachNo     int     `json:"attachNo" binding:"required"`     // 附件编号 注:对应上传待签署文件接口(createContract)中,合同附件(contractFiles)或合同模板(templates)参数中的List排序序号(例如:1,2,3...)
-	LocationMode int     `json:"locationMode" binding:"required"` // 定位方式:2:坐标签章 3:关键字签章 4:模板坐标签章
-	CanDrag      int     `json:"canDrag" structs:",omitempty"`    // 签章位置是否可以拖动 1:可以, 其他值:不可以
-	SignKey      string  `json:"signKey" structs:",omitempty"`    // 关键字或签署区名称key(定位方式为关键字签章时此处需传定位关键字,定位方式为模板坐标签章时此处需传模板中设置的签署区名称)
-	SignType     int     `json:"signType" structs:",omitempty"`   // 印章类型:1:签名/签章(默认) 2:时间戳
-	SignPage     int     `json:"signPage" structs:",omitempty"`   // 签章页码(定位方式为坐标签章时必传)
-	SignX        float64 `json:"signX" structs:",omitempty"`      // 签章位置与当前签约文件的左内边距与当前签约文件宽度的比例(精确到小数点后2位)(定位方式为坐标签章时必传)
-	SignY        float64 `json:"signY" structs:",omitempty"`      // 签章位置与当前签约文件的上内边距与当前签约文件高度的比例(精确到小数点后2位)(定位方式为坐标签章时必传)
-	OffsetX      float64 `json:"offsetX" structs:",omitempty"`    // 坐标偏移量(像素PX)
-	OffsetY      float64 `json:"offsetY" structs:",omitempty"`    // 坐标偏移量(像素PX)
+	AttachNo     int     `json:"attachNo" structs:"attachNo" binding:"required"`         // 附件编号 注:对应上传待签署文件接口(createContract)中,合同附件(contractFiles)或合同模板(templates)参数中的List排序序号(例如:1,2,3...)
+	LocationMode int     `json:"locationMode" structs:"locationMode" binding:"required"` // 定位方式:2:坐标签章 3:关键字签章 4:模板坐标签章
+	CanDrag      int     `json:"canDrag" structs:"canDrag,omitempty"`                    // 签章位置是否可以拖动 1:可以, 其他值:不可以
+	SignKey      string  `json:"signKey" structs:"signKey,omitempty"`                    // 关键字或签署区名称key(定位方式为关键字签章时此处需传定位关键字,定位方式为模板坐标签章时此处需传模板中设置的签署区名称)
+	SignType     int     `json:"signType" structs:"signType,omitempty"`                  // 印章类型:1:签名/签章(默认) 2:时间戳
+	SignPage     int     `json:"signPage" structs:"signPage,omitempty"`                  // 签章页码(定位方式为坐标签章时必传)
+	SignX        float64 `json:"signX" structs:"signX,omitempty"`                        // 签章位置与当前签约文件的左内边距与当前签约文件宽度的比例(精确到小数点后2位)(定位方式为坐标签章时必传)
+	SignY        float64 `json:"signY" structs:"signY,omitempty"`                        // 签章位置与当前签约文件的上内边距与当前签约文件高度的比例(精确到小数点后2位)(定位方式为坐标签章时必传)
+	OffsetX      float64 `json:"offsetX" structs:"offsetX,omitempty"`                    // 坐标偏移量(像素PX)
+	OffsetY      float64 `json:"offsetY" structs:"offsetY,omitempty"`                    // 坐标偏移量(像素PX)
 }
 
 // APIReceiverFillStrategy 接收方模板填充策略
@@ -266,28 +266,28 @@ type APIReceiverFillStrategy struct {
 //
 // 参数说明:https://preweb.asign.cn/platform/openDoc/docDetail?mid=addSigner
 type APIAddSignerReq struct {
-	ContractNo               string                    `json:"contractNo" binding:"required"`                 // 合同唯一编码 (40位之内)
-	Account                  string                    `json:"account" binding:"required"`                    // 用户唯一识别码
-	SignType                 int                       `json:"signType" binding:"required"`                   // 签约方式:2:无感知签约(需要开通权限) 3:有感知签约
-	SealNo                   string                    `json:"sealNo" structs:",omitempty"`                   // 印章编号【注】若不传值,则由当前主体的默认印章进行签署
-	AuthSignAccount          string                    `json:"authSignAccount" structs:",omitempty"`          // 指定授权签约用户,该用户需要有印章编号【sealNo】的有效授权记录,如若不指定则印章的默认使用者进行签署,如无默认使用者,则由当前主体【account】进行签署
-	NoticeMobile             string                    `json:"noticeMobile" structs:",omitempty"`             // 通知手机号(用于接收合同签署链接的通知短信)
-	NoticeEmail              string                    `json:"noticeEmail" structs:",omitempty"`              // 通知邮箱号(用于接收合同签署链接的通知短信)
-	SignOrder                string                    `json:"signOrder" structs:",omitempty"`                // 使用顺序签约时签约顺序编号(从1开始),无序签约都为1
-	IsNotice                 int                       `json:"isNotice" structs:",omitempty"`                 // 是否接收合同签署链接的短信通知,优先级高于添加用户接口同名参数:0 - 否(默认),1 - 是
-	ValidateType             int                       `json:"validateType" structs:",omitempty"`             // 签署方式指定:(从以下分类中指定一种) 1:短信验证码签约(支持企业和个人) 2:签约密码签约(支持企业和个人) 3:人脸识别签约(支持企业和个人) 4:手写签名(不推荐,仅限个人,需要开通权限) 5:宋体章签名(不推荐,仅限个人,需要开通权限) 6:手写识别签名+短信签约(仅限个人) 7:手写签名+短信签约(仅限个人) 8:手写签名+人脸识别签约(仅限个人) 9:手写识别签名+人脸识别签约(仅限个人) 10:手写签名 + 认证意愿合一(仅支持个人陌生用户) 11:手写签名识别 + 认证意愿合一(仅支持个人陌生用户) 12:宋体章 + 认证意愿合一(仅支持个人陌生用户) 13:视频双录核身签约(需要开通权限)
-	FaceAuthMode             int                       `json:"faceAuthMode" structs:",omitempty"`             // 人脸识别方式:1:支付宝(不可在支付宝小程序中接入) 2:H5(默认) 4:微信小程序(支持在微信小程序内唤起人脸识别,需联系商务人员开启权限后使用) 5:支付宝小程序(支持在支付宝小程序内唤起人脸识别,需联系商务人员开启权限后使用) 【注】签署方式包含人脸(3,8,9)时,可指定人脸识别方式,不传默认为H5
-	ValidateTypeList         string                    `json:"validateTypeList" structs:",omitempty"`         // 组合签署方式指定:(从以上分类中指定多种以逗号间隔,示例:1,2,3)。允许开发者可以自主控制展示几种签署方式,让签约用户选择。【注】 validateTypeList和validateType都有传值时,签署方式按照validateTypeList指定
-	AutoSwitch               int                       `json:"autoSwitch" structs:",omitempty"`               // 自动切换签约方式:开发者可以自主控制手写内容识别和人脸刷脸识别多次不通过时,是否允许用户切换方式 1 - 仅手写识别允许切换(默认) 2 - 仅人脸识别允许切换 3 - 全部允许 0 - 全部不允许 【注】手写识别三次失败时,会允许用户切换成宋体印章。人脸识别三次不通过,允许切换为短信验证码方式。
-	IsNoticeComplete         int                       `json:"isNoticeComplete" structs:",omitempty"`         // 合同签署完成后是否通知用户:1 - 是,0 - 否(默认)
-	WaterMark                int                       `json:"waterMark" structs:",omitempty"`                // 是否在距底部10px中央位置添加日期水印: 1 - 是,0 - 否(默认)
-	AutoSms                  int                       `json:"autoSms" structs:",omitempty"`                  // 是否自动触发验证码短信:(仅短信验证码方式签署时生效)1:是(默认) 0:否(需要用户手动点击“获取验证码”触发)
-	CustomSignFlag           int                       `json:"customSignFlag" structs:",omitempty"`           // 签章位置策略:0(默认)- 由该接口的参数signStrategyList或signStrikeList指定 1 - 签署用户在签署时自行拖动签章位置 2 - 签署用户在签署时自行拖动签章位置和骑缝章位置
-	IsIframe                 int                       `json:"isIframe" structs:",omitempty"`                 // 如果认证页面使用了iframe,且签约涉及人脸识别,则需传入此参数 1.是 0.否(默认) 接入方需要给iframe开启相机权限,方可正常使用实时检测人脸核身功能<iframe allow="camera;"></iframe>
-	SignStrategyList         []APISignStrategy         `json:"signStrategyList" binding:"required"`           // 签章策略
-	SignStrikeList           []interface{}             `json:"signStrikeList" structs:",omitempty"`           // 骑缝章策略
-	ReceiverFillStrategyList []APIReceiverFillStrategy `json:"receiverFillStrategyList" structs:",omitempty"` // 接收方模板填充策略
-	AuthConfig               interface{}               `json:"authConfig" structs:",omitempty"`               // 添加陌生签署人认证参数配置
+	ContractNo               string                    `json:"contractNo" structs:"contractNo" binding:"required"`                    // 合同唯一编码 (40位之内)
+	Account                  string                    `json:"account" structs:"account" binding:"required"`                          // 用户唯一识别码
+	SignType                 int                       `json:"signType" structs:"signType" binding:"required"`                        // 签约方式:2:无感知签约(需要开通权限) 3:有感知签约
+	SealNo                   string                    `json:"sealNo" structs:"sealNo,omitempty"`                                     // 印章编号【注】若不传值,则由当前主体的默认印章进行签署
+	AuthSignAccount          string                    `json:"authSignAccount" structs:"authSignAccount,omitempty"`                   // 指定授权签约用户,该用户需要有印章编号【sealNo】的有效授权记录,如若不指定则印章的默认使用者进行签署,如无默认使用者,则由当前主体【account】进行签署
+	NoticeMobile             string                    `json:"noticeMobile" structs:"noticeMobile,omitempty"`                         // 通知手机号(用于接收合同签署链接的通知短信)
+	NoticeEmail              string                    `json:"noticeEmail" structs:"noticeEmail,omitempty"`                           // 通知邮箱号(用于接收合同签署链接的通知短信)
+	SignOrder                string                    `json:"signOrder" structs:"signOrder,omitempty"`                               // 使用顺序签约时签约顺序编号(从1开始),无序签约都为1
+	IsNotice                 int                       `json:"isNotice" structs:"isNotice,omitempty"`                                 // 是否接收合同签署链接的短信通知,优先级高于添加用户接口同名参数:0 - 否(默认),1 - 是
+	ValidateType             int                       `json:"validateType" structs:"validateType,omitempty"`                         // 签署方式指定:(从以下分类中指定一种) 1:短信验证码签约(支持企业和个人) 2:签约密码签约(支持企业和个人) 3:人脸识别签约(支持企业和个人) 4:手写签名(不推荐,仅限个人,需要开通权限) 5:宋体章签名(不推荐,仅限个人,需要开通权限) 6:手写识别签名+短信签约(仅限个人) 7:手写签名+短信签约(仅限个人) 8:手写签名+人脸识别签约(仅限个人) 9:手写识别签名+人脸识别签约(仅限个人) 10:手写签名 + 认证意愿合一(仅支持个人陌生用户) 11:手写签名识别 + 认证意愿合一(仅支持个人陌生用户) 12:宋体章 + 认证意愿合一(仅支持个人陌生用户) 13:视频双录核身签约(需要开通权限)
+	FaceAuthMode             int                       `json:"faceAuthMode" structs:"faceAuthMode,omitempty"`                         // 人脸识别方式:1:支付宝(不可在支付宝小程序中接入) 2:H5(默认) 4:微信小程序(支持在微信小程序内唤起人脸识别,需联系商务人员开启权限后使用) 5:支付宝小程序(支持在支付宝小程序内唤起人脸识别,需联系商务人员开启权限后使用) 【注】签署方式包含人脸(3,8,9)时,可指定人脸识别方式,不传默认为H5
+	ValidateTypeList         string                    `json:"validateTypeList" structs:"validateTypeList,omitempty"`                 // 组合签署方式指定:(从以上分类中指定多种以逗号间隔,示例:1,2,3)。允许开发者可以自主控制展示几种签署方式,让签约用户选择。【注】 validateTypeList和validateType都有传值时,签署方式按照validateTypeList指定
+	AutoSwitch               int                       `json:"autoSwitch" structs:"autoSwitch,omitempty"`                             // 自动切换签约方式:开发者可以自主控制手写内容识别和人脸刷脸识别多次不通过时,是否允许用户切换方式 1 - 仅手写识别允许切换(默认) 2 - 仅人脸识别允许切换 3 - 全部允许 0 - 全部不允许 【注】手写识别三次失败时,会允许用户切换成宋体印章。人脸识别三次不通过,允许切换为短信验证码方式。
+	IsNoticeComplete         int                       `json:"isNoticeComplete" structs:"isNoticeComplete,omitempty"`                 // 合同签署完成后是否通知用户:1 - 是,0 - 否(默认)
+	WaterMark                int                       `json:"waterMark" structs:"waterMark,omitempty"`                               // 是否在距底部10px中央位置添加日期水印: 1 - 是,0 - 否(默认)
+	AutoSms                  int                       `json:"autoSms" structs:"autoSms,omitempty"`                                   // 是否自动触发验证码短信:(仅短信验证码方式签署时生效)1:是(默认) 0:否(需要用户手动点击“获取验证码”触发)
+	CustomSignFlag           int                       `json:"customSignFlag" structs:"customSignFlag,omitempty"`                     // 签章位置策略:0(默认)- 由该接口的参数signStrategyList或signStrikeList指定 1 - 签署用户在签署时自行拖动签章位置 2 - 签署用户在签署时自行拖动签章位置和骑缝章位置
+	IsIframe                 int                       `json:"isIframe" structs:"isIframe,omitempty"`                                 // 如果认证页面使用了iframe,且签约涉及人脸识别,则需传入此参数 1.是 0.否(默认) 接入方需要给iframe开启相机权限,方可正常使用实时检测人脸核身功能<iframe allow="camera;"></iframe>
+	SignStrategyList         []APISignStrategy         `json:"signStrategyList" structs:"signStrategyList" binding:"required"`        // 签章策略
+	SignStrikeList           []interface{}             `json:"signStrikeList" structs:"signStrikeList,omitempty"`                     // 骑缝章策略
+	ReceiverFillStrategyList []APIReceiverFillStrategy `json:"receiverFillStrategyList" structs:"receiverFillStrategyList,omitempty"` // 接收方模板填充策略
+	AuthConfig               interface{}               `json:"authConfig" structs:"authConfig,omitempty"`                             // 添加陌生签署人认证参数配置
 }
 
 // APISignUserDetail 合同用户信息
@@ -368,8 +368,8 @@ type APIModifySealReq struct {
 
 // APIGetUserSealsReq 查询印章入参
 type APIGetUserSealsReq struct {
-	Account string `json:"account" binding:"required"` // 用户唯一识别码
-	SealNo  string `json:"sealNo"`                     // 印章编号(不传则返回印章列表)
+	Account string `json:"account" structs:"account" binding:"required"` // 用户唯一识别码
+	SealNo  string `json:"sealNo" structs:"sealNo,omitempty"`            // 印章编号(不传则返回印章列表)
 }
 
 // APISealInfo 印章信息

+ 6 - 5
services/asign/servcies.go

@@ -281,7 +281,7 @@ func CaptchaVerify(req CaptchaVerifyReq) (err error) {
 	// 获取临时存储的用户认证信息
 	cacheMap := make(map[string]interface{})
 	if err = json.Unmarshal([]byte(record.AUTHINFO), &cacheMap); err != nil {
-		logger.GetLogger().Error("反序列化临时存储用户信息失败, AUTHINFO:", record.AUTHINFO)
+		logger.GetLogger().Errorf("反序列化临时存储用户信息失败, AUTHINFO: %s", record.AUTHINFO)
 		return
 	}
 	// 调用JAVA实名认证接口
@@ -573,7 +573,7 @@ func CreateContract(req CreateContractReq) (rsp CreateContractRsp, err error) {
 	// 获取临时存储的用户认证信息
 	cacheMap := make(map[string]interface{})
 	if err = json.Unmarshal([]byte(recordAuth.AUTHINFO), &cacheMap); err != nil {
-		logger.GetLogger().Error("反序列化临时存储用户信息失败, AUTHINFO:", recordAuth.AUTHINFO)
+		logger.GetLogger().Errorf("反序列化临时存储用户信息失败, AUTHINFO: %s", recordAuth.AUTHINFO)
 		return
 	}
 	if recordAuth.AUTHINFO == "" {
@@ -623,9 +623,8 @@ func CreateContract(req CreateContractReq) (rsp CreateContractRsp, err error) {
 	if len(receiverFillStrategyList) > 0 {
 		appAddSignerReq2.ReceiverFillStrategyList = receiverFillStrategyList
 	}
-	apiAddSignerReq := new(APIReq[[]APIAddSignerReq])
-	apiAddSignerReq.Data = []APIAddSignerReq{appAddSignerReq1, appAddSignerReq2}
-	apiAddSignerRsp, err := APIPost[[]APIAddSignerReq, APIAddSignerRsp](*apiAddSignerReq, APIURL_AddSigner)
+	apiAddSignerReq := APIReq[APIAddSignerReq]{Datas: []APIAddSignerReq{appAddSignerReq1, appAddSignerReq2}}
+	apiAddSignerRsp, err := APIPost[APIAddSignerReq, APIAddSignerRsp](apiAddSignerReq, APIURL_AddSigner)
 	if err != nil {
 		return
 	}
@@ -712,6 +711,8 @@ func buildStrategyByPartyB(templateConfigId int, fieldUserType int, cacheMap map
 			receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "P_PARTYB_NAME", Value: cacheMap["realName"].(string)})
 		case "P_PARTYB_ID": // 乙方证件号码
 			receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "P_PARTYB_ID", Value: cacheMap["idCardNo"].(string)})
+		case "P_PARTYB_MOBILE": // 乙方电话号码
+			receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "P_PARTYB_MOBILE", Value: cacheMap["mobile"].(string)})
 		case "P_PARTYB_SIGNATURE": // 乙方签章(个人)
 			signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "P_PARTYB_SIGNATURE", SignType: 1})
 		case "P_PARTYB_DATE": // 乙方签署时间

+ 27 - 0
services/asign/templates/中融/MTP2.0_db_init_R0041_054_00811_01.sql

@@ -0,0 +1,27 @@
+
+
+
+
+delete from esigntemplateconfig ;
+insert into esigntemplateconfig (templateconfigid, esigntype, templateno, templatetype, templatename, orderindex, creatorid, createtime, updatetime)
+values (1, 1, '', 1, '实名认证', 1, 1, sysdate, sysdate);
+insert into esigntemplateconfig (templateconfigid, esigntype, templateno, templatetype, templatename, orderindex, creatorid, createtime, updatetime)
+values (2, 1, '', 2, '客户交易须知', 2, 1, sysdate, sysdate);
+
+delete from esigntemplatefield;
+insert into esigntemplatefield (TEMPLATEFIELDID, TEMPLATECONFIGID, FIELDNAME, FIELDKEY, FIELDTYPE, REMARK, CREATETIME, FIELDUSERTYPE)
+values ('1', '2', '甲方签章(企业印章)', 'PARTYA_SIGNATURE', '3', null, sysdate, '2');
+insert into esigntemplatefield (TEMPLATEFIELDID, TEMPLATECONFIGID, FIELDNAME, FIELDKEY, FIELDTYPE, REMARK, CREATETIME, FIELDUSERTYPE)
+values ('2', '2', '甲方签署时间', 'PARTYA_DATE', '3', null, sysdate, '2');
+insert into esigntemplatefield (TEMPLATEFIELDID, TEMPLATECONFIGID, FIELDNAME, FIELDKEY, FIELDTYPE, REMARK, CREATETIME, FIELDUSERTYPE)
+values ('3', '2', '乙方签章(个人)', 'P_PARTYB_SIGNATURE', '3', null, sysdate, '1');
+insert into esigntemplatefield (TEMPLATEFIELDID, TEMPLATECONFIGID, FIELDNAME, FIELDKEY, FIELDTYPE, REMARK, CREATETIME, FIELDUSERTYPE)
+values ('4', '2', '乙方证件号码', 'P_PARTYB_ID', '1', null, sysdate, '1');
+insert into esigntemplatefield (TEMPLATEFIELDID, TEMPLATECONFIGID, FIELDNAME, FIELDKEY, FIELDTYPE, REMARK, CREATETIME, FIELDUSERTYPE)
+values ('5', '2', '乙方电话号码', 'P_PARTYB_MOBILE', '1', null, sysdate, '1');
+insert into esigntemplatefield (TEMPLATEFIELDID, TEMPLATECONFIGID, FIELDNAME, FIELDKEY, FIELDTYPE, REMARK, CREATETIME, FIELDUSERTYPE)
+values ('6', '2', '乙方签署时间', 'P_PARTYB_DATE', '2', null, sysdate, '1');
+
+insert into UPDATEVERSION values ('MTP2.0_db_init_R0041_054_00811_01','v2_19_中融文遗通\MTP2.0_db_init_R0041_054_00811_01.sql',sysdate); 
+commit;
+prompt v2_19_中融文遗通\MTP2.0_db_init_R0041_054_00811_01_Finished

+ 7 - 0
services/asign/test.go

@@ -0,0 +1,7 @@
+package asign
+
+func TestAPI(req string) (rspBody []byte, err error) {
+	rspBody, err = TestHttpPost(APIURL_AddSigner, req)
+
+	return
+}

+ 0 - 89
services/asign/test/main.go

@@ -1,94 +1,5 @@
 package main
 
-import (
-	"fmt"
-	"mtp2_if/utils"
-	"reflect"
-	"sort"
-
-	"github.com/fatih/structs"
-)
-
-type aPIAAA struct {
-	Account         string   `json:"account" binding:"required"`            // 用户唯一识别码(请转入UserID)
-	SerialNo        string   `json:"serialNo"`                              // 实名认证流水号
-	Name            *string  `json:"name" structs:",omitempty"`             // 用户姓名
-	IdCard          string   `json:"idCard"  structs:",omitempty"`          // 个人身份证、台胞证、港澳通行证等证件号
-	IdCardType      *int     `json:"idCardType" structs:",omitempty"`       // 证件类型 1:居民身份证 2:台湾居民来往内地通行证 3:港澳居民往来内地通行证 10:武装警察身份证 11:军人身份证 15:警察(警官)证 21:外国人永久居留证 23:护照
-	Mobile          string   `json:"mobile"  structs:",omitempty"`          // 手机号码
-	SignPwd         string   `json:"signPwd"  structs:",omitempty"`         // 签约密码(MTP2登录密码加密方式),如果为空将随机生成签约密码(当签约方式为“签约密码签约”时会使用到,可通过重置接口修改)
-	IsSignPwdNotice *float64 `json:"isSignPwdNotice"  structs:",omitempty"` // 是否将签约密码以短信形式通知用户 0:不通知(默认) 1:通知
-	IsNotice        *bool    `json:"isNotice"  structs:",omitempty"`        // 用户发起合同或需要签署时是否进行短信通知 0:否(默认) 1:是
-}
-
 func main() {
-	req := &aPIAAA{
-		Account: "1111",
-	}
-	req.SerialNo = "2222"
-	req.Name = utils.SetPointValue("")
-	req.IdCardType = utils.SetPointValue(1)
-	req.IsSignPwdNotice = utils.SetPointValue(5.01)
-	reqMap := structs.Map(req)
-
-	aaa := sortMapByKey(reqMap)
-
-	fmt.Println(aaa)
-}
-
-func sortMapByKey(data map[string]interface{}) (sortedData string) {
-	keys := make([]string, 0, len(data))
-	for k := range data {
-		keys = append(keys, k)
-	}
-	sort.Strings(keys)
-	for i, k := range keys {
-		if i > 0 {
-			sortedData += ","
-		}
-
-		// 判断是否指针
-		v := reflect.ValueOf(data[k])
-		if v.Kind() == reflect.Ptr {
-			switch data[k].(type) {
-			case *string:
-				sortedData += fmt.Sprintf(`"%s":"%s"`, k, *(data[k].(*string)))
-			case *map[string]interface{}:
-				sortedData += fmt.Sprintf(`"%s":%s`, k, sortMapByKey(*(data[k].(*map[string]interface{}))))
-			case *[]interface{}:
-				list := data[k].([]interface{})
-				sortedData += fmt.Sprintf(`"%s":[`, k)
-				for j, item := range list {
-					if j > 0 {
-						sortedData += ","
-					}
-					sortedData += sortMapByKey(item.(map[string]interface{}))
-				}
-				sortedData += "]"
-			default:
-				sortedData += fmt.Sprintf(`"%s":%v`, k, reflect.ValueOf(data[k]).Elem())
-			}
-		} else {
-			switch data[k].(type) {
-			case string:
-				sortedData += fmt.Sprintf(`"%s":"%s"`, k, data[k].(string))
-			case map[string]interface{}:
-				sortedData += fmt.Sprintf(`"%s":%s`, k, sortMapByKey(data[k].(map[string]interface{})))
-			case []interface{}:
-				list := data[k].([]interface{})
-				sortedData += fmt.Sprintf(`"%s":[`, k)
-				for j, item := range list {
-					if j > 0 {
-						sortedData += ","
-					}
-					sortedData += sortMapByKey(item.(map[string]interface{}))
-				}
-				sortedData += "]"
-			default:
-				sortedData += fmt.Sprintf(`"%s":%v`, k, data[k])
-			}
-		}
-	}
 
-	return fmt.Sprintf("{%s}", sortedData)
 }