iOS iap receipt 服务器校验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
{
	'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'
}

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

 

分享文章:

猜你喜欢:

发表评论

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