0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

個人開発のフリマアプリを、App StoreとGoogle Playに出すまで(Next.js + Expo WebView + Stripe Connect)

0
Posted at

フリマアプリ「LOVEBAIT(ラブベイト)」を、AI(Claude)の助けも借りながら作り、App StoreとGoogle Playに出しました。構成と、詰まったところ・直したところをまとめます。うまくいった話だけでなく、審査で一度却下された話や、本番に入れてはいけない物を入れていた話も書きます。

1. 全体の構成

層 使ったもの
Web本体 Next.js(App Router)、Vercelでホスティング
iOS / Android Expo(React Native)の薄い殻。中身は、WebViewでWeb本体を表示。カメラ・音声入力・プッシュ通知だけネイティブ連携
決済 Stripe(Connect)。出品者の本人確認(KYC)はStripeの手続き
画像・ファイル Vercel Blob
メール Resend
認証 自前のセッション(jose)、Googleログイン
AI 写真解析・音声の整理・英訳。Gemini(既定)とClaude(切替可)を、共通の口で呼ぶ
多言語 アプリの画面は9言語(日・英・中・独・仏・西・伊・韓・葡)。Webの紹介ページにはロシア語もあり

2. なぜ「WebView殻」にしたか

1人+AIで、Web・iOS・Androidを同じ中身で、早く出したかったからです。Web本体を直せば、アプリも(ストアの再審査なしで)変わります。
一方で、ストアの審査では不利になることがあると、後で分かりました(後述)。

3. 写真から出品の案を作る

写真を撮ると、AIが「商品名・ブランド・カテゴリ・状態・参考価格・説明・タグ」をJSONで返します。型は zod で縛り、スキーマに合わない返答は捨てて、エラーにします。

const AnalysisSchema = z.object({
  title: z.string(),
  brand: z.string(),
  condition: z.enum(["未使用", "新品", "美品", "良好", "やや傷あり"]),
  suggestedPrice: z.number(),
  description: z.string(),
  tags: z.array(z.string()),
  authenticityRisk: z.boolean(),        // 価格の不自然さの簡易判定
  authenticityRiskReason: z.string(),
});
  • AIの案は、そのまま出品しない。出品者が、読んで直す前提の画面にしています。
  • LLM呼び出しは、generateStructured({ prompt, schema, imageUrl }) の1つの口にまとめ、環境変数で Gemini↔Claude を切り替えられます(費用を測るため、使ったトークン数もログに残します)。
  • 音声入力は、expo-speech-recognition で聞き取ったテキストを、AIに渡して項目に整理します。既存の入力を消さず、補う動きにしています。

4. 偽造品対策(完全ではない、が、やったこと)

フリマは、構造上、コピー品が紛れ込みます。決済のStripeにも、制限業種(偽造品など)があります。そこで:

  1. 出品時に、「本物であり、他人の権利を侵していない」への同意チェックを必須に(サーバー側でも二重に確認)
  2. AIが、ブランド名と価格の不自然さを参考として知らせる(出品は止めない。誤検知で、正規の掘り出し物を止めたくないため)
  3. 商品ページに通報ボタン(運営へメールで通知。保存と通知を二重化)
  4. 買った人の受け取り確認まで、代金を出品者に渡さない

「偽造品ゼロ」とは言えません。参考機能であり、真贋を保証するものではないと、画面と説明に書いています。

5. 審査で詰まったところ

(a) App Store: ガイドライン2.3.1(a)「説明にない隠れた機能」で却下

  • 却下の理由は「バイナリの中に、出品・価格データ、審査時に有効化されなかったバックエンド接続のコードがある」という趣旨でした。
  • WebView殻なので、審査員がアプリを触った限りでは、サーバーとの通信が見えにくかったのが一因だと考えています。
  • 返信で、「WebView殻であること・全ユーザー同じ動作であること」を説明し、さらに「ブラウズ・検索・詳細表示の間の通信を確認できる手順」を送りました。その後、審査が完了し、公開されました。

(b) Google Play

  • 初期は、Webを包む形(TWA)で出していました。のちに、Expoの殻に置き換えました。
  • Expo SDK 52 → 54 に上げました。Google Playの16KBのメモリページサイズへの対応のためです。

6. 本番に「サンプル」を混ぜていた話(反省)

開発中に作った架空のサンプル商品(約100件)が、本番のホームとサイトマップに出ていました。検索にも載る状態で、実在の商品に見える危険がありました。さらに、決済の処理が、サンプル商品でも決済セッションを作る分岐を持っていました(実際に購入できる恐れ。本番では試していません)。
対応:

  • 決済・入札・コメントを、サンプルではAPIで拒否
  • 一覧はサーバー配信に切り替え、サンプルには「サンプル」表示を付けました
  • ページは noindex、サイトマップから除外
    開発用のデータは、本番のコードから、はっきり分けておく。AIとの開発でも、レビューは人が見る、と実感しました。

7. AIと開発して、よかったこと・困ったこと

よかった

  • 設計の相談から、コード、テスト、文面まで、一人で見る量を減らせた
  • 規約や審査の返信文など、文章の下書きが早い

困った

  • 長い会話が続くと、前提のずれが出る。メモ(決めたこと)を、ファイルに残すのが必須
  • 実機でしか分からない問題(WindowsのPowerShellで、eas-cli の対話入力に貼り付けるとクラッシュする、など)は、人が見つける
  • 決済・規約・審査の返信は、最終判断を人がする

8. 今後

  • 出品を増やす(いまは、出品がまだ少ない段階です)
  • アプリ内の言語宣言、検索まわり(ASO・SEO)の改善

ご意見・ご指摘を、お待ちしています。(お問い合わせ: info@love-ap.net)

LOVEBAIT(ラブベイト)は、App Storeと Google Play で公開中です。「ラブベイト」で検索してください。


この記事は、AIを使って下書きし、作者(鹿島公胤)が確認しています。内容は2026年10月時点です。売れる・稼げることを保証するものではありません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?