Skip to content

Instantly share code, notes, and snippets.

@vzsg
Last active September 15, 2023 18:42
Show Gist options
  • Save vzsg/998ee839b6e82012a2dc78bc85e654ea to your computer and use it in GitHub Desktop.
Save vzsg/998ee839b6e82012a2dc78bc85e654ea to your computer and use it in GitHub Desktop.
Starting point for App Store receipt validation with Vapor 3
import Foundation
struct AppStoreReceiptValidationRequest: Encodable {
let receiptData: String
let password: String?
let excludeOldTransactions: Bool
private enum CodingKeys: String, CodingKey {
case receiptData = "receipt-data"
case password
case excludeOldTransactions = "exclude-old-transactions"
}
}
struct AppStoreReceiptValidationResponse: Decodable {
let status: Int
// TODO: other fields
enum ValidationStatus: Int {
case success = 0
case invalidJSON = 21000
case invalidReceiptData = 21002
case authenticationFailed = 21003
case invalidSharedSecret = 21004
case serverUnavailable = 21005
case subscriptionExpired = 21006
case testReceiptInProduction = 21007
case productionReceiptInTest = 21008
case authorizationFailed = 21010
}
}
public func routes(_ router: Router) throws {
router.post("ios-receipt") { request -> Future<String> in
// Represents the body that the iOS application POSTs to the server.
// For the sake of simplicity, it's assumed to contain a base64-encoded receipt.
struct ReceiptRequest: Decodable {
let receipt: String
}
let client = try request.make(Client.self)
let receipt = try request.content.syncDecode(ReceiptRequest.self).receipt
let appStoreRequest = AppStoreReceiptValidationRequest(receiptData: receipt, password: nil, excludeOldTransactions: false)
let postReq = Request(http: HTTPRequest(method: .POST, url: "https://buy.itunes.apple.com/verifyReceipt"), using: request)
try postReq.content.encode(appStoreRequest, as: .json)
return client.send(postReq)
.flatMap { try $0.content.decode(AppStoreReceiptValidationResponse.self) }
.map { (resp: AppStoreReceiptValidationResponse) -> String in
// TODO: check resp.status and other fields
// TODO: if all is well, give the user what he purchased and return a successful response
return "ok"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment