苹果商店退款API PHP验签 signedPayload
2022-11-04 本文已影响0人
belm
- 苹果商店后台配置服务端退款和订阅通知接受地址
打开 https://appstoreconnect.apple.com/apps 进入到对应的APP
综合=》App信息 ,可分别配置正式和沙盒接受地址
image.png
参考地址 https://help.apple.com/app-store-connect/#/dev0067a330b
2.目前苹果此通知API已经更新到第2个版本, 此版本使用JWT签名,需要我们验签后使用,通知数据格式如下:
{"signedPayload":"xxxxxx"}
可以将签名内容复制到https://jwt.io/ 是验签ok的,后面就想办法用PHP验签
jwt官网显示header部分如下
{
"alg": "ES256",
"x5c": ['key1', 'key2', 'key3']
}
alg是加密算法,x5c是一种协议标准,可参考定义https://www.rfc-editor.org/rfc/rfc7515
x5c里面的3个key, 第1个公钥是用来验证payload里面的值是否合法的,第3个公钥是用来跟苹果的root证书比对是否一致 https://www.apple.com/certificateauthority/
下载https://www.apple.com/certificateauthority/AppleRootCA-G3.cer
openssl x509 -inform der -in AppleRootCA-G3.cer -out AppleRootCA-G3.pem
得出来pem的值应该跟x5c里面的第3个一样。
php引用jwt库
"firebase/php-jwt": "^5.2",
public static function decodePayNotifyV2($jwt)
{
list($header, $payload, $sign) = explode('.', $jwt);
$header_decode = base64_decode($header);
$header_json =json_encode($header_decode);
if (!isset($header_json['x5c'])) {
return false;
}
//这一步是将公钥转成对应的格式
$pubkey = createPublicKey($header_json['x5c'][0], 'BEGIN CERTIFICATE', 'END CERTIFICATE');
try {
$decoded = JWT::decode($jwt, $pubkey, array($header_json['alg']));
} catch (UnexpectedValueException $e) {
return false;
}
return get_object_vars($decoded);
}
$payload_json = Apple::decodePayNotifyV2($data['signedPayload']);
if (empty($payload_json) || !isset($payload_json['data'])) {
return;
}
$payload_json['data'] = get_object_vars($payload_json['data']);
$t_payload_json = Apple::decodePayNotifyV2($payload_json['data']['signedTransactionInfo']);
if (empty($t_payload_json) || empty($t_payload_json['transactionId'])) {
return;
}
$vals = $t_payload_json;
$vals['appid'] = $appid;
$vals['notificationType'] = $payload_json['notificationType'];
$vals['notificationUUID'] = $payload_json['notificationUUID'];
$vals['appAppleId'] = $payload_json['data']['appAppleId'];
$vals['bundleVersion'] = $payload_json['data']['bundleVersion'];
$vals['version'] = $payload_json['version'];
$vals['purchaseDate'] = date('Y-m-d H:i:s', substr($vals['purchaseDate'], 0, 10));
$vals['originalPurchaseDate'] = date('Y-m-d H:i:s', substr($vals['originalPurchaseDate'], 0, 10));
$vals['signedDate'] = date('Y-m-d H:i:s', substr($vals['signedDate'], 0, 10));
if (isset($vals['revocationDate'])) {
$vals['revocationDate'] = date('Y-m-d H:i:s', substr($vals['revocationDate'], 0, 10));
}
遇到的问题
1.刚开始生成公钥,使用的是
-----BEGIN PUBLIC KEY-----
xxxxx
-----END PUBLIC KEY-----
一直验签不通过,后面改成下面这样就正常了,猜想这是x5c规范?
-----BEGIN CERTIFICATE-----
xxxxx
-----END CERTIFICATE-----
2.x5c里面的第一个是用来验签的key
3.参考文档
https://cloud.tencent.com/developer/article/1939304