---
title: 不正検知 (後払い決済未払い防止)
slug: japanese/U5aX2m_h8DG5HmVU0tMUJ
docTags: 
createdAt: 2025-07-02T14:58:37.822Z
---

## Forter不正検知の概要

Forterの不正検知により、正常かつ真正な顧客のみがお客様のサイトで決済でき、不正者を特定・ブロックすることができます。Forterはすべての取引に対して、「承認」と「拒否」の2択で判定を送信します。



## 実装プロセス

![](https://files.readme.io/1a2e082ffb779c20891195fd1c9a6da1cb19bd0ce1843f0c130a9b1fa48e0fb4-image.png)



**開発**

- フロントエンド：JSやSDK実装
- バックエンド：Orders APIとOrder Status API実装
- 履歴データ受け渡し

**リッスンモード**

- 本番環境で実際の注文をForterに送る
- APIの連携内容を確認し、必要があれば修正
- その後Forterでモデルチューニング
- 期間中、Forterから判定は返却されず、レスポンスが'Not Reviewed'となる

## システム概要



![](https://api.archbee.com/api/optimize/gmEle7zEqeUqLJAkHuNZq/Q2sKS8fEnP3NrImLEvElQ_image.png)

1. SDKで振る舞い情報、デバイス情報、接続情報を自動収集（モバイルアプリ）
   1. カート・決済画面がWebviewの場合、SDKの実装は任意
2. Forterによる判定（「承認」と「拒否」の2択）
3. 注文状況をForterへAPI連携





## 1. WEB用Javascript

### 動作

- Javascriptが読み込み時にforterTokenを生成（forterTokenはOrders APIのリクエスト時に必要）
- 振る舞い情報、デバイス情報、接続情報を収集し、Forterへ定期的に自動的に送る

### 実装方法

- ForterのJavascriptスニペットを、全てのページのbody閉じタグ(`</body>`)直前に埋め込む
  - 全てのページが難しい場合、多くの購入者が経由するページに埋め込む（ホームページ、商品ページ、ショッピングカートページ、購入ページは必須）
  - タグマネージャー内での利用は極力避ける(ブラウザの拡張機能にブロックされる可能性があるため)
- 上記のスニペット前にイベントリスナーを実装
  - `ftr:tokenReady`というイベントに登録
  - forterTokenは`event`の`detail`として渡される
- forterTokenを取得しバックエンドへ渡す処理を実装

### Forter Javascriptスニペット例

```javascript
<script type="text/javascript" id="${siteId}">
    (function () {
        var merchantConfig = {
            csp: false
        };
        
        var siteId = "${siteId}";
function t(t,n){for(var e=t.split(""),r=0;r<e.length;++r)e[r]=String.fromCharCode(e[r].charCodeAt(0)+n);return e.join("")}function n(n){return t(n,-S).replace(/%SN%/g,siteId)}function e(){var t="no"+"op"+"fn",n="g"+"a",e="n"+"ame";return window[n]&&window[n][e]===t}function r(){return!(!navigator.brave||"function"!=typeof navigator.brave.isBrave)}function o(){return document.currentScript&&document.currentScript.src}function i(t){try{B.ex=t,e()&&-1===B.ex.indexOf(R.uB)&&(B.ex+=R.uB),r()&&-1===B.ex.indexOf(R.uBr)&&(B.ex+=R.uBr),o()&&-1===B.ex.indexOf(R.nIL)&&(B.ex+=R.nIL),window.ftr__snp_cwc||(B.ex+=R.s),F(B)}catch(t){}}function c(t,n){function e(o){try{o.blockedURI===t&&(n(),document.removeEventListener(r,e))}catch(t){document.removeEventListener(r,e)}}var r="securitypolicyviolation";document.addEventListener(r,e),setTimeout(function(){document.removeEventListener(r,e)},2*60*1e3)}function a(t,n,e,r){var o=!1;t="https://"+t,c(t,function(){r(!0),o=!0});var i=document.createElement("script");i.onerror=function(){if(!o)try{r(!1),o=!0}catch(t){}},i.onload=e,i.type="text/javascript",i.id="ftr__script",i.async=!0,i.src=t;var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(i,a)}function u(t,n,e,r){var o=!1,i=new XMLHttpRequest;if(c("https:"+t,function(){e(new Error("CSP Violation"),!0),o=!0}),"withCredentials"in i)i.open("GET",t,!0);else{if("undefined"==typeof XDomainRequest)return;i=new XDomainRequest,i.open("GET",t)}Object.keys(r).forEach(function(t){i.setRequestHeader(t,r[t])}),i.onload=function(){"function"==typeof n&&n(i)},i.onerror=function(t){if("function"==typeof e&&!o)try{e(t,!1),o=!0}catch(t){}},i.onprogress=function(){},i.ontimeout=function(){"function"==typeof e&&e("tim"+"eo"+"ut",!1)},setTimeout(function(){i.send()},0)}function d(t,siteId,n){function e(t){var n=t.toString(16);return n.length%2?"0"+n:n}function r(t){if(t<=0)return"";for(var n="0123456789abcdef",e="",r=0;r<t;r++)e+=n[Math.floor(Math.random()*n.length)];return e}function o(t){for(var n="",r=0;r<t.length;r++)n+=e(t.charCodeAt(r));return n}function i(t){for(var n=t.split(""),e=0;e<n.length;++e)n[e]=String.fromCharCode(255^n[e].charCodeAt(0));return n.join("")}n=n?"1":"0";var c=[];return c.push(t),c.push(siteId),c.push(n),function(t){var n=40,e="";return t.length<n/2&&(e=","+r(n/2-t.length-1)),o(i(t+e))}(c.join(","))}function f(){function t(){C&&(Q(R.dUAL),setTimeout(s,E,R.dUAL))}function n(t,n){i(n?R.uAS+R.uF+R.cP:R.uAS+R.uF)}window.ftr__fdad(t,n)}function s(t){try{var n=t===R.uDF?q:C;if(!n)return;a(n,void 0,function(){try{X(),i(t+R.uS)}catch(t){}},function(n){try{X(),B.td=1*new Date-B.ts,i(n?t+R.uF+R.cP:t+R.uF),t===R.uDF&&f()}catch(t){i(R.eUoe)}})}catch(n){i(t+R.eTlu)}}var h="22g6otrwjeq6qsu1forxgiurqw1qhw2vwdwxv",v="fort",w="erTo",l="ken";window.ftr__config={m:merchantConfig,s:"15",si:siteId};var m=!1,p=v+w+l,g=10,_={write:function(t,n,e,r){void 0===r&&(r=!0);var o,i;if(e?(o=new Date,o.setTime(o.getTime()+24*e*60*60*1e3),i="; expires="+o.toGMTString()):i="",!r)return void(document.cookie=escape(t)+"="+escape(n)+i+"; path=/");for(var c=1,a=document.domain.split("."),u=g,d=!0;d&&a.length>=c&&u>0;){var f=a.slice(-c).join(".");document.cookie=escape(t)+"="+escape(n)+i+"; path=/; domain="+f;var s=_.read(t);null!=s&&s==n||(f="."+f,document.cookie=escape(t)+"="+escape(n)+i+"; path=/; domain="+f),d=-1===document.cookie.indexOf(t+"="+n),c++,u--}},read:function(t){var n=null;try{for(var e=escape(t)+"=",r=document.cookie.split(";"),o=32,i=0;i<r.length;i++){for(var c=r[i];c.charCodeAt(0)===o;)c=c.substring(1,c.length);0===c.indexOf(e)&&(n=unescape(c.substring(e.length,c.length)))}}finally{return n}}},y=window.ftr__config.s;y+="ck";var T=function(t){if(document.head){var n=function(){var n=document.createElement("link");return n.setAttribute("rel","pre"+"con"+"nect"),n.setAttribute("cros"+"sori"+"gin","anonymous"),n.onload=function(){document.head.removeChild(n)},n.onerror=function(t){document.head.removeChild(n)},n.setAttribute("href",t),document.head.appendChild(n),n}();setTimeout(function(){document.head.removeChild(n)},3e3)}},S=3,x=n(h||"22g6otrwjeq6qsu1forxgiurqw1qhw2vwdwxv"),A=t("[0Uhtxhvw0LG",-S),L=t("[0Fruuhodwlrq0LG",-S),k=t("Li0Qrqh0Pdwfk",-S),C,U="fgq71iruwhu1frp",q=n("(VQ(1"+U+"2vq2(VQ(2vfulsw1mv"),D=n("(VQ(1"+U+"2vqV2(VQ(2vfulsw1mv"),E=10;window.ftr__startScriptLoad=1*new Date;var b=function(t){var n="ft"+"r:tok"+"enR"+"eady";window.ftr__tt&&clearTimeout(window.ftr__tt),window.ftr__tt=setTimeout(function(){try{delete window.ftr__tt,t+="_tt";var e=document.createEvent("Event");e.initEvent(n,!1,!1),e.detail=t,document.dispatchEvent(e)}catch(t){}},1e3)},F=function(t){var n=function(t){return t||""},e=n(t.id)+"_"+n(t.ts)+"_"+n(t.td)+"_"+n(t.ex)+"_"+n(y);_.write(p,e,400,!0),b(e),window.ftr__gt=e},I=function(){var t=_.read(p)||"",n=t.split("_"),e=function(t){return n[t]||void 0};return{id:e(0),ts:e(1),td:e(2),ex:e(3),vr:e(4)}},V=function(){for(var t={},n="fgu",e=[],r=0;r<256;r++)e[r]=(r<16?"0":"")+r.toString(16);var o=function(t,n,r,o,i){var c=i?"-":"";return e[255&t]+e[t>>8&255]+e[t>>16&255]+e[t>>24&255]+c+e[255&n]+e[n>>8&255]+c+e[n>>16&15|64]+e[n>>24&255]+c+e[63&r|128]+e[r>>8&255]+c+e[r>>16&255]+e[r>>24&255]+e[255&o]+e[o>>8&255]+e[o>>16&255]+e[o>>24&255]},i=function(){if(window.Uint32Array&&window.crypto&&window.crypto.getRandomValues){var t=new window.Uint32Array(4);return window.crypto.getRandomValues(t),{d0:t[0],d1:t[1],d2:t[2],d3:t[3]}}return{d0:4294967296*Math.random()>>>0,d1:4294967296*Math.random()>>>0,d2:4294967296*Math.random()>>>0,d3:4294967296*Math.random()>>>0}},c=function(){var t="",n=function(t,n){for(var e="",r=t;r>0;--r)e+=n.charAt(1e3*Math.random()%n.length);return e};return t+=n(2,"0123456789"),t+=n(1,"123456789"),t+=n(8,"0123456789")};return t.safeGenerateNoDash=function(){try{var t=i();return o(t.d0,t.d1,t.d2,t.d3,!1)}catch(t){try{return n+c()}catch(t){}}},t.isValidNumericalToken=function(t){return t&&t.toString().length<=11&&t.length>=9&&parseInt(t,10).toString().length<=11&&parseInt(t,10).toString().length>=9},t.isValidUUIDToken=function(t){return t&&32===t.toString().length&&/^[a-z0-9]+$/.test(t)},t.isValidFGUToken=function(t){return 0==t.indexOf(n)&&t.length>=12},t}(),R={uDF:"UDF",dUAL:"dUAL",uAS:"UAS",mLd:"1",eTlu:"2",eUoe:"3",uS:"4",uF:"9",tmos:["T5","T10","T15","T30","T60"],tmosSecs:[5,10,15,30,60],bIR:"43",uB:"u",uBr:"b",cP:"c",nIL:"i",s:"s"};try{var B=I();try{B.id&&(V.isValidNumericalToken(B.id)||V.isValidUUIDToken(B.id)||V.isValidFGUToken(B.id))?window.ftr__ncd=!1:(B.id=V.safeGenerateNoDash(),window.ftr__ncd=!0),B.ts=window.ftr__startScriptLoad,F(B),window.ftr__snp_cwc=!!_.read(p),window.ftr__snp_cwc||(q=D);for(var G="for"+"ter"+".co"+"m",M="ht"+"tps://c"+"dn9."+G,O="ht"+"tps://"+B.id+"-"+siteId+".cd"+"n."+G,j="http"+"s://cd"+"n3."+G,N=[M,O,j],H=0;H<N.length;H++)T(N[H]);var P=new Array(R.tmosSecs.length),Q=function(t){for(var n=0;n<R.tmosSecs.length;n++)P[n]=setTimeout(i,1e3*R.tmosSecs[n],t+R.tmos[n])},X=function(){for(var t=0;t<R.tmosSecs.length;t++)clearTimeout(P[t])};window.ftr__fdad=function(n,e){if(!m){m=!0;var r={};r[k]=d(window.ftr__config.s,siteId,window.ftr__config.m.csp),u(x,function(e){try{var r=e.getAllResponseHeaders().toLowerCase();if(r.indexOf(L.toLowerCase())>=0){var o=e.getResponseHeader(L);window.ftr__altd2=t(atob(o),-S-1)}if(r.indexOf(A.toLowerCase())<0)return;var i=e.getResponseHeader(A),c=t(atob(i),-S-1);if(c){var a=c.split(":");if(a&&2===a.length){for(var u=a[0],d=a[1],f="",s=0,h=0;s<20;++s)f+=s%3>0&&h<12?siteId.charAt(h++):B.id.charAt(s);var v=d.split(",");if(v.length>1){var w=v[0],l=v[1];C=u+"/"+w+"."+f+"."+l}}}n()}catch(t){}},function(t,n){e&&e(t,n)},r)}},Q(R.uDF),setTimeout(s,E,R.uDF)}catch(t){i(R.mLd)}}catch(t){}})();
</script>
```

必ず、Forterの管理画面の\[Settings(設定)]ページで有効になっている `${siteId}`を含めるようにします。

### イベントリスナー例

```javascript
document.addEventListener('ftr:tokenReady', function(evt) {
  var token = evt.detail; // Retrieve the token to be sent to your back-end
});
```

### CSP

CSP関連の制限については、以下のように対処可能です。

- ForterのJavaScriptがデフォルトで行うCSPレポートをオフにしたい：
  - 上記のForter Javascriptスニペットで`csp: true`に設定する
- インラインのJavaScriptタグが制限されている：
  - Forterスクリプトが特定のドメインやソースから読み込まれることを許可するルールをCSPヘッダーに追加（詳細は実装時にご案内）
- インラインスクリプトが全面的に禁止されている：
  - 特定のハッシュ値をCSPヘッダーに追加することで、そのハッシュ値に一致するインラインスクリプトのみをホワイトリスト化します（詳細は実装時にご案内）
  - 注意点として、テスト環境（sandbox）と本番環境（production）では異なるハッシュが提供されるため、それぞれの環境に対応したハッシュを使用してください



## 2. モバイルアプリ用SDK (カート・決済画面がWebviewの場合、任意)

### 動作

- アプリ起動時に、SDKを初期化
  - Flutterの場合、こちらのメソッドを使う：initialize(String siteId, String mobileUid)
- SDKに組み込まれたメソッドを使用し、Mobile UIDを生成する。
  - 生成したUIDは、判定用のOrders APIの`forterMobileUID`にセットする。
- SDKに組み込まれたメソッドを使用し、ログイン時にアカウントIDをSDKに渡す
  - Forter内部で突合用にOrders APIリクエストの`accountOwner.accountId`に同じIDをセットいただく
- その後、接続情報や行動情報を定期的に収集し、Forterへ自動的に送る
- （任意）SDKに組み込まれたメソッドを使用し、ロケーション情報をSDKに渡す
- （WebviewとNativeが混在している場合）Webview立ち上げ時にSDKに組み込まれたメソッドを使用し、Mobile UIDをJSに渡す

### 実装方法

- Forter モバイルSDKをインストールする
- アプリ起動時に、SDKを立ち上げる処理を実装
- MobileUIDとアカウントIDをSDKに渡す処理を実装
- （任意）ロケーション情報をSDKに渡す処理を実装
- （WebviewとNativeが混在している場合）Mobile UIDをJSに渡す処理を実装

### 詳細資料

- [概要](https://docs.forter.com/docs/mobile-sdks-overview-jp)
- [Flutter plugin](https://bitbucket.org/forter-mobile/forter-flutter-plugin/src/master/README.md)
- [iOS](https://docs.forter.com/docs/fraud-ios-sdk-jp)
- [Android](https://docs.forter.com/docs/fraud-android-sdk-jp)
- [Webview](https://docs.forter.com/docs/fraud-webview-integrations-jp)
- [React Native](https://docs.forter.com/docs/fraud-react-native-jp)



## 3. 判定

### リクエスト

Forterの判定が必要な時（顧客が決済を行う時）、Orders APIをリクエストしてください。

###

＊内容は貴社向けにカスタマイズされていないので、あくまで一例として参考にしてください。
＊全ての項目が必要になるわけではありません。
＊一方、追加で情報をいただく可能性もあります。

### レスポンス

Forterの判定がレスポンスに含まれます。レスポンス内容に従って、決済処理を行なってください。		&#x9;

- "forterDecision": "APPROVE" → 不正ではないので決済処理
- "forterDecision": "DECLINE" → 不正なのでブロック							&#x9;



**Approve判定**

```json
{
　"status": "success",
　"transaction": "EC230913-019003553",
　"forterDecision": "approve",
　"message": " | Link in portal: https://portal.forter.com/dashboard/EC230913-019003553",
    "reasonCode": "",
    "recommendation": []
}
```



**Decline判定**

```json
{
　"status": "success",
　"transaction": "EC230913-019003553",
　"forterDecision": "decline",
　"message": " | Link in portal: https://portal.forter.com/dashboard/EC230913-019003553",
    "reasonCode": "",
    "recommendation": []
}
```



**Not Reviewed判定 (リッスンモード中など)**

```json
{
　"status": "success",
　"transaction": "EC230913-019003553",
　"forterDecision": "not reviewed",
　"message": " | Link in portal: https://portal.forter.com/dashboard/EC230913-019003553",
    "reasonCode": "ListenMode",
    "recommendation": []
}
```





## 4. 注文状況

### リクエスト

注文の状態が変更した場合（キャンセル、内容変更など）をOrder Status APIでForterに伝えてください。

その際、以下の状態のいずれかを、updatedStatusにセットしてください。

- COMPLETED：注文確定
- CANCELLED\_BY\_MERCHANT：加盟店理由でのキャンセル（Forterによる拒否判定、決済失敗、注文が詐欺らしい、など）
- CANCELLED\_BY\_CUSTOMER：顧客の要望により、注文がキャンセル

###



＊内容は貴社向けにカスタマイズされていないので、あくまで一例として参考にしてください。
＊全ての項目が必要になるわけではありません。
＊一方、追加で情報をいただく可能性もあります。

###

### レスポンス

**例**

```json
{
    "status": "success",
    "message": "Transaction #EC230914-019855647 status received"
}
```



## 履歴データ

履歴データはjsonlinesまたはcsvいずれかのフォーマットで頂戴する必要があります。
Orders APIのリクエストで送る内容と同じが項目が理想ですが、保存していない項目はなくても問題ありません。
期間は一年分必要です。（難しい場合はご相談ください）

**jsonlinesの例**

```json
{"orderId":"2356fdse0rr489", "checkoutTime": 1415273168, "totalAmount": { "amountUSD": "24.0" } ....., "primaryDeliveryDetails": { "deliveryType": "DIGITAL", "deliveryMethod": "USPS - Ground Mail", "delayedDeliveryDate": "2014-12-15", "deliveryPrice": { "amountUSD": "99.95" }}
"{""orderId"":""2356fdse0rr579"", ""checkoutTime"": 1415273245, ""totalAmount"": { ""amountUSD"": ""83.0"" } ....., ""primaryDeliveryDetails"": { ""deliveryType"": ""DIGITAL"", ""deliveryMethod"": ""USPS - Ground Mail"", ""delayedDeliveryDate"": ""2014-12-19"", ""deliveryPrice"": { ""amountUSD"": ""99.95"" }}
    "
"{""orderId"":""2356fdse0rr310"", ""checkoutTime"": 1415273299, ""totalAmount"": { ""amountUSD"": ""53.50"" } ....., ""primaryDeliveryDetails"": { ""deliveryType"": ""DIGITAL"", ""deliveryMethod"": ""USPS - Ground Mail"", ""delayedDeliveryDate"": ""2014-12-19"", ""deliveryPrice"": { ""amountUSD"": ""25.95"" }}
    "
```



**csvの例**

```json
orderId,checkoutTime,totalAmount.amountUSD,...,primaryDeliveryDetails.deliveryType,primaryDeliveryDetails.deliveryMethod,primaryDeliveryDetails.delayedDeliveryDate,primaryDeliveryDetails.deliveryPrice.amountUSD
2356fdse0rr489,1415273168,24.0,...,DIGITAL,"USPS - Ground Mail",2014-12-15,99.95
2356fdse0rr579,1415273245,83.0,...,DIGITAL,"USPS - Ground Mail",2014-12-19,99.95
2356fdse0rr310,1415273299,53.50,...,DIGITAL,"USPS - Ground Mail",2014-12-19,25.95
```

