1. Apple itunes connect inside purchase product information entry.
1) Create an in-app purchase item (create New) and select the type:
1. Consumable items
For consumable in-App purchases, users must purchase each time they download. Disposable services are typically consumable items, such as bait in a phishing app.
2. Non-expendable items
For non-consumable in-App purchases, users only need to purchase one time. Services that do not expire or are reduced with use are typically non-expendable items, such as the new runway of the game app.
3. Automatic subscription Renewal
By automatically renewing subscriptions, users can purchase updates and dynamic content for a specified period of time. Subscriptions (such as magazine subscriptions, etc.) are automatically renewed unless the user cancels the selection.
4. Free Subscription
With a free subscription, developers can put free subscriptions into "newspapers and magazines". When a user registers for a free subscription, the subscription will appear on all devices associated with the user's Apple ID. Please note that free subscriptions do not expire and are only available in apps that support newspaper and magazine features.
5. Non-renewal subscriptions
Non-renewing subscriptions allow for sometimes limited marketing services. Non-renewal subscriptions are required for time-limited access to items in an in-App purchase. For example, a one-week subscription to the Voice Navigation feature in the navigation app, or an online catalog of archived video or audio for an annual subscription.
Be sure to choose the right one for your application, or you will be rejected by the App Store review team. In-app tokens are consumed and fixed-time members choose to renew their subscriptions automatically. You can also only select the virtual currency to recharge their back-office purchase situation to solve the membership problem.
2) Generate shared Key
A shared key is a unique code that is used when you contact our server to obtain an in-App purchase item receipt. Without a shared key, you will not be able to test auto-renew in-App purchases in sandbox technology mode. In addition, shared keys cannot be used in the App Store.
Note: Regardless of which App is associated, all your auto-renewing subscriptions will use the same shared key.
This shared key is used by the background server to verify the credentials of the user's purchase item, and generates XINMI to the server and immediately changes the authentication key. The shared key must be required when verifying the automatic renewal subscription type project.
3) Status of in-purchase items
A) Pending Developer Approval–your in Apppurchase have been created but have not been tested in a sandbox environment anda Pproved by.
B) approved by Developer–your in Apppurchase have been tested in a sandbox environment and have been approved by you.
C) Waiting for Review–you has submittedyour in app purchase to being reviewed by Apple.
D) in Review–your on app purchase iscurrently being reviewed by Apple No edits can be made.
E) Developer Action required–in app Purchasedetail changes that you submitted has been rejected. You is required to takeaction to edit the detail information or cancel the request to change thedetail information before This in app purchase can reviewed again. (The internal purchase item Detail interface will prompt that place to have the problem, slightly modifies again to submit on the line)
F) ready for Sale–apple have approved your Inapp purchase to go live in the App Store with its associated application. Thein app purchase must is cleared for sale in ITunes Connect to is ready forsale.
G) Rejected–apple have rejected your in apppurchase during the review process. If you had not already been contacted Byapple with more information about your rejection, you may inquire through Thecont Act Us section of ITunes Connect. A rejected in app purchase cannot bereinstated. You must create a new on app purchase if you still wish for it tobe sold.
H) Developer removed from Sale–you havemarked your on app purchase as not cleared for Sale in ITunes Connect.
2.app Programming Code (code for reference only)
#pragma mark-paid in simple interest form
+ (purchasesobject*) sharepurchases
{
Static dispatch_once_t Oncetoken;
Dispatch_once (&oncetoken, ^{
if (_purchase = = nil) {
_purchase = [[Super Alloc]init];
[[Skpaymentqueue defaultqueue]addtransactionobserver:_purchase];
}
});
return _purchase;
}
+ (ID) allocwithzone: (struct _nszone *) zone
{
Static dispatch_once_t Oncetoken;
Dispatch_once (&oncetoken, ^{
if (_purchase = = nil) {
_purchase = [[Super Allocwithzone:zone]init];
}
});
return _purchase;
}
+ (ID) alloc
{
return _purchase;
}
#pragma mark-Pay diamond Members
_alter = [[Uialertview alloc]initwithtitle:@ visitor mode purchase only the rights purchased for the current device, it is recommended that you sign in to purchase Message:nil delegate:self Cancelbuttontitle : @ Cancel otherbuttontitles:@ Login Purchase (recommended), @ Visitor mode purchase, nil];
Tourist purchases are important and will be rejected by the AppStore audit team.
#pragma mark-start paying, AppStore request product information according to the product ID of the entry in the purchase item.
if ([Skpaymentqueue canmakepayments]) {
Nsset * set = [Nsset Setwitharray:@[productid]];
Skproductsrequest * request = [[Skproductsrequest alloc] initwithproductidentifiers:set];
Request.delegate = self;
[Request start];
}
Else
{
NSLog (@ no permission to purchase);
}
#pragma mark-skproductsrequestdelegate get Appstroe product information
-(void) Productsrequest: (Skproductsrequest *) Requestdidreceiveresponse: (Skproductsresponse *) Response {
self.mySelfView.userInteractionEnabled = NO;
[Aftools showhud:@ obtain product information AtView:self.mySelfView];
NSLog (@-----------received product feedback--------------);
Nsarray *myproduct = response.products;
if (Myproduct.count = = 0) {
[Aftools alertwithtitle:@ purchase Failure message:@ Unable to obtain product information];
NSLog (@ Unable to get product information, purchase failed.) );
Return
}
NSLog (@ product products==%@,myproduct);
NSLog (@ product id==%@,response.invalidproductidentifiers);
NSLog (@ Product quantity ==========%lu, (unsigned long) myproduct.count);
For (skproduct *product in myproduct) {
Skmutablepayment
NSLog (@SKProduct description information%@, [Product description]);
NSLog (@ Product title%@, Product.localizedtitle);
NSLog (@ Product description information:%@, product.localizeddescription);
NSLog (@ Price:%@, Product.price);
NSLog (@Product ID:%@, product.productidentifier);
Skmutablepayment *mpayment = [Skmutablepayment paymentwithproduct:product];
NSLog (@===%@,mpayment.requestdata);
if ([[Skpaymentqueue Defaultqueue]respondstoselector: @selector (addpayment:)]) {
[[Skpaymentqueue Defaultqueue] addpayment:mpayment];
}
Else
{
}
}
}
#pragmamark-skpaymenttransactionobserver Payment Results
-(void) Paymentqueue: (Skpaymentqueue *) Queueupdatedtransactions: (Nsarray *) transactions
{
For (Skpaymenttransaction *transaction in Transactions)
{
Switch (transaction.transactionstate)
{
Case SKPAYMENTTRANSACTIONSTATEPURCHASED://Transaction completed
NSLog (@ transaction completed transactionidentifier=%@, transaction.transactionidentifier);
[Self completetransaction:transaction];
Break
Case SKPAYMENTTRANSACTIONSTATEFAILED://Transaction failed
[Self failedtransaction:transaction];
NSLog (@ transaction failed);
Break
Case skpaymenttransactionstaterestored://has already purchased the product.
[Self restoretransaction:transaction];
NSLog (@ has bought a product);
Break
Case skpaymenttransactionstatepurchasing://product Add to List
NSLog (@ Product added into the list);
Break
Default
Break
}
}
}
-(void) Paymentqueue: (Skpaymentqueue *) Queueremovedtransactions: (Nsarray *) transactions
{
NSLog (@---------------remove-------------);
}
-(void) Paymentqueue: (Skpaymentqueue *) Queuerestorecompletedtransactionsfailedwitherror: (Nserror *) error
{
NSLog (@---------------Repeat payment failure-------------);
}
-(void) Completetransaction: (skpaymenttransaction *) Transaction {
NSLog (@-------------------payment completed--------------------);
[Self commitseverssucceewithtransaction:transaction];
}
-(void) Restoretransaction: (skpaymenttransaction *) transaction
{
NSLog (@----------------repeat payment-----------------);
[Self commitseverssucceewithtransaction:transaction];
}
-(void) Commitseverssucceewithtransaction: (skpaymenttransaction *) transaction
{
NSString * Productidentifier = transaction.payment.productIdentifier;
NSString *transactionreceiptstring= Nil;
System IOS7.0 the way to get the payment verification voucher should be changed, and the data structure returned by the cut verification is different.
if (iossystemversion>=7.0)
{
Nsurlrequest*appstorerequest = [Nsurlrequest requestwithurl:[[nsbundle Mainbundle]appstorereceipturl]];
Nserror *error = nil;
NSData * Receiptdata = [nsurlconnection sendSynchronousRequest:appstoreRequestreturningResponse:nil error:&error ];
Transactionreceiptstring = [Receiptdatabase64encodedstringwithoptions:nsdatabase64encodingendlinewithlinefeed];
}
Else
{
NSData * Receiptdata = transaction.transactionreceipt;
Transactionreceiptstring = [receiptdatabase64encodedstring];
}
Verify the proof of purchase to your own server
}
-(void) Failedtransaction: (skpaymenttransaction *) Transaction {
[[Skpaymentqueue Defaultqueue] finishtransaction:transaction];
}
It is better to key a database on the client, track the status of the order, to prevent the user order in a certain aspect of the problem can not find the order to do two times processing.
When you go to AppStore to request data, sometimes errors occur, and you can connect us in itunes Connect to write email feedback questions. But most of the time you have to wait and you can solve it. Maybe he'll be fine that day.
3. Background Server Authentication
There are two modes of payment in IOS:
1) built-in mode
2) Server Mode
The process of built-in mode can be summarized in the following steps simply:
1) app to get product information from App Store
2) The user chooses the product which needs to purchase
3) app send payment request to App Store
4) The App store handles payment requests and returns transaction information
5) The app will show the content of the purchase to the user
The main process for server mode is as follows:
1) The app gets a list of product identities from the server
2) app to get product information from App Store
3) The user chooses the product which needs to purchase
4) app send payment request to App Store
5) The App store handles payment requests and returns transaction information
6) The app sends transaction receipt to the server
7) The server receives the receipt and sends it to the app Stroe to verify the validity of the receipt
8) The App Store returns the verification result of the receipt
9) based on the results returned by the App Store, determines whether the user purchased the success
The difference between the above two modes is mainly: Receipt verification of transactions, built-in model does not specifically verify the transaction receipts, and the server mode will use a separate server to verify the transaction receipts. Built-in mode is simple and quick, but easy to crack. The server mode process is relatively complex, but relatively secure.
At the beginning of the development, Apple was responsible for informing us that our servers were not stable. After the real development, Apple was found to be responsible, not only unstable, but slow enough. App Store server verifies that a receipt takes 3-6s time.
1. Can the user endure 3-6s waiting time
2. If the App Store server goes down, how to ensure that users who have paid successfully will get regular service.
For the first question, we have reason to believe that the user is completely unbearable, so in the way of asynchronous authentication, the server receives the request from the client and puts the request into MCQ.
For the second issue, because the Apple staff is very responsible for the notification: Our server is not stable, so do not exclude the receipt verification timeout situation. For receipts that validate timeouts, are saved to the database and marked as a validation timeout, timed tasks go to the app store at regular intervals to verify the results of receipt validation.
In the development process, it is necessary to test whether the application will be able to make a normal payment, but cannot make a real payment, so it needs to use the sandbox store test provided by Apple. The store kit cannot be used in the iOS emulator, and the test store must be on the real machine.
Verify the receipt in the sandbox
Https://sandbox.itunes.apple.com/verifyReceipt
Validating receipt in a production environment
Https://buy.itunes.apple.com/verifyReceipt
During the actual development process, the server side through the Issandbox field identifies whether the receipt passed by the client is a receipt in the sandbox environment or a receipt in the production environment. There is no problem with sandbox testing until the Apple review is submitted. After submitting the Apple audit, was told the purchase failed, the audit did not pass. The query log found that the transaction receipt sent by the client was a sandbox receipt, but the Issandbox field was identified as a production environment.
Conclusion: When Apple reviews the app, it still tests in a sandbox environment. However, the client colleague writes the Issandbox field to the production environment when the app submits an Apple audit. This causes the sandbox receipts to be sent to Https://buy.itunes.apple.com/verifyReceipt to verify.
So how to automatically identify whether the receipt is a sandbox receipt it?
There are two ways to identify receipts in a sandbox environment:
1. According to the receipt field environment = sandbox.
2. Verify the status code returned by the interface according to the receipt
If status=21007, the current receipt is the receipt for the sandbox environment, and T is verified.
Status code for Apple feedback;
21000APP Store cannot read the JSON data you provide
21002 The receipt data does not conform to the format
21003 receipts cannot be verified
21004 the shared key you provided is inconsistent with the shared key of the account
21005 the receipt server is not currently available
21006 the receipt is valid, but the subscription service has expired. When this message is received, the decoded receipt information is also included in the returned content
21007 Receipt information is test (sandbox), but is sent to the product environment to verify
21008 The receipt information is used in the product environment but is sent to the test environment to verify
Production verification after the test verification, you can avoid the trouble of switching interfaces back and forth. Test validation will only be used if you use your own test AppID, the user will not have the test AppID, so will not go to the test to verify this step. Even if a production validation error occurs, you should not return the 21007 status again. Test verification through the user name, and the top-up amount of the best use of database records, convenient company funds check.
iOS in-app payment (IAP) Development steps