iOS內(nèi)購全面實戰(zhàn)

內(nèi)購是啥

App 內(nèi)購買項目允許顧客通過訪問 App Store 購買您 App 中的內(nèi)容、功能或服務(wù),并安全處理來自用戶的付款癌淮。

詳情傳送門https://help.apple.com/itunes-connect/developer/#/devb57be10e7

下面來說內(nèi)購集成流程

1.協(xié)議

登錄蘋果開發(fā)者中心翰撑,進入iTunes Connect,再進入“協(xié)議无虚、稅務(wù)和銀行業(yè)務(wù)”頁面,如圖

image

點擊進入可以看到,目前共有兩個分組衍锚,三種合同友题。(此處有坑,比如我們當前賬號不能申請合同戴质!如下圖)

Request Contracts 可以申請的合同度宦;

Contracts In Effect 已經(jīng)生效的合同。

三種合同分別是

Free Applications 免費應(yīng)用(默認已經(jīng)生效)告匠;

Paid Applications 付費應(yīng)用戈抄,需要申請;

iAd App Network 廣告應(yīng)用后专,需要申請划鸽。

image

內(nèi)購對應(yīng)的是Paid Applications 付費應(yīng)用,需要申請,如圖2.(如果Request按鈕不顯示,則說明當前賬號權(quán)限有問題)

點擊Request完善信息,提交就行.

2.內(nèi)購集成

內(nèi)購實現(xiàn)流程:

1.客戶端向Appstore請求購買產(chǎn)品(假設(shè)產(chǎn)品信息已經(jīng)取得)戚哎,Appstore驗證產(chǎn)品成功后裸诽,從用戶的Apple賬戶余額中扣費。

2.Appstore向客戶端返回一段receipt-data型凳,里面記錄了本次交易的證書和簽名信息丈冬。

3.客戶端向我們可以信任的服務(wù)器提供receipt-data

4.服務(wù)器對receipt-data進行一次base64編碼

5.把編碼后的receipt-data發(fā)往itunes.appstore進行驗證

6.itunes.appstore返回驗證結(jié)果給服務(wù)器

7.服務(wù)器對商品購買狀態(tài)以及商品類型,向客戶端發(fā)放相應(yīng)的道具與推送數(shù)據(jù)更新通知

注,下圖3步驟和上面流程不是一一對應(yīng)

image

我項目里面的購買流程,加入了一點業(yè)務(wù)邏輯和后臺驗證流程,有什么問題歡迎大家指出.

image

3.去蘋果開發(fā)者中心創(chuàng)建內(nèi)購商品

如下圖5,點擊+號去創(chuàng)建內(nèi)購商品,產(chǎn)品id最好是當前應(yīng)用+數(shù)字,價格區(qū)間蘋果提供了一張表,商品價格只能是表上的價格,蘋果會抽取30%,商家能收到的錢是用戶充值的70%.這就造成了部分平臺區(qū)分安卓和蘋果.兩端賬號不互通,也造就了代充行業(yè),再次就不展開說了.

商品價格大于100$,提交審核的時候要說明這個金額是確認過的,不然可能會被拒

image

4.代碼集成

建議單獨建一個類來處理內(nèi)購業(yè)務(wù)
.h類

//
//  EMAppStorePay.h
//  MobileFixCar
//
//  Created by Wcting on 2018/4/11.
//  Copyright ? 2018年 XXX有限公司. All rights reserved.
//

/*
 wct20180917 內(nèi)購支付類甘畅,短視頻e豆購買用到埂蕊。
 */

#import <Foundation/Foundation.h>

@class EMAppStorePay;

@protocol EMAppStorePayDelegate <NSObject>;

@optional

/**
 wct20180418 內(nèi)購支付成功回調(diào)

 @param appStorePay 當前類
 @param dicValue 返回值
 @param error 錯誤信息
 */
- (void)EMAppStorePay:(EMAppStorePay *)appStorePay responseAppStorePaySuccess:(NSDictionary *)dicValue error:(NSError*)error;


/**
 wct20180423 內(nèi)購支付結(jié)果回調(diào)提示
 
 @param appStorePay 當前類
 @param dicValue 返回值
 @param error 錯誤信息
 */
- (void)EMAppStorePay:(EMAppStorePay *)appStorePay responseAppStorePayStatusshow:(NSDictionary *)dicValue error:(NSError*)error;

@end

@interface EMAppStorePay : NSObject

@property (nonatomic, weak)id<EMAppStorePayDelegate> delegate;/**<wct20180418 delegate*/


/**
  wct20180411 點擊購買

 @param goodsID 商品id
 */
-(void)starBuyToAppStore:(NSString *)goodsID;

@end

.m類(里面有客戶端驗證receipt的代碼,解開注釋就可以,用于調(diào)試.驗證建議放后臺去做)

//
//  EMAppStorePay.m
//  MobileFixCar
//
//  Created by Wcting on 2018/4/11.
//  Copyright ? 2018年 XXX有限公司. All rights reserved.
//

#import "EMAppStorePay.h"
#import <StoreKit/StoreKit.h>

//#define goods1 @"net.ejiajx.MobileFixCar06"

@interface EMAppStorePay()<SKPaymentTransactionObserver,SKProductsRequestDelegate>

@property (nonatomic, strong)NSString *goodsId;/**<wct20180420  商品id*/

@end

@implementation EMAppStorePay

- (instancetype)init
{
    self = [super init];
    if (self) {
       
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];// 4.設(shè)置支付服務(wù)
    }
    return self;
}
//結(jié)束后一定要銷毀
- (void)dealloc
{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
#pragma mark - public
-(void)starBuyToAppStore:(NSString *)goodsID
{
    if ([SKPaymentQueue canMakePayments]) {//5.判斷app是否允許apple支付
      
        [self getRequestAppleProduct:goodsID];// 6.請求蘋果后臺商品
        
    } else {
//        NSLog(@"not");
    }
}

#pragma mark - private
#pragma mark ------ 請求蘋果商品
- (void)getRequestAppleProduct:(NSString *)goodsID
{
    self.goodsId = goodsID;//把前面?zhèn)鬟^來的商品id記錄一下往弓,下面要用
    // 7.這里的com.czchat.CZChat01就對應(yīng)著蘋果后臺的商品ID,他們是通過這個ID進行聯(lián)系的。
    NSArray *product = [[NSArray alloc] initWithObjects:goodsID,nil];
    NSSet *nsset = [NSSet setWithArray:product];
    
    //SKProductsRequest參考鏈接:https://developer.apple.com/documentation/storekit/skproductsrequest
    //SKProductsRequest 一個對象蓄氧,可以從App Store檢索有關(guān)指定產(chǎn)品列表的本地化信息函似。
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];// 8.初始化請求
    request.delegate = self;
    [request start];// 9.開始請求
}
#pragma mark ------ 支付完成
- (void)completeTransaction:(SKPaymentTransaction *)transaction{
    //交易驗證 本地驗證方法
    /*NSURL *recepitURL = [[NSBundle mainBundle] appStoreReceiptURL];
     NSData *receipt = [NSData dataWithContentsOfURL:recepitURL];
     
     if(!receipt){
     
     }
     
     NSError *error;
     NSDictionary *requestContents = @{
     @"receipt-data": [receipt base64EncodedStringWithOptions:0]
     };
     NSLog(@"requestContentstr:%@",[receipt base64EncodedStringWithOptions:0]);
     NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
     options:0
     error:&error];
     
     
     //In the test environment, use https://sandbox.itunes.apple.com/verifyReceipt
     //In the real environment, use https://buy.itunes.apple.com/verifyReceipt
     // Create a POST request with the receipt data.
     NSURL *storeURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];
     NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
     [storeRequest setHTTPMethod:@"POST"];
     [storeRequest setHTTPBody:requestData];
     
     // Make a connection to the iTunes Store on a background queue.
     NSOperationQueue *queue = [[NSOperationQueue alloc] init];
     [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
     completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
     if (connectionError) {
     } else {
     NSError *error;
     NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
     if (!jsonResponse) {  }
     //Parse the Response
     NSLog(@"成功了:%@",jsonResponse);
     }
     }];*/
    
    //此時告訴后臺交易成功,并把receipt傳給后臺驗證
    NSString *transactionReceiptString= nil;
    //系統(tǒng)IOS7.0以上獲取支付驗證憑證的方式應(yīng)該改變匀们,切驗證返回的數(shù)據(jù)結(jié)構(gòu)也不一樣了缴淋。
    // 驗證憑據(jù)准给,獲取到蘋果返回的交易憑據(jù)
    // appStoreReceiptURL iOS7.0增加的泄朴,購買交易完成后,會將憑據(jù)存放在該地址
    NSURLRequest *appstoreRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] appStoreReceiptURL]];
    NSError *error = nil;
    // 從沙盒中獲取到購買憑據(jù)
    
    NSData * receiptData = [NSURLConnection sendSynchronousRequest:appstoreRequest returningResponse:nil error:&error];
    // 20 BASE64 常用的編碼方案露氮,通常用于數(shù)據(jù)傳輸祖灰,以及加密算法的基礎(chǔ)算法,傳輸過程中能夠保證數(shù)據(jù)傳輸?shù)姆€(wěn)定性 21 BASE64是可以編碼和解碼的 22
    transactionReceiptString = [receiptData base64EncodedStringWithOptions:0];//[receiptData base64EncodedStringWithOptions:0];
    //    NSLog(@"requestContentstr:%@",[receiptData base64EncodedStringWithOptions:0]);
    
    //    NSDictionary *dic = @{@"orderCode":self.dataOrder.orderCode,
    //                          @"receipt":transactionReceiptString,
    //                          @"category":@"1"
    //                          };
    //    NSLog(@"diczhi:%@",dic);
    //
    //    self.tran = transaction;
    //    [self.bizEBeanBuy requestAppStorePaySuccessCallBack:dic];//蘋果支付成功畔规,傳receipt-data給后臺驗證
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(EMAppStorePay:responseAppStorePaySuccess:error:)]) {
        [self.delegate EMAppStorePay:self responseAppStorePaySuccess:@{@"value":transactionReceiptString} error:nil];
    }
    
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    
}

#pragma mark - delegate
#pragma mark ------ SKProductsRequestDelegate
// 10.接收到產(chǎn)品的返回信息,然后用返回的商品信息進行發(fā)起購買請求
- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    NSArray *product = response.products;
    
    if([product count] == 0){//如果服務(wù)器沒有產(chǎn)品
        return;
    }
    
    SKProduct *requestProduct = nil;
    for (SKProduct *pro in product) {
//        NSLog(@"%@", [pro description]);
//        NSLog(@"%@", [pro localizedTitle]);
//        NSLog(@"%@", [pro localizedDescription]);
//        NSLog(@"%@", [pro price]);
//        NSLog(@"%@", [pro productIdentifier]);
        // 11.如果后臺消費條目的ID與我這里需要請求的一樣(用于確保訂單的正確性)
        if([pro.productIdentifier isEqualToString:self.goodsId]){
            requestProduct = pro;
        }
    }
    // 12.發(fā)送購買請求局扶,創(chuàng)建票據(jù)  這個時候就會有彈框了
    SKPayment *payment = [SKPayment paymentWithProduct:requestProduct];
    [[SKPaymentQueue defaultQueue] addPayment:payment];//將票據(jù)加入到交易隊列
    
}
#pragma mark ------ SKRequestDelegate (@protocol SKProductsRequestDelegate <SKRequestDelegate>)
//請求失敗
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
//    NSLog(@"error:%@", error);
}
//反饋請求的產(chǎn)品信息結(jié)束后
- (void)requestDidFinish:(SKRequest *)request
{
//    NSLog(@"信息反饋結(jié)束");
}

    
#pragma mark ------ SKPaymentTransactionObserver 監(jiān)聽購買結(jié)果
// 13.監(jiān)聽購買結(jié)果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction
{

    if (self.delegate && [self.delegate respondsToSelector:@selector(EMAppStorePay:responseAppStorePayStatusshow:error:)]) {
        [self.delegate EMAppStorePay:self responseAppStorePayStatusshow:@{@"value":transaction} error:nil];
    }
    
//    if (transaction.count > 0) {
//        //檢測是否有未完成的交易
//        SKPaymentTransaction* tran = [transaction firstObject];
//        if (tran.transactionState == SKPaymentTransactionStatePurchased) {
//            [self completeTransaction:tran];
//            [[SKPaymentQueue defaultQueue] finishTransaction:tran];//未完成的交易在此給它結(jié)束
//            return;
//        }
//    }

    for(SKPaymentTransaction *tran in transaction){

//        NSLog(@"%@",tran.payment.applicationUsername);
        switch (tran.transactionState) {
            case SKPaymentTransactionStatePurchased:{
//                NSLog(@"交易完成");
                // 購買后告訴交易隊列,把這個成功的交易移除掉叁扫。
                //走到這就說明這單交易走完了三妈,無論成功失敗,所以要給它移出莫绣。finishTransaction
                [self completeTransaction:tran];//這兒出了問題拋異常畴蒲,導(dǎo)致下面一句代碼沒執(zhí)行
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                
            }
                break;
                
            case SKPaymentTransactionStatePurchasing:
//                NSLog(@"商品添加進列表");
                break;
                
            case SKPaymentTransactionStateRestored:
//                NSLog(@"已經(jīng)購買過商品");
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                break;
                
            case SKPaymentTransactionStateFailed:
//                NSLog(@"交易失敗");
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                break;
                
            case SKPaymentTransactionStateDeferred:
//                NSLog(@"交易還在隊列里面,但最終狀態(tài)還沒有決定");
                break;
                
            default:
                break;
        }
        
    }

    
}

@end

5.沙盒測試

如下圖6,點添加創(chuàng)建沙盒測試賬號,賬號未未注冊成AppleID的賬號,測試前先到設(shè)置里退出當前AppleID,登錄沙盒測試賬號,沙盒測試賬號只能用來測試沙盒支付,不具備正常AppleID的功能.

image
準備工作

1.第一次測試內(nèi)購需要卸載之前APP对室,找開發(fā)人員安裝可測試內(nèi)購的APP模燥。防止App Store下載的app走sandbox環(huán)境走不通;
2.在iPhone設(shè)置里面掩宜,退出原有賬號蔫骂。登錄開發(fā)人員提供的內(nèi)購測試賬號(可找開發(fā)申請新測試賬號);

6.交易安全機制

1.雙重驗證

蘋果審核人員審核內(nèi)購的時候走的是沙盒環(huán)境對應(yīng)沙盒驗證接口https://sandbox.itunes.apple.com/verifyReceipt,如果驗證receipt只有正式環(huán)境https://buy.itunes.apple.com/verifyReceipt,蘋果審核員走內(nèi)購會驗證失敗,交易走不通,后果就是審核被拒.所以驗證的時候先默認走正式環(huán)境,如果返回21007的錯誤碼就去沙盒環(huán)境驗證,保證審核通過.

2.交易憑據(jù)receipt判重

一般我們驗證支付憑據(jù)(receipt)是否有效放后臺去做,如果后臺不做判重,同一個憑據(jù)就可以無數(shù)次驗證通過(蘋果也不判重),后臺就會給前端發(fā)放無數(shù)次商品,但是用戶只支付了一次錢取到一個支付憑據(jù).所以安全的做法是后臺把驗證通過的支付憑據(jù)做個記錄,每次來新的憑據(jù)先判斷是否已經(jīng)使用過,防止多次發(fā)放商品.

3.本地交易流水

在測試過程中,由于蘋果不提供交易流水,所以會出現(xiàn)無法對賬的情況,會提出一些莫名bug,因為測試不知道某個單的支付狀態(tài),這時前端需要做個交易流水記錄,方便對賬和避免不必要的bug及撕逼.

在支付成功回調(diào)里面把當前交易數(shù)據(jù)存在本地持久化,然后去后臺驗證,出問題就那本地存的交易數(shù)據(jù)和后臺對,找出問題.

#pragma mark - EMAppStorePayDelegate
-(void)EMAppStorePay:(EMAppStorePay *)appStorePay responseAppStorePaySuccess:(NSDictionary *)dicValue error:(NSError *)error
{
   
    NSString *transactionReceiptString = [ZSTools objectOrNilForKey:@"value" fromDictionary:dicValue];
    
    NSDictionary *dic = @{@"orderCode":self.strOrderCode,
                          @"receipt":transactionReceiptString,
                          @"category":@"1"
                          };
//    NSLog(@"222diczhi:%@",dic);
    
    /*
     //wct20180601 本地交易流水牺汤,不測試內(nèi)購就給注釋吧辽旋,省手機內(nèi)存
    NSMutableDictionary *dicRec = [NSMutableDictionary dictionaryWithDictionary:self.dicPay];
    [dicRec setValue:self.strOrderCode forKey:@"orderCode"];
    [dicRec setValue:transactionReceiptString forKey:@"receipt"];
    [dicRec setValue:@"1" forKey:@"category"];
    NSString *time = [self getCurrentTimes];
    [dicRec setValue:time forKey:@"creatTime"];

    [self.modelEBean addDicReconciliation:dicRec];//對應(yīng)下面的實現(xiàn)方法
*/
    
    [self.bizEBeanBuy requestAppStorePaySuccessCallBack:dic];//蘋果支付成功,傳receipt-data給后臺驗證
    [ZSTools loadActivityIndicatorOn:self.view withCenterPoint:self.view.center withTitleString:@"正在購買..." sizeType:2];

}

存儲持久化實現(xiàn)

-(void)addDicReconciliation:(NSDictionary *)dicEBean
{
    if (![self.arrReconciliationModel containsObject:dicEBean]) {
        [self.arrReconciliationModel addObject:dicEBean];
    }
    [self saveReconciliation];
}

- (void)saveReconciliation
{
    NSString *path = [NSString stringWithFormat:@"%@/%@_reconciliation.plist", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0], [EMVideoUserSingleton sharedInstance].ugsvId];
    [self.arrReconciliationModel writeToFile:path atomically:NO];
}

7.注意事項

1.對賬問題

通過textflight下載的app走內(nèi)購也是在sandbox環(huán)境檐迟。這時走內(nèi)購不需要支付相應(yīng)金額补胚,但是對應(yīng)的咱們后臺是正式環(huán)境,內(nèi)購走通后返回的e豆(商品,以下e豆都對應(yīng)商品)是正式環(huán)境锅减。這就會造成沒支付錢糖儡,但是正式環(huán)境得到e豆了,對賬的時候要作記錄怔匣。

2.漏單的情況:

先看看支付流程握联,如下:
app iTunes app 后臺 app
1發(fā)起支付--->2扣費成功--->3得到receipt(支付憑據(jù))--->4去后臺驗證憑據(jù)獲取e豆--->5返回數(shù)據(jù)桦沉,前端刷新數(shù)據(jù)

漏單情況1

3到4的時候出問題,比如斷網(wǎng)金闽。此時前端會把支付憑據(jù)持久化存儲下來(期間用戶卸載APP此單在前端就真漏了)纯露,下次進入購買頁會先判斷有無未成功的支付,有就提示用戶代芜,用戶選擇找回埠褪,重走4,5流程挤庇。

漏單情況2

4到5的時候出問題钞速。此時后臺其實已經(jīng)成功,只是前端沒獲取到數(shù)據(jù)嫡秕,當漏單處理渴语,還是上面的邏輯,會把該單存儲昆咽。下次進入的時候會先刷新數(shù)據(jù)(此時未獲取到e的豆已經(jīng)獲取到了)驾凶,然后提示有未完成單,此時點找回會提示無效的憑據(jù)掷酗,這是正常的调违,因為豆已經(jīng)給了,此單已結(jié)束泻轰。

漏單情況3

2到3環(huán)節(jié)出問題屬于蘋果的問題技肩,目前沒做處理。

3.漏單處理

1.在后臺返回商品支付回調(diào)失敗里面把當前交易數(shù)據(jù)持久化存儲,成功狀態(tài)下移除當前單數(shù)據(jù).并檢查是否有已扣款未返商品單,對應(yīng)下面checkHaveDidNotPay

}else{
        if (dicPara) {
            [self.modelEBean addDicEBean:dicPara];//傳receipt失敗糕殉,
            [self checkHaveDidNotPay];
        }
- (void)checkHaveDidNotPay
{
    if (self.modelEBean.arrEBeanBuyModel.count) {
        [EMTextAlertView title:@"溫馨提示" message:@"網(wǎng)絡(luò)不給力亩鬼,e豆數(shù)據(jù)可能更新不及時,請重新加載阿蝶。" leftTitle:@"下次再說" rightTitle:@"重新加載" complete:^(NSInteger index, NSString *title) {

            if (index == 1){//重新獲取會重新調(diào)用購買驗證
                for (NSDictionary *dic in self.modelEBean.arrEBeanBuyModel) {
                    [self.bizEBeanBuy requestAppStorePaySuccessCallBack:dic];
                }
            }
            
        }];
    }
}

根據(jù)需求,每次購買前先檢查有無之前漏單,有先處理漏單.視需求定.
我們目前是每次到購買頁面先檢查有無漏單

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.bizVideoMine requestVideoMineData:nil];
    [self checkHaveDidNotPay];

}

有問題下面留言,有不足的地方歡迎指正.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末雳锋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子羡洁,更是在濱河造成了極大的恐慌玷过,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件筑煮,死亡現(xiàn)場離奇詭異辛蚊,居然都是意外死亡,警方通過查閱死者的電腦和手機真仲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門袋马,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人秸应,你說我怎么就攤上這事虑凛”纾” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵桑谍,是天一觀的道長延柠。 經(jīng)常有香客問我,道長锣披,這世上最難降的妖魔是什么贞间? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮雹仿,結(jié)果婚禮上增热,老公的妹妹穿的比我還像新娘。我一直安慰自己盅粪,他們只是感情好钓葫,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布悄蕾。 她就那樣靜靜地躺著票顾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪帆调。 梳的紋絲不亂的頭發(fā)上奠骄,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音番刊,去河邊找鬼含鳞。 笑死,一個胖子當著我的面吹牛芹务,可吹牛的內(nèi)容都是我干的蝉绷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼枣抱,長吁一口氣:“原來是場噩夢啊……” “哼熔吗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起佳晶,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤桅狠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后轿秧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體中跌,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年菇篡,在試婚紗的時候發(fā)現(xiàn)自己被綠了漩符。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡驱还,死狀恐怖嗜暴,靈堂內(nèi)的尸體忽然破棺而出津滞,到底是詐尸還是另有隱情,我是刑警寧澤灼伤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布触徐,位于F島的核電站,受9級特大地震影響狐赡,放射性物質(zhì)發(fā)生泄漏撞鹉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一颖侄、第九天 我趴在偏房一處隱蔽的房頂上張望鸟雏。 院中可真熱鬧,春花似錦览祖、人聲如沸孝鹊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽又活。三九已至,卻和暖如春锰悼,著一層夾襖步出監(jiān)牢的瞬間柳骄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工箕般, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留耐薯,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓丝里,卻偏偏與公主長得像曲初,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子杯聚,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353