8 ms·
Google refunded $200 because I missed 5 lines of Code
- mauflows 7y agoShoutout to the people who cared enough to want to pay for it
- teh_klev 7y agoI kinda thought that myself.
- gibolt 7y agoSeems like this shouldn't be the default. As accepting and then refunding a payment is so uncommon, it should require extra code for that case instead.
- derefr 7y agoI think it’s for the case where the app crashes after accepting payment but before writing the granted asset token to the user’s profile. No real way around that other than two-phase commit.
- tedunangst 7y agoIf you don't deliver the purchased good, a refund seems like a reasonable default. Want to keep the money? Acknowledge you've delivered the good.
- ShinTakuya 7y agoThe issue is that if you have a bug where the feature isn't activated even if they pay, the user would lose money. It's natural that as you activate the feature you should acknowledge the purchase. Otherwise you could have bugs like double charging and such. It was an unfortunate mistake by the author, but it makes perfect sense why it happened. The person who made the mistake should lose out.
- inlined 7y agoThis seems like something that static analysis can correct before the new app is even allowed in the App Store. If you accept a purchase but have no calls the the acknowledgement APIs then bounce with a message. Hell, it could even be a compiler warning. This seems squarely Google’s issue and the refund should be returned.
- aswinmohanme 7y agoYeah a static analysis would have been awesome. Now the refund amount has gotten to over $300 because of the time users tke to update their apps.
- inlined 7y agoOr even an different API design. Eg a @noignore return value that guides/requires the dev to acknowledgement.
- ehsankia 7y agoStatic analysis aside, as soon as it happens even once, you'd think that there would be a big red warning on your dashboard saying "X purchases were refunded because they weren't acknowledged". The fact that the author had to figure it out through user emails and negative growth is strange.
- shearskill 7y agoMobile games get frequent refund requests and devs are more than a few steps removed from the actual accounting from app stores. The analytics might throw an event if there’s a hook for a refund request but Apple and Google own the bank in a black box. Basically devs get a monthly statement with refunds subtracted from their cut.
- ehsankia 7y agoThere's a huge difference between the user explicitely requesting a refund, and Google automatically ordering one because the purchase wasn't acknowledged. I'm not familiar with the API, and I could see both of them looking the same on the dashboard, but Google themselves should be able to distinguish between the two, and one of the two cases is very likely a bug in the app code. I could not see a case where not acknowledging the purchase would be intended.
- iliketosleep 7y agoNear the end of the article: These kinds of incidents make us wonder the real cost of Code and the more real cost of messing up Imagine having an app about there ticking away and making pretty decent revenue. Little do you know there's a subtle error in business critical code (e.g. in-app purchases, ads, etc), reducing the revenue by over 50%. This is something I've seen first-hand and have become quite paranoid about. I suspect that it happens a lot. The reality is, no matter how many times one looks at their own code, there is no substitute for continuous testing of typical use cases in a production environment, ensuring that business critical code functions as expected. It's a continious process, because even if the code works properly at the beginng and isn't modified, the underlying OS or API's it interacts with can change and introduce unexpected behaviour.
- tehlike 7y agoI suspect this happens quite often. There are ways to mitigate this: 1. Instrument, monitor, alert 2. Experiment, and convert canaries to experiments.
- opportune 7y agoThis is why software asks you for usage data
- lallysingh 7y agoAdd instrumentation. At some point in the code, the data before the bug won't line up with the data after. Watch the metrics and make sure they make sense. Validate the theories your have about what you think users are doing.
- kaicianflone 7y agoRE: Indie Devs shouldn't short on QA
- mcv 7y agoI've worked for a company that went bankrupt over some accounting system they'd built and used themselves. It contained a subtle bug that made them think they had more money than they had. It's really vital to thoroughly test and verify any financial code. Any code, but financial doubly so. And do it again in production. Even small errors can really add up over time.
- wiradikusuma 7y agoI was surprised when I read that he moved back from Fluter to Kotlin, down the line I read it's due to APK size. I'm happy to hear some developers still care about size esp. for mobile, but on the other end, I'm sad because I'm currently using Flutter for building apps and I'm jealous of that 4.5MB difference :D
- aswinmohanme 7y agoI love everything about flutter except the size, and I would have stayed on flutter if it wasn't for the competition's app weighing around 1.6 MB.
- monsieurbanana 7y agoDoes the size of an app affects something besides the initial download? Maybe it also lengthens the app loading but everybody here doesn't talk about it because it's well known of android developers, which I'm not?
- anoncake 7y agoYes, bigger apps take up more space in storage.
- winter_squirrel 7y agoI feel like most phones nowadays don't really care about a 5mb difference considering they have multiple GB's of space. At least on my phone, the space taken by the actual app binaries is negligible compared to media.
- cozzyd 7y agoMost people have no concept of how much space things take. When their phone fills up because of too many videos of toddlers bumbling around they assume it's the apps.
- 7y ago
- anonu 7y agoSeems like a PEBCAK
- deanCommie 7y ago> In order for Google Play to ensure a consistent purchase experience regardless of where the user purchases your product, you must acknowledge all purchases received through the Google Play Billing Library as soon as possible after granting entitlement to the user. Can someone who understands this domain better explain why this exists? A superficial reading of the text triggers thoughts of "fraud prevention", but the code the author uses to fix it is clearly one a fraudulent app can also easily include. Other thoughts about preventing poor user experiences such as dark patterns to trigger accidental purchases, or bait-and-switch functionality with Fremium apps also don't seem to be prevented by this. So what's going on?
- foota 7y agoMy guess would be to prevent lost delivery of the "payment received" notification from impacting the purchaser.
- sbov 7y agoSo Google knows that you know that they paid, would be my guess.
- jonny_eh 7y agoI was confused too because it sounded like the developer had to log in and click something to acknowledge the purchases. But it’s the app that needs to acknowledge that it has unlocked its features for the user. Makes sense to me now.
- tjohns 7y agoPlay Billing 2.0 added the ability to purchase in-app items from outside of the application. This ACK confirms that the application properly processed the notification and delivered the item to the user. Otherwise, Play assumes that the purchase was lost in the ether sometime before fulfillment (e.g. bug, the app crashed, etc.).
- fopen64 7y agoRushed to check whether my app was affected, it was not because I still use the old AIDL API (IInAppBillingService). In-app purchases are difficult and a PITA to test. At least the documentation offers a basic abstraction library, I suspect many use it as I did, but who knows if it covers all bases?
- mrb 7y agoWait a minute. 5 lines of code were missing in the app, causing users to be refunded. So does this mean a malicious user could decompile the app, remove this code, recompile, and get these auto refunds? This seems a way easier mechanism to get free in-app purchases rather than reverse-engineering the rest of the code.
- tomglynch 7y agoGreat potential exploit. From what I have read, decompiling usually doesn't reproduce the app 100% though so it usually won't run. Is this correct?
- mruts 7y agoHow could this be?
- abedja 7y agoYour recompiled version would not have the proper cryptographic signature as you don't have the keystore used by the dev on your pc
- numerlo 7y agoThe version without those 5 lines will now be forever out there though. Malicious peers can download the apk and get the premium version for free. This feels like a poorly thought out design on Google's part.
- mesaframe 7y agoLittle off topic. How was your experience with Flutter? How does it compare with other two?
- JmPotato 7y agoThat's very meaningful…
- 2pointsomone 7y agoAlso off-topic, but why move away from React Native?
- benjaminwootton 7y agoI once worked on a platform where you could buy ringtones, wallpapers, jokes etc by SMS pre App Store and play store. Every night the platform would kick off a process to claim money from the telco using some key which was tied to an SMS the user had sent. That process was responsible for more than $1 million a month, but it was buggy as hell. Half of the billing attempts would fail, the retry logic was buggy, processes would crash so you would just start them again without proper semantics to ensure you don’t bill people twice. After a while there were so many retries outstanding that you couldn’t get through them overnight, so we would try in random orders and we would have the process running from 3 days ago whilst try close off today’s bills. I’m sure people were billed incorrectly and a lot of money was left on the table from users who should have been billed. We never really heard a lot of noise about this either. So I’m sympathetic to this process and glad that Apple and Google have improved the confidence around mobile commerce.
- tomglynch 7y agoThat's very interesting. I'm sure there are a lot of stories like this from back in the day - charging people has never been easier than it is now.
- LeonM 7y agoNot just back in the day, I have at least a couple of customers of which I know they are losing money because of billing issues. Why? Because most accounting software is horrible and have minimal to no third party integration options. Many of them don't have an API, so the only option you're left with is manually (!) importing some XML structure every day. The logic is usually very limited so stuff like record mutations are often silently ignored during the import. The accounting software world is evil. Deliberately engineered vendor lock-in, very limited third party integrations, ridiculous charges for 'custom' implementations, etc. I once build a migration tool for a well known accounting/ERP suite, and my partnership with them was immediately terminated due to 'breach of terms'.
- fibers 7y ago
- PaulBGD_ 7y agoJust installed your launcher, exactly what I was looking for :) One change I'd suggest, dragging to reorder custom apps.
- rognjen 7y agoAlternative title: I missed 5 lines of code and lost $200 (and it's all my fault)
- fencepost 7y agoI'd have just added "of sales" or "of my sales" after the dollar amount to make it more clear. I actually looked at this because I thought Google had refunded money to the author and I wanted to see what had actually inspired an act of customer service from a company known for not having it.
- whitecrow90 7y agodid the same implementation one month ago (and also missed the acknowledgement step :/) and we are 1 month before release, first thing on Monday morning to add and test it. Thanks dude cheers :D
- ddffre 7y agoNew payment API, it was something they have mentioned. A lesson for next time always read blog posts about new APIs you are planning on implementing, especially when it comes to payments.
- deleted 7y ago[deleted]
- fjsolwmv 7y agoBuilding a successful business requires taking responsibility for all the boring details. Complaining that it is someone else's fault wastes precious time and hurts morale.
- deleted 7y ago[deleted]