こんにちは、Udesk WebIMウェブプラグインへのご利用を歓迎します。以下に基本的な使用方法、注意事項、パラメータ説明、メソッド説明、イベント説明、関連するサンプルなどを提供します。

基本的な使用方法

Udeskサポートシステムの管理者アカウントでログインし、管理センター -> チャネル管理 -> インスタントメッセージング -> ウェブプラグイン -> (特定のプラグイン)管理で基本属性を設定した後、コードをウェブページにコピーすると、Udesk IMが有効になります。

注意事項

デバイスサポート

WebIMは現在、PC/Android(タブレット含む)/iOS(タブレット含む)などのデバイスをサポートしています。

ブラウザ互換性

WebIMは現在、IE8+(以上)のIEブラウザとそのカーネルに基づくブラウザ(360/qq/...)、その他の主要ブラウザ(chrome/firefox/...)をサポートしています。

基本的なサンプル

埋め込みコードサンプル

<body>
    <!-- ウェブページの内容 具体的なコードは管理者のインスタントメッセージングウェブプラグインでコピーしてください -->

    <script>
    (function(a,h,c,b,f,g){a["UdeskApiObject"]=f;a[f]=a[f]||function(){(a[f].d=a[f].d||[]).push(arguments)};g=h.createElement(c);g.async=1;g.src=b;c=h.getElementsByTagName(c)[0];c.parentNode.insertBefore(g,c)})(window,document,"script","https://xxx.xxxx.cn/im_client/js/udeskApi.js?1487931175918","ud");
    ud({
        "code": "xxxx",
        "link": "https://xxx.xxxx.cn/im_client/?web_plugin_id=1",
        "isInvite": true,
        "mode": "inner",
        "color": "#307AE8",
        "pos_flag": "srb",
        "language": "en-us", //言語-英語
        "onlineText": "カスタマーサポートに連絡し、オンラインで相談する",
        "offlineText": "サポートは退勤しました。メッセージを残してください",
        "mobile": { //レスポンシブレイアウトのため、pc、mobileのカスタマイズを提供
            "mode": "blank",
            "color": "#307AE8",
            "pos_flag": "crb",
            "onlineText": "カスタマーサポートに連絡し、オンラインで相談する",
            "offlineText": "サポートは退勤しました。メッセージを残してください"
        }
    });
    </script>
</body>

リンクサンプル

https://xxx.xxxx.cn/im_client/?web_plugin_id=xx&language=zh-cn&agent_id=xxx&group_id=xxx

カスタム設定

開発者は自身のニーズに応じて関連設定をカスタマイズできます。すべての属性、イベントはud({...})内で設定され、すべてのメソッドはud(methodName, ...arguments)の方法で呼び出されます。

設定方法

1. ud({key: val, key2: val2, ...});
2. ud(key, val);

パラメータ説明

グローバルパラメータ

パラメータ名 必須 説明
code String 系统生成 はい 企業の一意識別子
link String 系统生成 はい 企業IMクライアントリンクアドレス
isInvite Boolean trueまたはfalse(デフォルト) いいえ ビジター招待機能を有効にするか
管理台可配
agent_id String 指定されたカスタマーサポートID、デフォルトでは指定なし いいえ セッションの担当カスタマーサポートを指定
group_id String 指定されたカスタマーサポートグループID、デフォルトでは指定なし いいえ セッションのカスタマーサポートグループを指定
session_key String 6桁のランダム文字列 いいえ 同じ顧客でも、異なるsesstion_keyは新しいセッションをトリガーします。
英字、数字、アンダースコアのみサポート、特殊文字は禁止
merchant_id String 加盟店ID いいえ merchant_idを渡した場合、session_key、merchant_idの両方に同じ加盟店IDを渡す必要があります。
セッションロジック:関連する加盟店パラメータを渡すと保存され、既存のセッション順序を乱さず、ロボット、事前問い合わせフォーム、メッセージなどは、人工セッション時にのみパラメータを保存して表示置換を行います
merchant_name String 加盟店名 いいえ このカスタマーサポートとのセッションで【カスタマーサポート紹介】が【加盟店名】に置き換えて表示されます
merchant_avatar String 加盟店アイコン いいえ このカスタマーサポートとのセッションで【カスタマーサポートアイコン】が【加盟店アイコン】に置き換えて表示されます
merchant_list Boolean trueまたはfalse(デフォルト) いいえ ウェブプラグインリンクにmerchant_list=trueがある場合、ウェブプラグインは現在の顧客の過去のセッションにおけるすべての加盟店を読み込み、各加盟店の最新のセッション時間でソートして表示します
mode String inner:ウェブページ埋め込みモード(デフォルト)
blank:独立ウィンドウモード
いいえ ボタンでウィンドウを開く際の表示モード
管理台可配
color String ボタンカラーコード、デフォルト:#307AE8 いいえ IMボタンの色を設定
管理台可配
pos_flag String ボタン形状+位置
1)形状: h(横) v(縦) c(円形) i(画像);
2)位置: lt(左上) mt(中上) rt(右上) lm(左中) mm(中央) rm(右中) lb(左下) mb(中下) rb(右下)
デフォルト値:crb(pc)、hrb(mobile)
いいえ ボタン形状+位置
例:vrb(縦右下)
画像設定パス:管理センター-チャネル管理-インスタントメッセージ-ウェブプラグイン-管理-ボタン設定
onlineText String カスタマーサポートオンライン表示テキスト、デフォルトは「カスタマーサポートに連絡、オンライン相談」 はい 管理台可配
offlineText String カスタマーサポートオフライン表示テキスト、デフォルトは「カスタマーサポートは退勤中、メッセージを残してください」 はい 管理台可配
noBubble Boolean trueまたはfalse(デフォルト) いいえ メッセージポップアップバブル通知を表示しない
manualInit Boolean trueまたはfalse(デフォルト) いいえ 手動初期化、trueに設定すると、埋め込みコードは自動的に初期化されず、ud('init')メソッドを明示的に呼び出す必要があります
language String "zh-cn"(中国語)、"en-us"(英語)など いいえ クライアントの多言語設定[詳細]
channel String カスタムチャネル いいえ 管理台可配
targetSelector String #id,.class,tagName,...をサポート
默认系统生成 唯一
いいえ メインターゲットボタンセレクター
1) チャットウィンドウをトリガーするため
2) 代替システムが提供するデフォルトボタンに使用、指定が有効になるとデフォルトボタンは表示されなくなります
3) 招待を受け取るため
4) 新着メッセージ通知を受け取るため
5) ...
selector String #id,.class,tagName,...をサポート
デフォルトなし 可多个
いいえ 補助ボタンセレクター
1) チャットウィンドウをトリガーするため
css Object ボタンカスタムスタイル、例:css:{top:10%}、デフォルトなし いいえ
window Object 仅独立窗口模式 独立ウィンドウのデフォルトサイズは幅780、高さ560
例 window: {"width": "780", "height": "560"}
いいえ 独立ウィンドウのサイズを設定
panel Object 仅网页内嵌模式 いいえ セッションパネル [詳細]
pop Object いいえ メッセージ通知バブル [詳細]
customer Object いいえ 顧客情報 [詳細]
im_client_valid {v_nonce:string,v_timestamp:string,v_signature:string} いいえ リクエスト権限検証が有効な場合は必須 [詳細]
product Object いいえ 相談対象 [詳細]
hide_product Boolean いいえ パラメータがtrueの場合、クライアント側の相談対象の表示が非表示になりますが、カスタマーサポート側には表示されます
mobile Object いいえ モバイル端末関連設定 [詳細]
ウェブサイトがレスポンシブレイアウトの場合、pc、mobileのカスタマイズを提供
robot_modelKey String ロボットFAQテンプレートID いいえ ロボットFAQテンプレートIDに基づいてFAQテンプレートを呼び出し、「Km-ロボット-FAQ対話-ナレッジベース-よくある質問-ID」で確認できます
c_cf_dialogueDesc String カスタム値、カンマ区切りで複数値をサポート いいえ このフィールドは、顧客がロボットに任意のカスタム情報を渡すニーズを満たすためのものです。
使用方法:まず、カスタマーサポートシステムの顧客カスタムフィールド内に、c_cf_dialogueDescという名前のカスタムフィールドを設定します。顧客のこのフィールド値を設定した後、web IMウェブプラグインを開き、このフィールドをパスパラメータに追加します。形式は以下の通りです https://xxx.udesk.cn/im_client/?web_plugin_id=41597&c_cf_dialogueDesc=* これにより、システムは自動的にc_cf_dialogueDescのパラメータ値をロボットに渡し、ロボットの対話説明フィールドがこの値を受け取ります
uba {app_key: string} ユーザー行動分析設定 いいえ 例:ud({uba:{app_key: 'xxxxxxx'}})
src_url String http URLアドレス いいえ 参照元URL
### サンプル
ud({
    "code": "xxxx",
    "link": "https://xxx.xxxx.cn/im_client/",
    "mode": "inner",
    "color": "#307AE8",
    "pos_flag": "srb",
    "onlineText": "カスタマーサポートに連絡、オンライン相談",
    "offlineText": "サポートは終了しました、メッセージをお残しください",
    "targetSelector": "#btn_udesk_im",
    "selector": ".udesk_im",
    "pop": {},
    "panel": {},
    "mobile": {},
    "window": {}
});

> モバイル端末 - パラメータ説明

パラメータ名 タイプ 必須かどうか 説明
mode String inner:ウェブページ埋め込みモード(デフォルト)
blank:独立ウィンドウモード
いいえ ボタンで開くウィンドウの表示モード
管理台可配
color String ボタンの色コード、デフォルト:#307AE8 いいえ IMボタンの色を設定
管理台可配
pos_flag String ボタンの形状+位置
1)形状: h(横長) v(縦長) c(円形) i(画像);
2)位置: lt(左上) mt(中上) rt(右上) lm(左中) mm(中央) rm(右中) lb(左下) mb(中下) rb(右下)
デフォルト値:crb(pc)、hrb(mobile)
いいえ ボタンの形状+位置
例:vrb(縦長右下角)
画像設定パス:管理センター-チャネル管理-インスタントメッセージ-ウェブプラグイン-管理-ボタン設定
onlineText String サポートオンライン時表示テキスト、デフォルト「カスタマーサポートに連絡、オンライン相談」 はい 管理台可配
offlineText String サポートオフライン時表示テキスト、デフォルト「サポートは終了しました、メッセージをお残しください」 はい 管理台可配
noBubble Boolean trueまたはfalse(デフォルト) いいえ メッセージポップアップバブル通知を表示しない
language String "zh-cn"(中国語) または "en-us"(英語) いいえ クライアントの多言語設定
targetSelector String #id,.class,tagName,...をサポート
默认系统生成 唯一
いいえ メインターゲットボタンセレクタ
1) チャットウィンドウをトリガーするため
2) 代替システムデフォルト提供ボタン、指定有効後デフォルトボタンは表示されない
3) 招待を受信するため
4) 新着メッセージ通知を受信するため
5) ...
selector String #id,.class,tagName,...をサポート
デフォルト無し 可多个
いいえ 補助ボタンセレクタ
1) チャットウィンドウをトリガーするため
css Object ボタンカスタムスタイル、例:css:{top:10%}、デフォルト無し いいえ
pop Object いいえ メッセージ通知バブル [詳細]
### サンプル
ud({
    "mobile", {
        "mode": "blank",
        "color": "#307AE8",
        "pos_flag": "crb",
        "onlineText": "カスタマーサポートに連絡、オンライン相談",
        "offlineText": "サポートは終了しました、メッセージを残してください",
        "pop": {
            "direction": "top",
            "arrow": {
                "top": 0,
                "left": "70%"
            }
        }
    }
});

> チャットパネル - パラメータ説明

パラメータ名 タイプ 必須かどうか 説明
css Object カスタムスタイル、例:css:{top:10%}、デフォルトは無し いいえ パネルの位置は top、left、right のみサポート
onToggle Function カスタムメソッド
パラメータ:data.visible(trueまたはfalse)},
いいえ 現在のチャットパネルが開いているかどうかを検出、visibleがtrueの場合は開いている状態

サンプル

ud({
    "panel": {
        "css": {
            "top": "0",
            "left": "0"
        },
        "onToggle": function(data) {  //パネルの開閉イベント
            if (data.visible) {
                //console.log('ウィンドウが開きました');
            }
            else{
                //console.log('ウィンドウが閉じました');
            }
        }
    }
});

> メッセージ通知バルーン - パラメータ説明

パラメータ名 タイプ 必須かどうか 説明
css Object カスタムスタイル、例:css:{top:10%}、デフォルトは無し いいえ
direction String バルーンの表示方向、"top"(デフォルト);"right";"left";"bottom" いいえ
offset Object バルーンの位置オフセット、{top:0,left:0}、デフォルトは中央揃え いいえ
arrow Object バルーン矢印の設定、{top:0,left:0}、デフォルトは中央揃え いいえ
### サンプル
ud({
    "pop": {
        "direction": "top",
        "arrow": {
            "top": 0,
            "left": "70%"
        }
    }
});

> 顧客情報 - パラメータ説明

概要

WebサイトにログインしているユーザーがWeb IMを通じてチャットを行う際に、顧客情報をリンク経由でUdeskに転送することができます。これにより、サポート担当者は顧客との対話中に直接顧客情報を確認できます。顧客情報補助コンポーネントを通じて、この顧客の注文情報などをさらに把握することも可能です。

使用方法

Web IM対話ウィンドウのリンク(https://xxxx.udesk.cn/im_client/)に、以下のルールに従ってパラメータと暗号化情報を追加することで、顧客情報を送信できます。

メールアドレスと電話番号は顧客識別に使用されます。つまり、Udeskシステム内のCRMの既存データと照合され、既存の顧客の場合は情報が更新され、一致しない場合は新しい顧客が作成されます。

> 顧客認証 - リクエストパラメータ

顧客情報や業務記録を渡すには、認証が必要です signature暗号化アルゴリズム。これらのデータを渡す必要がない場合は、認証は不要です。
顧客識別の有効期間: 4日間
顧客識別の優先順位: web_token > customer_token > c_email > c_phone
渡されたweb_tokenまたはcustomer_tokenがシステムに存在しない場合でも、渡されたc_emailまたはc_phoneが既に存在する場合、システムは元の顧客として識別します。 web_tokenのみを渡し、customer_token、c_email、c_phoneなどの識別データを渡さない場合、web_tokenは顧客のweb_tokenデータのみと照合され、一致しない場合は新しい顧客が作成されます。

パラメータ名 タイプ 必須 説明
nonce String ランダム値 はい ランダム値。動的なランダム値は静的なものよりもセキュリティが高くなります。
timestamp String タイムスタンプ はい 現在のタイムスタンプ(13桁ミリ秒)
web_token String 顧客ID はい 顧客の一意の識別子。メールアドレス、電話番号などの使用を推奨します。
英数字とアンダースコアのみサポート。特殊文字は使用禁止
customer_token String 顧客外部ID いいえ 顧客の外部一意識別子。open_api_tokenと同等です。
英数字とアンダースコアのみサポート。特殊文字は使用禁止
signature String 暗号化署名 はい [signature暗号化アルゴリズム]
encryption_algorithm String SHA1またはSHA256 いいえ 暗号化アルゴリズム。未指定の場合はデフォルトでSHA1。SHA256の使用を推奨します。
### signature暗号化アルゴリズム(3ステップ)

1、以下のパラメータと順序で文字列を連結し、key=value&の形式にします: noncetimestampweb_tokenim_user_key
im_user_keyの取得場所【管理センター-インスタントメッセージング-ウェブプラグイン-管理/顧客情報追加内のKEY】

sign_str = nonce=value&timestamp=value&web_token=value&im_user_key

2、 暗号化アルゴリズムを使用して署名文字列を計算します

sign_str = sha1(sign_str) または sign_str = sha256(sign_str)

3、 文字列を大文字に変換します

sign_str = sign_str.toUpperCase()

4、よくある間違い

1、 im_user_keyはパラメータ名が不要で、値のみ必要です 2、 signature文字列は大文字に変換する必要があります

SHA1の例:
    sign_str = "nonce=9ca6fff5a509fb887ac72cf5c92010e7&timestamp=1455675719000&web_token=test@udesk.cn&b476f9f8-5309-4d0a-a2d4-af08c4507a15";
    sign_str = sha1(sign_str);
    sign_str = sign_str.toUpperCase();

// SHA1の例
ud({
    "customer": {
        "nonce": "9ca6fff5a509fb887ac72cf5c92010e7",
        "signature": "9B2619225AA6476DC1EB80DBB8801E1575EBE39C",
        "timestamp": "1455675719000",
        "web_token": "test@udesk.cn"
    }
});

// SHA256の例
ud({
    "customer": {
        "nonce": "9ca6fff5a509fb887ac72cf5c92010e7",
        "signature": "4CC40FA2D762DAB1D4509750A7135123743D26F2552B7E23611AB8CB5D35825B",
        "timestamp": "1455675719000",
        "web_token": "test@udesk.cn",
        "encryption_algorithm": "SHA256"
    }
});

顧客パラメータ

パラメータ名 タイプ 必須かどうか 説明
c_name String 顧客名 いいえ
c_email String 顧客メールアドレス唯一 いいえ
c_phone String 顧客電話番号唯一 いいえ
customer_token String 顧客外部識別子唯一 いいえ open_api_tokenと同じフィールド
c_desc String 顧客説明 いいえ
c_org String 会社名 いいえ 複数会社を有効にしている場合は、複数渡すことができ、英語のカンマで区切ります 例:"かっこいい,きれい";有効にしていない場合は最初のもののみ取得
c_tags String 顧客タグ いいえ 顧客タグを渡し、カンマで区切ります 例:"かっこいい,きれい"
c_owner String 顧客担当者ID いいえ
c_vip String 'vip'(VIP顧客) または 'normal'(一般顧客) いいえ 顧客VIP識別
c_owner_group String 顧客担当グループID いいえ
c_other_emails String 顧客のその他のメールアドレスリスト いいえ カンマ区切り 例:"a@xxx.cn,b@xxx.cn"
c_cf_<カスタムフィールド名> String 顧客カスタムフィールド いいえ 顧客カスタムフィールド 例: c_cf_名前、c_cf_age、...
## > 業務記録 - リクエストパラメータ
パラメータ名 タイプ 必須 説明
c_cn_title String 業務記録主題 いいえ 業務記録の主題を入力します
c_cn_<カスタムフィールド名> String 業務記録カスタムフィールド いいえ 業務記録のカスタムフィールド 例: c_cn_名前、c_cn_age、...

ud({
    "customer": {
        "c_name": "顧客名kimi",
        "c_email": "newest3@udesk.cn",
        "c_other_emails": '11@udesk.cn,22@udesk.cn',
        "c_desc": "見込み顧客、潜在力が大きい",
        "c_org": "desc",
        "c_phone": "1100110012",
        "c_tags": "ハンサム,新規追加",
        "c_owner_group": "62",
        "c_owner": "3",
        "c_vip": "vip",
        "c_qq": "123123",
        "c_cf_年齢": 10,
        "c_cf_趣味": "エクストリームチャレンジ",
        "c_cn_title":"業務記録主題",
        "c_cn_名前":"業務記録の名前",
        "nonce": "694db2645b3f69a8",
        "signature": "315345C77C73A128CF9850EAD777F7A71D423A36",
        "timestamp": "1465878579000",
        "web_token": "newest3@udesk.cn"
    }
});

リンク例

渡すパラメータはエンコード処理してください。そうしないと文字化けが発生します!

https://xxx.udesk.cn/im_client/?c_desc=test123456789&c_email=jiangst%40udesio.com&c_phone=15888888888&echostr=hello&nonce=cdebd5d13f4d331e&signature=693140534BDDDAF002A46F0027E06244DF0B21AB&timestamp=1457696747000&web_token=42f6607e-8892-4fcf-889b-f9babf627060

> チケット情報 - リクエストパラメータ

パラメータ名 タイプ 必須 説明
t_subject String チケット主題 いいえ チケットの主題
t_content String チケット説明 いいえ 値を渡すとページに反映され、メッセージ内容テンプレートを上書きします
t_priority_id String チケット優先度 いいえ t_priority_idの取り得る値 1(緊急)、2(高)、3(標準)、4(低) 詳細
t_status_id String チケット状態 いいえ t_status_idの取り得る値 1(オープン)、2(解決済み)、3(クローズ済み)、4(解決中) 詳細
t_tags String チケットタグ いいえ チケットタグを入力します。カンマで区切ります 例:"tag1,tag2,tag3"
t_cf_<カスタムフィールド名> String チケットカスタムフィールド いいえ チケットのカスタムフィールド。APIでフィールド詳細リストを取得します 例: t_cf_TextField_213、t_cf_SelectField_225 詳細
### サンプル
ud({
    "ticket": {
        "t_subject": "チケット件名",
        "t_content": "チケット説明",
        "t_priority_id": '3',//標準
        "t_status_id": "1",//オープン
        "t_tags": "遠雷、雨待ち、ここに留まれ",
        "t_cf_TextField_213": "テキスト",
        "t_cf_TextField_214": "12:00:00",//時間
        "t_cf_TextField_215": "2018-10-26",//日付
        "t_cf_TextField_215": "2018-10-20 12:00",//日時
        "t_cf_SelectField_225": "3",//単一選択またはドロップダウン
        "t_cf_SelectField_226": "1,2",//複数選択
        "t_cf_SelectField_227": "0,0",//カスケード
    }
});

リンクサンプル

渡すパラメータはエンコード処理してください。そうしないと文字化けが発生する可能性があります!

https://xxx.udesk.cn/im_client/?t_priority_id=3&t_status_id=1&t_cf_TextField_124=%E6%96%87%E6%9C%AC%E6%A1%86&t_cf_TextField_135=2018-10-20&t_cf_TextField_136=12:00:00&t_cf_TextField_137=2018-10-20%2012:00&t_cf_TextField_138=3.14&t_cf_TextField_139=250&t_cf_TextField_140=https://www.baidu.com&t_cf_TextField_141=abc&t_cf_TextField_142=%E9%80%9A%E5%8E%BF&t_cf_SelectField_134=1&t_cf_SelectField_135=0,0&t_cf_SelectField_136=0&t_cf_SelectField_137=1,2&t_tags=%E6%B5%8B%E8%AF%951,%E5%BC%A0%E4%B8%89,%E6%9D%8E%E5%9B%9B,%E7%8E%8B%E4%BA%94&c_name=im_client%E6%B5%8B%E8%AF%95%E5%AE%A2%E6%88%B7&c_email=t_im_client@163.com&c_phone=13520361010

> コンサルティングオブジェクト - パラメータ説明

2種類の導入方法を提供します:URLパラメータ方式、JavaScript導入方式

パラメータ説明

名前 説明
title String タイトル
title_style String タイトルのスタイル、例:color:rgb(50,50,50);font-weight:bold
url String 遷移先ページのリンクアドレス
image String 表示画像アドレス
send trueまたはfalse trueの場合、コンサルティングオブジェクトの下に送信ボタンが表示され、クリックすると現在のコンサルティングオブジェクトが商品メッセージとしてカスタマーサポートに送信されます
<カスタムパラメータ> 複数のカスタムパラメータを定義できます。日本語も可能です
<カスタムパラメータ>_style String カスタムパラメータのスタイル
### URLパラメータ渡し方式

すべてのパラメータの前にプレフィックス product_ を付け、渡すパラメータはエンコード処理を行ってください。そうしないと文字化けが発生する可能性があります!

例:https://udeskdemo.udesk.cn/im_client/?product_send=true&product_title=Apple%20iPhone%207&product_url=http%3A%2F%2Fitem.jd.com%2F3133829.html%3Fcu%3Dtrue%26utm_source%E2%80%A6erm%3D9457752645_0_11333d2bdbd545f1839f020ae9b27f14&product_image=http%3A%2F%2Fimg14.360buyimg.com%2Fn1%2Fs450x450_jfs%2Ft3157%2F63%2F1645131029%2F112074%2Ff4f79169%2F57d0d44dN8cddf5c5.jpg%3Fv%3D1474635884816&product_%E4%BB%B7%E6%A0%BC=%EF%BF%A56189.00&product_%E4%BF%83%E9%94%80%E4%BF%A1%E6%81%AF=%E8%B4%AD%E4%B9%B0%E4%BA%AC%E4%B8%9C%E8%87%AA%E8%90%A5%E7%94%B5%E8%84%91%2C%E6%89%8B%E6%9C%BA%2C%E6%95%B0%E7%A0%81%E5%93%81%E7%B1%BB%E6%8C%87%E5%AE%9A%E4%BA%A7%E5%93%81%2C%E5%AE%9E%E9%99%85%E4%B8%8B%E5%8D%95%E7%BB%93%E7%AE%97%E9%87%91%E9%A2%9D%E6%BB%A1199%E5%85%83%2C%E8%BF%94%E4%BA%AC%E4%B8%9C%E8%87%AA%E8%90%A5%E5%A4%A7%E9%97%B8%E8%9F%B9%E4%B8%9C%E5%88%B8%E4%B8%80%E5%BC%A0.

JavaScript連携方式

ud({
    product: {
        title: "Apple iPhone 7",
        url: "http://item.jd.com/3133829.html?cu=true&utm_source…erm=9457752645_0_11333d2bdbd545f1839f020ae9b27f14",
        image: "http://img14.360buyimg.com/n1/s450x450_jfs/t3157/63/1645131029/112074/f4f79169/57d0d44dN8cddf5c5.jpg",
        "価格": "¥6189.00",
        "プロモーション価格": "¥6188.00"
   }
});

> クライアントの多言語設定 - 詳細

多言語設定から既に設定されている多言語言語コードを探す

多言語機能はUdeskに個別にご連絡いただき、有効化してください

管理 -> アカウント設定 -> 多言語サポート

言語名 ファイル名 言語コード 更新日時 操作
English reocar_language_translation(en-us).xlsx en-us 2017/08/23 14:30 ファイルダウンロード ファイルアップロード 更新

設定された言語コード en-uslanguage パラメータとして使用します。フランス語を使用する場合は、まずフランス語の多言語設定を行い、多言語サポートリストの 法语配置记录 の言語コードを使用してください。

zh-cn(簡体字中国語)はすでにシステムデフォルトとして設定されており、直接使用できます。多语言支持 で設定する必要はありません。

もし language多语言支持列表 で設定されていない言語コードパラメータが渡された場合、デフォルトの簡体字中国語が使用されます。

フロントエンドの静的リソース内の表示内容は現在、簡体字中国語とEnglishをサポートしています。カスタム言語翻訳はサポートしていません。より多くの言語をサポートする必要がある場合は、弊社までご連絡ください。

多言語言語コード設定規定

言語コードは以下のリストから選択する必要があります:

設定したい多言語言語コードが以下のリストにない場合は、Udeskにお問い合わせください。

言語名 言語コード
アラビア語 ar
English en-us
スペイン語 es
フランス語 fr
日本語 ja
朝鮮語/韓国語 ko
タイ語 th
インドネシア語 id
繁体字中国語 zh-TW
ポルトガル語 pt
ロシア語 ru

メソッド説明

メソッド名 パラメータ 説明
init なし 手動初期化。ただし、manualInittrueに設定されている場合に有効です。例:ud("init")
hidePanel なし 手動でチャットパネルを非表示にします。例:ud("hidePanel")
showPanel なし 手動でチャットパネルを表示します。例:ud("showPanel")
dataTrace type(データタイプ), data(データ) データ追跡:閲覧履歴、イベントなどを含みます。

> 商品閲覧履歴アップロード

メソッド説明

ud("dataTrace", type, data);

パラメータ説明

パラメータ名 タイプ 必須 説明
type String product はい 追跡タイプ
data Object はい 追跡データ
data.name String はい 商品名
data.url String いいえ 商品へのリンク(新しいページで表示)。値が空の場合、クリックできません。
data.imgUrl String いいえ 値が空の場合、表示されません。
data.params Object いいえ パラメータリスト
data.params.text String いいえ パラメータテキスト
data.params.color String いいえ パラメータの色値。16進数の色を指定します(例:#ff0000)。
data.params.fold Boolean いいえ 太字にするかどうか
data.params.break Boolean いいえ 改行するかどうか
data.params.size Number デフォルト12 いいえ フォントサイズ
### サンプル
// 商品閲覧履歴
ud("dataTrace", "product", {
    "name": " Apple iPhone X (A1903) 64GB 深空灰色 移动联通4G手机",
    "url": "https://item.jd.com/6748052.html",
    "imgUrl": "http://img12.360buyimg.com/n1/s450x450_jfs/t10675/253/1344769770/66891/92d54ca4/59df2e7fN86c99a27.jpg",
    "params": [
        {
            "text": "¥6999.00",
            "color": "#FF0000",
            "fold": false,
            "break": false,  //breakはキーワードのため、IE8では引用符で囲む必要があります
            "size": 12
        }
    ]
});

> 注文イベントのアップロード

注文イベントをアップロードするには、まず顧客認証を行い、その後以下の方法で呼び出してください。

メソッド説明

ud("dataTrace", type, data);

パラメータ説明

パラメータ名 タイプ 必須かどうか 説明
type String order 必須 トラッキングタイプ
data Object 必須 トラッキングデータ
data.order_no String 必須 注文番号
data.name String 必須 注文名
data.url String 任意 注文へのリンクURL
data.price Number 必須 注文金額
data.order_at Date 必須 注文日時
data.pay_at Date 任意 支払い日時
data.status String 必須 注文ステータス: wait_pay(支払い待ち)、paid(支払い済み)、closed(キャンセル済み)
data.remark String 任意 備考、最大長は1000バイト(日本語は2バイト)
data.consignee_name String 任意 受取人氏名
data.consignee_phone String 任意 受取人電話番号
data.commodit_num String 任意 商品総数
commodities Array 任意 商品情報Array(Ojbect)
### commodities商品情報オブジェクト
パラメータ名 タイプ 必須 説明
commodit_name string いいえ 商品名
commodit_no string いいえ 商品番号
commodit_count numeric いいえ 商品数量
commodit_fee string いいえ 商品価格

サンプル

ud("dataTrace", "order", {
    order_no: '1',
    name: '最初の注文',
    url: 'http://xxx.xxxx.com/注文リンク',
    price: 16.8,
    order_at: new Date(),
    pay_at: new Date(),
    status: 'wait_pay',
    remark: '備考',
    consignee_name: '張三',
    consignee_phone: '01012345',
    consignee_address: '北京市大興区',
    commodit_num: 88,
    commodities: [
      {
        commodit_name: '牛乳A',
        commodit_no: 'NO123456',
        commodit_count: 1,
        commodit_fee: '46.5'
      }
    ]
});

> マーケティングセッションイベントトラッキング

メソッド説明

ud("dataTrace", type, data);

パラメータ説明

パラメータ名 タイプ 必須 説明
type String marketing はい トラッキングタイプ
data Object はい トラッキングデータ
data.name String はい イベント名

サンプル

// 商品閲覧履歴
ud("dataTrace", "marketing", {
    "name": "注文キャンセル"
});

イベント説明

パラメータ名 タイプ 必須 説明
onReady Function リスナーイベント, パラメータなし いいえ Udesk IMプラグイン初期化完了イベントコールバック
onUnread Function リスナーイベント, パラメータ:data:{count:1 //未読メッセージ数} いいえ 未読メッセージイベントコールバック
### サンプル
ud({
    "onReady": function() {
        console.log('初期化完了');
    },
    "onUnread": function(data) {
        console.log('未読メッセージ数'+data.count);
    }
});

> ボタン位置の変更(ドラッグ)

概要

主にサードパーティがボタンの位置を変更し、カスタムドラッグイベントを実現するために使用します。 classがudesk-client-btnのCSS(top, right, bottom, left)を変更します。

注意事項

ドラッグクリックによるチャットテンプレートの展開や招待の受け入れなどのイベントを防ぐためには、以下が必要です: document.onmousedownイベント内でud('noDrag');を呼び出します。 document.onmousemoveイベント内でud('isDrag')を呼び出します。

サンプル

  1. ボタン位置の変更: カスタマーサポートシステム管理画面 -> チャネル管理 -> インスタントメッセージング -> 特定のウェブプラグイン(管理をクリック)-> ボタン設定(右上)
  2. ドラッグによる変更方法: ユーザー自身が実装します。ネイティブのmousemovemouseupメソッドを使用し、自身の実際のビジネスロジックに基づいて実装できます。

ウィンドウ設定 - 情報エリアのカスタムURL

Udeskウェブプラグインを使用し、かつウェブプラグインのウィンドウ設定でカスタムURLを構成した場合、構成されたページ内からUdeskカスタマーサポート/ボットにメッセージを送信できます。

基本的な使い方

カスタムURLページは、postMessageを使用して親ページと通信し、特定のメッセージ形式に従う必要があります。

カスタマーサポートチャット画面: テキストメッセージと商品メッセージを送信できます。

ボットチャット画面: テキストメッセージのみサポートしています。

現在のウィンドウのウェブリンクをカスタムiframeに渡す

ウィンドウは、現在のウェブページリンクのパラメータをカスタムURLのiframeに渡します。(ただし、cur_urlcur_titlepre_urlsrc_urlの4つのパラメータは渡しません)。

パラメータ説明

パラメータ名 タイプ 必須かどうか 説明
method String 'sendMsg' はい メソッド名、現在はsendMsgのみサポートしています
type String 'text' または 'product' はい メッセージタイプ: 文本消息 または 商品消息
content String Object はい メッセージ内容

サンプル

1. テキストメッセージ

    var data = JSON.stringify({
            method: "sendMsg",   // 固定method
            type: "text",        // 固定type
            content:  "xxx"      // 送信するメッセージ
        });
    var origin = "*";
    window.parent.postMessage(data, origin);

2. 商品メッセージ パラメータ詳細

    var data = JSON.stringify({
            method: "sendMsg",      // 固定method
            type: "product",        // 固定type
            content: {              // 商品メッセージ形式
                name: "Apple iPhone X (A1903) 64GB 深空灰色 移動通信4G携帯電話",
                url: "https://item.jd.com/6748052.html",
                imgUrl: "http://img12.360buyimg.com/n1/s450x450_jfs/t10675/253/1344769770/66891/92d54ca4/59df2e7fN86c99a27.jpg",
                params: [{
                    text: "¥6999.00",
                    color: "#FF0000",
                    fold: false,
                    break: false,
                    size: 12
                }, {
                    text: "1999元以上購入で30円追加"
                }]
            }
        });
    var origin = "*";
    window.parent.postMessage(data, origin);

注意事項

  1. 送信頻度を制限してください
  2. メッセージ形式に注意してください

カスタム検索キーワード

パラメータ名 タイプ 説明
udesk_wd String 検索キーワード。サードパーティ(例:百度広告)からリダイレクトされた場合に使用

サードパーティウェブサイトリンク例(例:企業公式サイト)

https://www.企業ドメイン.com?udesk_wd=xxxx

ウェブプラグインリンク例

https://企業ドメイン.udesk.cn/im_client/?udesk_wd=xxxx

外部へのイベント通知

ウェブプラグインは window.postMessage を使用して外部にイベントを通知します。

サードパーティページは window.addEventListener('message',function (event) { //event }) で受信します。

    window.addEventListener('message',function (event) {
        /*
            セッション終了イベントを例に挙げます
            受信した `type` でイベントタイプを区別します。具体的なイベントタイプはパラメータ説明を参照してください
        */
        let receiveEvent = JSON.parse(event.data)
        if (receiveEvent.type === 'chatDone') {
            //カスタムイベント処理
        }
    })
説明
chatting セッション開始イベント
chatDone セッション終了イベント
queuing 待機列入りイベント
hidePanel ウィンドウ非表示イベント

"web IMリクエスト権限検証" 有効化後の検証方法

ウェブプラグインリンクが検証後にのみアクセスを許可されるように強制したい場合は、 管理センター -> ウェブプラグイン -> その他設定 で "web IMリクエスト権限検証" を有効にしてください。 有効にした後、プラグインリンクには v_signaturev_timestampv_nonce を渡す必要があります。

v_signature 暗号化アルゴリズム(3ステップ)

  1. 以下のパラメータと順序で文字列を連結します(key=value& 形式): v_noncev_timestampim_user_key im_user_key の取得場所:【管理センター - インスタントメッセージング - ウェブプラグイン - 管理/顧客情報追加 内の KEY】

    sign_str = v_nonce=value&v_timestamp=value&im_user_key

  2. 暗号化アルゴリズムを使用して署名文字列を計算します

    sign_str = sha1(sign_str)

  3. 文字列を大文字に変換します

    sign_str = sign_str.toUpperCase()

Javaコード例

1.依存関係のインストール

sha1 計算用の commons-codec

<dependency>
  <groupId>commons-codec</groupId>
  <artifactId>commons-codec</artifactId>
  <version>1.17.0</version>
</dependency>

2.コード実装

import org.apache.commons.codec.digest.DigestUtils;

public class App {
    public static void main(String[] args) {
        // プラグイン専用リンク
        String baseURL = "[ここをプラグイン専用リンクに置き換えてください]";
        // プラグインの認証キー
        String im_user_key = "[ここをプラグインの im_user_key に置き換えてください]";
        // タイムスタンプ(単位:ミリ秒)
        long timestamp = System.currentTimeMillis();
        // ランダム文字列
        String nonce = Long.toString(Double.valueOf(Math.ceil(Math.random() * Long.MAX_VALUE)).longValue(), 36);
        // 署名用の文字列に結合
        String s = String.format("v_nonce=%s&v_timestamp=%s&%s", nonce, timestamp, im_user_key);
        // sha1を計算し、結果を大文字に変換
        String signature = DigestUtils.sha1Hex(s).toUpperCase();
        // 最終的なウェブプラグインリンクを結合
        String url = String.format(
                "%s&v_nonce=%s&v_timestamp=%s&v_signature=%s",
                baseURL,
                nonce,
                timestamp,
                signature
        );

        System.out.println(url);

        // コード連携方式を使用する場合
        System.out.printf(
                "ud({\n  code: '%s',\n  link: '%s',\n  im_client_valid:{\n    v_nonce:'%s',\n    v_timestamp:'%s',\n    v_signature:'%s'\n  }\n})\n",
                "[ここを code に置き換えてください]",
                baseURL,
                nonce,
                timestamp,
                signature
        );
    }
}

ウェブプラグインパラメータの暗号化方法

URL方式でウェブプラグインと連携する場合、顧客情報はすべてURLに結合され、さらに平文で送信されます。
この問題を解決するため、Udeskは、c_で始まるすべてのURLパラメータを公開鍵で暗号化し、
暗号化された暗号文をパラメータ customer_encrypt の値として設定する方法を提供しています。

以下は、この機能をJavaで実装した例です。

1.依存関係のインストール

commons-lang3 は Java でよく使用されるユーティリティクラスです。
commons-codec は署名計算に使用されます。
jackson-databind は object を JSON 文字列に変換するために使用されます。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.16.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.16.2</version>
</dependency>

2.コード実装

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RandomStringUtils;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;

public class DemoUdeskImClientApplication {

    // c_で始まるすべてのパラメータを暗号化するために使用
    private static final String PUBLIC_KEY = "[ウェブプラグインの公開鍵に置き換えてください]";
    // パラメータ署名に使用
    private static final String IM_USER_KEY = "[ウェブプラグインの認証用キーに置き換えてください]";
    private static final String URL_BASE = "https://[ここをカスタマーサポートシステムのドメインに置き換えてください]/im_client/?web_plugin_id=[ウェブプラグインIDに置き換えてください]";

    public static void main(String[] args) throws Exception {
        Customer customer = new Customer(
                "李四",
                "lisi@udesk.cn",
                "18518518518",
                "李四はテスト顧客です",
                "顧客タグ,顧客タグ2",
                "normal",
                "AAJD1710397772205@udesktest.com"
        );

        String params = String.format(
                "nonce=%s&timestamp=%s&web_token=%s",
                RandomStringUtils.random(5, true, true),
                System.currentTimeMillis(),
                customer.getWeb_token()
        );

        String url = URL_BASE
                + "&customer_encrypt=" + encode(customer)
                + "&" + params
                + "&encryption_algorithm=SHA256"
                + "&signature=" + getSignature(params);

        System.out.println(url);
    }

    public static String encode(Customer customer) throws Exception {
        // customer を JSON 文字列に変換
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
        String message = objectMapper.writer().writeValueAsString(customer);

        // RSAPublicKey オブジェクトを取得
        byte[] encoded = Base64.getDecoder().decode(PUBLIC_KEY);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
        RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);

        // Cipher を初期化
        Cipher encryptCipher = Cipher.getInstance("RSA");
        encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);

        // 平文をセグメント化
        int dataCount = (int) Math.ceil((double) message.getBytes().length / 117);
        byte[][] datas = new byte[dataCount][];
        for (int i = 0; i < dataCount; i++) {
            int length = (i == dataCount - 1) ? (message.getBytes().length % 117) : 117;
            byte[] item = Arrays.copyOfRange(message.getBytes(), i * 117, i * 117 + length);
            datas[i] = item;
        }

        // セグメント化された平文を暗号化し、1つの大きな byte 配列に合成してから、この大きな配列を base64 でエンコード
        byte[] mi = new byte[]{};
        for (byte[] s : datas) {
            mi = ArrayUtils.addAll(mi, encryptCipher.doFinal(s));
        }
        return Base64.getEncoder().encodeToString(mi);
    }

    public static String getSignature(String paramString) {
        return DigestUtils.sha256Hex(paramString + "&" + IM_USER_KEY).toUpperCase();
    }

    @JsonRootName("customer")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    static class Customer {
        String c_name;
        String c_email;
        String c_phone;
        String c_desc;
        String c_tags;
        String c_vip;

        String web_token;

        public Customer(String c_name, String c_email, String c_phone, String c_desc, String c_tags, String c_vip, String web_token) {
            this.c_name = c_name;
            this.c_email = c_email;
            this.c_phone = c_phone;
            this.c_desc = c_desc;
            this.c_tags = c_tags;
            this.c_vip = c_vip;
            this.web_token = web_token;
        }

        public Customer(String c_name) {
            this.c_name = c_name;
        }

        public String getC_name() {
            return c_name;
        }

        public void setC_name(String c_name) {
            this.c_name = c_name;
        }

        public String getWeb_token() {
            return web_token;
        }

        public void setWeb_token(String web_token) {
            this.web_token = web_token;
        }

        public String getC_email() {
            return c_email;
        }

        public void setC_email(String c_email) {
            this.c_email = c_email;
        }

        public String getC_phone() {
            return c_phone;
        }

        public void setC_phone(String c_phone) {
            this.c_phone = c_phone;
        }

        public String getC_desc() {
            return c_desc;
        }

        public void setC_desc(String c_desc) {
            this.c_desc = c_desc;
        }

        public String getC_tags() {
            return c_tags;
        }

        public void setC_tags(String c_tags) {
            this.c_tags = c_tags;
        }

        public String getC_vip() {
            return c_vip;
        }

        public void setC_vip(String c_vip) {
            this.c_vip = c_vip;
        }
    }
}

よくある質問

企業WeChat H5で写真が撮れない?

Udeskカスタマーサポートに連絡し、企業WeChatの代行開発アプリケーションの信頼できるドメインを設定してもらってください。

Android WebViewで写真や動画が撮れない?

ウェブプラグインのファイル、写真、動画はすべて通常の<input type='file'>タグです。
Android WebViewでは、いくつかのコードを書いて適応させる必要があります。
以下のコードは以下の機能を実装しています。動画で効果を確認する
1. 写真撮影をクリックすると直接カメラが開き、動画撮影をクリックすると直接カメラで録画が始まり、ファイルをクリックするとすべての種類のファイルを選択できます。
2. 未承認のアプリが写真や画面録画を行う際に権限をリクエストします。
3. カメラ権限が拒否された場合、「設定へ」というメッセージボックスを表示します。

import android.Manifest;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.Settings;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity {

    private static final int FILE_CHOOSER_REQUEST_CODE = 1;
    private static final int CAMERA_PERMISSION_REQUEST_CODE = 2;
    private static final int CAMERA_VIDEO_PERMISSION_REQUEST_CODE = 3;

    private WebView webView;
    private ValueCallback<Uri[]> filePathCallback;
    private String cameraPhotoPath;
    private String cameraVideoPath;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webview);
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        webView.setWebViewClient(new WebViewClient());
        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                MainActivity.this.filePathCallback = filePathCallback;
                String[] acceptTypes = fileChooserParams.getAcceptTypes();
                if (acceptTypes.length > 0) {
                    String acceptType = acceptTypes[0];

                    if (acceptType.equals("video/*") || acceptType.equals("image/*")) {
                        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                            ActivityCompat.requestPermissions(
                                    MainActivity.this,
                                    new String[]{Manifest.permission.CAMERA},
                                    acceptType.equals("video/*") ? CAMERA_VIDEO_PERMISSION_REQUEST_CODE : CAMERA_PERMISSION_REQUEST_CODE
                            );
                            return true;
                        } else {
                            if (acceptType.equals("image/*")) {
                                openImageChooser();
                                return true;
                            } else if (acceptType.equals("video/*")) {
                                openVideoChooser();
                                return true;
                            }
                        }
                    }
                }

                openFileChooser();
                return true;
            }
        });

        webView.loadUrl("https://[あなたの専用ドメインに置き換えてください]/im_client/");
    }

    private void openImageChooser() {
        // カメラを呼び出すためのIntentを作成
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // 撮影した画像を保存するためのファイルを作成
            File photoFile = null;
            try {
                photoFile = createImageFile();
                takePictureIntent.putExtra("PhotoPath", cameraPhotoPath);
            } catch (IOException ex) {
                // エラー処理
                ex.printStackTrace();
            }

            if (photoFile != null) {
                cameraPhotoPath = "file:" + photoFile.getAbsolutePath();
                Uri photoURI = FileProvider.getUriForFile(this, "udesk.im.client.webview.demo.provider", photoFile);
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
            } else {
                takePictureIntent = null;
            }
        }

        startActivityForResult(takePictureIntent, FILE_CHOOSER_REQUEST_CODE);
    }

    private File createImageFile() throws IOException {
        // 画像ファイル名を作成
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = getExternalFilesDir(null);
        return File.createTempFile(imageFileName, ".jpg", storageDir);
    }

    private void openVideoChooser() {
        // カメラ録画を呼び出すためのIntentを作成
        Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
            // 録画ファイルを保存するためのファイルを作成
            File videoFile = null;
            try {
                videoFile = createVideoFile();
                takeVideoIntent.putExtra("VideoPath", cameraVideoPath);
            } catch (IOException ex) {
                // エラー処理
                ex.printStackTrace();
            }

            if (videoFile != null) {
                cameraVideoPath = "file:" + videoFile.getAbsolutePath();
                Uri videoURI = FileProvider.getUriForFile(this, "udesk.im.client.webview.demo.provider", videoFile);
                takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, videoURI);
            } else {
                takeVideoIntent = null;
            }
        }

        startActivityForResult(takeVideoIntent, FILE_CHOOSER_REQUEST_CODE);
    }

    private File createVideoFile() throws IOException {
        // 動画ファイル名を作成
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String videoFileName = "MP4_" + timeStamp + "_";
        File storageDir = getExternalFilesDir(null);
        return File.createTempFile(videoFileName, ".mp4", storageDir);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == FILE_CHOOSER_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            Uri[] results = null;
            if (resultCode == Activity.RESULT_OK) {
                if (data == null || data.getData() == null) {
                    if (cameraPhotoPath != null) {
                        results = new Uri[]{Uri.parse(cameraPhotoPath)};
                    }
                } else {
                    String dataString = data.getDataString();
                    if (dataString != null) {
                        results = new Uri[]{Uri.parse(dataString)};
                    }
                }
            }
            filePathCallback.onReceiveValue(results);
            filePathCallback = null;
        } else {
            if (filePathCallback != null) {
                filePathCallback.onReceiveValue(null);
                filePathCallback = null;
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == CAMERA_PERMISSION_REQUEST_CODE || requestCode == CAMERA_VIDEO_PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (requestCode == CAMERA_VIDEO_PERMISSION_REQUEST_CODE) {
                    openVideoChooser(); // 録画をクリックして権限をリクエストした際に同意して権限を付与
                } else if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
                    openImageChooser(); // 写真撮影をクリックして権限をリクエストした際に同意して権限を付与
                }
            } else {
                if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
                    showPermissionDeniedDialog();  // 権限が拒否され、かつ「今後表示しない」がチェックされている場合。
                } else {
                    Toast.makeText(this, "写真撮影と画面録画にはカメラ権限が必要です。", Toast.LENGTH_SHORT).show();
                }
                if (filePathCallback != null) {
                    filePathCallback.onReceiveValue(null);
                    filePathCallback = null;
                }
            }
        }
    }


    private void openFileChooser() {
        Intent takePictureIntent = new Intent(Intent.ACTION_GET_CONTENT);
        takePictureIntent.setType("*/*");
        startActivityForResult(takePictureIntent, FILE_CHOOSER_REQUEST_CODE);
    }

    private void showPermissionDeniedDialog() {
        new AlertDialog.Builder(this)
                .setTitle("権限が必要です")
                .setMessage("写真撮影にはカメラ権限が必要です。設定でこの権限を有効にしてください。")
                .setPositiveButton("設定へ", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        openAppSettings();
                    }
                })
                .setNegativeButton("キャンセル", null)
                .show();
    }

    private void openAppSettings() {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", getPackageName(), null);
        intent.setData(uri);
        startActivity(intent);
    }
}

Android WebViewで画像をダウンロードする方法は?

ウェブプラグインで画像をクリックすると、専用の画像表示画面が表示され、画面の上部にダウンロードボタンがあります。
このボタンは通常のaタグであり、このaタグをクリックすると新しいページで画像が開きます。
したがって、Androidアプリ内でこの動作をインターセプトし、ダウンロードに変更する必要があります。

以下は具体的なコード実装です。

import android.app.DownloadManager;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private WebView myWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myWebView = findViewById(R.id.webview);
        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.setWebViewClient(new MyWebViewClient());
        myWebView.loadUrl("https://[あなたの専用ドメインに置き換えてください]/im_client/");
    }

    private class MyWebViewClient extends WebViewClient {

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (isImageUrl(url)) {
                // 画像リンクの場合、ダウンロードメソッドを呼び出す
                downloadImage(MainActivity.this, url);
                return true;
            } else {
                // 画像リンクでない場合、URLの読み込みを続行する
                return false;
            }
        }

        private boolean isImageUrl(String url) {
            // URLが画像形式かどうかをチェックする
            return url.endsWith(".jpg")
                    || url.endsWith(".jpeg")
                    || url.endsWith(".png")
                    || url.endsWith(".gif")
                    || url.contains(".jpg?")
                    || url.contains(".jpeg?")
                    || url.contains(".png?")
                    || url.contains(".gif?");
        }

        private void downloadImage(Context context, String url) {
            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
            request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, url.substring(url.lastIndexOf("/") + 1));
            request.allowScanningByMediaScanner();
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
            if (downloadManager != null) {
                downloadManager.enqueue(request);
                Toast.makeText(context, "ダウンロード中...", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(context, "ダウンロードマネージャーが利用できません", Toast.LENGTH_SHORT).show();
            }
        }
    }
}