クレジットカードの読み取り機能を実装する！

##はじめに

先日、クレジットカードをiPhonのカメラで読みとり、入力フォームに自動で入力される機能の実装を行なったので記事を書きます！
この機能の実装自体は難しくなかったですが、httpsで接続していないとこの機能は動かないみたいで、動作を検証する際に悩みました。。

##やりたいこと
以下画像のように、クレカ読み取り機能で、クレカを枠内に入れたらフォームにクレカ情報が自動的に入力されるようにしたい。
<img width="400" alt="IMG_2544.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497827/cc4f1054-a2a1-3fbe-4976-27348c0fce64.png">


※注意
・読み取れる項目は、カードナンバーと有効期限とカードのタイプのみのようです。名前とCVVは手動で入力する必要があります。 (今回は、カードナンバーと有効期限のみ)
・iOS8以上でないと、読み取り機能は正常に機能しないみたいなので注意が必要です！
・Angularのアプリケーション内で実装したのですが、Angular Materialの mat-selectタグを使用すると上手く行かなかったので、通常のselectタグを使用しました。→ mat-selectタグでも実装できた人教えてください！笑

##環境 

環境はこんな感じです。

```bash
$ ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 11.0.7
Node: 14.15.1
OS: darwin x64

Angular: 11.0.9
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1100.7
@angular-devkit/build-angular   0.1100.7
@angular-devkit/core            11.0.7
@angular-devkit/schematics      11.0.7
@angular/cli                    11.0.7
@schematics/angular             11.0.7
@schematics/update              0.1100.7
rxjs                            6.6.7
typescript                      4.0.7
```


##実装

View側

特別な実装は以下の3点かと思います。
・カードナンバーフォームのname属性として、「"cardNumber"」を指定する。
・有効期限（月）フォームのname属性として、「"cardExpirationMonth"」を指定する。
・有効期限(年)フォームのname属性として、「"cardExpirationYear"」を指定する。

```html
<form [formGroup]="paymentForm" (ngSubmit)="onSubmit()">
  <div>
    <input id="cardNumber" name="cardNumber" formControlName="cardNumber"><br><br>
  </div>
  <div>
    <select formControlName="expiration_month" name="cardExpirationMonth">
      <option *ngFor="let m of monthList">
        {{ m + '月'}}
      </option>
    </select>
    <select formControlName="expiration_year" name="cardExpirationYear">
      <option *ngFor="let key of yearList">{{ key }}</option>
    </select>
  </div>
  <button type="submit">決定</button>
</form>
```

コンポーネント側
通常のReactvieFormを作成するのと特に変わっていることはありません。

```javascript
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-counter',
  templateUrl: './counter.component.html',
  styleUrls: ['./counter.component.scss']
})
export class CounterComponent implements OnInit {


  // セレクトタグのフォームの部品となる「月」の配列
  public monthList = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ];

  // セレクトタグのフォームの部品となる「年」の配列
  public yearList = [2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031];
  
  public paymentForm: FormGroup;

  constructor(
    private fb: FormBuilder
  ) { }

  ngOnInit(): void {
    this.paymentForm = this.fb.group({
      'cardNumber': ['', [Validators.required]],
      'expiration_month': ['', [Validators.required]],
      'expiration_year' : ['', [Validators.required]]
    })
  }

// 一旦入力された値をコンソールログに出力する。
  public onSubmit(): void {
    console.log(this.paymentForm.get('cardNumber').value);
    console.log(this.paymentForm.get('expiration_month').value);
    console.log(this.paymentForm.get('expiration_year').value);
  }

}
```



##ローカル環境での動作確認

これでフォームとしては、機能しますが**https**で接続していないと機能しません。なので、ローカル環境での検証をどうしようかなと調べました。どうにかして、ローカル環境にhttps接続したい。。。

調べた結果...
**ngrok**というライブラリを使用すると、ローカル環境にhttpsで接続することができます！
<font color="red">※ローカル環境にどこからでもアクセスできるようになってしまう為、セキュリティー的には危険です。その辺りを意識しながら使用してください。</font>

さっそくインストール！

```bash
$ brew install ngrok --cask
```
バージョンが確認できればインストール完了です。

```bash
$ ngrok -v
$ ngrok version 2.3.39
```

ローカル環境にhttps接続する為には以下のコマンドを実行します。

```bash
# ポート番号は自分が立ち上げているアプリケーションのポート番号を指定
$ ngrok http 4200 -host-header="localhost:4200" 
```

上記コマンドを実行したら、下記のように表示されます。
スマホでSafariを開き、ForwardingのURLをアレスバーに入力すると、ページが表示されるはずです。

```bash
ngrok by @inconshreveable                                                                                   (Ctrl+C to quit)
                                                                                                                            
Session Status                online                                                                                        
Session Expires               1 hour, 59 minutes                                                                            
Version                       2.3.39                                                                                        
Region                        United States (us)                                                                            
Web Interface                 http://127.0.0.1:4040                                                                         
Forwarding                    http://acf3da528cdc.ngrok.io -> http://localhost:4200                                         
Forwarding                    https://acf3da528cdc.ngrok.io -> http://localhost:4200                                        
                                                                                                                            
Connections                   ttl     opn     rt1     rt5     p50     p90                                                   
                              0       0       0.00    0.00    0.00    0.00   
``` 

httpsで接続して、inputフォームをクリックする、以下の画像のように入力欄が表示され、「クレジットカードを読み取る」という項目が表示されます。
<img width="400" alt="クレジットカードを読み取る.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497827/ad530b63-a6a1-dd7a-4cf9-8cb39aacf103.png">

この項目をクリックするとカメラが起動して、以下の画像のような表示になります。
枠内にクレジットカードを入れるとフォームに自動的に、カード番号、有効期限が入力されます。

<img width="400" alt="IMG_2544.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497827/cc4f1054-a2a1-3fbe-4976-27348c0fce64.png">

これで実装とローカルでの動作確認は終わりです！

##まとめ
クレジットカードの読み取り機能は、もう少し難しい実装になると思いましたが、案外簡単にできました。
ローカル環境にhttps接続する方法もついでに学べたので、よかったです。
ngrokではなく、serveoというサービスを使用してもできるようですので、今度はそちらを触ってみようかと思っています。

何か間違えている部分やこうしたほうが良いってところがあれば、コメント等で教えて頂ければ嬉しいです！


##参考##
クレカ読み取りについて
https://qiita.com/okumura_daiki/items/c5c28117b999252e22ca

ngrokについて
https://qiita.com/T-Com/items/7f1468167f80df00a87d
https://qiita.com/kitaro0729/items/44214f9f81d3ebda58bd
https://www.mathkuro.com/mac/brew-cask-command-error/


serveoについて
https://qiita.com/kaba/items/53b297e2bfb5b4f20a48