omise-iosを利用して、決済機能を導入する方法

# omise-iosを利用して、決済機能を導入する方法
個人開発で決済機能があるアプリを開発していました。
その開発しているアプリには、決済機能があったため、、さまざまなサービスを見て、最も導入しやすそうな[Omise](https://www.omise.co/)というサービスを選びました。
最初はstripeを利用するつもりでしたが、導入方法を模索しているうちに時間がかかりすぎていたため、今回は導入しやすいOmiseにしました。

## Omiseを導入するメリット
### 導入が簡単
GitHubに公開されている[Omise iOS SDK](https://github.com/omise/omise-ios)と、HPにある[ドキュメント](https://www.omise.co/docs)を見て、真似するだけで導入できます。
ドキュメントに関しては日本語版もあります。
また、GitHubのSDKに関しては、翻訳ツールを使えば大丈夫なほど簡単に書かれています。
僕自身、READMEやドキュメントを読んだことがありませんでしたが、いけました。
### 対応が早い
Swiftが初めてのプログラミング言語で、まだ半年も学んでいない人はつまづくかもしれません。
しかし、そのときは運営に問い合わせることで疑問を解決してくれます。
営業時間内であれば、1~2時間あれば返信をくれることが多いです。
実際に僕はつまづいたり、疑問が出てきたときに何回も問い合わせましたが、丁寧にすぐに返信してくれました。

上記より、学び始めて半年も経たない人で、決済機能を導入したい人はOmiseがおすすめです。

## omise-iosを利用して、決済機能を導入する方法
今回は、決済を行う部分だけを紹介します。
その他の機能のほとんどは、以下で紹介する方法でいけます。

### アカウントを作る
まずは、OmiseのHPに飛んで、アカウントを作ってください。

### OmiseSDKをインストールする
Xcode12以上なら、[Omise iOS SDK](https://github.com/omise/omise-ios) をSwift Package Managerでインストールできます。
ついでに、[CurlDSL](https://github.com/zonble/CurlDSL)をインストールしておいてください。
これは通信するときに利用します。
他のライブラリーで対応するという方は必要ありません。

### シークレットキーとパブリックキーを書く
ダッシュボードの左のメニューから「キー」を選ぶと、シークレットキーとパブリックキーを見れます。
最初は、テスト用のダッシュボードで試すことをおすすめします。
僕は、以下のように書くと、どのファイルからでも取り出せます。
ドキュメントを見ると、本番用を使うときは、暗号化することをおすすめされています。

```swift
import OmiseSDK

class Omise {
    private init() {}
    static let shared = Omise()

    let publicKey = "自分のパブリックキーを打つ"
    let secretKey = "自分のシークレットキーを打つ"
    let client = OmiseSDK.Client.init(publicKey: "自分のパブリックキーを打つ")
}
```

### クレジットカード情報を書くフォームを準備する
クレジットカード情報を書くフォームは自身で準備しても大丈夫ですが、運営から提供されているものを使うと簡単です。


```swift
import OmiseSDK // at the top of the file

class ViewController: UIViewController {
    private let publicKey = "自分のパブリックキーを持ってくる"

    @IBAction func displayCreditCardForm() {
        let creditCardView = CreditCardFormViewController.makeCreditCardFormViewController(withPublicKey: publicKey)
        creditCardView.delegate = self
        creditCardView.handleErrors = true

        present(creditCardView, animated: true, completion: nil)
    }
}
```

```swift
extension ViewController: CreditCardFormViewControllerDelegate {
  func creditCardFormViewController(_ controller: CreditCardFormViewController, didSucceedWithToken token: Token) {
    dismissCreditCardForm()

    // Sends `Token` to your server to create a charge, or a customer object.
  }

  func creditCardFormViewController(_ controller: CreditCardFormViewController, didFailWithError error: Error) {
    dismissCreditCardForm()

    // Only important if we set `handleErrors = false`.
    // You can send errors to a logging service, or display them to the user here.
  }
}
```
このコードにある```CreditCardFormViewController```がECサイトなどで見る、クレジットカード情報を書くフォームになります。
キーボードタイプの設定やバリデーションなどを既に設定してくれているので、簡単にフォームを実装できます。
実際のフォームの写真は以下に貼っておきます。
![スクリーンショット 2021-07-29 15.40.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401623/7ea95ea5-e518-fbf1-737a-a00bf8b1a1d5.png)

### extensionを書く
```extension``` には、　Payボタンの処理が失敗したときと成功したときにどうするかを書く必要があります。
しかし、ここで注意点があります。
・Payを押されたときには、まだ決済が完了していないこと
Payを押されて、```success```が返ってきたら決済が成功したと勘違いするかもしれません。
しかし、実際にPayボタンを押されたときに行われることは、以下の通りです。
1. クレジットカード情報をOmise側のサーバーに送る
2. Omise側のサーバーでクレジットカード情報をトークン化する
3. そのトークン化されたものを受け取る(success)
そのため、```success```がきたということはトークンを受け取れたという意味です。
このときに、自分のサーバー(FirebaseやAWS)にクレジットカード情報を送信しないでください。
自分のサーバーに送ると、それを管理するコストが発生するため、運営も禁止しています。
そして、その受け取ったトークンを使い、決済を行います。
決済を行うコードは以下の通りです。

```swift
import OmiseSDK
import CurlDSL

func creditCardFormViewController(_ controller: CreditCardFormViewController, didSucceedWithToken token: Token) {
    
    // 最低でもこの3つのパラメーターは必要です。
    let parameters = ["amount": 100000, //金額は自由です。
                      "currency": "jpy", //日本円
                      "card": token.id] as [String : Any]

    let session = URLSession.shared

    var request = try? CURL("curl -X POST -u \(シークレットキーを書く): https://api.omise.co/charges").buildRequest()

    do {
        request?.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
    } catch let error {
        print(error.localizedDescription)
    }

    request?.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request?.addValue("application/json", forHTTPHeaderField: "Accept")

    let task = session.dataTask(with: (request ?? URLRequest(url: url)) as URLRequest, completionHandler: { data, response, error in
        // この辺の処理は自由に
        do {
            if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
                // この辺の処理は自由に
            }
        } catch {
　　　　　　　　　　　　　　　　    // この辺の処理は自由に
        }
    })
    task.resume()
}
```
```CurlDSL```をインストールしてもらった理由は、```request```を作成するときに、```-u \(シークレットキーを書く):```を再現する方法がわからなかったからです。
ここはドキュメントを見ても、書かれておらず、運営に問い合わせても期待した答えは返ってきませんでした(聞き方が悪かったかもしれません)。
そのため、できる方はご自身のやり方で通信してみてください。
＊ぜひ他の方法がわかる方はコメントで教えてください。

これでダッシュボードでシュミレーターや実機で試してみると、ダッシュボードに反映されています。
また、試すときには[テストカード](https://www.omise.co/ja/api-testing/japan)を使ってください。

``` var request = try? CURL("curl -X POST -u \(シークレットキーを書く): https://api.omise.co/charges").buildRequest()``` この```POST```やURLを変えることで他の機能も使えます。

## 最後に
間違えていたり、簡単に書けたりするところあれば、教えていただきたいです。
また、誰かの参考になれば、幸いです。