iOS iap receipt 服务器校验

import json
import requests

SAND_BOX_VERIFY_URL = 'https://sandbox.itunes.apple.com/verifyReceipt'
VERIFY_URL = 'https://buy.itunes.apple.com/verifyReceipt'

#  /**
#          * 服务器二次验证代码
#          * 21000 App Store不能读取你提供的JSON对象
#          * 21002 receipt-data域的数据有问题
#          * 21003 receipt无法通过验证
#          * 21004 提供的shared secret不匹配你账号中的shared secret
#          * 21005 receipt服务器当前不可用
#          * 21006 receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送
#          * 21007 receipt是Sandbox receipt,但却发送至生产系统的验证服务
#          * 21008 receipt是生产receipt,但却发送至Sandbox环境的验证服务
#          */


def verify_receipt_with_apple(receipt, is_sandbox=False):
    jsonStr = json.dumps({"receipt-data": receipt})

    headers = {'Content-Type': 'application/json'}
    url = VERIFY_URL
    if is_sandbox:
        url = SAND_BOX_VERIFY_URL
    rep = requests.post(url=url, data=jsonStr, headers=headers)
    # print(rep.text)
    return rep.text


def verify_receipt_with_apple_json(receipt, is_sandbox=False):
    resp = verify_receipt_with_apple(receipt, is_sandbox)
    try:
        json_data = json.loads(resp)
    except:
        return None
    return json_data

if __name__ == "__main__":
    receipt = "MIITrQYJKoZIhvcNAQcCoIITnjCCE5oCAQExCzAJBgUrDgMCGg"

    js = verify_receipt_with_apple_json(recpt, True)

    print(js['receipt'])

    print(js['receipt']['in_app'])
    print(js['receipt']['in_app'][0])

服务器的校验代码相对来说并没有什么比较复杂的内容,但是返回的数据确比较让人抑郁。苹果的服务器返回的的receipt并不包含任何的用户信息,也不会包含购买的物品信息。于是要想知道买的什么东西就比较麻烦。

其实服务器在进行数据校验的时候最好一起把transactionID一起发送带服务器进行校验处理。因为苹果的验证服务器会返回多个收据信息,在in-app中包含的数据并没有按照时间或者特定的顺序进行排列,所以从其他地方看到的直接获取最后的一条in-app信息来获取购买的数据是存在问题的。可以通过in-app中的transactionID字段来获取最后买的数据。

例如,客户端在完成购买之后获取的信息为:

{
	"transactionID": "1000000625912120",
	"currencyCode": "CNY",
	"receiptCipheredPayload": "MIITtAYJKWc=",
	"title": "小袋",
	"receipt": "",
	"price": "¥6.00",
	"id": "test01",
	"priceValue": 6,
	"description": "小袋,用于应用内的审核",
	"name": "small_one"
}

在校验之后返回的数据同样可以拿到包含这个字段的in-app数据。

{
	'receipt': {
		'receipt_type': 'ProductionSandbox',
		'adam_id': 0,
		'app_item_id': 0,
		'bundle_id': 'obaby.mars.game',
		'application_version': '1.0',
		'download_id': 0,
		'version_external_identifier': 0,
		'receipt_creation_date': '2020-02-17 08:43:26 Etc/GMT',
		'receipt_creation_date_ms': '1581929006000',
		'receipt_creation_date_pst': '2020-02-17 00:43:26 America/Los_Angeles',
		'request_date': '2020-02-17 08:43:33 Etc/GMT',
		'request_date_ms': '1581929013522',
		'request_date_pst': '2020-02-17 00:43:33 America/Los_Angeles',
		'original_purchase_date': '2013-08-01 07:00:00 Etc/GMT',
		'original_purchase_date_ms': '1375340400000',
		'original_purchase_date_pst': '2013-08-01 00:00:00 America/Los_Angeles',
		'original_application_version': '1.0',
		'in_app': [{
			'quantity': '1',
			'product_id': 'viptest01',
			'transaction_id': '1000000627719846',
			'original_transaction_id': '1000000627719846',
			'purchase_date': '2020-02-17 08:14:47 Etc/GMT',
			'purchase_date_ms': '1581927287000',
			'purchase_date_pst': '2020-02-17 00:14:47 America/Los_Angeles',
			'original_purchase_date': '2020-02-17 08:14:47 Etc/GMT',
			'original_purchase_date_ms': '1581927287000',
			'original_purchase_date_pst': '2020-02-17 00:14:47 America/Los_Angeles',
			'is_trial_period': 'false'
		}, {
			'quantity': '1',
			'product_id': 'viptest02',
			'transaction_id': '1000000625912120',
			'original_transaction_id': '1000000625912120',
			'purchase_date': '2020-02-17 06:44:13 Etc/GMT',
			'purchase_date_ms': '1581921853000',
			'purchase_date_pst': '2020-02-16 22:44:13 America/Los_Angeles',
			'original_purchase_date': '2020-02-17 06:44:13 Etc/GMT',
			'original_purchase_date_ms': '1581921853000',
			'original_purchase_date_pst': '2020-02-16 22:44:13 America/Los_Angeles',
			'is_trial_period': 'false'
		}, {
			'quantity': '1',
			'product_id': 'viptest02',
			'transaction_id': '1000000627681920',
			'original_transaction_id': '1000000627681920',
			'purchase_date': '2020-02-17 06:46:41 Etc/GMT',
			'purchase_date_ms': '1581922001000',
			'purchase_date_pst': '2020-02-16 22:46:41 America/Los_Angeles',
			'original_purchase_date': '2020-02-17 06:46:41 Etc/GMT',
			'original_purchase_date_ms': '1581922001000',
			'original_purchase_date_pst': '2020-02-16 22:46:41 America/Los_Angeles',
			'is_trial_period': 'false'
		}, {
			'quantity': '1',
			'product_id': 'viptest02',
			'transaction_id': '1000000627734213',
			'original_transaction_id': '1000000627734213',
			'purchase_date': '2020-02-17 08:43:26 Etc/GMT',
			'purchase_date_ms': '1581929006000',
			'purchase_date_pst': '2020-02-17 00:43:26 America/Los_Angeles',
			'original_purchase_date': '2020-02-17 08:43:26 Etc/GMT',
			'original_purchase_date_ms': '1581929006000',
			'original_purchase_date_pst': '2020-02-17 00:43:26 America/Los_Angeles',
			'is_trial_period': 'false'
		}, {
			'quantity': '1',
			'product_id': 'viptest04',
			'transaction_id': '1000000627684632',
			'original_transaction_id': '1000000627684632',
			'purchase_date': '2020-02-17 06:49:55 Etc/GMT',
			'purchase_date_ms': '1581922195000',
			'purchase_date_pst': '2020-02-16 22:49:55 America/Los_Angeles',
			'original_purchase_date': '2020-02-17 06:49:55 Etc/GMT',
			'original_purchase_date_ms': '1581922195000',
			'original_purchase_date_pst': '2020-02-16 22:49:55 America/Los_Angeles',
			'is_trial_period': 'false'
		}]
	},
	'status': 0,
	'environment': 'Sandbox'
}

不过需要说明一点,虽然上面的方法校验了收据信息,但是不能防御中间人攻击!

 

☆版权☆

* 网站名称:obaby@mars
* 网址:https://lang.ma/
* 个性:https://oba.by/
* 本文标题: 《iOS iap receipt 服务器校验》
* 本文链接:https://lang.ma/2020/02/6974
* 短链接:https://oba.by/?p=6974
* 转载文章请标明文章来源,原文标题以及原文链接。请遵从 《署名-非商业性使用-相同方式共享 2.5 中国大陆 (CC BY-NC-SA 2.5 CN) 》许可协议。


You may also like

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注