Shipping BNPL and credit card features inside an 8M-user retail superapp
Client & context
Żappka is Żabka Group's retail superapp, the companion app for over 9,000 convenience stores across Poland, used by more than 8 million people. Żabka's fintech division, GreenHive, set out to embed financial products directly into the app: Buy Now Pay Later and a credit card, issued in partnership with PKO Bank Polski, Poland's largest bank.
After four years building other Żabka Group products, I joined the fintech division as a senior iOS developer. My scope was the BNPL flow and the credit card integration, not the whole app. That distinction matters. I was adding payment features to a product that already had millions of daily users and an established codebase, which is a different problem from greenfield work.
The challenge
Adding lending and card products to an app this size is hard for reasons that have little to do with UI.
Scale amplifies every defect. A bug that hits 0.1% of sessions is a rounding error in most apps. Here it means thousands of people locked out of a payment.
Consumer credit in Poland is regulated, and the bank had its own security and audit requirements for how credentials, keys, and payment data move through the client. The mobile app is part of the compliance surface, not just a frontend.
The core retail app also could not degrade while fintech features shipped underneath it. Releases had to be feature-flagged, backwards compatible, and recoverable. And in payments, the unhappy paths are the product: 3DS challenges, declined transactions, retries, expired tokens. That is where user trust is won or lost.
What I did
I designed and implemented the iOS side of both products, working against PKO Bank Polski's APIs and payment providers including PlanetPay.
The BNPL purchase and repayment flows, end to end on the client. The credit card integration: application flow, card management, transaction surfaces, plus PIN setup and PIN changes. PIN handling is the kind of feature where the security model has to be right the first time.
Under both sat the client-side security layer I implemented: RSA encryption (PKCS#1 OAEP SHA256) of sensitive payloads, JWT authentication with JWKS signature verification, token rotation, Keychain-backed storage, biometric auth.
I also owned the failure surface: 3DS step-up flows, declines with messaging that tells the user what to do next, retry logic that never double-charges.
I worked autonomously inside the team's release process, from technical design through App Store release. I coordinated directly with backend and bank-side engineers, not through a manager.
How: the decisions behind it
Payment flows are state machines with money attached, so I built them in The Composable Architecture, which makes every state transition explicit and testable. When a compliance question is "what exactly happens when the token expires mid-payment," the answer is a reducer you can read and a test you can run, not a whiteboard session. Swift Concurrency and Combine handle the async orchestration underneath.
On security the rule was: verify, don't trust. JWKS verification means the client checks token signatures against the bank's published keys instead of trusting whatever arrives. Token rotation limits the damage of any leaked credential. Sensitive payloads get RSA-encrypted before they leave the device. None of this is exotic. The hard part is applying it consistently, in a codebase other people maintain after you.
Every payment path was designed backwards from its failure modes. A declined BNPL transaction tells the user what to do next. A dropped connection during 3DS resolves to a known state, never a limbo where the user doesn't know if they paid.
Outcome
- BNPL and credit card features live in production for 8M+ users.
- Zero security incidents attributable to the client-side implementation.
- The features passed PKO Bank Polski's security requirements.
The takeaway
If you're a CTO evaluating a contractor for payments or other regulated mobile work, "can they write Swift" is the wrong question. The real one is "can I let them near the payment flow without adding risk." My answer is a track record: two years shipping lending and card features into one of Europe's largest consumer apps, inside someone else's codebase and release process, with the security done properly and the edge cases treated as real work.