Service De Channel Activate

作者 forcedotcome5164d94d751無授權條款1K 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫昨天更新

Activate an Enhanced `MessagingChannel` (WhatsApp/Apple/Facebook/SMS/RCS) by PATCHing `MessagingChannelUsage.DeploymentStatus` from `Disabled` to `Provisioning` via the REST sobject endpoint. The UDD save-hook dispatches by `MessageType` for the external callout (`WHATS_APP`→Meta `/register`, `FACEBOOK`→`subscribeFacebookPage`, `TEXT`→`registerCsotSms`; Apple/LINE need none), writes the terminal `Active`/`Error`, and flips `IsActive`. Synchronous on the HTTP response — WhatsApp returns 204 after Meta confirms (~15-21s); no-callout channels are near-instant. No Aura RPC, no CSRF cookies. Use to activate an already-inserted Enhanced channel headlessly via REST. Do not use for full end-to-end setup — use `service-de-headless-channel-configure`.

僅含說明DevOps & Cloud
AI 產生的概覽

透過 REST 將現有 Salesforce Enhanced MessagingChannel 的 MessagingChannelUsage DeploymentStatus 修補為 Provisioning 來啟用頻道。

功能
讀取 MessagingChannel 及其 MessagingChannelUsage 資料列,檢查路由與是否已啟用等前置條件,然後送出 REST PATCH 將 DeploymentStatus 設為 Provisioning。伺服器端儲存鉤子會執行平台特定的外部呼叫,並寫入最終的 Active 或 Error 狀態,技能接著讀回狀態與 IsActive 旗標。它會傳回 JSON 結果,回報成功、無操作或分類後的失敗,並包含 WhatsApp 電話號碼驗證子流程。
適用情境
用於透過 REST 以無介面方式啟用已插入的 Enhanced 訊息頻道,支援 WhatsApp、Apple、Facebook、SMS 或 RCS 等平台。它不適用於完整的端對端頻道設定,那屬於無介面頻道設定技能。
執行需求
需要 sf CLI(2.0.0+)、Node.js 20+ 與 jq,以及已驗證的 Salesforce 組織目標和存取該組織 REST API 的網路連線。頻道必須已存在且已設定路由。此技能不附帶指令碼,僅提供指示與參考文件。

Activating a Messaging Channel

What this skill does

Given a {CHANNEL_ID}, reads the channel's MessagingChannelUsage.Id, then fires PATCH /services/data/v{V}/sobjects/MessagingChannelUsage/{MCU_ID} with body {"DeploymentStatus":"Provisioning"}. The server-side chain:

  1. MessagingChannelUsageFunctions.validateBeforeSave runs validateDeploymentStatus → validateChannelReadinessOnProvisioning. For WhatsApp this confirms consent is configured. Rejected writes return HTTP 400 FIELD_INTEGRITY_EXCEPTION.
  2. MessagingChannelUsageFunctions.saveHook_PostStmtExecuteOnce fires unconditionally after the UPDATE statement. It calls MessagingChannelUsageFunctionsHelper.handlePostSave which registers a post-commit TransactionObserver.
  3. At commit, the observer calls ConversationChannelUsageDeploymentStatusService.handleProvisioning (inherited from AbstractChannelUsageDeploymentStatusService), which:
    • Calls runProvisioning — switch-dispatches by MessageType for the external callout:
      • WHATS_APP → registerCsotWhatsAppNumber → LiveMessageSetupApi.registerWhatsAppNumber → Meta /register + status verification. 15-21s wall-clock.
      • FACEBOOK → metaGraphApiService.subscribeFacebookPage.
      • TEXT → registerCsotSms.
      • AppleBusinessChat, Line, everything else → default branch, no external callout, no network wait.
    • On success: writes DeploymentStatus = 'Active' via PLSQL.
    • On failure: writes DeploymentStatus = 'Error' plus ErrorReason / ErrorDetails.
  4. Inside the same observer, a second pass syncs MessagingChannel.IsActive = true once MCU reaches Active (the isTransitioningStatus flag skips the flip while status is still Provisioning).

All synchronous within the PATCH request — the 204 response only comes back after the full chain completes. WhatsApp: ~15-21s (Meta /register round-trip). Apple / Line: ~1s (no external call; just the local save-hook + observer + PLSQL write). Verified on wadtesting 2026-04-30.

Reference File Index

Reference fileLoad when
references/phone-verification.mdStage 3 comes back with ErrorReason === "VERIFICATION_REQUIRED" (WhatsApp only) — the phone-number OTP verification sub-flow.
references/worked-examples.mdYou want a reference run of the WhatsApp happy-path, Apple activation, a readiness failure, or the already-active no-op.
references/gotchas.mdTroubleshooting an unexpected result, or before modifying this skill — the eleven known gotchas.

Why REST PATCH instead of Apex?

A direct REST PATCH produces the identical save-hook chain as the old activateChannelUsage Apex method, with substantially less machinery — no CSRF cookie acquisition, no bootstrap fetch, no Aura response parsing, no double-wrapped returnValue. REST semantics are honest: 204 means the transition succeeded; 4xx means it didn't.

Code proof: MessagingChannelUsageFunctions.saveHook_PostStmtExecuteOnce fires on any DML path (REST, SOAP, Apex, Metadata API) — there is no Apex-specific gate. The entity XML (MessagingChannelUsage.entity.xml) marks DeploymentStatus as editAccess="always" with no <readonly> attribute. The transition validator (getValidAPIStatusTransitions) allows Disabled → Provisioning (and New → Provisioning, and Error → Provisioning | Deprovisioning, and Active → Deprovisioning). The DB-only transitions Provisioning → Active | Error are reserved for the observer's PLSQL call — that's why we write Provisioning and let the server pick the terminal state.

When NOT to use this skill

  • The channel is already IsActive=true. Re-firing is blocked by the API transition validator (Active → Provisioning is not in getValidAPIStatusTransitions()) — the PATCH would return 400. The Stage 1 precondition check catches this and emits noop:true.
  • Routing isn't configured. activateChannelUsage used to fail with LiveMessageSetupException / nullQueueId at the Apex entry point. With the REST path the same guard lives in validateChannelReadinessOnProvisioning — write with SessionHandlerId=null && FallbackQueueId=null → 400 FIELD_INTEGRITY_EXCEPTION. Run service-de-channel-routing-configure first. The Stage 1 check still runs defensively.
  • The MCU doesn't exist. Can't PATCH a row that's missing. Run the insertion skill first — it always creates the MCU as a side-effect of addChannel.

Inputs (from caller)

  • {CHANNEL_ID} — a 15- or 18-char MessagingChannel.Id (prefix 0Mj). The channel must already exist with a non-null SessionHandlerId or FallbackQueueId.
  • {ORG_ALIAS} — optional; the sf CLI target-org alias. Default: whatever sf config get target-org returns. Used for OAuth and SOQL reads.
  • {API_VERSION} — optional; REST API version. Default: 68.0. Any version where MessagingChannelUsage is addressable as a standard sobject is fine (v50+ should work; not exhaustively tested).

Unlike the old Aura-based version of this skill, there are no {POLL_TIMEOUT_S} / {POLL_INTERVAL_S} inputs — the PATCH is synchronous end-to-end.

Output (to caller)

Success — channel is live:

json
{"ok": true, "channelId": "0Mj...", "mcuId": "0gL...", "deploymentStatus": "Active", "isActive": true, "messageType": "WhatsApp", "durationMs": 20934}

Success — no-op (already active):

json
{"ok": true, "noop": true, "channelId": "0Mj...", "message": "Channel already active"}

Failure — precondition not met:

json
{"ok": false, "kind": "no-routing",     "hint": "run service-de-channel-routing-configure first"}{"ok": false, "kind": "no-mcu",         "hint": "no MessagingChannelUsage row for this channel — run the insertion skill first"}{"ok": false, "kind": "channel-missing","hint": "MessagingChannel id not found"}

Failure — validator or server-side provisioning error:

json
{"ok": false, "kind": "readiness-failed", "errorCode": "FIELD_INTEGRITY_EXCEPTION", "message": "...", "hint": "validateChannelReadinessOnProvisioning rejected the write — most commonly missing consent; run service-de-channel-settings-configure first"}{"ok": false, "kind": "provisioning-error", "mcuId": "0gL...", "errorReason": "MetaRegistrationFailed", "errorDetails": "..."}{"ok": false, "kind": "verification-failed", "hint": "WhatsApp phone number verification failed or was declined by user"}{"ok": false, "kind": "verification-request-failed", "errorCode": "...", "message": "...", "hint": "Could not request verification code from Meta"}

Failure — auth / transport:

json
{"ok": false, "kind": "auth",      "hint": "OAuth token invalid / expired — run 'sf org login web'"}{"ok": false, "kind": "transport", "status": 500, "message": "..."}

Stage 1: Precondition checks

Read the channel, then its MCU, as two separate SOQL calls. A combined subquery would be cheaper but fails on orgs where the child relationship is unnameable (see gotcha #4).

bash
sf data query --target-org '{ORG_ALIAS}' \  --query "SELECT Id, DeveloperName, MessageType, IsActive, SessionHandlerId, FallbackQueueId, MessagingPlatformKey FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" \  --json > /tmp/amc-precheck-channel.json
sf data query --target-org '{ORG_ALIAS}' \  --query "SELECT Id, DeploymentStatus, DeploymentType, ErrorReason, ErrorDetails FROM MessagingChannelUsage WHERE MessagingChannelId = '{CHANNEL_ID}'" \  --json > /tmp/amc-precheck-mcu.json

Let channel = /tmp/amc-precheck-channel.json records[0] and mcu = /tmp/amc-precheck-mcu.json records[0]:

ConditionEnvelope
Channel query returned 0 records{ok:false, kind:"channel-missing", hint:"MessagingChannel id not found"}
channel.IsActive === true{ok:true, noop:true, channelId, message:"Channel already active"} — return
channel.SessionHandlerId == null && channel.FallbackQueueId == null{ok:false, kind:"no-routing", hint:"run service-de-channel-routing-configure first"}
MCU query returned 0 records{ok:false, kind:"no-mcu", hint:"no MessagingChannelUsage row for this channel — run the insertion skill first"}
OtherwiseRecord {MCU_ID} = mcu.Id, {MESSAGE_TYPE} = channel.MessageType, {MESSAGING_PLATFORM_KEY} = channel.MessagingPlatformKey, {INITIAL_MCU_STATUS} = mcu.DeploymentStatus and continue to Stage 2.

Also record {T0} (epoch ms at start of Stage 2) so the final envelope can report durationMs.

Stage 1.1: Fast path for already-provisioning MCU

If {INITIAL_MCU_STATUS} === "Provisioning" — the MCU is already mid-flight from a prior call in this transaction window. Skip Stage 2 (firing the PATCH) entirely and jump to Stage 3 (verification). This is a rare race guard: the observer is synchronous with the PATCH, so by the time the caller sees the 204 the status is already terminal (Active or Error) — Provisioning should be invisible from outside. If we do see it in the precheck, something wrote Provisioning in a separate DML and the observer is still mid-flight — don't fire a second PATCH.


Stage 2: PATCH MessagingChannelUsage.DeploymentStatus = "Provisioning"

Use sf api request rest so authentication stays inside the CLI's transport — no OAuth token is ever extracted into shell state.

Fire the PATCH. This call can take 15-30 seconds for WhatsApp — the observer runs synchronously, including Meta's /register round trip. sf api request rest has no separate client-side timeout to raise; it waits on the underlying HTTP call.

bash
sf api request rest \  "/services/data/v{API_VERSION}/sobjects/MessagingChannelUsage/{MCU_ID}" \  --method PATCH \  --target-org '{ORG_ALIAS}' \  --header 'Content-Type: application/json' \  --body '{"DeploymentStatus":"Provisioning"}' \  --include \  > /tmp/amc-patch-response.txt 2>&1HTTP_CODE=$(head -1 /tmp/amc-patch-response.txt | grep -oE '[0-9]{3}')

--include prints the HTTP status/headers block ahead of the (typically empty, on 204) body — read the status line from that block rather than a -w-style trailing marker.

Classify by HTTP status:

StatusBodyHandling
204emptySuccess. The observer ran to completion; MCU is Active or Error. Continue to Stage 3 to read the terminal state.
400[{errorCode:"FIELD_INTEGRITY_EXCEPTION", message:"..."}]Validator rejection. See table below.
400[{errorCode:"INVALID_FIELD_FOR_INSERT_UPDATE" or "MALFORMED_ID", ...}]Skill bug — the MCU_ID from Stage 1 was wrong, or the body shape is off. Emit {ok:false, kind:"transport", status:400, message}.
401(usually empty)Bearer token invalid. Emit {ok:false, kind:"auth", hint:"OAuth token invalid / expired — run 'sf org login web'"}.
403[{errorCode:"INSUFFICIENT_ACCESS"}]User lacks perm to write DeploymentStatus. Emit {ok:false, kind:"business", errorCode:"INSUFFICIENT_ACCESS", message}.
5xxvariesTransport. The observer may have partially committed — Stage 3's SOQL is the source of truth. Read MCU state; if it's Active, report success with a warning; if Error or still Disabled, classify as {ok:false, kind:"transport", status, message}.

Known 400 FIELD_INTEGRITY_EXCEPTION messages:

Message fragmentMeaningEnvelope
"invalid deployment status transition"The current status doesn't allow → Provisioning (e.g. MCU is already Active — Stage 1 should have caught this, but there's a race window).Re-read MCU; if now Active, emit success-noop. If Provisioning, Stage 3 poll. Otherwise emit {ok:false, kind:"readiness-failed", ...}.
"consent" / "keyword" / mentions of STOP/HELPvalidateChannelReadinessOnProvisioning rejected — channel doesn't have required consent configured.{ok:false, kind:"readiness-failed", errorCode:"FIELD_INTEGRITY_EXCEPTION", message, hint:"channel requires a ConsentType and a matching MsgChannelLanguageKeyword record (opt-out keyword + confirmation) before activation — run service-de-channel-settings-configure"}.
"routing" / "queue" / "SessionHandler"Routing precondition (Stage 1 should have caught, but the validator re-checks).{ok:false, kind:"no-routing", message, hint:"run service-de-channel-routing-configure first"}.
otherUnrecognized validator error.{ok:false, kind:"readiness-failed", errorCode, message}.

Stage 3: Read the terminal MCU state

The PATCH is synchronous, so by the time we're here the MCU is Active or Error — no polling. Read once:

bash
sf data query --target-org '{ORG_ALIAS}' \  --query "SELECT Id, DeploymentStatus, ErrorReason, ErrorDetails FROM MessagingChannelUsage WHERE Id = '{MCU_ID}'" \  --json > /tmp/amc-poststate-mcu.json
StatusHandling
ActiveContinue to Stage 4.
Error with ErrorReason === "VERIFICATION_REQUIRED"For WhatsApp channels only: phone number needs OTP verification. Continue to Stage 3.2 (WhatsApp verification flow).
Error (other)Emit {ok:false, kind:"provisioning-error", mcuId, errorReason, errorDetails}.
ProvisioningUnexpected — the observer was supposed to terminate before the PATCH returned 204. Fall through to a defensive poll (see Stage 3.1).
DisabledThe PATCH returned 204 but the write didn't take? Emit {ok:false, kind:"transport", message:"PATCH returned 204 but MCU is still Disabled — observer didn't commit"}.

Stage 3.2: WhatsApp phone number verification (only if ErrorReason === "VERIFICATION_REQUIRED")

This sub-flow only runs for WhatsApp channels when activation fails with ErrorReason === "VERIFICATION_REQUIRED" — the phone number needs OTP verification with Meta before it can be registered. If the MCU comes back with ErrorReason === "VERIFICATION_REQUIRED" (WhatsApp only), load references/phone-verification.md and follow it to drive the phone-number verification sub-flow (request code → prompt user → validate code → retry activation once).

Stage 3.1: Defensive poll (only if Stage 3 saw Provisioning)

The observer's external-callout block (WhatsApp/Facebook/SMS) runs synchronously inside the PATCH request — there's no async queue indirection in runProvisioning for any message type (verified against the switch/case in ConversationChannelUsageDeploymentStatusService). So a Provisioning status at Stage 3 should not happen in steady state. Possible causes if it does: an exception thrown after the external call succeeded but before the PLSQL terminal-write ran; unusual instance config with async observer execution; or a future MessageType whose dispatch behavior we haven't accounted for. If Stage 3 returned Provisioning, loop:

bash
for i in 1 2 3 4 5 6 7 8 9 10; do  sleep 3  STATUS=$(sf data query --target-org '{ORG_ALIAS}' \    --query "SELECT DeploymentStatus FROM MessagingChannelUsage WHERE Id='{MCU_ID}'" --json \    | node -e 'console.log(JSON.parse(require("fs").readFileSync(0,"utf8")).result.records[0].DeploymentStatus)')  case "$STATUS" in    Provisioning) continue ;;    Active|Error) break ;;  esacdone

Max wait: 30s. If still Provisioning after the loop: emit {ok:false, kind:"timeout", mcuId, lastStatus:"Provisioning", elapsedS:30}. Verified on WhatsApp/wadtesting 2026-04-30: this loop should never actually iterate.


Stage 4: Verify MessagingChannel.IsActive

The observer flips IsActive inside the same callback as the status terminal write. In principle this is set by the time the PATCH returns. Confirm:

bash
sf data query --target-org '{ORG_ALIAS}' \  --query "SELECT Id, IsActive FROM MessagingChannel WHERE Id = '{CHANNEL_ID}'" --json > /tmp/amc-verify-channel.json

If IsActive === true: compute durationMs = Date.now() - T0 and emit success. If IsActive !== true despite MCU Active: the IsActive sync pass skipped (e.g. isTransitioningStatus was true when the observer ran, which shouldn't happen post-terminal). Emit:

json
{"ok": false, "kind": "provisioning-error", "mcuId": "...", "errorReason": "mcu-active-but-channel-inactive", "errorDetails": "MCU DeploymentStatus=Active but MessagingChannel.IsActive=false — observer's IsActive sync pass didn't run. Inspect MessagingChannelUsageFunctionsHelper.handlePostSave."}

Stage 5: Report to caller

Build the success envelope:

json
{"ok": true, "channelId": "{CHANNEL_ID}", "mcuId": "{MCU_ID}", "deploymentStatus": "Active", "isActive": true, "messageType": "{MESSAGE_TYPE}", "durationMs": 20934}

If this skill is the leaf (user invoked it directly), render:

  • Success — Activated — MessagingChannel {CHANNEL_ID} ({messageType}) is now live. MCU DeploymentStatus=Active, IsActive=true. (~{durationMs/1000}s)
  • Info: Already active — MessagingChannel {CHANNEL_ID} is IsActive=true. No changes. (no-op path)
  • Error: Routing not configured — run 'service-de-channel-routing-configure' skill first. (no-routing)
  • Error: No MessagingChannelUsage row — run the insertion skill first. (no-mcu)
  • Error: Readiness check failed: {message} — if it mentions consent/keywords, run 'service-de-channel-settings-configure' first. (readiness-failed)
  • Error: Activation failed: {errorReason} — {errorDetails} (provisioning-error)
  • Error: WhatsApp phone number verification failed: {hint} (verification-failed)
  • Error: Could not request verification code: {message} (verification-request-failed)
  • Timeout: Activation timed out after {elapsedS}s with MCU.DeploymentStatus={lastStatus}. Defensive-poll limit hit; this is unusual. Check MCU {mcuId} in Setup. (timeout)

Worked examples

For end-to-end activation traces (WhatsApp happy-path, Apple activation, a readiness-validator failure, and the already-active no-op), see references/worked-examples.md.


Gotchas

Eleven known gotchas — synchronous PATCH timing for WhatsApp, valid API status transitions, the IsActive sync pass, relationship-name variance across orgs, consent preconditions, DeploymentStatus picklist casing, the REST-vs-Apex equivalence, ErrorReason values, VERIFICATION_REQUIRED handling, OAuth token extraction, and the Status-code-409 Admin API conflict. Before troubleshooting an unexpected result or modifying this skill, load references/gotchas.md and follow it.

來源與署名

來源:forcedotcom/sf-skills位於skills/service-de-channel-activate提交e5164d9

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架

更多來自 forcedotcom/sf-skills 的技能

Service Itsm Teams Itservice Configure

forcedotcom

Configure the "Set Up Salesforce IT Service" checklist for Microsoft Teams Employee Service (ITSM) — the employee side, covering app enablement, marketplace install guidance, user access assignment, and Digital Experience Site selection. Use this for: 'turn on Salesforce IT Service', 'set up IT Service on Teams', 'assign Teams for Employee permission set', 'give employees access to Teams for Employee Service', 'manage user access for Teams ITSM', 'grant users the permission sets needed for Teams Employee Service', 'select a digital experience site for Teams', 'install Salesforce IT Service app on Teams', or any request to complete the IT Service half of the Teams ITSM Go page checklist (including the Manage User Access step). DO NOT TRIGGER for the base Teams Salesforce Go page toggle or Azure/Entra app setup (service-itsm-teams-configure) or for the IT Desk/fulfiller half of the checklist (service-itsm-teams-itdesk-configure).

待分類1K昨天更新

Service Itsm Teams Coordinate

forcedotcom

End-to-end autopilot orchestrator for setting up Microsoft Teams integration in Salesforce Service Cloud ITSM — runs the whole flow (enable the Teams for Employee Service Go feature, register the Microsoft Entra app, populate Named Credentials, configure the IT Desk and IT Service checklists, turn on Swarming, and optionally embed the Agentforce agent) in one continuous pass, stopping only at the points a human must act. Use when the user asks to set up Microsoft Teams for ITSM end to end, 'set up teams for it service', 'do the whole teams itsm setup', 'configure microsoft teams for employee service', or wants a guided Teams ITSM walkthrough. Delegates each stage to a specialized child skill while driving the sequence itself. DO NOT TRIGGER when the user asks to enable Teams alone, configure just the IT Desk or IT Service checklist alone, or enable Swarming alone — delegate directly to the specific child skill in those cases.

待分類1K昨天更新

Service Itsm Teams Itdesk Configure

forcedotcom

Configure the "Set Up Salesforce IT Desk" checklist for Microsoft Teams Employee Service (ITSM) — the fulfiller/agent side, covering app enablement, marketplace install guidance, user access assignment, and Swarming collaboration-tool setup. Use this for: 'turn on Salesforce IT Desk', 'set up IT Desk on Teams', 'assign Teams for IT Desk permission set', 'set Teams as collaboration tool for swarming', 'install Salesforce IT Desk app on Teams', or any request to complete the IT Desk half of the Teams ITSM Go page checklist. DO NOT TRIGGER for the base Teams Salesforce Go page toggle or Azure/Entra app setup (service-itsm-teams-configure) or for the IT Service/employee half of the checklist (service-itsm-teams-itservice-configure).

待分類1K昨天更新

Service Itsm Teams Debug

forcedotcom

透過對 Salesforce 組織執行通過/失敗設定檢查清單,診斷 Microsoft Teams 員工服務(ITSM)設定失敗問題。

DevOps & Cloud1K昨天更新

Service Itsm Teams Employee Agent Configure

forcedotcom

Configure the embedded Agentforce Employee Agent so it replies inside the Microsoft Teams ITSM custom client ('Salesforce Employee Assist' / 'Ask AI Agent'). Use this for: 'set up employee agent in Teams', 'embed Agentforce agent in Teams', 'make the IT Service Employee Agent reply in Teams', 'Teams Ask AI Agent not responding', 'agent joins then leaves without replying', 'configure MIAW deployment for Teams employee agent', 'Teams embedded messaging agent setup'. Builds the whole stack headlessly (zero Setup-UI clicks): the Web messaging channel with User Verification ON, the Enhanced Chat User Verification Key Set (JWKS_URL) it requires, the Teams_AgentForce custom-client deployment, the routing flow to the agent, and the Agent Access permission set that lets the portal user reach the agent. DO NOT TRIGGER for enabling the Teams feature Salesforce Go page toggle (service-itsm-teams-configure) or for configuring notification preferences.

待分類1K昨天更新

Service Itsm Swarming Configure

forcedotcom

透過 Connect API 呼叫啟用 Salesforce Swarming ITSM 功能,並將協作工具設為 Teams。

DevOps & Cloud1K昨天更新