From a21494655ee0ea74d8d66fd4ede9a899054230f3 Mon Sep 17 00:00:00 2001 From: Satoshi Imai Date: Mon, 3 Aug 2026 20:10:14 +0900 Subject: [PATCH 1/2] fix: pin JSON keys clobbered by the clean regeneration 3d753f8 regenerated every .g.dart from a clean build. For four fields the committed JSON keys changed, because their Dart field names do not round-trip through json_serializable's `field_rename: snake` (which inserts `_` before every single uppercase letter): PrivateMoney.onlineMessage oneline_message -> online_message PrivateMoney.canUseC2CTransfer can_use_c2c_transfer -> can_use_c2_c_transfer BankPayRedirectUrl.redirectUrl redirectUrl -> redirect_url BankPayRedirectUrl.paytreeCustomerNumber paytreeCustomerNumber -> paytree_customer_number Both are non-nullable in PrivateMoney, so fromJson now throws on every response the API actually returns. Pin the keys with @JsonKey so they survive any future regeneration, and regenerate the two affected files. `onlineMessage` is a typo of `oneline` introduced in 51b7a62; the field name is left alone to avoid a breaking API change. Note this also repairs its toJson side, which had been emitting `online_message` since that commit. Co-Authored-By: Claude Opus 5 (1M context) --- lib/responses/bankpay_redirect_url.dart | 4 ++++ lib/responses/bankpay_redirect_url.g.dart | 8 ++++---- lib/responses/private_money.dart | 5 +++++ lib/responses/private_money.g.dart | 8 ++++---- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/lib/responses/bankpay_redirect_url.dart b/lib/responses/bankpay_redirect_url.dart index 0d73513..0647136 100644 --- a/lib/responses/bankpay_redirect_url.dart +++ b/lib/responses/bankpay_redirect_url.dart @@ -4,7 +4,11 @@ part 'bankpay_redirect_url.g.dart'; @JsonSerializable() class BankPayRedirectUrl { + // このエンドポイントのレスポンスキーは snake_case ではなく camelCase のため、 + // field_rename: snake を @JsonKey で打ち消す。 + @JsonKey(name: 'redirectUrl') final String redirectUrl; + @JsonKey(name: 'paytreeCustomerNumber') final String? paytreeCustomerNumber; BankPayRedirectUrl({ diff --git a/lib/responses/bankpay_redirect_url.g.dart b/lib/responses/bankpay_redirect_url.g.dart index 06f3857..0a2d19f 100644 --- a/lib/responses/bankpay_redirect_url.g.dart +++ b/lib/responses/bankpay_redirect_url.g.dart @@ -8,12 +8,12 @@ part of 'bankpay_redirect_url.dart'; BankPayRedirectUrl _$BankPayRedirectUrlFromJson(Map json) => BankPayRedirectUrl( - redirectUrl: json['redirect_url'] as String, - paytreeCustomerNumber: json['paytree_customer_number'] as String?, + redirectUrl: json['redirectUrl'] as String, + paytreeCustomerNumber: json['paytreeCustomerNumber'] as String?, ); Map _$BankPayRedirectUrlToJson(BankPayRedirectUrl instance) => { - 'redirect_url': instance.redirectUrl, - 'paytree_customer_number': instance.paytreeCustomerNumber, + 'redirectUrl': instance.redirectUrl, + 'paytreeCustomerNumber': instance.paytreeCustomerNumber, }; diff --git a/lib/responses/private_money.dart b/lib/responses/private_money.dart index e7cd273..869938e 100644 --- a/lib/responses/private_money.dart +++ b/lib/responses/private_money.dart @@ -13,6 +13,9 @@ class PrivateMoney { final String type; final String unit; final String description; + // フィールド名は oneline (一行) の typo だが、公開 API 互換のため改名せず + // JSON キーだけ明示する。field_rename: snake では online_message になってしまう。 + @JsonKey(name: 'oneline_message') final String onlineMessage; final String? accountImage; final Images images; @@ -26,6 +29,8 @@ class PrivateMoney { final String? paymentActUrl; final String? commercialActUrl; final bool canUseCreditCard; + // field_rename: snake は大文字1文字ごとに _ を挟むため C2C が c2_c になる。 + @JsonKey(name: 'can_use_c2c_transfer') final bool canUseC2CTransfer; final String? customDomainName; final List? topupMethods; diff --git a/lib/responses/private_money.g.dart b/lib/responses/private_money.g.dart index 8c1693b..de9afaf 100644 --- a/lib/responses/private_money.g.dart +++ b/lib/responses/private_money.g.dart @@ -12,7 +12,7 @@ PrivateMoney _$PrivateMoneyFromJson(Map json) => PrivateMoney( type: json['type'] as String, unit: json['unit'] as String, description: json['description'] as String, - onlineMessage: json['online_message'] as String, + onlineMessage: json['oneline_message'] as String, accountImage: json['account_image'] as String?, images: Images.fromJson(json['images'] as Map), organization: @@ -26,7 +26,7 @@ PrivateMoney _$PrivateMoneyFromJson(Map json) => PrivateMoney( paymentActUrl: json['payment_act_url'] as String?, commercialActUrl: json['commercial_act_url'] as String?, canUseCreditCard: json['can_use_credit_card'] as bool, - canUseC2CTransfer: json['can_use_c2_c_transfer'] as bool, + canUseC2CTransfer: json['can_use_c2c_transfer'] as bool, customDomainName: json['custom_domain_name'] as String?, topupMethods: (json['topup_methods'] as List?) ?.map((e) => TopupMethod.fromJson(e as Map)) @@ -40,7 +40,7 @@ Map _$PrivateMoneyToJson(PrivateMoney instance) => 'type': instance.type, 'unit': instance.unit, 'description': instance.description, - 'online_message': instance.onlineMessage, + 'oneline_message': instance.onlineMessage, 'account_image': instance.accountImage, 'images': instance.images, 'organization': instance.organization, @@ -53,7 +53,7 @@ Map _$PrivateMoneyToJson(PrivateMoney instance) => 'payment_act_url': instance.paymentActUrl, 'commercial_act_url': instance.commercialActUrl, 'can_use_credit_card': instance.canUseCreditCard, - 'can_use_c2_c_transfer': instance.canUseC2CTransfer, + 'can_use_c2c_transfer': instance.canUseC2CTransfer, 'custom_domain_name': instance.customDomainName, 'topup_methods': instance.topupMethods, }; From 59567436eb9a8b937cdaa1f0565005f33f5d5a60 Mon Sep 17 00:00:00 2001 From: Satoshi Imai Date: Tue, 4 Aug 2026 00:17:52 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E3=83=8D=E3=82=A4=E3=83=86?= =?UTF-8?q?=E3=82=A3=E3=83=96SDK=E3=81=8C=E6=97=A2=E3=81=AB=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C=E6=B8=88=E3=81=BF=E3=81=AE5=E3=83=95=E3=82=A3?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=83=89=E3=82=92Dart=E3=81=AB=E9=80=9A?= =?UTF-8?q?=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit flutter-sdk はサーバを直接叩かず、ネイティブSDK (pokepaylib / Pokepay pod) の型付きレスポンスクラスを経由して再シリアライズされた JSON を読む。 Android は FAIL_ON_UNKNOWN_PROPERTIES=false で未知キーを捨てたうえ Response.toString() が宣言済みフィールドだけを書き戻し、iOS も Codable + 明示 CodingKeys で同じ挙動になる。したがってネイティブ側に無いキーは Dart まで届かず、Dart にフィールドを足しても常に null になる。 監査で挙がった 27 件のうち、ネイティブ 2.0.28 が既に対応していて Dart 側だけが欠けている 5 件を通す。 レスポンス (未対応1 のうち 4 件): CvsAuthorization に haraikomi_url / receipt_no / done_at / canceled_at を追加。 Android BankAPI/autogen/responses/CvsAuthorization.java と iOS Responses/CvsAuthorization.swift の双方が既に保持している。 done_at / canceled_at はネイティブが String のまま素通しするため、 同クラスの pay_limit や UserTransaction.done_at と揃えて String? で受ける。 4 件とも nullable なので既存レスポンスでも fromJson は落ちない。 リクエスト (未対応2 のうち 1 件): patchAccountCouponDetail に code を追加。 PokepaySdkPlugin.java は既に call.argument("code") を読んで PatchAccountCouponDetail に渡しており、Dart が送っていなかった。 Swift 側は PatchCouponDetail の code 引数を渡し忘れていたので併せて修正。 残り 22 件は CreateBill / UpdateCashtray / CreateAccountCpmToken 等の コンストラクタ自体にパラメータが無く、PrivateMoney / UserTransaction / Account / AccountCpmToken のレスポンスクラスにもフィールドが無いため、 android-sdk と ios-sdk の改修とリリースが先に必要になる。 Co-Authored-By: Claude Opus 5 (1M context) --- ios/Classes/SwiftPokepaySdkPlugin.swift | 3 ++- lib/bank_api/account.dart | 2 ++ lib/responses/cvs_authorization.dart | 11 +++++++++++ lib/responses/cvs_authorization.g.dart | 8 ++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ios/Classes/SwiftPokepaySdkPlugin.swift b/ios/Classes/SwiftPokepaySdkPlugin.swift index 39b74bc..9a1801d 100644 --- a/ios/Classes/SwiftPokepaySdkPlugin.swift +++ b/ios/Classes/SwiftPokepaySdkPlugin.swift @@ -506,7 +506,8 @@ class MethodCallTask { let accountId = args["accountId"] as! String let couponId = args["couponId"] as! String let isReceived = args["is_received"] as! Bool - client.send(BankAPI.Account.PatchCouponDetail(accountId: accountId, couponId: couponId,isReceived: isReceived),handler: self.after) + let code = args["code"] as? String + client.send(BankAPI.Account.PatchCouponDetail(accountId: accountId, couponId: couponId,isReceived: isReceived, code: code),handler: self.after) case "receiveMessageAttachment": let env = flutterEnvToSDKEnv(ienv: args["env"] as! Int32) let accessToken = args["accessToken"] as! String diff --git a/lib/bank_api/account.dart b/lib/bank_api/account.dart index acbafc3..7d1ef76 100644 --- a/lib/bank_api/account.dart +++ b/lib/bank_api/account.dart @@ -151,6 +151,7 @@ extension AccountAPI on PokepayAPI { required String accountId, required String couponId, required bool isReceived, + String? code, }) async { return await invokeMethod( (j) => CouponDetail.fromJson(j), @@ -161,6 +162,7 @@ extension AccountAPI on PokepayAPI { 'accountId': accountId, 'couponId': couponId, 'is_received': isReceived, + 'code': code, }, ); } diff --git a/lib/responses/cvs_authorization.dart b/lib/responses/cvs_authorization.dart index 0d4fd65..84ce0d8 100644 --- a/lib/responses/cvs_authorization.dart +++ b/lib/responses/cvs_authorization.dart @@ -13,6 +13,13 @@ class CvsAuthorization { final String tel; final String payLimit; final Account account; + // コンビニ払込票の URL・受付番号と、完了/取消時刻。 + // done_at / canceled_at はネイティブ SDK (Java String / Swift String?) が + // サーバの RFC3339 文字列をそのまま素通しするため、payLimit と同じく String で受ける。 + final String? haraikomiUrl; + final String? receiptNo; + final String? doneAt; + final String? canceledAt; CvsAuthorization({ required this.id, @@ -23,6 +30,10 @@ class CvsAuthorization { required this.tel, required this.payLimit, required this.account, + this.haraikomiUrl, + this.receiptNo, + this.doneAt, + this.canceledAt, }); factory CvsAuthorization.fromJson(Map json) => diff --git a/lib/responses/cvs_authorization.g.dart b/lib/responses/cvs_authorization.g.dart index c6b2492..d6ded0d 100644 --- a/lib/responses/cvs_authorization.g.dart +++ b/lib/responses/cvs_authorization.g.dart @@ -16,6 +16,10 @@ CvsAuthorization _$CvsAuthorizationFromJson(Map json) => tel: json['tel'] as String, payLimit: json['pay_limit'] as String, account: Account.fromJson(json['account'] as Map), + haraikomiUrl: json['haraikomi_url'] as String?, + receiptNo: json['receipt_no'] as String?, + doneAt: json['done_at'] as String?, + canceledAt: json['canceled_at'] as String?, ); Map _$CvsAuthorizationToJson(CvsAuthorization instance) => @@ -28,4 +32,8 @@ Map _$CvsAuthorizationToJson(CvsAuthorization instance) => 'tel': instance.tel, 'pay_limit': instance.payLimit, 'account': instance.account, + 'haraikomi_url': instance.haraikomiUrl, + 'receipt_no': instance.receiptNo, + 'done_at': instance.doneAt, + 'canceled_at': instance.canceledAt, };