diff --git a/.gitignore b/.gitignore
index 3e8a1553fcff7845c779d3cb8014e151a9931506..26bcd2533c237cc5afccd5984ad45900a65e1ab8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,8 @@
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+packages
+
# User-specific files
*.rsuser
*.suo
diff --git a/README.en.md b/README.en.md
deleted file mode 100644
index 7fc06df1df52584a329ed3e08c28bfd1c6101ba3..0000000000000000000000000000000000000000
--- a/README.en.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# signit-sdk-net
-
-#### Description
-signit.cn 的 .NET 接口
-
-#### Software Architecture
-Software architecture description
-
-#### Installation
-
-1. xxxx
-2. xxxx
-3. xxxx
-
-#### Instructions
-
-1. xxxx
-2. xxxx
-3. xxxx
-
-#### Contribution
-
-1. Fork the repository
-2. Create Feat_xxx branch
-3. Commit your code
-4. Create Pull Request
-
-
-#### Gitee Feature
-
-1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
-2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
-3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
-4. The most valuable open source project [GVP](https://gitee.com/gvp)
-5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
-6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
\ No newline at end of file
diff --git a/README.md b/README.md
index 5996a68e6c59ffd72ef27037759eb60fab9a9580..b79fe8f8f5e4e13fc543ee15597477d569f6f486 100644
--- a/README.md
+++ b/README.md
@@ -1,37 +1,15 @@
-# signit-sdk-net
+# 欢迎使用易企签 .NET SDK
-#### 介绍
-signit.cn 的 .NET 接口
+易企签 .NET SDK 包括:
-#### 软件架构
-软件架构说明
+- token授权获取
+- 快捷签署
+- 提交企业实名认证(即:开通在线电子签约服务接口(企业))
+- 提交个人实名认证(即:开通在线电子签约服务接口(个人))
+- 启动信封签署流程
+了解更多易企签详情请访问 [https://www.signit.cn](https://www.signit.cn)
-#### 安装教程
+## 更新日志
-1. xxxx
-2. xxxx
-3. xxxx
-
-#### 使用说明
-
-1. xxxx
-2. xxxx
-3. xxxx
-
-#### 参与贡献
-
-1. Fork 本仓库
-2. 新建 Feat_xxx 分支
-3. 提交代码
-4. 新建 Pull Request
-
-
-#### 码云特技
-
-1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
-2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com)
-3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目
-4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目
-5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
-6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
\ No newline at end of file
+### v1.0 ...
diff --git a/Sdk.sln b/Sdk.sln
new file mode 100644
index 0000000000000000000000000000000000000000..0175a056b0073a903413ac8cab9e9b62fb09d8d2
--- /dev/null
+++ b/Sdk.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.28917.181
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sdk", "Sdk\Sdk.csproj", "{E583EAF3-04F9-4AB6-B265-D737568AAEFC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E583EAF3-04F9-4AB6-B265-D737568AAEFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E583EAF3-04F9-4AB6-B265-D737568AAEFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E583EAF3-04F9-4AB6-B265-D737568AAEFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E583EAF3-04F9-4AB6-B265-D737568AAEFC}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {817A68CA-8343-42F8-990B-2BAB20226507}
+ EndGlobalSection
+EndGlobal
diff --git a/Sdk/Entity/BaseFileData.cs b/Sdk/Entity/BaseFileData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..47f9b24a84e37d74f9b616d80b661e7b2c7c4855
--- /dev/null
+++ b/Sdk/Entity/BaseFileData.cs
@@ -0,0 +1,8 @@
+namespace Signit.Sdk.Entity
+{
+ public class BaseFileData
+ {
+ public string Url { get; set; }
+ public string Base64 { get; set; }
+ }
+}
diff --git a/Sdk/Entity/CertData.cs b/Sdk/Entity/CertData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..44c70c4f9bab9e4734894e24a6253635d4dc0710
--- /dev/null
+++ b/Sdk/Entity/CertData.cs
@@ -0,0 +1,13 @@
+namespace Signit.Sdk.Entity
+{
+ /**
+ * 证书数据. 支持base64、URL、证书数据全局唯一ID中对的任意一种方式.
+ */
+ public class CertData : BaseFileData
+ {
+ /**
+ * 证书数据的全局唯一ID.
+ */
+ public string Wsid { get; set; }
+ }
+}
diff --git a/Sdk/Entity/Contact.cs b/Sdk/Entity/Contact.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3009d44de2270c04d41ea6a40a82394118beedee
--- /dev/null
+++ b/Sdk/Entity/Contact.cs
@@ -0,0 +1,18 @@
+namespace Signit.Sdk.Entity
+{
+ /**
+ * 用户联系方式. 包含邮箱和手机号码.
+ */
+ public class Contact
+ {
+ /**
+ * 电子邮箱.
+ */
+ public string Email { get; set; }
+
+ /**
+ * 手机号码.
+ */
+ public string Phone { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Entity/FileData.cs b/Sdk/Entity/FileData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ea2c98a8b62f2eb3dec104f54dea7e79ab02b37b
--- /dev/null
+++ b/Sdk/Entity/FileData.cs
@@ -0,0 +1,16 @@
+namespace Signit.Sdk.Entity
+{
+ public class FileData
+ {
+ public string Url { get; set; }
+ public string Base64 { get; set; }
+ public bool EnableSinglePage { get; set; }
+
+ public FileData() { }
+
+ public FileData(string url)
+ {
+ Url = url;
+ }
+ }
+}
diff --git a/Sdk/Entity/IdCardImage.cs b/Sdk/Entity/IdCardImage.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ccb817b02020724a4923ef441a18f817157665b9
--- /dev/null
+++ b/Sdk/Entity/IdCardImage.cs
@@ -0,0 +1,23 @@
+namespace Signit.Sdk.Entity
+{
+ ///
+ /// 证件图像数据.
+ ///
+ public class IdCardImage
+ {
+ ///
+ /// 图像名称.
+ ///
+ public string ImageName { get; set; }
+
+ ///
+ /// 图像标识码.
+ ///
+ public string ImageCode { get; set; }
+
+ ///
+ /// 图像标识码.
+ ///
+ public IdCardImageData ImageData { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Entity/IdCardImageData.cs b/Sdk/Entity/IdCardImageData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..359db9397d313190eac72545782287e144c18b54
--- /dev/null
+++ b/Sdk/Entity/IdCardImageData.cs
@@ -0,0 +1,18 @@
+namespace Signit.Sdk.Entity
+{
+ /**
+ * 证件图片数据.
+ *
+ * @since 2.0.0
+ */
+ public class IdCardImageData : BaseFileData
+ {
+ /**
+ * 证件的文件全局唯一ID.
+ *
+ * @since 2.0.0
+ */
+ public string FileWsid { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Entity/InitialValue.cs b/Sdk/Entity/InitialValue.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e8bf1cc69ab33941f38508dd7728137b892b35d4
--- /dev/null
+++ b/Sdk/Entity/InitialValue.cs
@@ -0,0 +1,73 @@
+using Signit.Sdk.Types;
+
+namespace Signit.Sdk.Entity
+{
+ /**
+ * 签名初始化数据。包含印章数据、手写数据、证书数据、证书签名证书秘钥访问口令、证书类型、 渲染模式、签名地理位置、联系方式、签名是否锁定、签名原因。
+ * 印章数据、手写数据仅一个不为空的有效。
+ */
+ public class InitialValue
+ {
+ /**
+ * 印章数据.
+ */
+ public SealData SealData { get; set; }
+
+ /**
+ * 手写签名数据.
+ */
+ public WriteData WriteData { get; set; }
+
+ /**
+ * 证书数据.
+ */
+ public CertData CertData { get; set; }
+
+ /**
+ * 证书签名证书密钥访问口令.
+ */
+ public string CertPassin { get; set; }
+
+ /**
+ * 证书类型.
+ * 对应枚举:CertType
+ */
+ public CertType CertType { get; set; }
+
+ /**
+ * 渲染模式. 对应枚举:
+ * 对应枚举:RenderMode
+ */
+ public RenderMode RenderingMode { get; set; } = RenderMode.GRAPHIC;
+
+ /**
+ * 签名地理位置.
+ */
+ public string Location { get; set; }
+
+ /**
+ * 联系方式.
+ */
+ public string Contact { get; set; }
+
+ /**
+ * 签名是否锁定.
+ */
+ public bool Locked { get; set; }
+
+ /**
+ * 签名原因.
+ */
+ public string Reason { get; set; }
+
+ /**
+ * 文本框文本内容
+ */
+ public string TextContent { get; set; }
+
+ /**
+ * 二维码内容字符串.
+ */
+ public string QrcodeContent { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Entity/KeywordPosition.cs b/Sdk/Entity/KeywordPosition.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d928c7af7e81dc5c9445d9b6d69a80af0df94c97
--- /dev/null
+++ b/Sdk/Entity/KeywordPosition.cs
@@ -0,0 +1,30 @@
+using Signit.Sdk.Types;
+
+namespace Signit.Sdk.Entity
+{
+ public class KeywordPosition
+ {
+ public float? Width { get; set; }
+ public float? RelativeWidthRatio { get; set; }
+ public float? Height { get; set; }
+ public float? RelativeHeightRatio { get; set; }
+ public Direction Direction { get; set; }
+ public float? Offset { get; set; }
+ public float? RelativeOffsetRatio { get; set; }
+ public string Keyword { get; set; }
+ public float? Scale { get; set; }
+ public string Pages { get; set; }
+
+ ///
+ /// x 方向的便移量 正是往右,负是往左,坐标缩放前进行最后的微调参数
+ ///
+ public float? XOffset { get; set; }
+
+ ///
+ /// y 方向的便移量 正是往上,负是往下,坐标缩放前进行最后的微调参数
+ ///
+ public float? YOffset { get; set; }
+
+ public int Index { get; set; }
+ }
+}
diff --git a/Sdk/Entity/PresetForm.cs b/Sdk/Entity/PresetForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5441ce078b33c0c2116c58d6fcc2ad1c94bbe11e
--- /dev/null
+++ b/Sdk/Entity/PresetForm.cs
@@ -0,0 +1,113 @@
+using Signit.Sdk.Types;
+
+namespace Signit.Sdk.Entity
+{
+ /**
+ * 预设表单信息。 包括表单类型、印章/手写签名名字、所签署文件ID、签署表单坐标位置、表单是否必填、表单缩放比例
+ * 、签名初始化值、表单是否允许修正、当前表单的自定义标识、是否是纠正创建的表单
+ */
+ public class PresetForm
+ {
+ /**
+ * 表单类型。 对应枚举:FormType
+ */
+ public FormType FormType { get; set; }
+
+ /**
+ * 当前表单要设置到的文件上,引用contentInfo.files[].id值.
+ */
+ public string FileId { get; set; }
+
+ /**
+ * 签署表单坐标位置.
+ */
+ public SignerPosition Position { get; set; }
+
+ /**
+ * 表单缩放比例.
+ */
+ public float Scale { get; set; } = 1.0f;
+
+ /**
+ * 签名初始化值.
+ */
+ public InitialValue InitialValue { get; set; }
+
+ /**
+ * 表单是否允许修正.
+ */
+ public bool Revisable { get; set; }
+
+ /**
+ * 当前表单的自定义标识.
+ */
+ public string TagId { get; set; }
+
+ /**
+ * 是否是纠正创建的表单.
+ */
+ public bool Corrected { get; set; }
+
+ /**
+ * 跨页表单距离页面边缘边距,单位px
+ * @since 2.1.0
+ */
+ public float Margin { get; set; }
+
+ /**
+ * 防伪标记中心按顺时针方向,沿页面边缘偏移的量
+ * @since 2.1.0
+ */
+ public float Offset { get; set; }
+
+ /**
+ * 签署完成后证书所在的页数,若为空字符串或null,则等价于为均为无证书骑缝章。支持格式形如:'first','last','all','odd','even','1','1-5','1,3,4,7,8',...
+ * @since 2.1.0
+ */
+ public string CertPages { get; set; }
+
+ /**
+ * 单位图片所占像素(当且仅当每页宽度不足1px时有效).
+ * @since 2.1.0
+ */
+ public int Pixel { get; set; }
+
+ /**
+ * 单页数是否加盖骑缝章
+ * @since 2.1.0
+ */
+ public bool SinglePageMark { get; set; }
+
+ /**
+ * 是否重设骑缝章尺寸
+ * @since 2.1.0
+ */
+ public bool Resizable { get; set; }
+
+ /**
+ * 重设骑缝章尺寸宽度.单位px.当resizablee时该值的设置才有效=tru
+ * @since 2.1.0
+ */
+ public float ResizeWidth { get; set; }
+
+ /**
+ * 重设骑缝章尺寸高度.单位px.当resizablee时该值的设置才有效=tru
+ * @since 2.1.0
+ */
+ public float ResizeHeight { get; set; }
+
+
+ /**
+ * 二维码宽,单位px.
+ * @since 2.1.0
+ */
+ public float Width { get; set; }
+
+
+ /**
+ * 二维码高,单位px.
+ * @since 2.1.0
+ */
+ public float Height { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Entity/Receiver.cs b/Sdk/Entity/Receiver.cs
new file mode 100644
index 0000000000000000000000000000000000000000..65fcbc520a0688a202bf3cae416d0279d01850f9
--- /dev/null
+++ b/Sdk/Entity/Receiver.cs
@@ -0,0 +1,85 @@
+using Signit.Sdk.Types;
+using System.Collections.Generic;
+
+namespace Signit.Sdk.Entity
+{
+ /**
+ * 接收方信息。 包含接收方名字、接收方联系方式、安全等级、接收方类型、 接收方是否必须预分配表单域、设置接收方私人信息、接收方处理顺序、
+ * 签署认证等级、接收方所在企业名称、信封自定义元数据信息、预设表单信息.
+ */
+ public class Receiver
+ {
+ /**
+ * 接收方名字.
+ */
+ public string Name { get; set; }
+ /**
+ * 接收方联系方式.
+ */
+ public Contact Contact { get; set; }
+ /**
+ * 安全等级.
+ *
+ * 对应枚举:SecureLevel
+ *
+ */
+ public SecureLevel SecureLevel { get; set; }
+ /**
+ * 接收方类型。 接收方类型:ReceiverType
+ *
+ */
+ public ReceiverType Type { get; set; }
+ /**
+ * 接收方是否必须预分配表单域.
+ */
+ public bool NeedForm { get; set; }
+ /**
+ * 设置接收方私人信息.
+ */
+ public string AssignedMessage { get; set; }
+ /**
+ * 接收方处理顺序.
+ */
+ public int AssignedSequence { get; set; }
+
+ /**
+ * 接收方所在企业名称.
+ */
+ public string EnterpriseName { get; set; }
+ /**
+ * 信封自定义元数据信息.
+ */
+ public string Metadata { get; set; }
+ /**
+ * 预设表单信息.
+ */
+ public IList PresetForms { get; set; }
+
+ public EnvelopeRoleType RoleType { get; set; }
+
+ /**
+ * 流程完成后删除当前参与者的信封。 默认:false
+ *
+ */
+ public bool DeleteCompletedEnvelope { get; set; }
+ /**
+ * 参与者处理表单各种模式的枚举
+ */
+ public ParticipantHandleMode HandleMode { get; set; }
+
+ public IList SelectedAuthTypes { get; set; }
+
+ /**
+ * 启用嵌入模式,调用方系统中直接嵌入易企签WEB流程时设置为true,签署流程消息只会通过webhook事件消息方式通知,用户在易企签平台设置的短信/邮件等消息将自动屏蔽。非必填,默认值:false.
+ * @since 2.1.0
+ */
+ public bool EnableEmbeddedMode { get; set; }
+
+ /**
+ * 签署接收方用户在调用方系统的唯一标识.
+ * enableEmbeddedMode为false时,非必填;当enableEmbeddedMode为true时,则必填。默认:null
+ * @since 2.1.0
+ */
+ public string ClientId { get; set; }
+ }
+}
diff --git a/Sdk/Entity/RectanglePosition.cs b/Sdk/Entity/RectanglePosition.cs
new file mode 100644
index 0000000000000000000000000000000000000000..191b915319887c334a5dab60ffbdc4499be30b93
--- /dev/null
+++ b/Sdk/Entity/RectanglePosition.cs
@@ -0,0 +1,12 @@
+namespace Signit.Sdk.Entity
+{
+ public class RectanglePosition
+ {
+ public float? Lrx { get; set; }
+ public float? Lry { get; set; }
+ public float? Ulx { get; set; }
+ public float? Uly { get; set; }
+ public float? Scale { get; set; }
+ public int? Page { get; set; }
+ }
+}
diff --git a/Sdk/Entity/SealData.cs b/Sdk/Entity/SealData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4a9cbe8b59e470b46052dfb9d147688b34cf3c5d
--- /dev/null
+++ b/Sdk/Entity/SealData.cs
@@ -0,0 +1,7 @@
+namespace Signit.Sdk.Entity
+{
+ public class SealData : FileData
+ {
+ public string Name { get; set; }
+ }
+}
diff --git a/Sdk/Entity/Sender.cs b/Sdk/Entity/Sender.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7b85d6752f7cb62fe32fe0c94e57bd1dbf0ac3b0
--- /dev/null
+++ b/Sdk/Entity/Sender.cs
@@ -0,0 +1,37 @@
+namespace Signit.Sdk.Entity
+{
+ /**
+ * 发送方信息。 包含姓名和联系方式.
+ */
+ public class Sender
+ {
+ /**
+ * 发送者名字.
+ */
+ public string Name { get; set; }
+
+ /**
+ * 发送者联系方式.
+ */
+
+ public Contact Contact { get; set; }
+ /**
+ * 流程完成后删除当前参与者的信封.
+ * 默认:false
+ *
+ */
+ public bool DeleteCompletedEnvelope { get; set; }
+
+ /**
+ * 启用嵌入模式,调用方系统中直接嵌入易企签WEB流程时设置为true,签署流程消息只会通过webhook事件消息方式通知,用户在易企签平台设置的短信/邮件等消息将自动屏蔽。非必填,默认值:false.
+ * @since 2.1.0
+ */
+ public bool EnableEmbeddedMode { get; set; }
+
+ /**
+ * 签署发送方用户在调用方系统的唯一标识.
+ * enableEmbeddedMode为false时,非必填;当enableEmbeddedMode为true时,则必填。默认:null
+ */
+ public string ClientId { get; set; }
+ }
+}
diff --git a/Sdk/Entity/Signer.cs b/Sdk/Entity/Signer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..108f6ea0199dd4b4278460b2e790bd66d608d39f
--- /dev/null
+++ b/Sdk/Entity/Signer.cs
@@ -0,0 +1,10 @@
+namespace Signit.Sdk.Entity
+{
+ public class Signer
+ {
+ public int Sequence { get; set; }
+ public SignerPosition Position { get; set; }
+ public SignerData Data { get; set; }
+ public SignerInfo SignerInfo { get; set; }
+ }
+}
diff --git a/Sdk/Entity/SignerData.cs b/Sdk/Entity/SignerData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b51473b32ee95525611bea56f68d0e0859970ae5
--- /dev/null
+++ b/Sdk/Entity/SignerData.cs
@@ -0,0 +1,8 @@
+namespace Signit.Sdk.Entity
+{
+ public class SignerData
+ {
+ public SealData SealData { get; set; }
+ public SealData WriteData { get; set; }
+ }
+}
diff --git a/Sdk/Entity/SignerInfo.cs b/Sdk/Entity/SignerInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1a02239f30c98b784b5b30ca39b23434327f11e4
--- /dev/null
+++ b/Sdk/Entity/SignerInfo.cs
@@ -0,0 +1,12 @@
+namespace Signit.Sdk.Entity
+{
+ public class SignerInfo
+ {
+ public string Name { get; set; }
+ public string OrgnizationName { get; set; }
+ public string IdCardNo { get; set; }
+ public string Location { get; set; }
+ public string Contact { get; set; }
+ public string Reason { get; set; }
+ }
+}
diff --git a/Sdk/Entity/SignerPosition.cs b/Sdk/Entity/SignerPosition.cs
new file mode 100644
index 0000000000000000000000000000000000000000..37b302f03501fa2bef544ddebf21c11da7c05b82
--- /dev/null
+++ b/Sdk/Entity/SignerPosition.cs
@@ -0,0 +1,79 @@
+namespace Signit.Sdk.Entity
+{
+ public class SignerPosition
+ {
+ public static Builder CreateBuilder() => new Builder();
+
+ public KeywordPosition KeywordPosition { get; set; }
+ public RectanglePosition RectanglePosition { get; set; }
+ public string FieldName { get; set; }
+
+ /**
+ * 表单坐标位置对象建造器
+ *
+ * @since 1.0.0
+ */
+ public class Builder
+ {
+ private KeywordPosition keywordPosition;
+ private RectanglePosition rectanglePosition;
+ private string fieldName;
+
+ /**
+ *
+ * @param keywordPosition
+ * 利用关键字定位签名矩形框所在位置的数据对象;利用关键字进行定位
+ * {@link KeywordPosition}
+ * @return 利用关键字定位签名矩形框所在位置的数据对象建造器{@link PositionBuilder}
+ * @since 1.0.0
+ */
+ public Builder WithKeywordPosition(KeywordPosition keywordPosition)
+ {
+ this.keywordPosition = keywordPosition;
+ return this;
+ }
+
+ /**
+ *
+ * @param rectanglePosition
+ * 直接设定好的签名矩形框坐标 {@link RectanglePosition}
+ * @return 利用关键字定位签名矩形框所在位置的数据对象建造器{@link PositionBuilder}
+ * @since 1.0.0
+ */
+ public Builder WithRectanglePosition(RectanglePosition rectanglePosition)
+ {
+ this.rectanglePosition = rectanglePosition;
+ return this;
+ }
+
+ /**
+ *
+ * @param fieldsName
+ * 签名域名称;签名文件格式需要是pdf,且签名文件中已经设置好签名域名称对应的签名域
+ * @return 利用关键字定位签名矩形框所在位置的数据对象建造器{@link PositionBuilder}
+ * @since 1.0.0
+ */
+ public Builder WithFieldName(string fieldName)
+ {
+ this.fieldName = fieldName;
+ return this;
+ }
+
+ /**
+ *
+ * @return 表单坐标位置对象 {@link Position}
+ * @since 1.0.0
+ */
+ public SignerPosition Build()
+ {
+ return new SignerPosition
+ {
+ KeywordPosition = keywordPosition,
+ RectanglePosition = rectanglePosition,
+ FieldName = fieldName,
+ };
+ }
+ }
+
+ }
+}
diff --git a/Sdk/Entity/WriteData.cs b/Sdk/Entity/WriteData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..660ec9d5cc78b120bb23855ad66d9cc1cd6f2933
--- /dev/null
+++ b/Sdk/Entity/WriteData.cs
@@ -0,0 +1,18 @@
+namespace Signit.Sdk.Entity
+{
+ /**
+ * 手写签名数据. 支持URL/Base64/签名全局唯一ID/签名名字,代表签名数据.
+ */
+ public class WriteData : BaseFileData
+ {
+ /**
+ * 手写签名全局唯一ID.
+ */
+ public string Wsid { get; set; }
+
+ /**
+ * 手写签名名子.
+ */
+ public string Name { get; set; }
+ }
+}
diff --git a/Sdk/Extentions/StreamExtention.cs b/Sdk/Extentions/StreamExtention.cs
new file mode 100644
index 0000000000000000000000000000000000000000..015d6b691e9778b0aa06fbb992949f1f617ec9ae
--- /dev/null
+++ b/Sdk/Extentions/StreamExtention.cs
@@ -0,0 +1,30 @@
+using System.IO;
+using Viyi.Util.Linq;
+
+namespace Signit.Sdk.Extentions
+{
+ public static class StreamExtention
+ {
+ public static T Write(this T stream, byte[] data)
+ where T : Stream
+ {
+ stream.Write(data, 0, data.Length);
+ return stream;
+ }
+
+ public static T Write(this T stream, byte[] data, byte[] suffix)
+ where T : Stream
+ {
+ stream.Write(data);
+ stream.Write(suffix);
+ return stream;
+ }
+
+ public static T Write(this T stream, params byte[][] multiData)
+ where T : Stream
+ {
+ multiData.ForEach(data => stream.Write(data));
+ return stream;
+ }
+ }
+}
diff --git a/Sdk/Extentions/TaskExtentions.cs b/Sdk/Extentions/TaskExtentions.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6a9e67c18015e713a047302ebb3bb1cd8cdcfcf5
--- /dev/null
+++ b/Sdk/Extentions/TaskExtentions.cs
@@ -0,0 +1,13 @@
+using System.Threading.Tasks;
+
+namespace Signit.Sdk.Extentions
+{
+ public static class TaskExtentions
+ {
+ public static T WaitResult(this Task task)
+ {
+ task.Wait();
+ return task.Result;
+ }
+ }
+}
diff --git a/Sdk/Http/AbstractSignitRequest.cs b/Sdk/Http/AbstractSignitRequest.cs
new file mode 100644
index 0000000000000000000000000000000000000000..36ea6e890f56d7ca9b1f6c40ea45f96dd18b2abb
--- /dev/null
+++ b/Sdk/Http/AbstractSignitRequest.cs
@@ -0,0 +1,22 @@
+using Signit.Sdk.Types;
+
+namespace Signit.Sdk.Http
+{
+ public abstract class AbstractSignitRequest
+ {
+ ///
+ /// 调用方自定义标识,易企签会原封不动返回.
+ ///
+ public string CustomTag { get; set; }
+
+ ///
+ /// 调用方自定义要求易企签的WEB平台在流程结束后需要跳转的指定URL地址
+ ///
+ public string ReturnUrl { get; set; }
+
+ ///
+ /// 调用方接受的响应数据类型,支持:BASE64/URL
+ ///
+ public AcceptDataType AcceptDataType { get; set; }
+ }
+}
diff --git a/Sdk/Http/AbstractSignitResponse.cs b/Sdk/Http/AbstractSignitResponse.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2f4056debac1d6c9b99968ffd37ff4fb97ad081f
--- /dev/null
+++ b/Sdk/Http/AbstractSignitResponse.cs
@@ -0,0 +1,31 @@
+namespace Signit.Sdk.Http
+{
+ public abstract class AbstractSignitResponse
+ {
+ public string Code { get; set; }
+ public string Message { get; set; }
+
+ // 自定义标识
+ public string CustomTag { get; set; }
+
+ // 服务调用唯一标识
+ public string InvokeNo { get; set; }
+
+ public bool IsSuccess
+ {
+ get
+ {
+ if (Code == null || Code.Length < 4)
+ {
+ return false;
+ }
+
+ var descCode = Code.Substring(Code.Length - 4);
+ return int.TryParse(descCode, out int code)
+ && code >= 0 && code < 100;
+ }
+ }
+
+ public ErrorResponse Error { get; set; }
+ }
+}
diff --git a/Sdk/Http/ApiOptions.cs b/Sdk/Http/ApiOptions.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f8cb95812fe05087365262c04c39540274344bf8
--- /dev/null
+++ b/Sdk/Http/ApiOptions.cs
@@ -0,0 +1,16 @@
+namespace Signit.Sdk.Http
+{
+ public class ApiOptions
+ {
+ public static ApiOptions Default => new ApiOptions();
+
+ public string EnvUrl = "https://open.signit.cn";
+ public string Encoding = "UTF-8";
+ public string BaseApiUrl = "/v1/open/signatures/quick-sign";
+ public string OAuthTokenUrl = "/v1/oauth/oauth/token";
+ public string ClientId = "client_id";
+ public string ClientSecret = "client_secret";
+ public string GrantType = "grant_type";
+ public string AppIdKey = "X-Signit-App-Id";
+ }
+}
diff --git a/Sdk/Http/Authentication.cs b/Sdk/Http/Authentication.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7f9e568523feee81ff8552a22a26e0ce27a124a8
--- /dev/null
+++ b/Sdk/Http/Authentication.cs
@@ -0,0 +1,114 @@
+using Signit.Sdk.Types;
+using Signit.Sdk.Util;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+using Viyi.Util.Codec;
+
+namespace Signit.Sdk.Http
+{
+ public class Authentication
+ {
+ private const string KeyBase64 = "9ijhWI+0fNf0RSRJxgPt7q2zciyGVxmcco95I+gKids=";
+
+ public string AppId { get; set; } = "";
+ public string SecuretKey { get; set; } = "";
+ public string AccessToken { get; set; } = "";
+ public TokenType AccessTokenType { get; set; } = TokenType.CLIENT_CREDENTIALS;
+
+ // TODO private string cacheTokenDir = System.getProperty("java.io.tmpdir");
+ public string CacheTokenDir = Path.GetTempPath();
+
+
+ public Authentication() { }
+
+ public Authentication(string apiKey, string secretKey, TokenType authType)
+ {
+ AppId = apiKey;
+ SecuretKey = secretKey;
+ AccessTokenType = authType;
+ InitFromLocal();
+ }
+
+ public bool HasAppId => !string.IsNullOrEmpty(AppId);
+ public bool HasSecretKey => !string.IsNullOrEmpty(SecuretKey);
+
+ public bool HasAccessToken
+ {
+ get
+ {
+ InitFromLocal();
+ return !string.IsNullOrEmpty(AccessToken);
+ }
+ }
+
+ private void CacheToLocal()
+ {
+ if (!string.IsNullOrWhiteSpace(AccessToken))
+ {
+ return;
+ }
+
+ string filePath = GenerateCachedTokenFilename();
+ if (filePath == null)
+ {
+ return;
+ }
+
+ try
+ {
+ byte[] data = Encoding.ASCII.GetBytes(AccessToken);
+ byte[] secretData = data.AesEncrypt(KeyBase64);
+ File.WriteAllBytes(filePath, secretData);
+ }
+ catch
+ {
+ // DO-NOTHING
+ return;
+ }
+ }
+
+ private void InitFromLocal()
+ {
+ if (!string.IsNullOrWhiteSpace(AccessToken))
+ {
+ return;
+ }
+
+ string filePath = GenerateCachedTokenFilename();
+ if (filePath == null || !File.Exists(filePath))
+ {
+ return;
+ }
+
+ try
+ {
+ var secretData = File.ReadAllBytes(filePath);
+ var data = secretData.AesDecrypt(KeyBase64);
+ AccessToken = Encoding.ASCII.GetString(data);
+ }
+ catch
+ {
+ // DO-NOTHING
+ return;
+ }
+ }
+
+ private string GenerateCachedTokenFilename()
+ {
+ if (string.IsNullOrEmpty(AppId) || string.IsNullOrEmpty(SecuretKey))
+ {
+ return null;
+ }
+
+ var combine = string.Join(",", new[]
+ {
+ AppId, SecuretKey, AccessTokenType.ToString()
+ });
+
+ var hash = MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(combine));
+ var filename = Path.Combine(CacheTokenDir, hash.Base64Encode());
+ return filename;
+ }
+ }
+}
diff --git a/Sdk/Http/Enterprise/EnterpriseAgent.cs b/Sdk/Http/Enterprise/EnterpriseAgent.cs
new file mode 100644
index 0000000000000000000000000000000000000000..18887bb2ca51c009a547456846cf68b8aa964e7e
--- /dev/null
+++ b/Sdk/Http/Enterprise/EnterpriseAgent.cs
@@ -0,0 +1,42 @@
+using Signit.Sdk.Entity;
+using Signit.Sdk.Types;
+using System.Collections.Generic;
+
+namespace Signit.Sdk.Http.Enterprise
+{
+ ///
+ /// 经办人信息
+ ///
+ public class EnterpriseAgent
+ {
+ ///
+ /// 委托书照片信息.
+ ///
+ public IdCardImage TrustInstrumentImage { get; set; }
+
+ ///
+ /// 待认证的用户姓名.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 待认证的用户手机号.
+ ///
+ public string Phone { get; set; }
+
+ ///
+ /// 待认证的用户证件类型.
+ ///
+ public IdCardType IdCardType { get; set; }
+
+ ///
+ /// 待认证的用户证件号.
+ ///
+ public string IdCardNo { get; set; }
+
+ ///
+ /// 待认证的用户证件照片数组.
+ ///
+ public IList IdCardImages { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Http/Enterprise/EnterpriseBankCardInfo.cs b/Sdk/Http/Enterprise/EnterpriseBankCardInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1fe9d02b3ddf4d4a32ae6c137b67cb2477d3e539
--- /dev/null
+++ b/Sdk/Http/Enterprise/EnterpriseBankCardInfo.cs
@@ -0,0 +1,33 @@
+namespace Signit.Sdk.Http.Enterprise
+{
+ ///
+ /// 对公银行账户信息
+ ///
+ public class EnterpriseBankCardInfo
+ {
+ ///
+ /// 银行(如:中国农业银行等).
+ ///
+ public string Bank { get; set; }
+
+ ///
+ /// 银行支行.
+ ///
+ public string BankBranch { get; set; }
+
+ ///
+ /// 银行卡号.
+ ///
+ public string BankCardNo { get; set; }
+
+ ///
+ /// 地区(省,市,区/县).
+ ///
+ public string Area { get; set; }
+
+ ///
+ /// 联行号.
+ ///
+ public string UnionBankNo { get; set; }
+ }
+}
diff --git a/Sdk/Http/Enterprise/EnterpriseLegalPerson.cs b/Sdk/Http/Enterprise/EnterpriseLegalPerson.cs
new file mode 100644
index 0000000000000000000000000000000000000000..24a63386ea0983ffb3a449eb45a2b8c6feb4df21
--- /dev/null
+++ b/Sdk/Http/Enterprise/EnterpriseLegalPerson.cs
@@ -0,0 +1,37 @@
+using Signit.Sdk.Entity;
+using Signit.Sdk.Types;
+using System.Collections.Generic;
+
+namespace Signit.Sdk.Http.Enterprise
+{
+ ///
+ /// 法人信息
+ ///
+ public class EnterpriseLegalPerson
+ {
+ ///
+ /// 待认证的用户姓名.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 待认证的用户手机号.
+ ///
+ public string Phone { get; set; }
+
+ ///
+ /// 待认证的用户证件类型.
+ ///
+ public IdCardType IdCardType { get; set; }
+
+ ///
+ /// 待认证的用户证件号.
+ ///
+ public string IdCardNo { get; set; }
+
+ ///
+ /// 待认证的用户证件照片数组.
+ ///
+ public IList IdCardImages { get; set; }
+ }
+}
diff --git a/Sdk/Http/Enterprise/EnterpriseVerifyRequest.cs b/Sdk/Http/Enterprise/EnterpriseVerifyRequest.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0745b3e7e3be9a690f5a6244162b0566638fce8c
--- /dev/null
+++ b/Sdk/Http/Enterprise/EnterpriseVerifyRequest.cs
@@ -0,0 +1,67 @@
+using Signit.Sdk.Entity;
+using Signit.Sdk.Types;
+using System.Collections.Generic;
+
+namespace Signit.Sdk.Http.Enterprise
+{
+ ///
+ /// 企业实名认证请求数据结构.
+ ///
+ public class EnterpriseVerifyRequest : AbstractSignitRequest
+ {
+ ///
+ /// 待认证企业名称.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 经办人信息.
+ ///
+ public EnterpriseAgent Agent { get; set; }
+
+ ///
+ /// 法人信息.
+ ///
+ public EnterpriseLegalPerson LegalPerson { get; set; }
+
+ ///
+ /// 统一社会信用代码.
+ ///
+ public string UnifiedSocialCode { get; set; }
+
+ ///
+ /// 营业执照照片信息.
+ ///
+ public IdCardImage BusinessLicenceImage { get; set; }
+
+ ///
+ /// 组织机构代码(已由“统一社会信用代码”替换).
+ ///
+ public string OrgCode { get; set; }
+
+ ///
+ /// 组织机构代码证照片信息.
+ ///
+ public IdCardImage OrgImage { get; set; }
+
+ ///
+ /// 工商注册号(已由“统一社会信用代码”替换).
+ ///
+ public string RegistCode { get; set; }
+
+ ///
+ /// LEGAL_PERSON-法人认证,AGENT-经办人认证.
+ ///
+ public EnterpriseAuthType AuthType { get; set; }
+
+ ///
+ /// 企业对公银行信息.
+ ///
+ public EnterpriseBankCardInfo BankCardInfo { get; set; }
+
+ ///
+ /// 额外认证所需照片信息数组.
+ ///
+ public IList ExtraAuthImages { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Http/Enterprise/EnterpriseVerifyResponse.cs b/Sdk/Http/Enterprise/EnterpriseVerifyResponse.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ef2f99250e669a1816fc3de36679575f8429574f
--- /dev/null
+++ b/Sdk/Http/Enterprise/EnterpriseVerifyResponse.cs
@@ -0,0 +1,6 @@
+namespace Signit.Sdk.Http.Enterprise
+{
+ public class EnterpriseVerifyResponse : AbstractSignitResponse
+ {
+ }
+}
diff --git a/Sdk/Http/Envelope/EnvelopeBasicInfo.cs b/Sdk/Http/Envelope/EnvelopeBasicInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4ee4af034ba141bc9d83ed7ee0e89361f47f6497
--- /dev/null
+++ b/Sdk/Http/Envelope/EnvelopeBasicInfo.cs
@@ -0,0 +1,37 @@
+using Signit.Sdk.Types;
+
+namespace Signit.Sdk.Http.Envelope
+{
+ /**
+ * 信封基本信息. 包含信封标题、信封主题、信封类型、信封认证等级、自定义元数据信息.
+ */
+ public class EnvelopeBasicInfo
+ {
+ /**
+ * 信封标题.
+ */
+ public string Title { get; set; }
+
+ /**
+ * 信封主题.
+ */
+ public string Subject { get; set; }
+
+ /**
+ * 信封类型.
+ * 对应枚举:EnvelopeType
+ */
+ public EnvelopeType Type { get; set; }
+
+ /**
+ * 信封认证等级.
+ * 对应枚举:AuthLevel
+ */
+ public AuthLevel AuthLevel { get; set; }
+
+ /**
+ * 自定义元数据信息.
+ */
+ public string Metadata { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Http/Envelope/EnvelopeContentInfo.cs b/Sdk/Http/Envelope/EnvelopeContentInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..84da7d0d4d9e45ba057db99f369664abb9c5513f
--- /dev/null
+++ b/Sdk/Http/Envelope/EnvelopeContentInfo.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+
+namespace Signit.Sdk.Http.Envelope
+{
+ /**
+ * 签署文件内容
+ */
+ public class EnvelopeContentInfo
+ {
+ /**
+ * 签署文件详细信息列表.
+ */
+ public IList Files { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Http/Envelope/EnvelopeFile.cs b/Sdk/Http/Envelope/EnvelopeFile.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5641bce40225d13684634816baf2930fae361a1d
--- /dev/null
+++ b/Sdk/Http/Envelope/EnvelopeFile.cs
@@ -0,0 +1,55 @@
+using Signit.Sdk.Entity;
+using Signit.Sdk.Types;
+
+namespace Signit.Sdk.Http.Envelope
+{
+ ///
+ /// 签署文件详细信息。包含:待签文件i唯一标识ID、该文件排列顺序、签署文件的数据、
+ /// 文件名、文件拥有者访问口令、文件类型、文件是否作为附件、自定义元数据信息
+ ///
+ public class EnvelopeFile
+ {
+ ///
+ /// 待签文件唯一标识ID.
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 该文件排列顺序.
+ ///
+ public int Sequence { get; set; }
+
+ ///
+ /// 签署文件的数据.
+ ///
+ public BaseFileData Data { get; set; }
+
+ ///
+ /// 文件名.
+ ///
+ public string FileName { get; set; }
+
+ ///
+ /// 文件拥有者访问口令.
+ ///
+ public string FileOverPassin { get; set; }
+
+ ///
+ /// 文件类型.
+ /// 对应枚举:FileType
+ ///
+ public FileType ContentType { get; set; }
+
+ ///
+ /// 文件是否作为附件.
+ /// 默认为false
+ ///
+ public bool IsAttached { get; set; }
+
+ ///
+ /// 自定义元数据信息.
+ ///
+ public string Metadata { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Http/Envelope/EnvelopeParticipantInfo.cs b/Sdk/Http/Envelope/EnvelopeParticipantInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..893cc32e18303f1496bcbc524a19aee7aeeec980
--- /dev/null
+++ b/Sdk/Http/Envelope/EnvelopeParticipantInfo.cs
@@ -0,0 +1,21 @@
+using Signit.Sdk.Entity;
+using System.Collections.Generic;
+
+namespace Signit.Sdk.Http.Envelope
+{
+ /**
+ * 参与文件签署人员的信息. 包含发送者信息和接受者信息列表.
+ */
+ public class EnvelopeParticipantInfo
+ {
+ /**
+ * 发送者信息.
+ */
+ public Sender Sender { get; set; }
+
+ /**
+ * 接受者信息列表.
+ */
+ public IList Receivers { get; set; }
+ }
+}
diff --git a/Sdk/Http/Envelope/StartEnvelopeRequest.cs b/Sdk/Http/Envelope/StartEnvelopeRequest.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b7f8e9967c9e12a4f9e3c388f982f4f306a118c5
--- /dev/null
+++ b/Sdk/Http/Envelope/StartEnvelopeRequest.cs
@@ -0,0 +1,23 @@
+namespace Signit.Sdk.Http.Envelope
+{
+ ///
+ /// 信封启动服务请求体. 包含信封基本信息、信封流程中的签署文件内容、签署参与者信息、自定义跳转URL、自定义可接受数据类型、自定义标识.
+ ///
+ public class StartEnvelopeRequest : AbstractSignitRequest
+ {
+ ///
+ /// 信封基本信息.
+ ///
+ public EnvelopeBasicInfo Basicinfo { get; set; }
+
+ ///
+ /// 信封流程中的签署文件内容.
+ ///
+ public EnvelopeContentInfo ContentInfo { get; set; }
+
+ ///
+ /// 签署参与者信息.
+ ///
+ public EnvelopeParticipantInfo ParticipantInfo { get; set; }
+ }
+}
diff --git a/Sdk/Http/Envelope/StartEnvelopeResponse.cs b/Sdk/Http/Envelope/StartEnvelopeResponse.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d9c55a1f9e4d8039fc98fa043cf244a055e7eef2
--- /dev/null
+++ b/Sdk/Http/Envelope/StartEnvelopeResponse.cs
@@ -0,0 +1,11 @@
+namespace Signit.Sdk.Http.Envelope
+{
+ ///
+ /// 启动信封响应
+ ///
+ public class StartEnvelopeResponse : AbstractSignitResponse
+ {
+
+ }
+
+}
diff --git a/Sdk/Http/ErrorResponse.cs b/Sdk/Http/ErrorResponse.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4aa9c7df05945c49437ade2197a3d1d5a69d35d8
--- /dev/null
+++ b/Sdk/Http/ErrorResponse.cs
@@ -0,0 +1,11 @@
+namespace Signit.Sdk.Http
+{
+ public class ErrorResponse
+ {
+ public string Code { get; set; }
+ public string ErrorWsid { get; set; }
+ public string UserMessage { get; set; }
+ public string DeveloperMessage { get; set; }
+ public string MoreInfo { get; set; }
+ }
+}
diff --git a/Sdk/Http/HttpClientSync.Response.cs b/Sdk/Http/HttpClientSync.Response.cs
new file mode 100644
index 0000000000000000000000000000000000000000..546d403f914242dadc5578b38fc6fec565f26d34
--- /dev/null
+++ b/Sdk/Http/HttpClientSync.Response.cs
@@ -0,0 +1,22 @@
+using Newtonsoft.Json;
+using System.Net;
+
+namespace Signit.Sdk.Http
+{
+ partial class HttpClientSync
+ {
+ public class Response
+ {
+ public HttpStatusCode Code { get; set; }
+ public string Content { get; set; }
+ public bool IsSuccessStatusCode { get; internal set; }
+
+ public T GetObject()
+ {
+ return string.IsNullOrWhiteSpace(Content)
+ ? default(T)
+ : JsonConvert.DeserializeObject(Content);
+ }
+ }
+ }
+}
diff --git a/Sdk/Http/HttpClientSync.cs b/Sdk/Http/HttpClientSync.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9652a3bca58a4057ff89eacb81ab6f539998d2d2
--- /dev/null
+++ b/Sdk/Http/HttpClientSync.cs
@@ -0,0 +1,105 @@
+using Signit.Sdk.Extentions;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using System.Linq;
+using System.Net.Http;
+using System.Web;
+using Viyi.Util.Linq;
+
+namespace Signit.Sdk.Http
+{
+ partial class HttpClientSync
+ {
+ private const string USER_AGENT = "Signit HTTP";
+ private const string DEFAULT_ENCODING = "UTF-8";
+
+ private static Response ConvertResponse(HttpResponseMessage response, bool needContentOnError = false)
+ {
+ var result = new Response()
+ {
+ IsSuccessStatusCode = response.IsSuccessStatusCode,
+ Code = response.StatusCode
+ };
+
+ if (needContentOnError || response.IsSuccessStatusCode)
+ {
+ result.Content = response.Content.ReadAsStringAsync().WaitResult();
+ }
+
+ Debug.WriteLine($"[RESPONSE] {result.Content}");
+ return result;
+ }
+
+ private NameValueCollection queryParams = new NameValueCollection();
+ private Authentication authentication;
+
+ public Response Get(string url)
+ {
+ url = ConcatQueryString(url);
+
+ Debug.WriteLine($"[GET] {url}");
+ HttpClient client = new HttpClient();
+ var response = client.GetAsync(url).WaitResult();
+ return ConvertResponse(response);
+ }
+
+ public Response Post(string url, object payload, NameValueCollection headers = null)
+ {
+ url = ConcatQueryString(url);
+ url = ConcatQueryParam(url, "access_token", authentication.AccessToken);
+
+ var content = new JsonContent(payload);
+
+ HttpClient client = new HttpClient();
+ client.DefaultRequestHeaders.Add("Accept", "application/json");
+ client.DefaultRequestHeaders.Add("Accept-Encoding", DEFAULT_ENCODING);
+ client.DefaultRequestHeaders.Add("User-Agent", USER_AGENT);
+
+ headers?.AllKeys.ForEach(key =>
+ {
+ client.DefaultRequestHeaders.Add(key, headers[key]);
+ });
+
+ Debug.WriteLine($"[POST] {url}");
+ var response = client.PostAsync(url, content).WaitResult();
+ return ConvertResponse(response, true);
+ }
+
+
+ private static string ConcatQueryParam(string url, string key, string value)
+ {
+ var pair = $"{key}={HttpUtility.UrlEncode(value)}";
+ return $"{url}{(url.Contains("?") ? "&" : "?")}{pair}";
+ }
+
+ private string ConcatQueryString(string url)
+ {
+ var pairs = queryParams.AllKeys
+ .SelectMany(key =>
+ {
+ return queryParams.GetValues(key)
+ .Select(v => $"{key}={HttpUtility.UrlEncode(v)}");
+ });
+ var queryString = string.Join("&", pairs);
+
+ if (!string.IsNullOrEmpty(queryString))
+ {
+ url = $"{url}{(url.Contains("?") ? "&" : "?")}{queryString}";
+ }
+
+ return url;
+ }
+
+ public HttpClientSync AddQueryParam(string name, string value)
+ {
+ queryParams.Add(name, value);
+ return this;
+ }
+
+ public HttpClientSync WithAuthentication(Authentication auth)
+ {
+ authentication = auth;
+ return this;
+ }
+ }
+}
diff --git a/Sdk/Http/JsonContent.cs b/Sdk/Http/JsonContent.cs
new file mode 100644
index 0000000000000000000000000000000000000000..28253da1e377ee0e543eb3a7c64ed01f223d3a72
--- /dev/null
+++ b/Sdk/Http/JsonContent.cs
@@ -0,0 +1,31 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Serialization;
+using System.Net.Http;
+using System.Text;
+
+namespace Signit.Sdk.Http
+{
+ public class JsonContent : StringContent
+ {
+ public JsonContent(object model) : base(ToJson(model), Encoding.UTF8, "application/json") { }
+
+ private static readonly JsonSerializerSettings defaultJsonSettings = CreateDefaultJsonSettings();
+
+ private static JsonSerializerSettings CreateDefaultJsonSettings()
+ {
+ var settings = new JsonSerializerSettings
+ {
+ ContractResolver = new CamelCasePropertyNamesContractResolver(),
+ };
+
+ settings.Converters.Add(new StringEnumConverter());
+ return settings;
+ }
+
+ private static string ToJson(object model, JsonSerializerSettings settings = null)
+ {
+ return JsonConvert.SerializeObject(model, settings ?? defaultJsonSettings);
+ }
+ }
+}
diff --git a/Sdk/Http/OAuthData.cs b/Sdk/Http/OAuthData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6fdfd42869ce8cf57d33e4a60469c995e9e90cba
--- /dev/null
+++ b/Sdk/Http/OAuthData.cs
@@ -0,0 +1,31 @@
+namespace Signit.Sdk.Http
+{
+ public class OAuthData
+ {
+ public string access_token { private get; set; }
+ public string token_type { private get; set; }
+ public int expires_in { private get; set; }
+ public string scope { private get; set; }
+
+ public string AccessToken
+ {
+ get => access_token;
+ set => access_token = value;
+ }
+ public string TokenType
+ {
+ get => token_type;
+ set => token_type = value;
+ }
+ public int ExpiresIn
+ {
+ get => expires_in;
+ set => expires_in = value;
+ }
+ public string Scope
+ {
+ get => scope;
+ set => scope = value;
+ }
+ }
+}
diff --git a/Sdk/Http/PersonVerifyResponse.cs b/Sdk/Http/PersonVerifyResponse.cs
new file mode 100644
index 0000000000000000000000000000000000000000..dfd0d7a03884e9986a0cba7125a7b4f87bae8b58
--- /dev/null
+++ b/Sdk/Http/PersonVerifyResponse.cs
@@ -0,0 +1,10 @@
+namespace Signit.Sdk.Http
+{
+ ///
+ /// 个人实名认证响应.
+ ///
+ public class PersonVerifyResponse : AbstractSignitResponse
+ {
+ }
+
+}
diff --git a/Sdk/Http/SignatureRequest.cs b/Sdk/Http/SignatureRequest.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0d99b8edf996895cde30988484dd87a308d02fee
--- /dev/null
+++ b/Sdk/Http/SignatureRequest.cs
@@ -0,0 +1,11 @@
+using Signit.Sdk.Entity;
+using System.Collections.Generic;
+
+namespace Signit.Sdk.Http
+{
+ public class SignatureRequest : AbstractSignitRequest
+ {
+ public FileData FileData;
+ public IList SignDetails;
+ }
+}
diff --git a/Sdk/Http/SignatureResponse.cs b/Sdk/Http/SignatureResponse.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5be40c9df449bc04a6ed8a340c26e8c9657a0d6f
--- /dev/null
+++ b/Sdk/Http/SignatureResponse.cs
@@ -0,0 +1,6 @@
+namespace Signit.Sdk.Http
+{
+ public class SignatureResponse : AbstractSignitResponse
+ {
+ }
+}
diff --git a/Sdk/Http/Webhook/AbstractWebhookResponse.cs b/Sdk/Http/Webhook/AbstractWebhookResponse.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a15de35f1812d7826bb48cd4925ccc82b0273bf5
--- /dev/null
+++ b/Sdk/Http/Webhook/AbstractWebhookResponse.cs
@@ -0,0 +1,6 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class AbstractWebhookResponse : AbstractSignitResponse
+ {
+ }
+}
diff --git a/Sdk/Http/Webhook/BoContact.cs b/Sdk/Http/Webhook/BoContact.cs
new file mode 100644
index 0000000000000000000000000000000000000000..814998b813575338997dd130fb3dc8d154080c43
--- /dev/null
+++ b/Sdk/Http/Webhook/BoContact.cs
@@ -0,0 +1,14 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ /**
+ * 联系方式详细数据.
+ *
+ * @since 2.0.0
+ */
+ public class BoContact
+ {
+ public string AuthorWsid { get; set; }
+ public string Email { get; set; }
+ public string Sms { get; set; }
+ }
+}
diff --git a/Sdk/Http/Webhook/BoContactMetadata.cs b/Sdk/Http/Webhook/BoContactMetadata.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f96b0f0ab40a99e8c2732c6012d42c00268fb976
--- /dev/null
+++ b/Sdk/Http/Webhook/BoContactMetadata.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+
+namespace Signit.Sdk.Http.Webhook
+{
+ /**
+ * 联系方式元数据.
+ *
+ * @since 2.0.0
+ */
+ public class BoContactMetadata
+ {
+ public IList Contacts { get; set; }
+ }
+}
diff --git a/Sdk/Http/Webhook/EnterpriseVerificationCompleted.cs b/Sdk/Http/Webhook/EnterpriseVerificationCompleted.cs
new file mode 100644
index 0000000000000000000000000000000000000000..57117ee5856bf1e7b349928c9d171ebc1aadd838
--- /dev/null
+++ b/Sdk/Http/Webhook/EnterpriseVerificationCompleted.cs
@@ -0,0 +1,6 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class EnterpriseVerificationCompleted : EnterpriseVerificationPrimaryCompleted
+ {
+ }
+}
diff --git a/Sdk/Http/Webhook/EnterpriseVerificationPaid.cs b/Sdk/Http/Webhook/EnterpriseVerificationPaid.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1c1bd1d4344ce4196f2ff88e656d17bc412d2330
--- /dev/null
+++ b/Sdk/Http/Webhook/EnterpriseVerificationPaid.cs
@@ -0,0 +1,6 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class EnterpriseVerificationPaid : EnterpriseVerificationPrimaryCompleted
+ {
+ }
+}
diff --git a/Sdk/Http/Webhook/EnterpriseVerificationPrimaryCompleted.cs b/Sdk/Http/Webhook/EnterpriseVerificationPrimaryCompleted.cs
new file mode 100644
index 0000000000000000000000000000000000000000..16ec1beeb41b85437777f0648f0c41baa8c0cd5c
--- /dev/null
+++ b/Sdk/Http/Webhook/EnterpriseVerificationPrimaryCompleted.cs
@@ -0,0 +1,10 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class EnterpriseVerificationPrimaryCompleted : AbstractWebhookResponse
+ {
+ public string Description { get; set; }
+ public string Status { get; set; }
+ public long? HandleDatetime { get; set; }
+ public long? SubmitDatetime { get; set; }
+ }
+}
diff --git a/Sdk/Http/Webhook/EnterpriseVerificationSubmitted.cs b/Sdk/Http/Webhook/EnterpriseVerificationSubmitted.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4de3edd57dd81f76ad0c85c4617e91c9a86dc10e
--- /dev/null
+++ b/Sdk/Http/Webhook/EnterpriseVerificationSubmitted.cs
@@ -0,0 +1,8 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class EnterpriseVerificationSubmitted : AbstractWebhookResponse
+ {
+ private string Status {get;set;}
+ private string ActionUrl {get;set;}
+ }
+}
diff --git a/Sdk/Http/Webhook/EnvelopeCompleted.cs b/Sdk/Http/Webhook/EnvelopeCompleted.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d9885b84669d52bcd0188183936622658740ba74
--- /dev/null
+++ b/Sdk/Http/Webhook/EnvelopeCompleted.cs
@@ -0,0 +1,6 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class EnvelopeCompleted : EnvelopeStarted
+ {
+ }
+}
diff --git a/Sdk/Http/Webhook/EnvelopeStarted.cs b/Sdk/Http/Webhook/EnvelopeStarted.cs
new file mode 100644
index 0000000000000000000000000000000000000000..532a2812c03517e05d11d7a6088f1dea6d70b26d
--- /dev/null
+++ b/Sdk/Http/Webhook/EnvelopeStarted.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+
+namespace Signit.Sdk.Http.Webhook
+{
+ public class EnvelopeStarted : AbstractWebhookResponse
+ {
+ // 执行的动作对应的URL地址
+ public string ActionUrl { get; set; }
+
+ // 流程允许在易企签WEB执行的动作
+ public IList Actions { get; set; }
+
+ // 接收方对应的在易企签的帐号
+ public string Account { get; set; }
+
+ // 信封基本信息
+ public RawDataBasicInfo BasicEnvelope { get; set; }
+
+ public Sender SenderParticipant { get; set; }
+ public Receiver ReceiverParticipant { get; set; }
+
+ // 已完成的签署数据
+ public SignData SignData { get; set; }
+
+ // 客户端回调地址
+ public string ReturnUrl { get; set; }
+ }
+}
diff --git a/Sdk/Http/Webhook/ParticipantConfirmed.cs b/Sdk/Http/Webhook/ParticipantConfirmed.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9eb5459d12856769affc39875a78f9e1522c7b63
--- /dev/null
+++ b/Sdk/Http/Webhook/ParticipantConfirmed.cs
@@ -0,0 +1,6 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class ParticipantConfirmed : EnvelopeStarted
+ {
+ }
+}
diff --git a/Sdk/Http/Webhook/ParticipantHandling.cs b/Sdk/Http/Webhook/ParticipantHandling.cs
new file mode 100644
index 0000000000000000000000000000000000000000..670f379c9aa56c44f16cfcd2379431cc90717b3a
--- /dev/null
+++ b/Sdk/Http/Webhook/ParticipantHandling.cs
@@ -0,0 +1,29 @@
+using System.Collections.Generic;
+
+namespace Signit.Sdk.Http.Webhook
+{
+ public class ParticipantHandling : AbstractWebhookResponse
+ {
+ // 执行的动作对应的URL地址
+ public string ActionUrl { get; set; }
+
+ // 流程允许在易企签WEB执行的动作
+ public IList Actions { get; set; }
+
+ // 接收方对应的在易企签的帐号
+ public string Account { get; set; }
+
+ // 信封基本信息
+ public RawDataBasicInfo BasicEnvelope { get; set; }
+
+ public Sender SenderParticipant { get; set; }
+ public Receiver ReceiverParticipant { get; set; }
+
+ // 已完成的签署数据
+ public SignData SignData { get; set; }
+
+ // 客户端回调地址
+ public string ReturnUrl { get; set; }
+ }
+
+}
diff --git a/Sdk/Http/Webhook/ParticipantRejected.cs b/Sdk/Http/Webhook/ParticipantRejected.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ee4982a9e25e677636b80f43032538a609d801b7
--- /dev/null
+++ b/Sdk/Http/Webhook/ParticipantRejected.cs
@@ -0,0 +1,7 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class ParticipantRejected : EnvelopeStarted
+ {
+
+ }
+}
diff --git a/Sdk/Http/Webhook/PersonVerificationCompleted.cs b/Sdk/Http/Webhook/PersonVerificationCompleted.cs
new file mode 100644
index 0000000000000000000000000000000000000000..c7faf834e308092b338d56fc5b49f4848a091de3
--- /dev/null
+++ b/Sdk/Http/Webhook/PersonVerificationCompleted.cs
@@ -0,0 +1,12 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class PersonVerificationCompleted : AbstractWebhookResponse
+ {
+ public string Description { get; set; }
+ public string Status { get; set; }
+ public long? HandleDatetime { get; set; }
+ public long? SubmitDatetime { get; set; }
+
+ }
+
+}
diff --git a/Sdk/Http/Webhook/PersonVerificationSubmitted.cs b/Sdk/Http/Webhook/PersonVerificationSubmitted.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f1526a83ed67e0fea7734149465913d784827e7d
--- /dev/null
+++ b/Sdk/Http/Webhook/PersonVerificationSubmitted.cs
@@ -0,0 +1,8 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class PersonVerificationSubmitted : EnterpriseVerificationPrimaryCompleted
+ {
+
+ }
+
+}
diff --git a/Sdk/Http/Webhook/QuickSignCompleted.cs b/Sdk/Http/Webhook/QuickSignCompleted.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9607b3118d216062a4bc48ae3d3a66df8682af07
--- /dev/null
+++ b/Sdk/Http/Webhook/QuickSignCompleted.cs
@@ -0,0 +1,8 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class QuickSignCompleted : AbstractWebhookResponse
+ {
+ public string Url { get; set; }
+ public string Base64 { get; set; }
+ }
+}
diff --git a/Sdk/Http/Webhook/RawDataBasicInfo.cs b/Sdk/Http/Webhook/RawDataBasicInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a68643cba4a596db80773fce36e1fdac7e3b268d
--- /dev/null
+++ b/Sdk/Http/Webhook/RawDataBasicInfo.cs
@@ -0,0 +1,31 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ /**
+ * 信封基本信息.
+ *
+ * @since 2.0.0
+ */
+ public class RawDataBasicInfo
+ {
+ // 信封全局唯一ID
+ public string Wsid { get; set; }
+
+ // 信封状态
+ public string Status { get; set; }
+
+ // 信封创建时间
+ public long? CreatedDatetime { get; set; }
+
+ // 信封过期时间
+ public long? ExpireDatetime { get; set; }
+
+ // 信封最新状态时间
+ public long? StatusDatetime { get; set; }
+
+ // 信封最新状态原因
+ public string StatusReason { get; set; }
+
+ // 当前签署方的序号
+ public int? CurrentSequence { get; set; }
+ }
+}
diff --git a/Sdk/Http/Webhook/Receiver.cs b/Sdk/Http/Webhook/Receiver.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3708bb66b440eee9ee519b00e6d943ce8787ff0d
--- /dev/null
+++ b/Sdk/Http/Webhook/Receiver.cs
@@ -0,0 +1,56 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ /**
+ * 当前需要签署的接收方信息.
+ *
+ * @since 2.0.0
+ */
+ public class Receiver
+ {
+ // 接收方信息
+ public string Name { get; set; }
+
+ // 接收方联系方式
+ public BoContactMetadata ContactMetadata { get; set; }
+
+ // 安全级别
+ public string SecureLevel { get; set; }
+
+ // 接收方类型
+ public string Type { get; set; }
+
+ // 接收方角色类型
+ public string RoleType { get; set; }
+
+ // 接收方是否必须预分配表单域
+ public bool NeedForm { get; set; }
+
+ // 设置接收方私人信息
+ public string AssignedMessage { get; set; }
+
+ // 设置接收方处理顺序
+ public int? AssignedSequence { get; set; }
+
+ // 签署认证等级
+ public string AuthLevel { get; set; }
+
+ // 接收方所在企业名称
+ public string EnterpriseName { get; set; }
+
+ // 信封自定义元数据信息
+ public string Metadata { get; set; }
+
+ // 签署状态
+ public string Status { get; set; }
+
+ // 接收方全局唯一标识
+ public string Wsid { get; set; }
+
+ // 处理时间
+ public long? HandleDatetime { get; set; }
+
+ // 处理原因
+ public string HandleReason { get; set; }
+
+ }
+}
diff --git a/Sdk/Http/Webhook/Sender.cs b/Sdk/Http/Webhook/Sender.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2561eb49b5cc9f59bde869ec5ebc19c46cf615f2
--- /dev/null
+++ b/Sdk/Http/Webhook/Sender.cs
@@ -0,0 +1,18 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ /**
+ * 发送方信息.
+ *
+ * @since 2.0.0
+ */
+ public class Sender
+ {
+ // 和Receiver同级
+ // 发送者姓名
+ public string Name { get; set; }
+
+ // 发送者联系方式
+ public BoContactMetadata ContactMetadata { get; set; }
+
+ }
+}
diff --git a/Sdk/Http/Webhook/SignData.cs b/Sdk/Http/Webhook/SignData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0a8d084b4e02cf3188df7dc848e61cabbf5c52b8
--- /dev/null
+++ b/Sdk/Http/Webhook/SignData.cs
@@ -0,0 +1,21 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ /**
+ * 已成功完成签署流程的文件数据.
+ *
+ *
+ * @since 2.0.0
+ */
+ public class SignData
+ {
+ // 文件ID
+ public string FileWsid { get; set; }
+
+ // 已签署的文件数据的URL地址
+ public string Url { get; set; }
+
+ // 已签署的文件数据数据的base64表示形式的字符串
+ public string Base64 { get; set; }
+
+ }
+}
diff --git a/Sdk/Http/Webhook/WebhookData.cs b/Sdk/Http/Webhook/WebhookData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f0377946d66afd22434fd808e2b809d239517165
--- /dev/null
+++ b/Sdk/Http/Webhook/WebhookData.cs
@@ -0,0 +1,7 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class WebhookData : WebhookDataBase
+ {
+ public SignatureResponse RawData { get; set; }
+ }
+}
diff --git a/Sdk/Http/Webhook/WebhookDataBase.cs b/Sdk/Http/Webhook/WebhookDataBase.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e93638470b4ea179a77bab4897cf50812e9711b9
--- /dev/null
+++ b/Sdk/Http/Webhook/WebhookDataBase.cs
@@ -0,0 +1,22 @@
+namespace Signit.Sdk.Http.Webhook
+{
+ public class WebhookDataBase
+ {
+ public string Event { get; set; }
+ public SourceType Source { get; set; }
+ public TargetType Target { get; set; }
+ public bool NeedCallback { get; set; }
+
+ public class SourceType
+ {
+ public string Platform { get; set; }
+ public string Destination { get; set; }
+ }
+
+ public class TargetType
+ {
+ public string WebhookWsid { get; set; }
+ public string Destination { get; set; }
+ }
+ }
+}
diff --git a/Sdk/Http/Webhook/WebhookResponse.cs b/Sdk/Http/Webhook/WebhookResponse.cs
new file mode 100644
index 0000000000000000000000000000000000000000..39503d9831a99219b39af5ae7a24cd6a2d64aaf3
--- /dev/null
+++ b/Sdk/Http/Webhook/WebhookResponse.cs
@@ -0,0 +1,43 @@
+using Newtonsoft.Json;
+using System;
+
+namespace Signit.Sdk.Http.Webhook
+{
+ public class WebhookResponse : WebhookDataBase
+ {
+ public string RawData { get; set; }
+
+ public AbstractWebhookResponse GetResponseData()
+ {
+ return JsonConvert.DeserializeObject(RawData, GetEventType()) as AbstractWebhookResponse;
+ }
+
+ public T GetResponseData()
+ where T : AbstractWebhookResponse
+ {
+ return JsonConvert.DeserializeObject(RawData);
+ }
+
+ private Type GetEventType()
+ {
+ var @event = Event;
+ var fullName = $"Signit.Sdk.Http.Webhook.{@event}";
+
+ try
+ {
+ var type = Type.GetType(fullName, true, true);
+ if (!typeof(AbstractWebhookResponse).IsAssignableFrom(type))
+ {
+ throw new SignitException("无法根据事件名称[%s]自动生成对应的webhook响应数据[%s],请选择重新解析方法");
+ }
+ return type;
+ }
+ catch (TypeLoadException tle)
+ {
+ throw new SignitException(
+ "无法根据事件名称[%s]自动生成对应的webhook响应数据[%s],请选择重新解析方法",
+ tle);
+ }
+ }
+ }
+}
diff --git a/Sdk/IVerifyRequest.cs b/Sdk/IVerifyRequest.cs
new file mode 100644
index 0000000000000000000000000000000000000000..819ea9e2d04e4ec19fe422c217fb936135e50de9
--- /dev/null
+++ b/Sdk/IVerifyRequest.cs
@@ -0,0 +1,11 @@
+namespace Signit.Sdk
+{
+ public interface IVerifyRequest
+ {
+ string GetHeader(string key);
+ string GetMethod();
+ string ContentType { get; }
+
+ byte[] GetBody();
+ }
+}
diff --git a/Sdk/Properties/AssemblyInfo.cs b/Sdk/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4a7bf64a80a2b6547324dd884f996f731a74fd03
--- /dev/null
+++ b/Sdk/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("Sdk")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("SignIt")]
+[assembly: AssemblyProduct("Sdk")]
+[assembly: AssemblyCopyright("Copyright © SignIt 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("e583eaf3-04f9-4ab6-b265-d737568aaefc")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Sdk/Sdk.csproj b/Sdk/Sdk.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..6417192fe6cf1661bde441a8c4ec538606e10ebe
--- /dev/null
+++ b/Sdk/Sdk.csproj
@@ -0,0 +1,181 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {E583EAF3-04F9-4AB6-B265-D737568AAEFC}
+ Library
+ Properties
+ Signit.Sdk
+ Signit.Sdk
+ v4.0
+ 512
+ true
+
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+
+ ..\packages\Newtonsoft.Json.12.0.2\lib\net40\Newtonsoft.Json.dll
+
+
+
+
+ ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll
+
+
+ ..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.dll
+
+
+ ..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.Extensions.dll
+
+
+ ..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.Primitives.dll
+
+
+ ..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.WebRequest.dll
+
+
+ ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll
+
+
+ ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll
+
+
+
+
+
+
+
+
+ ..\packages\Viyi.Util.1.1.2\lib\net40\Viyi.Util.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。
+
+
+
+
\ No newline at end of file
diff --git a/Sdk/SignitClient.cs b/Sdk/SignitClient.cs
new file mode 100644
index 0000000000000000000000000000000000000000..02e1cf20d59c066093596279f807b47a20972fc4
--- /dev/null
+++ b/Sdk/SignitClient.cs
@@ -0,0 +1,195 @@
+using Newtonsoft.Json;
+using Signit.Sdk.Http;
+using Signit.Sdk.Http.Webhook;
+using Signit.Sdk.Types;
+using Signit.Sdk.Util;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using Viyi.Util;
+
+namespace Signit.Sdk
+{
+ public class SignitClient
+ {
+ public static WebhookData ParseWebhookData(string raw)
+ {
+ return JsonConvert.DeserializeObject(raw);
+ }
+
+ public static WebhookResponse ParseWebhookResponse(string raw)
+ {
+ return JsonConvert.DeserializeObject(raw);
+ }
+
+ public Authentication Authentication { get; private set; }
+ private readonly ApiOptions options;
+
+ //private HttpClientWrapper httpClient;
+ //private readonly int MAX_COUNT = 3;
+ //private readonly AtomicInteger count = new AtomicInteger(MAX_COUNT);
+ //private const Pattern LEFT_QUOTATION = Pattern.compile("\"\\{");
+ //private const Pattern RIGHT_QUOTATION = Pattern.compile("\\}\"");
+ //private const Pattern BACKLASH_QUOTATION = Pattern.compile("\\\\\"");
+
+ public string BaseUrl { get; set; }
+ public string OAuthTokenUrl { get; set; }
+
+ public SignitClient(ApiOptions options = null) : this(null, null, options) { }
+
+ public SignitClient(string appId, string secretKey, string url)
+ : this(new Authentication() { AppId = appId, SecuretKey = secretKey },
+ url)
+ { }
+
+ public SignitClient(Authentication auth, string url = null, ApiOptions options = null)
+ {
+ this.options = options = options ?? ApiOptions.Default;
+ options.EnvUrl = url ?? options.EnvUrl;
+ SetUrl(options.EnvUrl);
+ Authentication = auth;
+ }
+
+ public string Url { set => SetUrl(value); }
+ public string EnvUrl => options.EnvUrl;
+
+ public SignitClient SetUrl(string envUrl)
+ {
+ var url = string.IsNullOrWhiteSpace(envUrl)
+ ? options.EnvUrl
+ : envUrl.Trim();
+
+ BaseUrl = $"{url}{options.BaseApiUrl}";
+ OAuthTokenUrl = $"{url}{options.OAuthTokenUrl}";
+
+ return this;
+ }
+
+ ///
+ /// 单纯的进行认证并获取授权相关信息,并不保存
+ ///
+ ///
+ ///
+ ///
+ ///
+ public OAuthData RequestAuthentication(string apiKey, string secretKey,
+ TokenType tokenType = TokenType.CLIENT_CREDENTIALS)
+ {
+ if (string.IsNullOrEmpty(apiKey) || string.IsNullOrEmpty(secretKey))
+ {
+ throw new SignitException("请完善开发者账户数据");
+ }
+
+ HttpClientSync client = new HttpClientSync()
+ .AddQueryParam(options.ClientId, apiKey)
+ .AddQueryParam(options.ClientSecret, secretKey)
+ .AddQueryParam(options.GrantType, tokenType.ToString().ToLower());
+
+ return client.Get(OAuthTokenUrl).GetObject();
+ }
+
+ ///
+ /// 授权并缓存获取的授权信息
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Authentication Authenticate(string apiKey, string secretKey,
+ TokenType tokenType = TokenType.CLIENT_CREDENTIALS)
+ {
+ OAuthData authData = RequestAuthentication(apiKey, secretKey, tokenType);
+ if (authData == null)
+ {
+ return null;
+ }
+
+ Authentication = new Authentication
+ {
+ AccessToken = authData.AccessToken,
+ AccessTokenType = tokenType,
+ AppId = apiKey,
+ SecuretKey = secretKey
+ };
+
+ return Authentication;
+ }
+
+ public T Execute(AbstractSignitRequest request)
+ where T : AbstractSignitResponse
+ {
+ if (request == null)
+ {
+ return null;
+ }
+
+ var auth = Authentication;
+ if (auth == null || !(auth.HasAppId && auth.HasSecretKey))
+ {
+ throw new SignitException("请完善开发者信息");
+ }
+
+ if (!auth.HasAccessToken)
+ {
+ Authenticate(auth.AppId, auth.SecuretKey, auth.AccessTokenType);
+ }
+
+ var client = new HttpClientSync();
+ var headers = new NameValueCollection
+ {
+ { options.AppIdKey, auth.AppId }
+ };
+
+ var response = client
+ .WithAuthentication(Authentication)
+ .Post(BaseUrl, request, headers);
+
+ var result = response.GetObject();
+ if (!result.IsSuccess)
+ {
+ result.Error = response.GetObject();
+ }
+ return result;
+ }
+
+ ///
+ /// 发送快捷签署请求
+ ///
+ /// 快捷签署请求
+ /// 快捷签署响应
+ public SignatureResponse QuickSign(SignatureRequest request)
+ {
+ return Execute(request);
+ }
+
+ public static bool Verify(string signitSignature, string appId, HmacSignatureBuilder builder)
+ {
+ if (builder == null || appId == null || signitSignature == null)
+ {
+ return false;
+ }
+
+ string selfSignature = $"{HmacSignatureBuilder.DEFAULT_ALGORITHM} {appId}:{builder.BuildAsBase64()}";
+ return selfSignature == signitSignature;
+ }
+
+ public static bool Verify(string appId, string secretKey, IVerifyRequest request)
+ {
+ var signature = request.GetHeader("X-Signit-Signature") ?? "";
+
+ HmacSignatureBuilder builder = new HmacSignatureBuilder()
+ .Scheme(request.GetHeader("X-Signit-Scheme"))
+ .ApiKey(appId)
+ .ApiSecret(secretKey.ToByteArray())
+ .Method(request.GetMethod().ToUpper())
+ .Payload(request.GetBody())
+ .ContentType(request.ContentType)
+ .Host(request.GetHeader("X-Signit-Host") ?? "")
+ .Resource(request.GetHeader("X-Signit-Resource") ?? "")
+ .Nonce(request.GetHeader("X-Signit-Nonce") ?? "")
+ .Date(request.GetHeader("X-Signit-Date") ?? "");
+
+ string selfSignature = $"{HmacSignatureBuilder.DEFAULT_ALGORITHM} {appId}:{builder.BuildAsBase64()}";
+ return selfSignature == signature;
+ }
+ }
+}
diff --git a/Sdk/SignitException.cs b/Sdk/SignitException.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8bfea0ca21bc7392d71aca1ec7bde1e3c264e8c0
--- /dev/null
+++ b/Sdk/SignitException.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace Signit.Sdk
+{
+ public class SignitException : Exception
+ {
+ private readonly int httpCode;
+ private readonly string type;
+
+ public SignitException(Exception e) : base(null, e) { }
+
+ public SignitException(string message) : base(message) { }
+
+ public SignitException(string message, Exception e) : base(message, e) { }
+
+ public SignitException(string message, int httpCode, string type)
+ : this(message, httpCode, type, null) { }
+
+ public SignitException(string message, int httpCode, string type, Exception e) : base(message, e)
+ {
+ this.httpCode = httpCode;
+ this.type = type;
+ }
+
+ public int getHttpCode()
+ {
+ return httpCode;
+ }
+
+ public string getType()
+ {
+ return type;
+ }
+ }
+}
diff --git a/Sdk/Types/AcceptDataType.cs b/Sdk/Types/AcceptDataType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..eb6d616f8a723bae184611a91c2da20a744e2a30
--- /dev/null
+++ b/Sdk/Types/AcceptDataType.cs
@@ -0,0 +1,7 @@
+namespace Signit.Sdk.Types
+{
+ public enum AcceptDataType
+ {
+ BASE64, URL
+ }
+}
diff --git a/Sdk/Types/AuthLevel.cs b/Sdk/Types/AuthLevel.cs
new file mode 100644
index 0000000000000000000000000000000000000000..fac3ab47fc886d762d7c76dea3f6a6d078ec919d
--- /dev/null
+++ b/Sdk/Types/AuthLevel.cs
@@ -0,0 +1,24 @@
+namespace Signit.Sdk.Types
+{
+
+ ///
+ /// 参与者签署认证等级枚举
+ ///
+ public enum AuthLevel
+ {
+ ///
+ /// 低等级
+ ///
+ LOW,
+
+ ///
+ /// 中等级
+ ///
+ MIDDLE,
+
+ ///
+ /// 高等级
+ ///
+ HIGH
+ }
+}
diff --git a/Sdk/Types/AuthType.cs b/Sdk/Types/AuthType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..19aa5eb5c5f4762072b9791c8126267671e047c6
--- /dev/null
+++ b/Sdk/Types/AuthType.cs
@@ -0,0 +1,51 @@
+namespace Signit.Sdk.Types
+{
+
+ /**
+ * 签署认证类型类型.
+ *
+ * 用户确认签署时,需要验证签署人身份,此处为所有验证方式枚举
+ *
+ * @since 2.1.0
+ */
+ public enum AuthType
+ {
+ /**
+ * 短信验证码
+ *
+ * @since 2.1.0
+ */
+ SMS_CODE,
+ /**
+ * 邮箱验证码
+ *
+ * @since 2.1.0
+ */
+ EMAIL_CODE,
+ /**
+ * 签署密码
+ *
+ * @since 2.1.0
+ */
+ SIGN_PIN,
+ /**
+ * 活体认证
+ *
+ * @since 2.1.0
+ */
+ LIVING_AUTH,
+ /**
+ * usbkey认证
+ *
+ * @since 2.1.0
+ */
+ USBKEY,
+ /**
+ * 手机盾认证
+ *
+ * @since 2.1.0
+ */
+ MOBILE_SHIELD
+
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/CertType.cs b/Sdk/Types/CertType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..262d0d3a1e2da366e9f6a4ef875d66a0e7e0dc63
--- /dev/null
+++ b/Sdk/Types/CertType.cs
@@ -0,0 +1,22 @@
+namespace Signit.Sdk.Types
+{
+
+ /**
+ *
+ * 签名所使用的证书类型枚举.
+ *
+ * @since 2.0.0
+ */
+ public enum CertType
+ {
+
+ /**
+ * 一次性证书
+ */
+ DISPOSABLE_CERT,
+ /**
+ * 标准证书
+ */
+ STANDARD_CERT
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/Direction.cs b/Sdk/Types/Direction.cs
new file mode 100644
index 0000000000000000000000000000000000000000..12f38f29daf3ba44df256fc5ca6cf3e3fd30fe68
--- /dev/null
+++ b/Sdk/Types/Direction.cs
@@ -0,0 +1,8 @@
+namespace Signit.Sdk.Types
+{
+
+ public enum Direction
+ {
+ TOP, BOTTOM, LEFT, RIGHT, CENTER
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/EnterpriseAuthType.cs b/Sdk/Types/EnterpriseAuthType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e327256d3558e5cb7c47175580bcf5d6d2398c4f
--- /dev/null
+++ b/Sdk/Types/EnterpriseAuthType.cs
@@ -0,0 +1,21 @@
+namespace Signit.Sdk.Types
+
+{
+ /**
+ *
+ * 企业实名认证类型.
+ *
+ * @since 1.0.2
+ */
+ public enum EnterpriseAuthType
+ {
+ /**
+ * 法人认证
+ */
+ LEGAL_PERSON,
+ /**
+ * 经办人认证
+ */
+ AGENT
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/EnvelopeRoleType.cs b/Sdk/Types/EnvelopeRoleType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..953c4f9df8011f7612a7f7aeff3a0249a4cfa744
--- /dev/null
+++ b/Sdk/Types/EnvelopeRoleType.cs
@@ -0,0 +1,20 @@
+namespace Signit.Sdk.Types
+{
+ /**
+ *
+ * 接收方角色类型.
+ *
+ * @since 1.0.2
+ */
+ public enum EnvelopeRoleType
+ {
+ /**
+ * 个人
+ */
+ PERSON,
+ /**
+ * 企业成员
+ */
+ ENTERPRISE_MEMBER
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/EnvelopeType.cs b/Sdk/Types/EnvelopeType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..db3d31827b03a537095c33505a77ca30110fff8f
--- /dev/null
+++ b/Sdk/Types/EnvelopeType.cs
@@ -0,0 +1,36 @@
+namespace Signit.Sdk.Types
+{
+
+ /**
+ * 信封类型枚举.
+ *
+ * @since 1.0.2
+ */
+ public enum EnvelopeType
+ {
+ /**
+ * 任意.
+ *
+ * @since 1.0.2
+ */
+ ANY,
+ /**
+ * 本人.
+ *
+ * @since 1.0.2
+ */
+ ME,
+ /**
+ * 我与他人.
+ *
+ * @since 1.0.2
+ */
+ ME_AND_OTHERS,
+ /**
+ * 他人.
+ *
+ * @since 1.0.2
+ */
+ OTHERS
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/FileType.cs b/Sdk/Types/FileType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..631af393eb6b4bd80e65da7747cc8577e871bd04
--- /dev/null
+++ b/Sdk/Types/FileType.cs
@@ -0,0 +1,174 @@
+namespace Signit.Sdk.Types
+{
+ /**
+ * 基于文件头描述源文件真实类型.
+ *
+ * @since 2.0.0
+ */
+ public enum FileType
+ {
+ /**
+ * JPEG.
+ */
+ JPEG,
+
+ /**
+ * JPG.
+ */
+ JPG,
+
+ /**
+ * JPE.
+ */
+ JPE,
+
+ /**
+ * PNG.
+ */
+ PNG,
+
+ /**
+ * GIF.
+ */
+ GIF,
+
+ /**
+ * TIFF.
+ */
+ TIFF,
+
+ /**
+ * Windows Bitmap.
+ */
+ BMP,
+
+ /**
+ * CAD.
+ */
+ DWG,
+
+ /**
+ * Adobe Photoshop.
+ */
+ PSD,
+
+ /**
+ * Rich Text Format.
+ */
+ RTF,
+
+ /**
+ * XML.
+ */
+ XML,
+
+ /**
+ * HTML.
+ */
+ HTML,
+
+ /**
+ * Email [thorough only].
+ */
+ EML,
+
+ /**
+ * Outlook Express.
+ */
+ DBX,
+
+ /**
+ * Outlook (pst).
+ */
+ PST,
+
+ /**
+ * MS 2003 Word/Excel/PointPower.
+ */
+ MS_2003,
+
+ /**
+ * MS 2007 and later Archive.MS Word/Excel/PointPower. (docx,pptx,xlsx)
+ */
+ MS_2007,
+
+ /**
+ * MS Access.
+ */
+ MDB,
+
+ /**
+ * WordPerfect.
+ */
+ WPD,
+
+ /**
+ * Postscript.
+ */
+ EPS,
+
+ /**
+ * Adobe Acrobat.
+ */
+ PDF,
+
+ /**
+ * Quicken.
+ */
+ QDF,
+
+ /**
+ * Windows Password.
+ */
+ PWL,
+
+ /**
+ * ZIP Archive. (docx,pptx,xlsx)
+ */
+ ZIP,
+
+ /**
+ * RAR Archive.
+ */
+ RAR,
+
+ /**
+ * Wave.
+ */
+ WAV,
+ /**
+ * AVI.
+ */
+ AVI,
+
+ /**
+ * Real Audio.
+ */
+ RAM,
+
+ /**
+ * Real Media.
+ */
+ RM,
+
+ /**
+ * MPEG (mpg).
+ */
+ MPG,
+
+ /**
+ * Quicktime.
+ */
+ MOV,
+
+ /**
+ * Windows Media.
+ */
+ ASF,
+
+ /**
+ * MIDI.
+ */
+ MID
+ }
+}
diff --git a/Sdk/Types/FormType.cs b/Sdk/Types/FormType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..074c598daae92fa9bdff12af3388eb39b02af179
--- /dev/null
+++ b/Sdk/Types/FormType.cs
@@ -0,0 +1,33 @@
+namespace Signit.Sdk.Types
+{
+ /**
+ *
+ * 表单类型枚举.
+ *
+ * @since 2.0.0
+ */
+ public enum FormType
+ {
+
+ /**
+ * 印章签名表单域
+ */
+ SEAL_SIGN,
+ /**
+ * 手写签名表单域
+ */
+ WRITE_SIGN,
+ /**
+ * 文本表单域
+ */
+ TEXT,
+ /**
+ * 骑缝章表单域
+ */
+ MULTI_CHECK_MARK,
+ /**
+ * 二维码骑缝章表单域
+ */
+ MULTI_QRCODE_MARK
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/IdCardType.cs b/Sdk/Types/IdCardType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ae9990fdd4994d027b136488ca9b4e8b67d89716
--- /dev/null
+++ b/Sdk/Types/IdCardType.cs
@@ -0,0 +1,25 @@
+namespace Signit.Sdk.Types
+{
+ /**
+ *
+ * 身份证类型枚举.
+ *
+ * @since 1.0.2
+ */
+ public enum IdCardType
+ {
+ /**
+ * 二代身份证
+ */
+ SECOND_GENERATION_IDCARD,
+ /**
+ * 临时身份证
+ */
+ TEMPORARY_IDCARD,
+ /**
+ * 护照
+ */
+ PASSPORT
+
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/NamingStyle.cs b/Sdk/Types/NamingStyle.cs
new file mode 100644
index 0000000000000000000000000000000000000000..23138ce82f493108676e00b1201be8c26fd74182
--- /dev/null
+++ b/Sdk/Types/NamingStyle.cs
@@ -0,0 +1,31 @@
+namespace Signit.Sdk.Types
+{
+ /**
+ * 命名风格的枚举.
+ *
+ * @author zhd
+ * @since 1.0.0
+ */
+ public enum NamingStyle
+ {
+ /**
+ * 小驼峰命名风格.如:nameStyle
+ */
+ CAMEL,
+
+ /**
+ * 字母间均大写命名风格.如:NameStyle
+ */
+ PASCAL,
+
+ /**
+ * 字母间均以下划线分隔命名风格(unix命名风格).如:name_style
+ */
+ SNAKE,
+
+ /**
+ * 字母间均以连词符分隔命名风格.如:name-style
+ */
+ KEBAB
+ }
+}
diff --git a/Sdk/Types/ParticipantHandleMode.cs b/Sdk/Types/ParticipantHandleMode.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b73840cc6464a21b84902dfba6f32cfe385f7f03
--- /dev/null
+++ b/Sdk/Types/ParticipantHandleMode.cs
@@ -0,0 +1,25 @@
+namespace Signit.Sdk.Types
+{
+ /**
+ * 参与者处理表单的模式枚举
+ *
+ * @since 2.0.0
+ */
+ public enum ParticipantHandleMode
+ {
+ /**
+ * 正常处理模式(默认).
+ *
+ * @since 2.0.0
+ */
+ NORMAL,
+ /**
+ * 静默处理模式.
+ * 该接受方不用执行签署流程,自动完成签署。接收方设置为静默签署条件:①接收方类型为签署者SIGNER;②接收方和发起方为同一企业下的同一人;③该接收方有预设表单,且该接收方的预设表单均设置了初始值(手写签名表单除外)。
+ *
+ * @since 2.0.0
+ */
+ SILENCE
+
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/PersonAuthType.cs b/Sdk/Types/PersonAuthType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..aa78860ee100b996bc5a954a74214b5ade1e6469
--- /dev/null
+++ b/Sdk/Types/PersonAuthType.cs
@@ -0,0 +1,16 @@
+namespace Signit.Sdk.Types
+{
+ /**
+ * 个人实名认证方式
+ *
+ * @since 2.1.0
+ */
+ public enum PersonAuthType
+ {
+ /**
+ * 三网手机号三元素实名认证方式
+ */
+ PHONE_AUTH
+
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/ReceiverType.cs b/Sdk/Types/ReceiverType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..125df206ace5d40849995d0699912ef440a2975b
--- /dev/null
+++ b/Sdk/Types/ReceiverType.cs
@@ -0,0 +1,23 @@
+namespace Signit.Sdk.Types
+{
+ /**
+ * 参与者类型状态枚举.
+ *
+ * @since 2.0.0
+ */
+ public enum ReceiverType
+ {
+ /**
+ * 签署者
+ *
+ * @since 2.0.0
+ */
+ SIGNER,
+ /**
+ * 审核者
+ *
+ * @since 2.0.0
+ */
+ CHECKER,
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/RenderMode.cs b/Sdk/Types/RenderMode.cs
new file mode 100644
index 0000000000000000000000000000000000000000..22ea1ec98d473faf4b4816f103bcbb952a731da2
--- /dev/null
+++ b/Sdk/Types/RenderMode.cs
@@ -0,0 +1,29 @@
+namespace Signit.Sdk.Types
+{
+ /**
+ * 签名渲染模式.
+ *
+ *
+ * @since 2.0.0
+ */
+ public enum RenderMode
+ {
+
+ /**
+ * The rendering mode is just the description.
+ */
+ DESCRIPTION,
+ /**
+ * The rendering mode is the name of the signer and the description.
+ */
+ NAME_AND_DESCRIPTION,
+ /**
+ * The rendering mode is an image and the description.
+ */
+ GRAPHIC_AND_DESCRIPTION,
+ /**
+ * The rendering mode is just an image.
+ */
+ GRAPHIC
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/SecureLevel.cs b/Sdk/Types/SecureLevel.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3cba61e95d326b328412af2ddf55a9a6973c90df
--- /dev/null
+++ b/Sdk/Types/SecureLevel.cs
@@ -0,0 +1,23 @@
+namespace Signit.Sdk.Types
+{
+ /**
+ * 要求的安全级别类型的枚举
+ *
+ * @since 2.0.0
+ */
+ public enum SecureLevel
+ {
+ /**
+ * 一次性证书.
+ *
+ * @since 2.0.0
+ */
+ DISPOSABLE_CERT,
+ /**
+ * 标准证书.
+ *
+ * @since 2.0.0
+ */
+ STANDARD_CERT
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Types/TokenType.cs b/Sdk/Types/TokenType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..06960ee25cfa159f3ba1f7ca251f09622a186c44
--- /dev/null
+++ b/Sdk/Types/TokenType.cs
@@ -0,0 +1,11 @@
+namespace Signit.Sdk.Types
+{
+ public enum TokenType
+ {
+ CLIENT_CREDENTIALS,
+ AUTHORIZATION_CODE,
+ IMPLICIT,
+ PASSWORD,
+ REFRESH_TOKEN,
+ }
+}
\ No newline at end of file
diff --git a/Sdk/Util/AesTool.cs b/Sdk/Util/AesTool.cs
new file mode 100644
index 0000000000000000000000000000000000000000..cb3a227d618ad5be04fbfeaa667e314511f4e423
--- /dev/null
+++ b/Sdk/Util/AesTool.cs
@@ -0,0 +1,98 @@
+using System.Security.Cryptography;
+
+namespace Signit.Sdk.Util
+{
+ public static class AesTool
+ {
+ ///
+ /// 获取所使用 AES 算法的块大小,单位:位
+ ///
+ public static int BlockSize { get { return Aes.BlockSize; } }
+
+ ///
+ /// 获取所使用 AES 算法的 Key 大小,单位:位
+ ///
+ public static int KeySize { get { return Aes.KeySize; } }
+
+ ///
+ /// 直接通过密码对数据加密。加密所使用的初始化向量根据密码生成。
+ ///
+ /// 需要加密的数据
+ /// 密码,不能为 null,但可以是 string.Empty
+ /// 加密后的数据
+ public static byte[] AesEncrypt(this byte[] me, string password)
+ {
+ return SymmetricTool.Encrypt(Aes, password, me);
+ }
+
+ ///
+ /// 直接通过密码对数据加密。加密所使用的初始化向量根据密码生成。
+ ///
+ /// 需要加密的数据,不能为 null
+ /// 起始位置
+ /// 需要加密的数据长度
+ /// 密码,不能为 null,但可以是 string.Empty
+ /// 加密后的数据
+ public static byte[] AesEncrypt(this byte[] me, int start, int length, string password)
+ {
+ return SymmetricTool.Encrypt(Aes, password, me, start, length);
+ }
+
+ ///
+ /// 直接通过密码对数据解密。解密所使用的初始化向量根据密码生成。
+ ///
+ /// 需要解密的数据
+ /// 密码,不能为 null,但可以是 string.Empty
+ /// 解密后的数据
+ public static byte[] AesDecrypt(this byte[] me, string password)
+ {
+ return SymmetricTool.Decrypt(Aes, password, me);
+ }
+
+ ///
+ /// 使用AES加密数据。
+ ///
+ /// 数据字节
+ /// 初始化向量
+ /// 密钥
+ /// 加密后的数据。
+ /// 如果原数据是null,则返回null
+ /// 如果需要加密字符串,可以使用string.ToByteArray扩展方法
+ /// 先把string转换成字符数组
+ public static byte[] AesEncrypt(this byte[] me, byte[] iv, byte[] key)
+ {
+ return InternalTool.Encrypt(Aes, me, iv, key);
+ }
+
+ ///
+ /// 使用AES加密数据
+ ///
+ /// 数据字节
+ /// 随机产生初始化向量并通过iv返回。
+ /// 如果源数据是null,返回null
+ /// 密钥
+ /// 加密后的数据。如果原数据是null,则返回null
+ /// 如果需要加密字符串,可以使用string.ToByteArray扩展方法
+ /// 先把string转换成字符数组
+ public static byte[] AesEncrypt(this byte[] me, out byte[] iv, byte[] key)
+ {
+ return InternalTool.Encrypt(Aes, me, out iv, key);
+ }
+
+ ///
+ /// 使用AES解密(加密后的)数据
+ ///
+ /// 数据字节
+ /// 初始化向量
+ /// 密钥
+ /// 解密后的数据,即源数据。
+ /// 如果数据字节是null,返回null
+ public static byte[] AesDecrypt(this byte[] me, byte[] iv, byte[] key)
+ {
+ return InternalTool.Decrypt(Aes, me, iv, key);
+ }
+
+ private static Aes Aes { get { return aesInstance ?? (aesInstance = Aes.Create()); } }
+ private static Aes aesInstance;
+ }
+}
diff --git a/Sdk/Util/HmacSignatureBuilder.cs b/Sdk/Util/HmacSignatureBuilder.cs
new file mode 100644
index 0000000000000000000000000000000000000000..675674bd9b3917d4ce8071dd4531f10defe9256e
--- /dev/null
+++ b/Sdk/Util/HmacSignatureBuilder.cs
@@ -0,0 +1,368 @@
+using Signit.Sdk.Extentions;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using Viyi.Util;
+using Viyi.Util.Codec;
+using Viyi.Util.Linq;
+
+namespace Signit.Sdk.Util
+{
+ public class HmacSignatureBuilder
+ {
+ public enum BuilderMode
+ {
+ ///
+ /// 所有字段均加入运算
+ ///
+ FULL,
+
+ ///
+ /// 只有请求头字段加入运算
+ ///
+ ONLY_HEADER
+ }
+
+ public const string DEFAULT_ALGORITHM = "HmacSHA512";
+ public const string DEFAULT_CHARSET = "UTF-8";
+ public static readonly byte[] DEFAULT_DELIMITER = "\n".ToByteArray(DEFAULT_CHARSET);
+ private byte[] delimiter = DEFAULT_DELIMITER;
+ private string charset = DEFAULT_CHARSET;
+ private string algorithm = DEFAULT_ALGORITHM;
+ private string scheme;
+ private string host;
+ private string method;
+ private string resource;
+ private string nonce;
+ private string apiKey;
+ private byte[] apiSecret;
+ private byte[] payload;
+ private string date;
+ private string contentType;
+
+ /**
+ * 设置加入运算的相关字符的字符集编码规则.
+ *
+ * @param charset
+ * 字符集编码规则
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder Charset(String charset)
+ {
+ this.charset = charset;
+ return this;
+ }
+
+ /**
+ * 设置加入运算的字符间的分隔符.
+ *
+ * @param delimiter
+ * 字符间的分隔符
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder Delimiter(byte[] delimiter)
+ {
+ this.delimiter = delimiter;
+ return this;
+ }
+
+ public HmacSignatureBuilder Delimiter(byte delimiter)
+ {
+ this.delimiter = new[] { delimiter };
+ return this;
+ }
+
+ /**
+ * 设置HMAC的算法.
+ *
+ * @param algorithm
+ * HMAC的算法
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder Algorithm(String algorithm)
+ {
+ this.algorithm = algorithm;
+ return this;
+ }
+
+ /**
+ * 设置需要加入运算的协议名称.
+ *
+ * @param scheme
+ * 协议名称(如: http/https/ftp/...)
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder Scheme(String scheme)
+ {
+ this.scheme = scheme;
+ return this;
+ }
+
+ /**
+ * 设置需要加入运算的主机名称.
+ *
+ * @param host
+ * 主机名称(如: signit.cn/10.10.10.10/...)
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder Host(String host)
+ {
+ this.host = host;
+ return this;
+ }
+
+ /**
+ * 设置需要加入运算的服务器授权给客户端的唯一公开标识.(与apiSecret
配套,允许公开).
+ *
+ * @param apiKey
+ * 服务器授权给客户端的唯一公开标识.(与apiSecret
配套,允许公开)
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder ApiKey(String apiKey)
+ {
+ this.apiKey = apiKey;
+ return this;
+ }
+
+ /**
+ * 设置需要加入运算的请求方法.
+ *
+ * @param method
+ * 请求方法(如: GET/POST/PUT/DELETE/...)
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder Method(String method)
+ {
+ this.method = method;
+ return this;
+ }
+
+ /**
+ * 设置需要加入运算的请求资源地址(URI).
+ *
+ * @param resource
+ * 请求资源地址(URI)(如: '/v1/users','/v1/users/123',...)
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder Resource(String resource)
+ {
+ this.resource = resource;
+ return this;
+ }
+
+ /**
+ * 设置需要加入运算的请求内容类型(Content-Type).
+ *
+ * @param contentType
+ * 请求内容类型(Content-Type)(如: 'application/json','image/jpeg',...)
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder ContentType(String contentType)
+ {
+ this.contentType = contentType;
+ return this;
+ }
+
+ /**
+ * 设置需要加入运算的请求时间(Date).
+ *
+ * @param date
+ * 请求时间(Date)(如: 'Sat, 02 Jul 2011 20:45:57 GMT','Wed, 02 Nov
+ * 2016 03:25:54 GMT',...)
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder Date(String date)
+ {
+ this.date = date;
+ return this;
+ }
+
+ /**
+ * 设置需要加入运算的随机数.
+ *
+ * @param nonce
+ * 随机数(如: '6m0S4nyH1dg7K2gh','8NQq53cLR4g5Y52I',...)
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder Nonce(String nonce)
+ {
+ this.nonce = nonce;
+ return this;
+ }
+
+ /**
+ * 设置需要加入运算的服务器授权给客户端的私密密钥.(与apiKey
配套,但不公开).
+ *
+
+ * @param apiSecret
+
+ * 服务器授权给客户端的私密密钥.(与apiKey
配套,但不公开)
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder ApiSecret(byte[] apiSecret)
+ {
+ this.apiSecret = apiSecret;
+ return this;
+ }
+
+ /**
+ * 设置需要加入运算的请求数据.
+ *
+
+ * @param payload
+
+ * 请求数据
+ * @return 当前HMAC建造器对象
+ * @author zhd
+ * @since 1.0.0
+ */
+ public HmacSignatureBuilder Payload(byte[] payload)
+ {
+ this.payload = payload;
+ return this;
+ }
+
+ public string BuildAsHex(BuilderMode builderMode = BuilderMode.FULL)
+ {
+ return Build(builderMode).HexEncode();
+ }
+
+ public string BuildAsBase64(BuilderMode builderMode = BuilderMode.FULL)
+ {
+ return Build(builderMode).Base64Encode();
+ }
+
+ /**
+ * 完成HMAC认证消息的构建,并获得签名摘要值.
+ *
+ * @param builderMode
+ * 构建模式的枚举
+ * @return HMAC原始签名摘要值的内存数据字节.若构建失败,则返回null
+ * @author zhd
+ * @since 1.0.0
+ */
+ public byte[] Build(BuilderMode builderMode = BuilderMode.FULL)
+ {
+ Func builder = null;
+ switch (builderMode)
+ {
+ case BuilderMode.FULL:
+ builder = GetFullStream;
+ break;
+ case BuilderMode.ONLY_HEADER:
+ builder = GetOnlyHeaderStream;
+ break;
+ }
+
+ if (builder == null)
+ {
+ Debug.WriteLine($"不支持的参数类型: {builderMode}");
+ return null;
+ }
+
+ var hmac = HMAC.Create(algorithm);
+ hmac.Key = apiSecret;
+ return hmac.ComputeHash(builder());
+ }
+
+
+ // 完整的数据运算
+ private Stream GetFullStream()
+ {
+ MemoryStream stream = new MemoryStream();
+ SignitStreamWriter writer = new SignitStreamWriter(stream)
+ .SetDelimiter(delimiter)
+ .SetEncoding(charset);
+
+ new[] { apiKey, contentType, date, host, method, nonce }
+ .ForEach(writer.Write);
+
+ if (payload?.Length > 0)
+ {
+ writer.Write(payload);
+ }
+
+ new[] { resource, scheme }
+ .ForEach(writer.Write);
+
+ stream.Seek(0, SeekOrigin.Begin);
+ return stream;
+ }
+
+ private Stream GetOnlyHeaderStream()
+ {
+ MemoryStream stream = new MemoryStream();
+ SignitStreamWriter writer = new SignitStreamWriter(stream)
+ .SetDelimiter(delimiter)
+ .SetEncoding(charset);
+
+ new[] { apiKey, contentType, date, host, method, nonce, resource, scheme }
+ .ForEach(writer.Write);
+
+ stream.Seek(0, SeekOrigin.Begin);
+ return stream;
+ }
+
+ public void VerifySignature(byte[] expect,
+ BuilderMode mode = BuilderMode.FULL,
+ string errMessage = null)
+ {
+ if (Enumerable.SequenceEqual(expect, Build(mode)))
+ {
+ return;
+ }
+
+ throw new ArgumentException(errMessage);
+ }
+
+ public void VerifyHexSignature(string expect,
+ BuilderMode mode = BuilderMode.FULL,
+ string errMessage = null)
+ {
+ if (expect == BuildAsHex(mode))
+ {
+ return;
+ }
+
+ throw new ArgumentException(errMessage);
+ }
+
+ public void VerifyBase64Signature(string expect,
+ BuilderMode mode = BuilderMode.FULL,
+ string errMessage = null)
+ {
+ if (expect == BuildAsBase64(mode))
+ {
+ return;
+ }
+
+ throw new ArgumentException(errMessage);
+ }
+ }
+}
diff --git a/Sdk/Util/InternalTool.cs b/Sdk/Util/InternalTool.cs
new file mode 100644
index 0000000000000000000000000000000000000000..718c57df4279dda08240bedf43d658e64355ac20
--- /dev/null
+++ b/Sdk/Util/InternalTool.cs
@@ -0,0 +1,123 @@
+using System.Security.Cryptography;
+using Viyi.Util.Codec;
+
+namespace Signit.Sdk.Util
+{
+ internal static class InternalTool
+ {
+ #region 对称加密算法模板
+ public static byte[] Encrypt(SymmetricAlgorithm algorithm, byte[] data, byte[] iv, byte[] key)
+ {
+ if (data == null) { return null; }
+
+ key = CheckAndPadKey(key, algorithm);
+ ICryptoTransform transform = algorithm.CreateEncryptor(key, iv);
+ return transform.TransformFinalBlock(data, 0, data.Length);
+ }
+
+ public static byte[] Encrypt(SymmetricAlgorithm algorithm, byte[] data, out byte[] iv, byte[] key)
+ {
+ if (data == null)
+ {
+ iv = null;
+ return null;
+ }
+
+ key = CheckAndPadKey(key, algorithm);
+ iv = algorithm.IV;
+ ICryptoTransform transform = algorithm.CreateEncryptor(key, iv);
+ return transform.TransformFinalBlock(data, 0, data.Length);
+ }
+
+ internal static byte[] Encrypt(
+ SymmetricAlgorithm algorithm,
+ byte[] data, int start, int length,
+ byte[] iv, byte[] key)
+ {
+ if (data == null) { return null; }
+ key = CheckAndPadKey(key, algorithm);
+ ICryptoTransform transform = algorithm.CreateEncryptor(key, iv);
+ return transform.TransformFinalBlock(data, start, length);
+ }
+
+ public static byte[] Decrypt(SymmetricAlgorithm algorithm, byte[] data, byte[] iv, byte[] key)
+ {
+ if (data == null) { return null; }
+
+ key = CheckAndPadKey(key, algorithm);
+ ICryptoTransform transform = algorithm.CreateDecryptor(key, iv);
+ return transform.TransformFinalBlock(data, 0, data.Length);
+ }
+ #endregion
+
+ #region 根据加密算法要求补齐Key
+
+ private static readonly byte[] PadingSalt
+ = "4KC8A0HCSLFDCPDREVQUVYYCPHB9L549UQ0WITFITWV19D8751QEXN6FTPIT8EGW".HexDecode();
+
+ private const int PaddingIterations = 64;
+
+ ///
+ /// 使用PBKDF2算法补齐密码
+ ///
+ ///
+ ///
+ ///
+ internal static byte[] PadKey(byte[] key, int length)
+ {
+ return key == null
+ ? null
+ : new Rfc2898DeriveBytes(key, PadingSalt, PaddingIterations).GetBytes(length);
+ }
+
+ ///
+ /// 检查key的长度对算法来说是否合法,如果合法,直接返回。
+ /// 如果不合法,使用PBKDF2算法对其进行补齐至最接近的长度,然后返回
+ ///
+ ///
+ ///
+ ///
+ private static byte[] CheckAndPadKey(byte[] key, SymmetricAlgorithm algorithm)
+ {
+ if (key == null) { return null; }
+
+ int length = key.Length * 8;
+ foreach (KeySizes sizes in algorithm.LegalKeySizes)
+ {
+ // 不在范围内,key无效
+ if (length < sizes.MinSize || length > sizes.MaxSize)
+ {
+ continue;
+ }
+
+ // 在范围内,又没有步长限制,key有效
+ if (sizes.SkipSize == 0) { return key; }
+
+ // 检查如果key的长度是合法长度,不需要Padding,直接返回
+ if ((length - sizes.MinSize) % sizes.SkipSize == 0)
+ {
+ return key;
+ }
+ }
+
+ // 检查key的长度不属于任何合法长度
+ KeySizes firstSizes = algorithm.LegalKeySizes[0];
+ int paddingLength;
+ if (length < firstSizes.MinSize)
+ {
+ paddingLength = firstSizes.MinSize;
+ }
+ else if (length > firstSizes.MaxSize)
+ {
+ paddingLength = firstSizes.MaxSize;
+ }
+ else
+ {
+ paddingLength = length + (length - firstSizes.MinSize) % firstSizes.SkipSize;
+ }
+
+ return PadKey(key, paddingLength / 8);
+ }
+ #endregion
+ }
+}
diff --git a/Sdk/Util/SignitStreamWriter.cs b/Sdk/Util/SignitStreamWriter.cs
new file mode 100644
index 0000000000000000000000000000000000000000..80f9632a0f4add21445568fafe5e32aaa8feb59e
--- /dev/null
+++ b/Sdk/Util/SignitStreamWriter.cs
@@ -0,0 +1,57 @@
+using Signit.Sdk.Extentions;
+using System.IO;
+using System.Text;
+using Viyi.Util;
+
+namespace Signit.Sdk.Util
+{
+ class SignitStreamWriter
+ {
+ public readonly Stream Stream;
+ private byte[] delimiter = new byte[0];
+ private Encoding encoding = Encoding.UTF8;
+
+ public SignitStreamWriter(Stream stream)
+ {
+ Stream = stream;
+ }
+
+ public SignitStreamWriter SetDelimiter(byte[] delimiter)
+ {
+ this.delimiter = delimiter ?? new byte[0];
+ return this;
+ }
+
+ public SignitStreamWriter SetEncoding(string encoding)
+ {
+ this.encoding = Encoding.GetEncoding(encoding);
+ return this;
+ }
+
+ public SignitStreamWriter SetEncoding(Encoding encoding)
+ {
+ this.encoding = encoding;
+ return this;
+ }
+
+ public SignitStreamWriter Write(byte[] data)
+ {
+ Stream.Write(data);
+ Stream.Write(delimiter);
+ return this;
+ }
+
+ public SignitStreamWriter Write(string s)
+ {
+ process();
+ return this;
+
+ void process()
+ {
+ if (s == null) { return; }
+ Stream.Write(s.ToByteArray(encoding))
+ .Write(delimiter);
+ }
+ }
+ }
+}
diff --git a/Sdk/Util/SymmetricTool.cs b/Sdk/Util/SymmetricTool.cs
new file mode 100644
index 0000000000000000000000000000000000000000..06c6b9eaa04005020c2603db5cbee7b46e813246
--- /dev/null
+++ b/Sdk/Util/SymmetricTool.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Signit.Sdk.Util
+{
+ ///
+ /// 用于对称加密算法的简化使用扩展方法工具类。该工具类使用户只需要提供密码即可对数据进行加解密。
+ /// 加解密所使用的初始化向量是通过密码来计算的。
+ /// 由于该工具类使用了特定的生成初始化向量的算法,所以 SymmetricTool.Decrypt 方法只能解密
+ /// 由 SymmetricTool.Encrypt 生成的,或通过其兼容算法生成的密文。
+ ///
+ ///
+ /// string EncryptConnectionString(string connStr, string password) {
+ /// Aes aes = Aes.Create();
+ /// byte[] ed = aes.Encrypt(password, connStr.ToByteArray(Encoding.UTF8));
+ /// return ed.HexEncode();
+ /// }
+ ///
+ /// string DecryptConnectionString(string hexStr, string password) {
+ /// byte[] d = Aes.Create().Decrypt(password, hexStr.HexDecode());
+ /// return d.GetString(Encoding.UTF8);
+ /// }
+ ///
+ ///
+ /// 对于 AES、DES 和 3DES 算法,可以直接使用 AesTool 或 DesTool 中定义的相关扩展方法。
+ ///
+ ///
+ ///
+ public static class SymmetricTool
+ {
+ ///
+ /// 根据指定的对称加密算法,使用给定的密码对数据进行加密。
+ ///
+ /// 对称加密算法
+ /// 密码,不能为 null,可以是 string.Empty
+ /// 需要加密的数据,数据为 null,则加密结果为 null
+ /// 已加密的数据
+ /// password 为 null
+ ///
+ /// 密码原文会通过 UTF-8 编码方式转换成字符数据用于加密。
+ ///
+ public static byte[] Encrypt(this SymmetricAlgorithm me, string password, byte[] data)
+ {
+ if (password == null)
+ {
+ throw new ArgumentNullException("password");
+ }
+
+ if (data == null)
+ {
+ return null;
+ }
+
+ byte[] keyData = Encoding.UTF8.GetBytes(password);
+ byte[] key = InternalTool.PadKey(keyData, me.KeySize / 8);
+ byte[] iv = InternalTool.PadKey(keyData, me.BlockSize / 8);
+ return InternalTool.Encrypt(me, data, iv, key);
+ }
+
+ ///
+ /// 根据指定的对称加密算法,使用给定的密码对数据的一部分或全部进行加密。
+ ///
+ /// 对称加密算法
+ /// 密码,不能为 null,可以是 string.Empty
+ /// 需要加密的数据,数据不能为 null
+ /// 原数据起始位置
+ /// 需要加密的原数据长度
+ /// 已加密的数据
+ /// password 或 data 为 null
+ ///
+ /// 密码原文会通过 UTF-8 编码方式转换成字符数据用于加密。
+ ///
+ public static byte[] Encrypt(this SymmetricAlgorithm me, string password, byte[] data, int start, int length)
+ {
+ if (password == null)
+ {
+ throw new ArgumentNullException("password");
+ }
+
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ byte[] keyData = Encoding.UTF8.GetBytes(password);
+ byte[] key = InternalTool.PadKey(keyData, me.KeySize / 8);
+ byte[] iv = InternalTool.PadKey(keyData, me.BlockSize / 8);
+ return InternalTool.Encrypt(me, data, start, length, iv, key);
+ }
+
+ ///
+ /// 根据指定的对称加密算法,使用给定的密码对加密数据进行解密。
+ ///
+ /// 对称加密算法
+ /// 密码,不能为 null,可以是 string.Empty
+ /// 已加密的数据
+ /// 解密后的数据
+ /// password 为 null
+ ///
+ /// 密码原文会通过 UTF-8 编码方式转换成字符数据用于解密。
+ ///
+ public static byte[] Decrypt(this SymmetricAlgorithm me, string password, byte[] encryptedData)
+ {
+ if (password == null)
+ {
+ throw new ArgumentNullException("password");
+ }
+
+ if (encryptedData == null)
+ {
+ return null;
+ }
+
+ byte[] keyData = Encoding.UTF8.GetBytes(password);
+ byte[] key = InternalTool.PadKey(keyData, me.KeySize / 8);
+ byte[] iv = InternalTool.PadKey(keyData, me.BlockSize / 8);
+ return InternalTool.Decrypt(me, encryptedData, iv, key);
+ }
+ }
+}
diff --git a/Sdk/app.config b/Sdk/app.config
new file mode 100644
index 0000000000000000000000000000000000000000..6d05181ceb303c22a9940403cd81f260c4399494
--- /dev/null
+++ b/Sdk/app.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Sdk/packages.config b/Sdk/packages.config
new file mode 100644
index 0000000000000000000000000000000000000000..b809fefc553d2e2ff4f04cb810f4db349b7a9108
--- /dev/null
+++ b/Sdk/packages.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file