Coder Social home page Coder Social logo

russell-archer / storehelper Goto Github PK

View Code? Open in Web Editor NEW
387.0 9.0 47.0 160.86 MB

Implementing In-App Purchases with StoreKit2 in Xcode 13 - 15 using SwiftUI, Swift 5.7 - 5.9, iOS 15 - 17 and macOS 12 - 14. Also supports tvOS and visionOS.

License: MIT License

Swift 100.00%
swiftui storekit ios15 in-app-purchases swift swift5 macos12 ios macos xcode

storehelper's Introduction


StoreHelper


Recent Major Changes

  • 2 April, 2024
    • Basic support for tvOS added by Hengyu (thank you!)
  • 15 March, 2024
    • Reorganization of documentation to support DocC
  • 8 March, 2024
    • Added Privacy Policy Manifest
  • 24 January, 2024
    • Basic support for visionOS added by Hengyu (thank you!)
  • 23 June, 2023
    • Improved handling of subscription renewals and expirations that happen when the app's not running
    • See AppStoreHelper.paymentQueue(_:updatedTransactions:) and StoreHelper.handleStoreKit1Transactions(productId:date:status:transaction:)
  • 12 February, 2023
    • Made the configuration of subscription products more flexible
    • You can now either rely on a naming convention (as before) or use a "Subscriptions" section in "Products.plist"
    • See the Samples/Configuration/SampleProducts.plist file for details
    • Added unit tests to StoreHelperDemo project
  • 27 January, 2023
    • Fixed a bug related to isPurchased for consumable products. Caused a crash on macOS and iOS (thank you Abdullah Kardaş!)
  • 18 January, 2023
    • Additional logging of various activities added
  • 17 January, 2023
    • Improved support for handling extended wait times for StoreKit and App Store responses
    • Improved caching of purchasing status
    • Updates to many shared views to handle unknown purchases status
  • 10 January, 2023
    • Added support for caching of product purchase status in isPurchased(productId:) using the purchasedProductsFallback collection
    • Using purchasedProductsFallback as a cache can be turned on/off using StoreHelper.doUsePurchasedProductsFallbackCache
    • The purchasedProductsFallback property is now public private(set) rather than public
    • Added "Refresh Products" button and support for pull-to-refresh to the products list
    • UI improvements to various views and improved sharing of views between iOS and macOS
    • Minor documentation updates (StoreHelper Guide)
  • 13 December, 2022
    • Added proof-of-concept demo showing StoreHelper in a UIKit project
  • 27 November, 2022
    • Major update to the way subscriptions are handled
    • Subscription prices now show prices and renewal periods
    • Promotional and Introductory offers on subscriptions are now supported
    • The most appropriate promotional or introductory offers or standard price and renewal period are automatically displayed
    • Additions to StoreHelper.SubscriptionHelper: hasLowerValueCurrentSubscription(than:), isLapsedSubscriber(to:), allSubscriptionTransactions()
    • Added in-app redemption of offer codes
    • Added new sections to the Guide on "Subscription Introductory and Promotional Offers" and "Supporting In-App Offer Code Redemption"
    • Quick Start and Guide documentation reviewed and updated for iOS16/macOS13/Xcode14 and new subscription features
  • 7 Nov, 2022
    • Minor changes re upgrade to iOS 16 and macOS 13
  • 19 October, 2022
    • Added new section to the Guide on "Restoring Previous Purchases"
  • 15 March, 2022
    • Changed the initialization flow because of a new warning in Xcode 13.3 related to having @MainActor init()
    • Removed the need for StoreHelper's init method to run on the main thread by moving some initialization code to a new start() method
    • You should now call StoreHelper.start() as soon as possible after initializing StoreHelper
    • The start() method starts listening for transactions and get localized product info from the App Store
    • Updated all documentation because of this change
  • 25 January, 2022
    • Refactored StoreHelper as a SPM Package
    • Moved example app to separate repo (StoreHelperDemo)
    • Updated documentation re change to SPM package
  • 19 January, 2022
    • Major updates to documentation
    • Added Mac target
  • 21 December, 2021
    • Updated documentation to reflect refactoring changes
  • 20 December, 2021
    • Refactored throughout so that this non-private version of StoreHelper is in-sync with private StoreHelper code used in an app released to the App Store

Overview of StoreHelper

StoreHelper is a Swift Package Manager (SPM) package that enables developers using Xcode 13 - 15 to easily add in-app purchase support to iOS 15 - 17 and macOS 12 - 14 SwiftUI apps. The package also provides basic support for visionOS and tvOS.

StoreHelper is used to provide in-app purchase support in Writerly (iOS/macOS), which is available on the App Store.

StoreHelper provides the following features:

  • Multi-platform (iOS, macOS) SwiftUI support for purchasing Consumable, Non-consumable and Subscription products
  • Detailed documentation and an example project
  • Supports transaction validation, pending ("ask to buy") transactions, cancelled and failed transactions
  • Supports customer refunds and management of subscriptions
  • Supports introdctory offers, in-app redeeming of offer codes and experimental support for promotional offers
  • Provides detailed transaction information and history for non-consumables and subscriptions
  • Support for direct App Store purchases of promoted in-app purchases

License

MIT license, copyright (c) 2022, 2023, 2024 Russell Archer. This software is provided "as-is" without warranty and may be freely used, copied, modified and redistributed, including as part of commercial software.

See License for details.

Requirements

StoreHelper uses Apple's StoreKit2, which requires iOS 15 - 17, macOS 12 - 14 and Xcode 13 - 15.

Getting Started

Jump to the StoreHelper Quick Start guide.

storehelper's People

Contributors

aehlke avatar chrmod avatar emilpedersen avatar hengyu avatar russell-archer avatar youkchansim avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

storehelper's Issues

Compile errors

Seeing this when building with this package in my project:

/Users/ray/Library/Developer/Xcode/DerivedData/Foo-dbwvioleuojlekfcjzuhvmapqlxu/SourcePackages/checkouts/StoreHelper/Sources/StoreHelper/Views/Shared/TermsOfServiceView.swift:20:38: error: variable binding in a condition requires an initializer
            if let termsOfServiceUrl { Link("Terms of Service", destination: termsOfServiceUrl) }
                                     ^
/Users/ray/Library/Developer/Xcode/DerivedData/Foo-dbwvioleuojlekfcjzuhvmapqlxu/SourcePackages/checkouts/StoreHelper/Sources/StoreHelper/Views/Shared/TermsOfServiceView.swift:22:37: error: variable binding in a condition requires an initializer
            if let privacyPolicyUrl { Link("Privacy Policy", destination: privacyPolicyUrl) }
                                    ^
/Users/ray/Library/Developer/Xcode/DerivedData/Foo-dbwvioleuojlekfcjzuhvmapqlxu/SourcePackages/checkouts/StoreHelper/Sources/StoreHelper/Views/Shared/TermsOfServiceView.swift:28:34: error: variable binding in a condition requires an initializer
            if let termsOfService, let tosUrl = URL(string: termsOfService) { termsOfServiceUrl = tosUrl }
                                 ^
/Users/ray/Library/Developer/Xcode/DerivedData/Foo-dbwvioleuojlekfcjzuhvmapqlxu/SourcePackages/checkouts/StoreHelper/Sources/StoreHelper/Views/Shared/TermsOfServiceView.swift:29:33: error: variable binding in a condition requires an initializer
            if let privacyPolicy, let ppUrl = URL(string: privacyPolicy) { privacyPolicyUrl =  ppUrl }

Certificate issue on device

iOS 16.4 (though same problem with iOS 16.3), Xcode 14.2 and 14.3.

Doing a non-consumable in-app purchase.
Code was running fine a few months ago, and recently started on an update, and encounter this issue. Running on simulator works as before - purchase validates and updates just fine. Running on a device (iPhone 12 Pro with 16.3 or 16.4) fails validation with:

2023-04-01 00:16:39.288226-0700 XXXXX[27827:2726419] [Default] Failed to verify certificate chain due to client recoverable failure:
Error Domain=NSOSStatusErrorDomain Code=-67843 "“StoreKit Testing in Xcode” certificate is not trusted" UserInfo={NSLocalizedDescription=“StoreKit Testing in Xcode” certificate is not trusted, NSUnderlyingError=0x28259a550 {Error Domain=NSOSStatusErrorDomain Code=-67843 "Certificate 0 “StoreKit Testing in Xcode” has errors: Root is not trusted;" UserInfo={NSLocalizedDescription=Certificate 0 “StoreKit Testing in Xcode” has errors: Root is not trusted;}}}
2023-04-01 00:16:39.289279-0700 XXXXXX[27827:2726418] [Default] Failed to verify signature for Transaction, will assume invalid: failedToVerifyCertificateChain

Subscriptions renewed when the MacOS app was closed are not picked up by Storekit2

I'm seeing a really strange behavior in Xcode 14.3 (14E222a, Ventura 13.3) for a MacOS app with auto-renewable subscriptions.

Scenario:

  1. Launch the app (local Xcode testing) and purchase a subscription -> works OK.
  2. Let the app run and after a while the subscription renews and StoreHelper picks up the renewal alright.
  3. Close the app and let the subscription renew a few times "in the background."
  4. When reopening the app, the latest transaction retrieved by a call to storeHelper.subscriptionHelper.subscriptionInfo(for: "Monthly") is the last one seen when the app was running. All the transactions happening while the app was closed are not there.
  5. The Storekit 1 call in AppStoreHelper is picking up the "ghost" transactions quite well, but it only passes down the stream the ProductID(s) associated with those transactions, which is quite useless without a proper subscriptionInfo object.

Am I the only one seeing this? Is this going to happen in production too, or is it just a bug in local testing?

How to disable logs?

Greeting from Ukraine! 🇺🇦

@russell-archer Thank you for this amazing project!

I just started to use it and while creating a SwiftUI views, in debug I see enormous logs like:

Request products from the App Store started
Request products from the App Store success
Request all products purchase status started
Request products from the App Store success
Request all products purchase status started
Request all products purchase status success
Request all products purchase status success

Which is really mixing with all other logs for my debug..

So I wonder, is there way to disable such logs from StoreHelper?
Or maybe I'm doing something wrong if even in views where I'm not using StoreHelper I still see such logs..

Question about localized content

Hiya. Have you had experience with localized content ?

I have localized my in app purchase item in App Store connect but am yet to see them in the other languages , even when using via testFlight and switching languages.

Is there something I'm missing ? Or will I only see them when I update to the appStore ?

Thanks

isPurchased with subscriptions

Hi,

I wanted to ask/suggest what happens to the function isPurchased when dealing with a subscription that may be cancelled or/and expired. The desirable behaviour is that isPurchased would return true when the subscription is autorenewing normally, or when it has been cancelled but still hasn't reached it's expiration date. And false otherwise, that is to say, when the subscribed content should be no longer available to the user. I haven't seen any status confirmation in the function, so I assume it returns true if it has been purchased at any time, even if it has been cancelled and expired.

Am I correct? If I am, what would be an optimal way to check this circumstance? The idea is to have a function that returns true if the user should have access to that premium content and false otherwise.

Thank you.

Do we have any idea on the next release

Hey team,

The package includes lots of major changes since the first release. I'm wondering if we could create a new tag for the next release. Since it's a common way to use version management in the Swift Package Manager.

Best,
Hengyu

Could not fetch Products array (tvOS)

In requestProductsFromAppStore on tvOS, debug mode (not yet live on the App Store) I get a failure of requestProductsFailure either by having nil Products or an empty array of Products.

The same happens on watchOS production mode, while it works ok in debug.

I narrowed down the issue to the line try? await Product.products(for: productIds)

It seems that there's a bug in StoreKit2 🤔

Any thoughts?

Question about using StoreHelper in Safari Extension project

Is it possible to use StoreHelper into a Xcode project created with SafariExtension multiplatform template?
Do you have some sample or guide (like the QuickStart) ?
In the meantime I'm trying it, but there are some discrepancies. For example, StoreHelper is present in Frameworks, Libraries... for iOS but not for MacOs. Before to going on I thought was better and safer to ask you.
Thanks

isPurchased() can't be called right after start()

I'm trying to determine if the user has purchased a subscription, e.g. on a previous run of the app. So I call:

            await storeHelper.start()
            
            // Update our knowledge of what products are purchased
            do {
                try await storeHelper.isPurchased(productId: PRO_PRODUCT_ID)

However, start() starts an async task, and isAppStoreAvailable isn't true until the task has finished, meaning that isPurchased fails right away, because isAppStoreAvailable is false.

I need to know if the subscription has been purchased to show or hide a feature in the UI without waiting for a network request, so I make these calls at app startup so that the purchase will be cached in purchasedProductsFallback, which I can check quickly.

What's the right way to do this with StoreHelper?

How to customize Product View

this package provider a Products list view, but I need a simpler view for only one subscription, just like Apple Docs:

image

so I write a view using PurchaseButton:

    var body: some View {
        if storeHelper.hasSubscriptionProducts, let subscriptions = storeHelper.subscriptionProducts {
            ForEach(subscriptions, id: \.id) { subscription in
                VStack {
                    Text(subscription.displayName)
                    Text(subscription.description)
                    PurchaseButton(purchaseState: $purchaseState, productId: productId, price: subscription.displayPrice)
                }
            }
        }
    }

but error:

'PurchaseButton' initializer is inaccessible due to 'internal' protection level

image

so, how to customize Product View?

Compile Issue

Hi,

XCode is throwing a compilation error:

Missing arguments for parameters 'content', 'publisher', 'action' in call

This from the MainView on the following line from the demo app:

NavigationLink(destination: SubscriptionView()) { Text("Subscriptions").font(.largeTitle).padding()}

SubscriptionView does not appear to take any parameters.

C

Auto-renew subscription eligibility

Hi,
in StoreDemoApp Product storekit file I changed the Gold subscription introductory offer to offer a 1 week free trial period.
I also changed the Subscription Renewal Rate of 1 month = 5 minutes to make local tests.

Running the app, Gold subscription buy product button caption correctly shows the 1 week free and I successfully bought it.

Then, without waiting the 5 minutes for the auto-renew, in the app I cancelled the subscription, and under Gold subscription I can see "Subscription cancelled. Will expire at..." with the date of expiring. So it knows that the trial period is still active.

But once the subscription has expired, under Gold I can see just a green mark. I expected to find some button saying "Renew" or "Buy" (obviously without the free trial because the user already used it and is no more eligible for the introductory offer...).

Is this normal? I mean, if a user cancels his subscription while in trial, at the end of the trial he should be able to buy the subscription again (without trial), or am I wrong?
Thanks

Screenshot 2023-06-20 alle 10 58 16

show two URL: Terms of Service, Privacy Policy

Guideline 3.1.2 - Business - Payments - Subscriptions

We noticed that your app did not meet all the terms and conditions for auto-renewing subscriptions, as specified in Schedule 2, section 3.8(b) of the Paid Applications agreement.

We were unable to find the following required information in your app's binary:

– A functional link to the Terms of Use (EULA)

– A functional link to the privacy policy

demo:

image

code:

var body: some View {
        if storeHelper.hasSubscriptionProducts, let subscriptions = storeHelper.subscriptionProducts {
            ForEach(subscriptions, id: \.id) { subscription in
                VStack {
                    Text("Upgrade to " + subscription.displayName).font(.title)
                    Text(subscription.description).font(.title2)
                    PurchaseButton(purchaseState: $purchaseState, productId: productId, price: subscription.displayPrice + " / " + period)
                }
                .padding()
                .task { await purchaseState(for: productId)}
                .onChange(of: storeHelper.purchasedProducts) { _ in
                    Task.init {
                        await purchaseState(for: productId)
                    }
                }
                .onAppear() {
                    self.productId = subscription.id
                    self.period = subscription.subscription?.subscriptionPeriod.unit.localizedDescription ?? ""
                    let periodValue = subscription.subscription?.subscriptionPeriod.value ?? 1
                    if periodValue != 1 {
                        // TODO Month to Months
                        self.period = String(periodValue) + " " + self.period
                    }
                }
            }
        }
        Text("[Terms of Service](https://www.apple.com/legal/internet-services/itunes/dev/stdeula/) and [Privacy Policy](https://example.com/)")
        Button(action: {
            Task.init {
                try? await AppStore.sync()
                purchasesRestored = true
            }
        }) {
            Text(purchasesRestored ? "Purchases Restored" : "Restore Purchases")
        }
        .padding()
        .disabled(purchasesRestored)
    }

Any support of Privacy Manifest?

Privacy Updates for AppStore submission

Expected Behavior

Developers are responsible for all code included in their apps. At WWDC23, Apple introduced new privacy manifests and signatures for commonly used third-party SDKs and announced that developers will need to declare approved reasons for using a set of APIs in their app’s privacy manifest.

Current Behavior

The library doesn't provide Privacy Manifest file

Possible Solution

The library should provide Privacy Manifest if it collects information or access "Required Reasons API"

Additional Info

Screenshot 2024-03-08 at 09 26 02

Cancellation not detected

Hi,

I'm revisiting an issue that I thought had seemed to be resolved, specifically, cancelling auto-renewable subscriptions using either XCode->Storekit->Manage Transactions or AppStore.showManageSubscriptions() from within an app. I've tested this with the StoreHelperDemo app and with my own code, and both consistently fail for me.

I'm on iOS 16.2 and the latest version of StoreHelper. While I can correctly monitor subscription status using: Product.SubscriptionInfo.Status.updates, the various transactions in StoreHelper don't seem to pick this up consistently.

What I believe needs to happen is that Status updates need to be monitored and the StoreHelper caches updated appropriately... Something along the lines of:

`for await status in Product.SubscriptionInfo.Status.updates {

            let result: VerificationResult<Product.SubscriptionInfo.RenewalInfo> = status.renewalInfo
            switch result {
                case .unverified(let unverifiedTransaction, let error):
                    print("unverified")
                
                case .verified(let verifiedTransaction):
                    let productId = verifiedTransaction.currentProductID
                    print("\(pid) verified")
            
                   if status.state == .subscribed || status.state == .inGracePeriod {
                      print("status subscribed or in grace")
                  } else if status.state == .revoked || status.state == .expired {
                     print("status cancelled")
                     updatePurchasedIdentifiers(productId, purchased: false)
                 } 
            }                

}`

Thanks.

Prepare for Swift 6.0

Swift 6.0 is expected to be released with Xcode 16 in September 2024. The swift6-support branch will be used to prepare StoreHelper for some major changes that will be required with regards to concurrency.

"Writerly" hard-coded into StoreHelper

In the Redeem an Offer section of Manage Purchases I get "Have an offer code for Writerly? Tap "Redeem an Offer" to...

This should be a configurable param rather than a string hard-coded into the package.

Missing products in production ready app

Hi, I have published my app with StoreHelper integration. During tests in dev mode, when I fetch information about the product all seem to work perfectly. Whenever I publish the app via TestFlight (so it's using the production version) the product information is not available. What am I missing here?

To mention, I have added Products.plist and Products.storekit to the bundle resources. Without this product info enabled, I can't properly display the subscription screen, which blocks me from being approved by Apple Review Team.

Should I provide a fallback screen with fixed information about the product (like price, and name) so Apple can review it and accept it? My first thoughts are that my subscription is not reviewed yet (in prod mode) that's why it's not fetched.

Appreciate any help.

Use custom colors

Is it possible to use custom colors? I see you are using predefined colors like .primary and .secondary, i will need to customize those to match the colors of my app.

Updated documentation regarding restore purchases [suggestion]

First off, thanks for this amazing project.
I'm using this project already in one app that is live at the App Store and the first build was rejected by the reviewer because I didn't had a restore purchases button. I didn't put that button because I read in the documentation that with StoreKit 2 it's not required to have that button.
Maybe you should updated the project document regarding that topic, because without a restore purchases button apps are being rejected. Also read on twitter about other people with apps rejected because of the same reason.

To restore I'm just using:
StoreKit.sync()

don't know if there's something more appropriate...

Thanks again for your work in the project!

Products not loading fast enough ..

Hiya,

I have everything pretty much working with your framework now so thanks for your hard work, and great documentation.
I haven't been able load the products as any point in the life Cycle early enough to not get a "need to refresh message" showing for a second or two. Is this normal ?
And if so , would it be possible to change the message to a ProgressView instead?
I hacked one myself :) Which is more reassuring than the nasty red message :-)

Thanks very much

James

Subscription group

Hi,

I am encountering an issue retrieving subsection info. Since I already have my app on app store, there's not way for me to adopt the subscriptions Id to the give format (com.{developer}.subscription.{subscriptionGroupName}.{productName})
Isn't there an alternative way to get the info for a subscription group?

Handling consumable example "Buy me a coffee"

Hiya,

is it possible to simply remove the restore button for a "buy me a coffee" situation ? I know this passes app review as I have done it before in UIKit with SwiftyStoreKit .

(edit : I think I understand now. I have copied the source package and made it editable)

Thanks for such. useful framework!

James

how to check subscribed on first View

I want show content or notice subscription on the App's first View, so I need check subscribed first.

but storeHelper.start() is a async function, so the storeHelper.subscriptionProductIds is empty, and can not check subscribed.

image

AppStore.showManageSubscriptions() sync issue

Hi,

When using AppStore.showManageSubscriptions() to cancel or change subscriptions, I'm not getting any subsequent Transaction updates and no change in the isPurchased() status regardless of what I do in the subscription sheet. Tested in Simulator with 16.1 and a local Product store configuration file. Any guidance would be appreciated.

Thanks.

Xcode Reports missing update task?

Xcode is reporting this warning at runtime (in Debug mode):
Sources/StoreHelper/Core/StoreHelper.swift:361 Making a purchase without listening for transaction updates risks missing successful purchases. Create a Task to iterate Transaction.updates at launch.

Can't compile on visionOS

Hey!

Will there be support here for a visionOS?

I know it's totally new, but it's really what we would need for a future, so better to start adopting now..

An issue that unconditionally returns true in shouldAddStorePayment method

/// Lets us know a user initiated an in-app purchase direct from the App Store, rather than via the app itself.
/// This method is required if you have IAP promotions.
public func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool {
        // Return true to continue the transaction. If this IAP has been previously purchased it'll be picked up
        // by StoreKit1 and re-purchase prevented
        return true
}

Hi~
I'm trying to call a custom purchase page without calling the purchase bottom sheet of the iOS.
But, since the above method is returning true, the purchase process of the system is called unconditionally.
A property that can return false is expected.

Or, it would be nice to be able to control it directly through a closure function.
Please review.
thank you.

support Xcode 14 for iOS 15

image

https://developer.apple.com/support/app-store/

now 82% iOS users is using iOS 15, I have saw StoreHelper docs:

using Xcode 14 to easily add in-app purchase support to iOS 16/macOS 13 SwiftUI apps. Xcode 13 with iOS 15/macOS 12 are also supported.

I am using Xcode 14 on macOS 13, I try to download Xcode 13, but run failed.

image

image

so I have to use Xcode 14 to develop app for iOS 15, does StoreHelper support it?

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.