Client library for making in-app purchases on iOS and macOS Automattic apps

Overview

MobilePayKit

Client library for making in-app purchases on iOS and macOS Automattic apps

Introduction

MobilePayKit is a client library for making in-app purchases. This project facilitates in-app purchases by coordinating requests to:

Realistically this library is only useful for Automattic-based projects, but the idea is to share what we've made.

Features

  • iOS and macOS compatible
  • Consumable in-app purchases support
  • Non-Consumable in-app purchases support
  • Auto-Renewable Subscriptions in-app purchases support
  • Non-Renewable Subscriptions in-app purchases support
  • Restoring purchases

Requirements

  • iOS 13+
  • macOS 10.15+
  • Swift 5.3

Installation

Cocoapods

To integrate MobilePayKit into your Xcode project via CocoaPods, specify it in your Podfile:

pod 'MobilePayKit', :git => '[email protected]:Automattic/MobilePay-Apple.git', :branch => 'develop'

Swift Package Manager

To integrate MobilePayKit into your Xcode project via Swift Package Manager, add MobilePayKit as a dependency in Package.swift:

dependencies: [
    .package(url: "https://github.com/Automattic/MobilePay-Apple", .upToNextMajor(from: "0.0.1"))
]

Usage

Check out the iOS and macOS examples under the Example directory for more information on how to make in-app purchases via MobilePayKit.

Import MobilePayKit

Import the MobilePayKit module in your project.

import MobilePayKit

Configuring MobilePayKit

Before you call any MobilePayKit methods, configure a MobilePayKit shared instance by setting the WordPress oAuth token as well as the app's bundle ID.

", bundleId: " " ) ">
MobilePayKit.configure(
    oAuthToken: "
     
      "
     ,
    bundleId: "
     
      "
     
)

Fetching products

Fetch products that are available for in-app purchases.

MobilePayKit.shared.fetchProducts { [weak self] result in
    switch result {
    case .success(let products):
        print("Fetched products: \(products)")
    case .failure(let error):
        print("Error fetching products: \(error.localizedDescription)")
    }
}

Purchasing a product

Purchase a product using the product identifier.

MobilePayKit.shared.purchaseProduct(with: identifier) { [weak self] result in
    switch result {
    case .success(let transaction):
        print("Purchased product: \(transaction.payment.productIdentifier)")
    case .failure(let error):
        print("Error purchasing product: \(error.localizedDescription)")
    }
}

Testing in-app purchases

Testing locally via Xcode

To test in-app purchases locally, each developer will have to modify their Xcode scheme to let Xcode know to use the local Configuration.storekit file. Check out the Apple documentation on testing locally via Xcode for more information.

  1. Click on your app's scheme at the top of Xcode and select Edit Scheme
  2. Select Run
  3. Select Options
  4. Change the StoreKit Configuration to point to Configuration.storekit (the local StoreKit file)

Testing via the App Store Connect Sandbox

TBD

Contributing

  1. Fork it!
  2. Create your feature branch: git checkout -b my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin my-new-feature
  5. Submit a pull request :D

License

MobilePayKit is available under the GPL license. See the LICENSE file for more info.

Comments
  • [Tooling] Enable pod push on BuildKite

    [Tooling] Enable pod push on BuildKite

    Request ref: paaHJt-2Gr-p2

    What

    Enables pod lint build & test, validate, lint, and pod push.

    Checklist

    • [x] Normalize podspec file
    • [X] Create the pipeline and script files in .buildkite
      • [x] Disable CDN push while we refine this PR, pushing on our internal spec repo instead
      • [x] Temporarily enable "Publish Podspec" step on this branch (and not just tag) while testing the PR
      • [x] Re-enable correct filter on "Publish Podspec" step to only be on tags
      • [x] Re-enable CDN push once everything is ready
    • [x] Configure BuildKite
      • [x] Create a pipeline in BuildKite with pipeline-upload step
      • [x] Configure the WebHooks
      • [x] Declare proper environment variables in mobile-secrets and upload them
      • [x] Create a sha-256 keypair, upload the pair to mobile-secrets, and the public key as Deploy key to GitHub
    opened by AliSoftware 6
  • Add initial networking layer

    Add initial networking layer

    Description

    Resolves https://github.com/wordpress-mobile/WordPress-iOS/issues/16863

    This PR adds the initial networking layer:

    • Added InAppPurchasesService to call the fetch product skus / create order endpoints
    • Added initial InAppPurchasesServiceTests
    • Added InAppPurchasesAPIRouter to organize the endpoints
    • Added Alamofire as a package dependency

    Notes

    • I will add more tests to InAppPurchasesService in a later PR

    How to test

    1. Go to Edit Scheme > Run > Options > StoreKit Configuration
    2. Choose Configuration.storekit
    3. Run the iOS app
    4. Tap on Rocket Fuel to purchase
    5. Tap Confirm
    6. Tap OK
    7. On Xcode debugger menu, click on the Manage StoreKit Transactions menu item (See example below)
    Screen Shot 2021-07-19 at 16 29 19
    1. ✅ There should be a record of Rocket Fuel being purchased (See example below)
    Screen Shot 2021-07-19 at 16 32 32 do not merge 
    opened by momo-ozawa 4
  • Change completion callback param to Result<T, Error>

    Change completion callback param to Result

    Description

    Resolves https://github.com/wordpress-mobile/WordPress-iOS/issues/17018

    This PR updates the completion callback param to Result<T, Error>

    • Added PurchaseError
    • Added error handling for AppStoreService.fetchProducts via SKProductsRequestDelegate (when request(_:didFailWithError:) gets called)
    • Added error handling for AppStoreService.purchaseProduct via SKPaymentTransactionObserver (when the updated transaction state is .failed)

    Notes

    • InAppPurchasesService error handling tests already exist
      • testFetchProductSkus_WhenRequestFails_PublishesReceivedError()
      • testCreateOrder_WhenRequestFails_PublishesReceivedError()

    How to test

    Running tests

    1. Run MobilePayKitTests test target
    2. ✅ Tests should pass

    Running the app

    1. Configure the bearer token in ProductListViewModel
    2. Run the iOS app
    3. Purchase the product by tapping on it
    4. Tap Confirm
    5. Tap OK
    6. On Xcode debugger menu, click on the Manage StoreKit Transactions menu item
    7. ✅ There should be a record of a product being purchased (See example below)
    Screen Shot 2021-07-19 at 16 32 32
    opened by momo-ozawa 2
  • Embed MobilePayKit as a local Swift Package

    Embed MobilePayKit as a local Swift Package

    Description

    This PR adds the StoreKit stack and embeds MobilePayKit as a local Swift package. This lays the groundwork for developing the MobilePayKit library.

    • Resolves https://github.com/wordpress-mobile/WordPress-iOS/issues/16862
    • Resolves https://github.com/wordpress-mobile/WordPress-iOS/issues/16865

    https://user-images.githubusercontent.com/6711616/126185663-4e34c2b8-3781-4c25-8f71-981be11ed1f1.mov

    Note

    • Not yet implemented: a button on the PurchasableContentDetail view that consumes the purchased consumable
    • I may rewrite the view logic in Swift (instead of SwiftUI)

    How to test

    1. Go to Edit Scheme > Run > Options > StoreKit Configuration
    2. Choose Configuration.storekit
    3. Run the iOS app
    4. Tap on Rocket Fuel to purchase
    5. Tap Confirm
    6. Tap OK
    7. On Xcode debugger menu, click on the Manage StoreKit Transactions menu item (See example below)
    Screen Shot 2021-07-19 at 16 29 19
    1. ✅ There should be a record of Rocket Fuel being purchased (See example below)
    Screen Shot 2021-07-19 at 16 32 32
    opened by momo-ozawa 2
  • Add: macOS example

    Add: macOS example

    Part of https://github.com/wordpress-mobile/WordPress-iOS/issues/16861

    • Added a macOS example
    • Changed the MobilePayKit.framework to be used for iOS and macOS

    To test

    1. Add your token
    2. Run the mac app
    3. Make sure the product appears
    4. Buy it :)
    opened by leandroalonso 1
  • Networking with URLSession

    Networking with URLSession

    Description

    Resolves https://github.com/wordpress-mobile/WordPress-iOS/issues/16863

    This PR adds the initial networking layer:

    • Added InAppPurchasesService to call the fetch product skus / create order endpoints
    • Added initial InAppPurchasesServiceTests
    • Added InAppPurchasesAPIRouter to organize the endpoints

    Endpoints ref: pdekpA-18-p2

    Notes

    • This PR is a combination of two earlier PRs
      • https://github.com/Automattic/MobilePay-Apple/pull/5 (approved)
      • https://github.com/Automattic/MobilePay-Apple/pull/7

    How to test

    1. Run the iOS app
    2. Tap on Rocket Fuel to purchase
    3. Tap Confirm
    4. Tap OK
    5. On Xcode debugger menu, click on the Manage StoreKit Transactions menu item
    6. ✅ There should be a record of Rocket Fuel being purchased (See example below)
    Screen Shot 2021-07-19 at 16 32 32
    opened by momo-ozawa 1
  • Remove Alamofire in favor of URLSession

    Remove Alamofire in favor of URLSession

    Description

    This PR removes Alamofire in favor of URLSession

    • Removed Alamofire from package dependencies
    • Added a Networking protocol (URLSession conforms to this protocol, which enables us to passURLSession.shared as the default parameter for InAppPurchasesService

    Notes

    • I'm skipping the InAppPurchaseServiceTests for now because the fetchProducts and createOrder methods aren't actually calling networking.load(request:) yet

    How to test

    1. Run the iOS app
    2. Tap on Rocket Fuel to purchase
    3. Tap Confirm
    4. Tap OK
    5. On Xcode debugger menu, click on the Manage StoreKit Transactions menu item
    6. ✅ There should be a record of Rocket Fuel being purchased
    opened by momo-ozawa 1
  • Encapsulate StoreKit inside MobilePayKit

    Encapsulate StoreKit inside MobilePayKit

    Description

    This PR encapsulates StoreKit completely inside the MobilePayKit library. This means that any app using MobilePayKit won't need to directly interface with StoreKit.

    Ref: https://github.com/Automattic/MobilePay-Apple/pull/1#discussion_r672486337

    How to test

    1. Go to Edit Scheme > Run > Options > StoreKit Configuration
    2. Choose Configuration.storekit
    3. Run the iOS app
    4. Tap on Rocket Fuel to purchase
    5. Tap Confirm
    6. Tap OK
    7. On Xcode debugger menu, click on the Manage StoreKit Transactions menu item (See example below)
    Screen Shot 2021-07-19 at 16 29 19
    1. ✅ There should be a record of Rocket Fuel being purchased (See example below)
    Screen Shot 2021-07-19 at 16 32 32
    opened by momo-ozawa 1
  • Map custom errors

    Map custom errors

    Description

    This PR maps custom API errors. This enables us to return more meaningful error messages to whoever is consuming MobilePayKit.

    Previously, all API errors were being propagated as decoding errors, since we weren't mapping custom errors.

    Before | After --- | --- Error fetching products: The data couldn’t be read because it isn’t in the correct format. | Error fetching products: The OAuth2 token is invalid.

    Notes

    I also added OHHTTPStubs to MobilePayKit's test target to make it easier to stub / write tests.

    How to test

    1. Run either the iOS target or the macOS target without configuring the token
    2. ✅ Notice the error message in the console reads: Error fetching products: The OAuth2 token is invalid.

    Also, make sure tests are green.

    opened by momo-ozawa 0
  • Fix macOS build

    Fix macOS build

    Description

    This PR fixes the macOS build

    • Updated ProductListViewModel in the macOS target (copied / pasted from iOS target)
    • Updated ProductList SwiftUI view in the macOS target

    How to test

    Running the app

    1. Configure the bearer token and site id in ProductListViewModel for macOS
    2. Run the macOS app
    3. Purchase the product by tapping on it
    4. Tap Confirm
    5. Tap OK
    6. On Xcode debugger menu, click on the Manage StoreKit Transactions menu item
    7. ✅ There should be a record of a product being purchased
    opened by momo-ozawa 0
  • Inject siteId

    Inject siteId

    Description

    This PR injects the site id into MobilePayKit.

    Notes

    Apply patch to test the new createOrders endpoint (D65254-code)

    For sandbox info, follow instructions in these posts:

    • pbMoDN-mH-p2
    • pbArwn-24D-p2

    How to test

    Running tests

    1. Run MobilePayKitTests test target
    2. ✅ Tests should pass

    Running the app

    1. Configure the bearer token and site id in ProductListViewModel

    https://github.com/Automattic/MobilePay-Apple/blob/03400b306c01ab8b1108302885577f5fca252157/Example/iOS/MobilePayKit-iOS/ProductListViewModel.swift#L31-L35

    1. Run the iOS app
    2. Purchase the product by tapping on it
    3. Tap Confirm
    4. Tap OK
    5. On Xcode debugger menu, click on the Manage StoreKit Transactions menu item
    6. ✅ There should be a record of a product being purchased (See example below)
    Screen Shot 2021-07-19 at 16 32 32
    opened by momo-ozawa 0
Owner
Automattic
We are passionate about making the web a better place.
Automattic
A document-based SwiftUI application for viewing and editing EEG data, aimed at making software for viewing brain imaging data more accessible.

Trace A document-based SwiftUI application for viewing and editing EEG data, aimed at making software for viewing brain imaging data more accessible.

Tahmid Azam 3 Dec 15, 2022
A simple star rating library for SwiftUI apps on macOS and iOS

DLDRating A simple star rating library for SwiftUI apps on macOS and iOS. Features Installation Usage Styling Credits DLDRating was made by Dionne Lie

null 1 Mar 6, 2022
Swift iPhone and iPad Client for Polls API, using Hyperdrive API client

Polls Client This is a Swift iPhone and iPad client for the Polls API - a simple application allowing users to view polls and vote in them. Polls is a

Apiary 34 Jul 15, 2022
Mastodon and Twitter client for iOS, iPadOS & macOS

Note: Mamoot! is under heavy development and is obviously far from complete at this moment. We're currently looking for more people to work with us, s

null 13 Nov 22, 2022
Seaglass is a truly native macOS client for Matrix. It is written in Swift and uses the Cocoa user interface framework.

Seaglass is a truly native macOS client for Matrix. It is written in Swift and uses the Cocoa user interface framework.

null 1 Jan 17, 2022
A completely native Discord client for macOS built 100% in Swift and SwiftUI

Swiftcord A completely native Discord client for macOS built 100% in Swift and SwiftUI This project aims to create a fully functional native Discord c

CryptoAlgo-Dev 1.1k Jan 9, 2023
An iPhone Simulator "Wrapper" for SwiftUI Apps on macOS

SwiftUIPhone Run a SwiftUI app (or any SwiftUI view) in an iPhone Simulator "wrapper", directly on macOS! To be clear, this is not an iPhone Simulator

Justin Kaufman 7 May 20, 2022
A swift client library for GoTrue.

gotrue-swift Swift client for the GoTrue API. Using The usage should be the same as gotrue-js except: Oauth2: signIn with oauth2 provider only return

Supabase 23 Jan 7, 2023
A swift client library for GoTrue.

gotrue-swift Swift client for the GoTrue API. Using The usage should be the same as gotrue-js except: Oauth2: signIn with oauth2 provider only return

Supabase Community 23 Jan 7, 2023
Swift client library to interact with Supabase Storage

storage-swift Swift Client library to interact with Supabase Storage.

Supabase Community 21 Dec 1, 2022
Lightweight library helping to embed Mercuryo Widget into their mobile apps

Mercuryo-Widget Mercuryo Widget Wrapper is a lightweight library for developers of apps who embed Mercuryo Widget into their mobile UX. Solely purpose

Mercuryo.io 3 Apr 22, 2022
Super basic iOS app to browse open-source-ios-apps

Super basic iOS app to browse open-source-ios-apps

null 76 Nov 28, 2022
This To-Do app was developed using Swift and SwiftUI and works on iOS, MacOS (Apple Silicon) and WatchOS. The tasks are kept on storage even when the app is restarted.

ToDo-SwiftUI This app has a lot of sentimental value for me, given that it helped me a lot to understand the process of doing an iOS app and became th

Augusto Galindo Ali 6 Jul 12, 2022
macOS application written in SwiftUI that downloads installer pkgs for the Install macOS Big Sur application.

Download Full Installer This is a Swift UI implementation of my fetch-installer-pkg script. It will list the full macOS Big Sur (and later) installer

Armin Briegel 654 Dec 31, 2022
"Podman for macOS" is a macOS frontend for Podman.

Podman for macOS "Podman for macOS" is a macOS frontend for Podman. It can be used to start and stop both the Podman Machine and its running container

Victor Gama 573 Jan 5, 2023
This app is a native client for openHAB which allows easy access to your sitemaps

openHAB client for iOS Introduction This app is a native client for openHAB which allows easy access to your sitemaps. Beta releases are available on

openHAB 176 Dec 30, 2022
Tutorial GraphQL + Node Express + MySQL, and sample for Android / iOS client

GraphQL-tutorial Tutorial for GraphQL + Node Express + MySQL, and sample for Android / iOS client Blog NeoRoman's GraphQL-tutorial (Korean) Materials

Henry Kim 4 Oct 20, 2022
Native Jellyfin Client for iOS and tvOS

Swiftfin Swiftfin is a modern client for the Jellyfin media server. Redesigned in Swift to maximize direct play with the power of VLC and look native

Jellyfin 1.1k Jan 6, 2023
iOS Trakt Client - Keep track of your favorite TV shows and movies on your iPhone. (Under development)

CouchTracker Keep track of your favorite movies and tv shows on your iPhone Setup for development You will need Xcode 11.2.1 Swift 5.1.2 Run the follo

Pietro Caselani 42 Apr 19, 2022