diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go
index 77ed8acb..30cf9d41 100644
--- a/internal/deployer/providers.go
+++ b/internal/deployer/providers.go
@@ -561,8 +561,9 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
 			switch options.Provider {
 			case domain.DeploymentProviderTypeGcoreCDN:
 				deployer, err := pGcoreCDN.NewDeployer(&pGcoreCDN.DeployerConfig{
-					ApiToken:   access.ApiToken,
-					ResourceId: maputil.GetInt64(options.ProviderExtendedConfig, "resourceId"),
+					ApiToken:      access.ApiToken,
+					ResourceId:    maputil.GetInt64(options.ProviderExtendedConfig, "resourceId"),
+					CertificateId: maputil.GetInt64(options.ProviderExtendedConfig, "certificateId"),
 				})
 				return deployer, err
 
diff --git a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go
index 95c0f9f4..2294ed03 100644
--- a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go
+++ b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go
@@ -63,6 +63,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
 		return nil, errors.New("config `domain` is required")
 	}
 
+	// 如果原证书 ID 为空,则新增证书;否则替换证书。
 	if d.config.CertificateId == "" {
 		// 新增证书
 		// REF: https://portal.baishancloud.com/track/document/downloadPdf/1441
diff --git a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go
index 66e56796..af2db885 100644
--- a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go
+++ b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go
@@ -8,8 +8,9 @@ import (
 	"strconv"
 
 	"github.com/G-Core/gcorelabscdn-go/gcore"
-	gprovider "github.com/G-Core/gcorelabscdn-go/gcore/provider"
+	"github.com/G-Core/gcorelabscdn-go/gcore/provider"
 	"github.com/G-Core/gcorelabscdn-go/resources"
+	"github.com/G-Core/gcorelabscdn-go/sslcerts"
 
 	"github.com/usual2970/certimate/internal/pkg/core/deployer"
 	"github.com/usual2970/certimate/internal/pkg/core/uploader"
@@ -22,25 +23,33 @@ type DeployerConfig struct {
 	ApiToken string `json:"apiToken"`
 	// CDN 资源 ID。
 	ResourceId int64 `json:"resourceId"`
+	// 证书 ID。
+	// 选填。
+	CertificateId int64 `json:"certificateId,omitempty"`
 }
 
 type DeployerProvider struct {
 	config      *DeployerConfig
 	logger      *slog.Logger
-	sdkClient   *resources.Service
+	sdkClients  *wSdkClients
 	sslUploader uploader.Uploader
 }
 
 var _ deployer.Deployer = (*DeployerProvider)(nil)
 
+type wSdkClients struct {
+	Resources *resources.Service
+	SSLCerts  *sslcerts.Service
+}
+
 func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
 	if config == nil {
 		panic("config is nil")
 	}
 
-	client, err := createSdkClient(config.ApiToken)
+	clients, err := createSdkClients(config.ApiToken)
 	if err != nil {
-		return nil, fmt.Errorf("failed to create sdk client: %w", err)
+		return nil, fmt.Errorf("failed to create sdk clients: %w", err)
 	}
 
 	uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
@@ -53,7 +62,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
 	return &DeployerProvider{
 		config:      config,
 		logger:      slog.Default(),
-		sdkClient:   client,
+		sdkClients:  clients,
 		sslUploader: uploader,
 	}, nil
 }
@@ -73,17 +82,47 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
 		return nil, errors.New("config `resourceId` is required")
 	}
 
-	// 上传证书到 CDN
-	upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
-	if err != nil {
-		return nil, fmt.Errorf("failed to upload certificate file: %w", err)
+	// 如果原证书 ID 为空,则创建证书;否则更新证书。
+	var cloudCertId int64
+	if d.config.CertificateId == 0 {
+		// 上传证书到 CDN
+		upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
+		if err != nil {
+			return nil, fmt.Errorf("failed to upload certificate file: %w", err)
+		} else {
+			d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
+		}
+
+		cloudCertId, _ = strconv.ParseInt(upres.CertId, 10, 64)
 	} else {
-		d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
+		// 获取证书
+		// REF: https://api.gcore.com/docs/cdn#tag/SSL-certificates/paths/~1cdn~1sslData~1%7Bssl_id%7D/get
+		getCertificateDetailResp, err := d.sdkClients.SSLCerts.Get(context.TODO(), d.config.CertificateId)
+		d.logger.Debug("sdk request 'sslcerts.Get'", slog.Any("sslId", d.config.CertificateId), slog.Any("response", getCertificateDetailResp))
+		if err != nil {
+			return nil, fmt.Errorf("failed to execute sdk request 'sslcerts.Get': %w", err)
+		}
+
+		// 更新证书
+		// REF: https://api.gcore.com/docs/cdn#tag/SSL-certificates/paths/~1cdn~1sslData~1%7Bssl_id%7D/get
+		changeCertificateReq := &sslcerts.UpdateRequest{
+			Name:           getCertificateDetailResp.Name,
+			Cert:           certPEM,
+			PrivateKey:     privkeyPEM,
+			ValidateRootCA: false,
+		}
+		changeCertificateResp, err := d.sdkClients.SSLCerts.Update(context.TODO(), getCertificateDetailResp.ID, changeCertificateReq)
+		d.logger.Debug("sdk request 'sslcerts.Create'", slog.Any("request", changeCertificateReq), slog.Any("response", changeCertificateResp))
+		if err != nil {
+			return nil, fmt.Errorf("failed to execute sdk request 'sslcerts.Update': %w", err)
+		}
+
+		cloudCertId = changeCertificateResp.ID
 	}
 
 	// 获取 CDN 资源详情
 	// REF: https://api.gcore.com/docs/cdn#tag/CDN-resources/paths/~1cdn~1resources~1%7Bresource_id%7D/get
-	getResourceResp, err := d.sdkClient.Get(context.TODO(), d.config.ResourceId)
+	getResourceResp, err := d.sdkClients.Resources.Get(context.TODO(), d.config.ResourceId)
 	d.logger.Debug("sdk request 'resources.Get'", slog.Any("resourceId", d.config.ResourceId), slog.Any("response", getResourceResp))
 	if err != nil {
 		return nil, fmt.Errorf("failed to execute sdk request 'resources.Get': %w", err)
@@ -91,7 +130,6 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
 
 	// 更新 CDN 资源详情
 	// REF: https://api.gcore.com/docs/cdn#tag/CDN-resources/operation/change_cdn_resource
-	updateResourceCertId, _ := strconv.ParseInt(upres.CertId, 10, 64)
 	updateResourceReq := &resources.UpdateRequest{
 		Description:        getResourceResp.Description,
 		Active:             getResourceResp.Active,
@@ -99,7 +137,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
 		OriginProtocol:     getResourceResp.OriginProtocol,
 		SecondaryHostnames: getResourceResp.SecondaryHostnames,
 		SSlEnabled:         true,
-		SSLData:            int(updateResourceCertId),
+		SSLData:            int(cloudCertId),
 		ProxySSLEnabled:    getResourceResp.ProxySSLEnabled,
 		Options:            &gcore.Options{},
 	}
@@ -109,7 +147,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
 	if getResourceResp.ProxySSLData != 0 {
 		updateResourceReq.ProxySSLData = &getResourceResp.ProxySSLData
 	}
-	updateResourceResp, err := d.sdkClient.Update(context.TODO(), d.config.ResourceId, updateResourceReq)
+	updateResourceResp, err := d.sdkClients.Resources.Update(context.TODO(), d.config.ResourceId, updateResourceReq)
 	d.logger.Debug("sdk request 'resources.Update'", slog.Int64("resourceId", d.config.ResourceId), slog.Any("request", updateResourceReq), slog.Any("response", updateResourceResp))
 	if err != nil {
 		return nil, fmt.Errorf("failed to execute sdk request 'resources.Update': %w", err)
@@ -118,15 +156,19 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
 	return &deployer.DeployResult{}, nil
 }
 
-func createSdkClient(apiToken string) (*resources.Service, error) {
+func createSdkClients(apiToken string) (*wSdkClients, error) {
 	if apiToken == "" {
 		return nil, errors.New("invalid gcore api token")
 	}
 
-	requester := gprovider.NewClient(
+	requester := provider.NewClient(
 		gcoresdk.BASE_URL,
-		gprovider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)),
+		provider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)),
 	)
-	service := resources.NewService(requester)
-	return service, nil
+	resourcesSrv := resources.NewService(requester)
+	sslCertsSrv := sslcerts.NewService(requester)
+	return &wSdkClients{
+		Resources: resourcesSrv,
+		SSLCerts:  sslCertsSrv,
+	}, nil
 }
diff --git a/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go
index c5dc5296..5987136e 100644
--- a/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go
+++ b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go
@@ -7,8 +7,8 @@ import (
 	"log/slog"
 	"time"
 
-	gprovider "github.com/G-Core/gcorelabscdn-go/gcore/provider"
-	gsslcerts "github.com/G-Core/gcorelabscdn-go/sslcerts"
+	"github.com/G-Core/gcorelabscdn-go/gcore/provider"
+	"github.com/G-Core/gcorelabscdn-go/sslcerts"
 
 	"github.com/usual2970/certimate/internal/pkg/core/uploader"
 	gcoresdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gcore/common"
@@ -22,7 +22,7 @@ type UploaderConfig struct {
 type UploaderProvider struct {
 	config    *UploaderConfig
 	logger    *slog.Logger
-	sdkClient *gsslcerts.Service
+	sdkClient *sslcerts.Service
 }
 
 var _ uploader.Uploader = (*UploaderProvider)(nil)
@@ -59,8 +59,8 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
 	certName = fmt.Sprintf("certimate_%d", time.Now().UnixMilli())
 
 	// 新增证书
-	// REF: https://api.gcore.com/docs/cdn#tag/CA-certificates/operation/ca_certificates-add
-	createCertificateReq := &gsslcerts.CreateRequest{
+	// REF: https://api.gcore.com/docs/cdn#tag/SSL-certificates/operation/add_ssl_certificates
+	createCertificateReq := &sslcerts.CreateRequest{
 		Name:           certName,
 		Cert:           certPEM,
 		PrivateKey:     privkeyPEM,
@@ -81,15 +81,15 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
 	}, nil
 }
 
-func createSdkClient(apiToken string) (*gsslcerts.Service, error) {
+func createSdkClient(apiToken string) (*sslcerts.Service, error) {
 	if apiToken == "" {
 		return nil, errors.New("invalid gcore api token")
 	}
 
-	requester := gprovider.NewClient(
+	requester := provider.NewClient(
 		gcoresdk.BASE_URL,
-		gprovider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)),
+		provider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)),
 	)
-	service := gsslcerts.NewService(requester)
+	service := sslcerts.NewService(requester)
 	return service, nil
 }
diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx
index c06087de..4d548949 100644
--- a/ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx
+++ b/ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx
@@ -5,6 +5,7 @@ import { z } from "zod";
 
 type DeployNodeConfigFormGcoreCDNConfigFieldValues = Nullish<{
   resourceId: string | number;
+  certificateId?: string | number;
 }>;
 
 export type DeployNodeConfigFormGcoreCDNConfigProps = {
@@ -28,6 +29,13 @@ const DeployNodeConfigFormGcoreCDNConfig = ({ form: formInst, formName, disabled
     resourceId: z.union([z.string(), z.number()]).refine((v) => {
       return /^\d+$/.test(v + "") && +v > 0;
     }, t("workflow_node.deploy.form.gcore_cdn_resource_id.placeholder")),
+    certificateId: z
+      .union([z.string(), z.number().int()])
+      .nullish()
+      .refine((v) => {
+        if (!v) return true;
+        return /^\d+$/.test(v + "") && +v > 0;
+      }, t("workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder")),
   });
   const formRule = createSchemaFieldRule(formSchema);
 
@@ -52,6 +60,15 @@ const DeployNodeConfigFormGcoreCDNConfig = ({ form: formInst, formName, disabled
       >
         <Input type="number" placeholder={t("workflow_node.deploy.form.gcore_cdn_resource_id.placeholder")} />
       </Form.Item>
+
+      <Form.Item
+        name="certificateId"
+        label={t("workflow_node.deploy.form.gcore_cdn_certificate_id.label")}
+        rules={[formRule]}
+        tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.gcore_cdn_certificate_id.tooltip") }}></span>}
+      >
+        <Input type="number" placeholder={t("workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder")} />
+      </Form.Item>
     </Form>
   );
 };
diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json
index da776fc9..0b503461 100644
--- a/ui/src/i18n/locales/en/nls.workflow.nodes.json
+++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json
@@ -356,6 +356,9 @@
   "workflow_node.deploy.form.gcore_cdn_resource_id.label": "Gcore CDN resource ID",
   "workflow_node.deploy.form.gcore_cdn_resource_id.placeholder": "Please enter Gcore CDN resource ID",
   "workflow_node.deploy.form.gcore_cdn_resource_id.tooltip": "For more information, see <a href=\"https://cdn.gcore.com/resources/list\" target=\"_blank\">https://cdn.gcore.com/resources/list</a>",
+  "workflow_node.deploy.form.gcore_cdn_certificate_id.label": "Gcore CDN certificate ID (Optional)",
+  "workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder": "Please enter Gcore CDN certificate ID",
+  "workflow_node.deploy.form.gcore_cdn_certificate_id.tooltip": "For more information, see <a href=\"https://cdn.gcore.com/ssl\" target=\"_blank\">https://cdn.gcore.com/ssl</a>",
   "workflow_node.deploy.form.goedge_resource_type.label": "Resource type",
   "workflow_node.deploy.form.goedge_resource_type.placeholder": "Please select resource type",
   "workflow_node.deploy.form.goedge_resource_type.option.certificate.label": "Certificate",
@@ -441,7 +444,7 @@
   "workflow_node.deploy.form.local_format.label": "File format",
   "workflow_node.deploy.form.local_format.placeholder": "Please select file format",
   "workflow_node.deploy.form.local_format.option.pem.label": "PEM (*.pem, *.crt, *.key)",
-  "workflow_node.deploy.form.local_format.option.pfx.label": "PFX (*.pfx)",
+  "workflow_node.deploy.form.local_format.option.pfx.label": "PFX (*.pfx, *.p12)",
   "workflow_node.deploy.form.local_format.option.jks.label": "JKS (*.jks)",
   "workflow_node.deploy.form.local_cert_path.label": "Certificate file saving path",
   "workflow_node.deploy.form.local_cert_path.placeholder": "Please enter saving path for certificate file",
@@ -506,7 +509,7 @@
   "workflow_node.deploy.form.ssh_format.label": "File format",
   "workflow_node.deploy.form.ssh_format.placeholder": "Please select file format",
   "workflow_node.deploy.form.ssh_format.option.pem.label": "PEM (*.pem, *.crt, *.key)",
-  "workflow_node.deploy.form.ssh_format.option.pfx.label": "PFX (*.pfx)",
+  "workflow_node.deploy.form.ssh_format.option.pfx.label": "PFX (*.pfx, *.p12)",
   "workflow_node.deploy.form.ssh_format.option.jks.label": "JKS (*.jks)",
   "workflow_node.deploy.form.ssh_cert_path.label": "Certificate file uploading path",
   "workflow_node.deploy.form.ssh_cert_path.placeholder": "Please enter uploading path for certificate file",
diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json
index 3f38a490..85d2aa6e 100644
--- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json
+++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json
@@ -355,6 +355,9 @@
   "workflow_node.deploy.form.gcore_cdn_resource_id.label": "Gcore CDN 资源 ID",
   "workflow_node.deploy.form.gcore_cdn_resource_id.placeholder": "请输入 Gcore CDN 资源 ID",
   "workflow_node.deploy.form.gcore_cdn_resource_id.tooltip": "这是什么?请参阅 <a href=\"https://cdn.gcore.com/resources/list\" target=\"_blank\">https://cdn.gcore.com/resources/list</a>",
+  "workflow_node.deploy.form.gcore_cdn_certificate_id.label": "Gcore CDN 原证书 ID(可选)",
+  "workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder": "请输入 Gcore CDN 原证书 ID",
+  "workflow_node.deploy.form.gcore_cdn_certificate_id.tooltip": "这是什么?请参阅 <a href=\"https://cdn.gcore.com/ssl\" target=\"_blank\">https://cdn.gcore.com/ssl</a><br><br>不填写时,将上传新证书;否则,将替换原证书。",
   "workflow_node.deploy.form.goedge_resource_type.label": "证书替换方式",
   "workflow_node.deploy.form.goedge_resource_type.placeholder": "请选择证书替换方式",
   "workflow_node.deploy.form.goedge_resource_type.option.certificate.label": "替换指定证书",
@@ -440,7 +443,7 @@
   "workflow_node.deploy.form.local_format.label": "文件格式",
   "workflow_node.deploy.form.local_format.placeholder": "请选择文件格式",
   "workflow_node.deploy.form.local_format.option.pem.label": "PEM 格式(*.pem, *.crt, *.key)",
-  "workflow_node.deploy.form.local_format.option.pfx.label": "PFX 格式(*.pfx)",
+  "workflow_node.deploy.form.local_format.option.pfx.label": "PFX 格式(*.pfx, *.p12)",
   "workflow_node.deploy.form.local_format.option.jks.label": "JKS 格式(*.jks)",
   "workflow_node.deploy.form.local_cert_path.label": "证书文件保存路径",
   "workflow_node.deploy.form.local_cert_path.placeholder": "请输入证书文件保存路径",
@@ -505,7 +508,7 @@
   "workflow_node.deploy.form.ssh_format.label": "文件格式",
   "workflow_node.deploy.form.ssh_format.placeholder": "请选择文件格式",
   "workflow_node.deploy.form.ssh_format.option.pem.label": "PEM 格式(*.pem, *.crt, *.key)",
-  "workflow_node.deploy.form.ssh_format.option.pfx.label": "PFX 格式(*.pfx)",
+  "workflow_node.deploy.form.ssh_format.option.pfx.label": "PFX 格式(*.pfx, *.p12)",
   "workflow_node.deploy.form.ssh_format.option.jks.label": "JKS 格式(*.jks)",
   "workflow_node.deploy.form.ssh_cert_path.label": "证书文件上传路径",
   "workflow_node.deploy.form.ssh_cert_path.placeholder": "请输入证书文件上传路径",