GithubHelp home page GithubHelp logo

cocoapriest / swifty-receipt-validator Goto Github PK

View Code? Open in Web Editor NEW

This project forked from crashoverride777/swifty-receipt-validator

0.0 1.0 0.0 666 KB

A Swift helper to handle in app purchase receipt validation.

License: MIT License

Ruby 2.06% Swift 95.94% Objective-C 2.00%

swifty-receipt-validator's Introduction

Swifty Receipt Validator

Swift 4.2 Platform CocoaPods Compatible

A swift helper to handle app store receipt validation.

Your own server

The recommned way by Apple is to use your own server to validate app store receipts. However for obvious reason this is a hassle for alot of people like me, because I dont have a webserver and dont understand languages like PHP to make it work.

In those cases where you dont want to use your own server you can communcate directly with Apples server. Doing this is apparently not very secure and therefore you should use your own server when verifying receipts

Nevertheless its still better than not doing any validation at all. I will eventually try to update this helper to include guidlines/sample code to make it work with your own server. My knowledge about server code is very basic at the moment.

https://www.raywenderlich.com/23266/in-app-purchases-in-ios-6-tutorial-consumables-and-receipt-validation

Before you go live

  • Test, Test, Test

Please test this properly, including production mode which will use apples production server URL. Use xcode release mode to test this to make sure everything is working. This is not something you want take lightly, triple check purchases are working when your app is in release mode.

Requirements

  • iOS 10.3+
  • Swift 4.2+

Installation

CocoaPods is a dependency manager for Cocoa projects. Simply install the pod by adding the following line to your pod file

pod 'SwiftyReceiptValidator'

There is now an app which makes handling pods much easier

Altenatively you can drag the swift file(s) manually into your project.

Usage

  • Add the import statement to your swift file(s) when you installed via cocoa pods
import SwiftyReceiptValidator
  • In your class with your in app purchase code create a reference to SwiftyReceiptValidator
class SomeClass {
    let receiptValidator = SwiftyReceiptValidator()
}

Validate purchases

  • Go to the following delegate method which you must implement for in app purchases
extension SomeClass: SKPaymentTransactionObserver {

    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        transactions.forEach {
            switch $0.transactionState {
                case .purchased:
                ...
                case .restored:
                ...
            }
        }
    }
}

and modify the .purchased and .restored enum cases to look like this

case .purchased:
        // Transaction is in queue, user has been charged.  Client should complete the transaction.
        let productId = transaction.payment.productIdentifier

        receiptValidator.validate(.purchase(productId: productId), sharedSecret: nil) { result in
            switch result {

           case .success(let response):
                 defer {
                    // Complete the transaction only after validation was successful
                    // if validation error e.g due to internet, the transaction will stay in pending state
                    // and than can/will be resumed on next app launch
                    queue.finishTransaction(transaction)
                }

               print("Receipt validation was successfull with receipt response \(response)")
                // Unlock products and/or do additional checks

            case .failure(let error, let code):
                print("Receipt validation failed with code \(code), error \(error.localizedDescription)")    
                // Inform user of error, maybe try validation again.
            }
        }
            
case .restored:
    // Transaction was restored from user's purchase history.  Client should complete the transaction.
    guard let productId = transaction.originalTransaction?.payment.productIdentifier else {
        queue.finishTransaction(transaction)
        return
    }

    receiptValidator.validate(.purchase(productId: productId), sharedSecret: nil) { result in
        switch result {

        case .success(let response):
            defer {
                // Complete the transaction only after validation was successful
                // if validation error e.g due to internet, the transaction will stay in pending state
                // and than can/will be resumed on next app launch
                queue.finishTransaction(transaction)
            }

            print("Receipt validation was successfull with receipt response \(response)")
            // Unlock products and/or do additional checks

       case .failure(let error, let code):
            print("Receipt validation failed with code \(code), error \(error.localizedDescription)")  
            // Inform user of error, maybe try validation again.
        }
    }              

In this example sharedSecret is set to nil because I am only validating regular in app purchases. To validate an auto renewable subscriptions you can enter your shared secret that you have set up in itunes.

Validate subscriptions

  • To validate your subscriptions (e.g on app launch), select .subscription as the validation method. This will search for all subscription receipts and check if there is at least 1 thats not expired.
receiptValidator.validate(.subscription, sharedSecret: "enter your secret or set to nil") { result in
    switch result {
    case .success(let response):
        print("Receipt validation was successfull with receipt response \(response)")
        // Unlock subscription features and/or do additional checks first
    case .failure(let error, let code):
        switch error {
        case .noValidSubscription:
            // no active subscription found, update your cache/app etc
        default:
            break // do nothing e.g internet error or other errors
        }
    }
}

Just fetch receipt

  • To only fetch the verified receipt, select .none as the validation method.
receiptValidator.validate(.none, sharedSecret: "enter your secret or set to nil") { result in
    switch result {
    case .success(let response):
        print("Receipt response \(response)")
        // Do additional checks etc
    case .failure(let error, let code):
        // Handle error e.g no internet
    }
}

StoreKit Alert Controllers

One thing I do not know about receipt validation is if there is a way to stop the default StoreKit alert controller to show. When you get to the purchase code and to the .purchased switch statement, storeKit automatically shows an AlertController ("Thank you, purchase was succesfull"). This however is the point where receipt validation is actually starting so it takes another few seconds for the products to unlock. I guess this must be normal, although it would be nicer to show that alert once receipt validation is finished.

Final Note

As per apples guidlines you should always first connect to apples production servers and than fall back on apples sandbox servers if needed. So keep this in mind when testing in sandbox mode, validation will take a bit longer due to this.

I will try to update this in the future if I have a better grasp of what is needed for your own server.

swifty-receipt-validator's People

Contributors

crashoverride777 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.