【kviewer】【JavaScript】送信データの文字コードを変更したい(UTF-8→Shift-JIS)

初投稿で失礼があったらすみません。
ChatGPTと数週間相談していたのですが、ついぞうまくいかないのでご相談します。
当方はJsの知識がほとんどありませんので、初歩的なところで躓いているかもしれません。
どなたかお知恵を拝借できますと幸いです。

目的

kViewerにボタンを設置し、別サイトにデータを送りたい
(別サイト:三井住友カードの決済ステーション 口座振替受付サービス)

発生している問題

別サイトへの画面遷移はできる(認証はされる)が、エラーになってしまう。
おそらく、遷移先サイトの指定する文字コード(Shift-JIS)でハッシュ値を送信できていないためである。
↑文字コードが違う可能性が高いと判断した根拠
①cust_name = ‘テスト太郎’ に対して、「日本語全角又は英数字全角で入力してください」というエラーが出る
②リクエストヘッダーに content-type application/x-www-form-urlencoded と表示されている

質問

kviewerに設置したボタンから、ハッシュ値をShift-JISで送信する方法が知りたい

試したこと

  1. formタグに
    accept-charset=“Shift_JIS”
    enctype=“application/x-www-form-urlencoded; charset=Shift_JIS”
    を設定 → 効かずUTF-8送信

  2. hidden inputの値を TextEncoder(‘shift-jis’) でバイト列化 → %xx化して送信
    → fetch()で送るとCORSエラー、form.submit()ではUTF-8送信に戻る

  3. をJSで追加 → Chromeでは無視

  4. SJIS変換後にform.submit() → 送信成功するがUTF-8のまま
    → SMBC側で文字化け(940006 / 960007)

  5. トヨクモに問合せ
    →回答待ち。ただ、サポート外なのでどうかなというところ

最新のコード(一部伏字***)

(function() {
  'use strict';

  const waitForViewer = setInterval(() => {
    const header = document.querySelector('.kv-header');
    if (!header) return;

    clearInterval(waitForViewer);
    if (document.getElementById('smbcButton')) return;

    const bill_no      = '999999990001';
    const version      = '130';
    const shop_cd      = '*******';
    const syuno_co_cd  = '*****';
    const koushin_kbn  = '0';
    const shop_pass    = '**********';
    const shoporder_no = '0000000000000000000000000';
    const cust_name    = 'テスト太郎';
    const cust_kana    = 'テストタロウ';

    async function sha256Hex(s) {
      const data = new TextEncoder().encode(s);
      const buf = await crypto.subtle.digest('SHA-256', data);
      return Array.from(new Uint8Array(buf))
        .map(b => b.toString(16).padStart(2, '0'))
        .join('');
    }

    // SJIS変換
    async function toSJIS(str) {
      try {
        const encoder = new TextEncoder('shift-jis');
        const bytes = encoder.encode(str);
        return new TextDecoder('shift-jis').decode(bytes);
      } catch {
        return str;
      }
    }

    const btn = document.createElement('button');
    btn.id = 'smbcButton';
    btn.textContent = '口座振替登録画面へ';
    btn.style.cssText = `
      display:inline-block;
      margin:16px 0;
      padding:10px 24px;
      background-color:#006400;
      color:#fff;
      border:none;
      border-radius:6px;
      cursor:pointer;
      font-size:15px;
      box-shadow:0 2px 5px rgba(0,0,0,0.15);
    `;
    header.insertAdjacentElement('afterend', btn);

    btn.addEventListener('click', async () => {
      const fs = await sha256Hex(shop_cd + syuno_co_cd + bill_no + shoporder_no + shop_pass);

      console.log('=== SMBC送信内容 ===');
      console.log({ version, shop_cd, syuno_co_cd, koushin_kbn, bill_no, shoporder_no, cust_name, cust_kana, fs });

      alert('コンソールの送信内容を確認してからOKを押してください');

      const form = document.createElement('form');
      form.method = 'POST';
      form.action = 'https://www.paymentstation.jp/customertest/sf/at/kokkzmoshikomi/begin.do';
      form.acceptCharset = 'Shift_JIS';

      // SJIS化してhiddenで送信
      const params = {
        version,
        shop_cd,
        syuno_co_cd,
        koushin_kbn,
        bill_no,
        shoporder_no,
        cust_name: await toSJIS(cust_name),
        cust_kana: await toSJIS(cust_kana),
        fs
      };

      Object.entries(params).forEach(([name, value]) => {
        const input = document.createElement('input');
        input.type = 'hidden';
        input.name = name;
        input.value = value;
        form.appendChild(input);
      });

      document.body.appendChild(form);
      form.submit(); // ← これでCORS回避して実際に画面遷移!
    });

    console.log('SMBCボタン生成完了', { bill_no });
  }, 800);
})();

以上、なにとぞお願いします…:person_bowing::person_bowing::person_bowing:

SMBC の API についてはドキュメントが公開されてない?っぽいのでよくわかりませんが、

この関数で返ってくるのは Shift-JIS のデータではなく UTF-8 のデータだと思います (decode() しているので)

一般的にリクエストの中に複数の文字コードを混在させることは無いと思うので、リクエスト本文全体を Shift-JIS に変換して、そのまま送ればいいんじゃないかと思います。

「いいね!」 1

ご回答ありがとうございます!

「リクエスト本文全体をShift-JISに変換して送る」という点について教えてください。

ブラウザ(Chrome)から外部サイトへPOSTする場合、
form.submit() は UTF-8 固定、fetch() や XHR は CORS でブロックされてしまったようで、
SJIS のバイナリをそのまま送る方法が見つけられていません。

JavaScript(ブラウザ環境)だけで
“リクエスト全体をShift-JISエンコードして外部サイトへPOST”
が可能な方法はありますでしょうか?

もし実現例やヒントがあれば教えていただきたいです。

まずkintoneのProxyをつかうのはどうでしょう?CORSとか回避するために用意されてるものですので、リクエストボディをSJISにしたうえで使えばいけるかも?

「いいね!」 1

あーすいません、kviewer上から、ですかね…失礼しました

ご認識のとおりブラウザから直接通信を行う場合は同一オリジンでないといけない(CORS)など制限がきついです
ので、受ける側の設定を変更できない限りは、AWSのAPI Gatewayなどのサービスをつかって迂回させるのが定石ですかね(もちろんそのほか自前のサーバーでも問題ないですが)

「いいね!」 2

ご回答ありがとうございます!
なるほど…そうなんですね泣
一般的にどう、というところを知らなかったので大変勉強になりました。
また、kintoneであれば回避ルートが用意されているというのも、今後どこかで使わせていただこうと思います。
受ける側はShift-JISのみなので、APIか自前serverかなにかで迂回させなくてはですね…。
素人が急にやっていいものじゃなかった…と後悔しています泣
リンクもありがとうございます!
個人情報を飛ばすものなので、セキュリティ面も踏まえ、慎重にやってみようと思います。

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。