OS——內購支付詳解程式碼部分(二)
阿新 • • 發佈:2018-12-21
一、程式碼及業務邏輯
業務邏輯
1. 獲取內購列表(從App內讀取或從自己伺服器讀取)
2. App Store請求可用的內購列表
3. 向用戶展示內購列表
4. 使用者選擇了內購列表,再發個購買請求,收到購買完成的回撥(購買完成後會把錢打給申請內購的銀行卡內)
5. 購買流程結束後, 向伺服器發起驗證憑證以及支付結果的請求
6. 自己的伺服器將支付結果資訊返回給前端併發放虛擬產品
7. 服務端的工作比較簡單,分4步:
1. 接收ios端發過來的購買憑證。
2. 判斷憑證是否已經存在或驗證過,然後儲存該憑證。
3. 將該憑證傳送到蘋果的伺服器驗證,並將驗證結果返回給客戶端。
4. 如果需要,修改使用者相應的會員許可權。
8. 考慮到網路異常情況,伺服器的驗證應該是一個可恢復的佇列,如果網路失敗了,應該進行重試。 簡單來說就是將該購買憑證用Base64編碼,然後POST給蘋果的驗證伺服器,蘋果將驗證結果以JSON形式返回。
程式碼如下 :
/*注意事項:
1.沙盒環境測試appStore內購流程的時候,請使用沒越獄的裝置。
2.請務必使用真機來測試,一切以真機為準。
3.專案的Bundle identifier需要與您申請AppID時填寫的bundleID一致,不然會無法請求到商品資訊。
4.如果是你自己的裝置上已經綁定了自己的AppleID賬號請先登出掉,否則你哭爹喊娘都不知道是怎麼回事。
5.訂單校驗 蘋果稽核app時,仍然在沙盒環境下測試,所以需要先進行正式環境驗證,如果發現是沙盒環境則轉到沙盒驗證。
識別沙盒環境訂單方法:
1.根據欄位 environment = sandbox。
2.根據驗證介面返回的狀態碼,如果status=21007,則表示當前為沙盒環境。
蘋果反饋的狀態碼:
21000App Store無法讀取你提供的JSON資料
21002 訂單資料不符合格式
21003 訂單無法被驗證
21004 你提供的共享金鑰和賬戶的共享金鑰不一致
21005 訂單伺服器當前不可用
21006 訂單是有效的,但訂閱服務已經過期。當收到這個資訊時,解碼後的收據資訊也包含在返回內容中
21007 訂單資訊是測試用(sandbox),但卻被髮送到產品環境中驗證
21008 訂單資訊是產品環境中使用,但卻被髮送到測試環境中驗證
*/
#import <Foundation/Foundation.h>
typedef enum {
SIAPPurchSuccess = 0, // 購買成功
SIAPPurchFailed = 1, // 購買失敗
SIAPPurchCancle = 2, // 取消購買
SIAPPurchVerFailed = 3, // 訂單校驗失敗
SIAPPurchVerSuccess = 4, // 訂單校驗成功
SIAPPurchNotArrow = 5, // 不允許內購
}SIAPPurchType;
typedef void (^IAPCompletionHandle)(SIAPPurchType type,NSData *data);
@interface STRIAPManager : NSObject
+ (instancetype)shareSIAPManager;
//開始內購
- (void)startPurchWithID:(NSString *)purchID completeHandle:(IAPCompletionHandle)handle;
@end
.m
#import "STRIAPManager.h"
#import <StoreKit/StoreKit.h>
@interface STRIAPManager()<SKPaymentTransactionObserver,SKProductsRequestDelegate>{
NSString *_purchID;
IAPCompletionHandle _handle;
}
@end
@implementation STRIAPManager
#pragma mark - ♻️life cycle
+ (instancetype)shareSIAPManager{
static STRIAPManager *IAPManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
IAPManager = [[STRIAPManager alloc] init];
});
return IAPManager;
}
- (instancetype)init{
self = [super init];
if (self) {
// 購買監聽寫在程式入口,程式掛起時移除監聽,這樣如果有未完成的訂單將會自動執行並回調 paymentQueue:updatedTransactions:方法
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
return self;
}
- (void)dealloc{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
#pragma mark -