PayPal Ruby SDKのSSL_connectエラーの解消方法

# はじめに
最近、PayPal Ruby SDKでエラーが出るようになったが、その解決方法はGoogle検索しても日本語情報は無く、英語もほとんどHitしないのでメモ。ここ数日の出来事らしい。

`SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)`

# 1.原因
原因はPayPal側にある。[PayPaｌ Ruby SDK](https://github.com/paypal/PayPal-Ruby-SDK) GemはSSL証明書を内部にPackageしてしまっており、この証明書が最近Removeになった事が原因。PayPalがどうして証明書をGemに入れ込むような作り方をしたのかは分からないが、SDKをハックすれば解消できる。



# 2.解決方法
SDK内部の証明書にまだ有効期限内のPEMを追記してRailsサーバーを再起動すれば解消する。

# 3.解決手順
## (1) PEMをダウンロード
参考記事でPayPalが発表しているPEMをダウンロードする。私はDigiCert High Assurance EV Root CAを使ったが、どれでも良いと思う。

DigiCert High Assurance EV Root CAの入手先

Download here: https://www.digicert.com/digicert-root-certificates.htm

ここからDigiCert High Assurance EV Root CAのPEMをダウンロードする。

![スクリーンショット 2020-08-04 午後10.29.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329289/07fc61f6-d9ba-ff40-22d7-83f6ac9df8fd.png)

## (2) SDK内のpaypal.crtの場所を検索
MacやUnixなら`find`コマンドで探す。Railsアプリの場合はアプリケーションのRootディレクトリ以下を探せば良いだろう。Production環境ではRubyが入っている場所、分からなければ sudo で / から全検索(`find / -name paypal.crt -print`)しても良い。

私のサーバーはAWSなので以下のように`~/`以下を検索した。

```ruby:rails_root
[ec2-user@awsome_server ~]$ find ./ -name paypal.crt -print 2>/dev/null
./.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/paypal-sdk-rest-1.7.4/data/paypal.crt
```

## (3) PEMをpaypal.crtに追記
ダウンロードしておいたPEMファイルの中身を確認。

```ruby:ローカルのMacのターミナル
$ cat DigiCertHighAssuranceEVRootCA.crt.pem
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL

途中省略

Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----
```

findで見つけたpaypal.crtを編集する。以下の172行目〜196行目が追加した部分である。単純に一番下に追加しただけであるが、======が必要なのと、正確な名称（DigiCert High Assurance EV Root CA）で区切ることに注意する。

```ruby:railsサーバーで実行
[ec2-user@awsome_server ~]$ sudo vi paypal.crt

    168 CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX
    169 bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/
    170 D/xwzoiQ
    171 -----END CERTIFICATE-----
    172 DigiCert High Assurance EV Root CA
    173 =======================================================
    174 -----BEGIN CERTIFICATE-----
    175 MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
    176 MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
    177 d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
    178 ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
    179 MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
    180 LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug

                           途中省略

    191 eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
    192 hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
    193 Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
    194 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
    195 +OkuE6N36B9K
    196 -----END CERTIFICATE-----
```

## (4) Railsサーバー再起動
環境によるが、私の場合はAWSでsystemctlで再起動できるので、実行。

```ruby:AWS
[ec2-user@awsome_server ~]$ sudo systemctl restart rails 
```

これでSSLエラーは出なくなり、正常にAPIコールできるようになった。

# 参考記事
- [(PayPal) Remove Support of Verisign G5 Root Certificate](https://www.paypal.com/va/smarthelp/article/discontinue-use-of-verisign-g5-root-certificates-ts2240)
- [Stackoverflow -PayPal SDK got SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)](https://stackoverflow.com/questions/63218952/paypal-sdk-got-ssl-connect-returned-1-errno-0-state-error-certificate-verify-fa)
- [Stackoverflow -OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)](https://stackoverflow.com/questions/63221087/opensslsslsslerror-ssl-connect-returned-1-errno-0-state-error-certificate/63256245#63256245)