概要
PokepayClient.getTokenInfo() と scanToken() の CPM トークン判定用正規表現が、サーバが実際に発行するトークン形式と一致しません。Dart・Android・iOS の 3 つとも一致せず、CPM 分岐に入ることが原理的にありません。
Android エミュレータ上で dev 環境に対して実際に確認しました。
PASS PokepayClient.getTokenInfo(CPM) type=TokenType.UNKNOWN
同じトークンを getCpmToken() に渡すと 200 で通るので、API 側は正規のトークンとして受理しています。
サーバの実装
pokepay-server の models/cpm-token.lisp:
(defparameter *pokepay-jpqr-company-code* "90000022")
(defun generate-cpm-token (money scopes &key (base64-length 6))
(concatenate 'string
*pokepay-jpqr-company-code* ; 8 文字
(money->header-id-base64 money) ; base64url(3 byte) = 4 文字
(scopes->bitmap-hex scopes) ; 2 文字
(jose/base64:base64url-encode (ironclad:random-data base64-length)))) ; base64url(6 byte) = 8 文字
合計 22 文字。カラム定義も (token :primary-key t :col-type (:varchar 22)) です。
base64url なので 小文字・-・_ を含みます。
dev で実際に発行された値:
90000022h8AS01gMOxHDiz -> "90000022" + "h8AS" + "01" + "gMOxHDiz"
90000022h8AS01tplLt_3h -> "90000022" + "h8AS" + "01" + "tplLt_3h" (アンダースコアを含む)
各 SDK の判定
| SDK |
箇所 |
正規表現 |
一致するか |
| flutter-sdk (Dart) |
lib/pokepay_sdk.dart:244 (getTokenInfo) |
^([0-9A-Z]{25})$ |
✗ 長さ 25≠22、小文字・_ 不可 |
| android-sdk |
Pokepay.java:158 (getTokenInfo) |
^[0-9]{20}$ |
✗ 長さ 20≠22、数字のみ |
| android-sdk |
Pokepay.java:203 (scanToken) |
^[0-9]{20}$ |
✗ 同上 |
| ios-sdk |
Pokepay.swift:160 (getTokenInfo) |
^[0-9]{20}$ |
✗ 同上 |
| ios-sdk |
Pokepay.swift:254 (scanToken) |
^[0-9]{20}$ |
✗ 同上 |
Dart とネイティブで期待形式が食い違っている (25 文字英大文字 vs 20 桁数字) 点からも、どちらも現行仕様から取り残されていると見られます。
影響
PokepayClient.getTokenInfo() に CPM トークンを渡すと TokenType.CPM ではなく TokenType.UNKNOWN が返る
scanToken() / invokeToken() に CPM トークンを渡しても CPM 決済の分岐に入らない (ネイティブ側の判定を通るため flutter-sdk 単独では直せない)
想定される修正
^[0-9A-Za-z_-]{22}$ 相当、あるいは JPQR カンパニーコード 90000022 の前方一致 + 長さ 22 での判定に寄せる。3 リポジトリで同じ判定に揃える必要があります。
scanToken 側はネイティブの判定を通るため、android-sdk / ios-sdk の修正が必須です。flutter-sdk 側は lib/pokepay_sdk.dart:244 の 1 箇所です。
確認していないこと
店頭でスキャンされるバーコードの中身がこの cpm_token 文字列と同一かは未確認です。もしバーコードが別表現 (20 桁数字など) を載せているなら、scanToken 側の ^[0-9]{20}$ は意図通りの可能性があります。その場合でも getTokenInfo に API 由来の cpm_token を渡す経路は壊れたままです。
再現環境
概要
PokepayClient.getTokenInfo()とscanToken()の CPM トークン判定用正規表現が、サーバが実際に発行するトークン形式と一致しません。Dart・Android・iOS の 3 つとも一致せず、CPM 分岐に入ることが原理的にありません。Android エミュレータ上で dev 環境に対して実際に確認しました。
同じトークンを
getCpmToken()に渡すと 200 で通るので、API 側は正規のトークンとして受理しています。サーバの実装
pokepay-serverのmodels/cpm-token.lisp:合計 22 文字。カラム定義も
(token :primary-key t :col-type (:varchar 22))です。base64url なので 小文字・
-・_を含みます。dev で実際に発行された値:
各 SDK の判定
lib/pokepay_sdk.dart:244(getTokenInfo)^([0-9A-Z]{25})$_不可Pokepay.java:158(getTokenInfo)^[0-9]{20}$Pokepay.java:203(scanToken)^[0-9]{20}$Pokepay.swift:160(getTokenInfo)^[0-9]{20}$Pokepay.swift:254(scanToken)^[0-9]{20}$Dart とネイティブで期待形式が食い違っている (25 文字英大文字 vs 20 桁数字) 点からも、どちらも現行仕様から取り残されていると見られます。
影響
PokepayClient.getTokenInfo()に CPM トークンを渡すとTokenType.CPMではなくTokenType.UNKNOWNが返るscanToken()/invokeToken()に CPM トークンを渡しても CPM 決済の分岐に入らない (ネイティブ側の判定を通るため flutter-sdk 単独では直せない)想定される修正
^[0-9A-Za-z_-]{22}$相当、あるいは JPQR カンパニーコード90000022の前方一致 + 長さ 22 での判定に寄せる。3 リポジトリで同じ判定に揃える必要があります。scanToken側はネイティブの判定を通るため、android-sdk / ios-sdk の修正が必須です。flutter-sdk 側はlib/pokepay_sdk.dart:244の 1 箇所です。確認していないこと
店頭でスキャンされるバーコードの中身がこの
cpm_token文字列と同一かは未確認です。もしバーコードが別表現 (20 桁数字など) を載せているなら、scanToken側の^[0-9]{20}$は意図通りの可能性があります。その場合でもgetTokenInfoに API 由来のcpm_tokenを渡す経路は壊れたままです。再現環境
5956743(PR fix: pin the clobbered JSON keys with @JsonKey and surface 5 fields the native SDKs already support #57 ブランチ)