Search code examples
iosswiftdatetimein-app-purchasestorekit

Swift: How to convert Date() to timezone of Apple's server to validate receipt?


Using Swift 3

When I call this code it shows as my timezone

let date = Date()
let todayDate = formatter.string(from: date)
print(todayDate)

I called the JSON response from the StoreKit receipt to check the original_purchase_date and expires_date to compare it to todayDate to validate the receipt.

What I want to do, for example

if (todayDate > expires_date ) {
    cancel subscription
}

I can't match the dates if Apple's purchase_date and expires_date are in GMT timezone while todayDate is in whatever timezone the user is in.

So I just need to convert whatever timezone the user is in when Date() is called and convert it to GMT like Apple's server so I can check if todayDate has passed the expired data on the Auto renewable subscription.

Also, is this a good approach to prevent from in app hacks? I got the receipt from my server using php which validates it from Apple.

if parseJSON["status"] as? Int == 0 {

print("Status Code for Receipt = 0!")

// Checking "latest_receipt_info"
if let receiptInfo: NSArray = parseJSON["latest_receipt_info"] as? NSArray {
    let lastReceipt = receiptInfo.lastObject as! NSDictionary

    // Get last receipt
    print("\nLAST RECEIPT INFORMATION: \n", lastReceipt)

    // Format date
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss VV"
    formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") as Locale!

    // Get "original_purchase_date" as NSDate
    let subscriptionBoughtDate: NSDate = formatter.date(from: lastReceipt["original_purchase_date"] as! String) as NSDate!
    print("\n   - DATE BOUGHT SUBSCRIPTION = \(subscriptionBoughtDate)\n")

    // Get "expires_date" as NSDate
    let subscriptionExpirationDate: NSDate = formatter.date(from: lastReceipt["expires_date"] as! String) as NSDate!
    print("\n   - DATE SUBSCRIPTION EXPIRES = \(subscriptionExpirationDate)\n")

    // Get Todays Date
    let date = Date()
    let todayDate = formatter.string(from: date)
    print("\n   - DATE TODAY = \(todayDate)\n")

    // See if current date has passed expired date
}

JSON response

LAST RECEIPT INFORMATION: 
{
"expires_date" = "2017-08-03 04:50:08 Etc/GMT";
"expires_date_ms" = 1501735808000;
"expires_date_pst" = "2017-08-02 21:50:08 America/Los_Angeles";
"is_trial_period" = false;
"original_purchase_date" = "2017-08-02 15:27:27 Etc/GMT";
"original_purchase_date_ms" = 1501687647000;
"original_purchase_date_pst" = "2017-08-02 08:27:27 America/Los_Angeles";
"original_transaction_id" = 1000000552288255;
"product_id" = "com.example.gg.month";
"purchase_date" = "2017-08-03 04:45:08 Etc/GMT";
"purchase_date_ms" = 1501735508000;
"purchase_date_pst" = "2017-08-02 21:45:08 America/Los_Angeles";
quantity = 1;
"transaction_id" = 1000000568853433;
"web_order_line_item_id" = 1000000055887122;
}

- DATE BOUGHT SUBSCRIPTION = 2017-08-02 15:27:27 +0000


- DATE SUBSCRIPTION EXPIRES = 2017-08-03 04:50:08 +0000


- DATE TODAY = 2017-08-04 17:26:51 America/New_York

Thank you!


Solution

  • You just have to set up the TimeZone property of your DateFormatter to GMT.

    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss VV"
    formatter.timeZone = TimeZone(secondsFromGMT: 0)
    

    A general advice: don't use Foundation types in Swift when native Swift alternatives are available, such as Array, Dictionary, Locale and Date. Use these instead of NSArray, NSDictionary, NSLocale and NSDate.