苹果支付刷单退款问题
一. 问题背景
苹果的霸王条款
- 支付限制只能苹果内购,(备注:苹果抽成30%,商户到账70%,比国内应用商店良心多了?如果接入H5支付,APP有下架风险
- 苹果内购支付退款,无需商户同意,苹果内部有一套自己的决策系统,由苹果决定到底退与不退
参考苹果退款政策地址
退货与退款
https://www.apple.com.cn/cn/shop/help/returns_refund
销售与退款条款和条件
https://www.apple.com.cn/shop/browse/open/salespolicies
苹果后台的对账缺陷
- 苹果开发者后台(developer.apple.com)无法查询到对应的订单号(数据安全,为了保护隐私?)且无法查询到当天的数据,只能查询到历史订单,导致对账困难,如下图

基于苹果退款政策和对账缺陷,苹果内购支付和退款问题需要处理,避免刷单导致企业利益受损
二. 处理方案
1.退款回调
苹果在WWDC 2020 苹果全球开发者大会,苹果宣布所有的内购项类型,当用户在应用内退款成功时,App Store Server 会发送实时的通知给开发者服务器告知有退款,开发者可通过处理该消息来更新用户的账户信息。
新的退款流程
- 用户购买内购商品
- 用户申请退款
- 苹果发起退款
- Apple Store Server 发送退款通知
- 用户收到退款成功的通知
- 开发者收到退款订单通知
基于以上流程,相较于支付流程,对于退款这种逆向流程,我们要做的就是需要对接的接口是苹果的退款通知接口
根据上述步骤4和6,苹果会发出两次通知
步骤4:通知类型为 CONSUMPTION_REQUEST,表示用户已经发起了退款(实际可能会发多次该类型通知)
(在发起退款48小时内,商户的服务端可以发送订单信息给苹果的决策系统,告诉苹果这笔订单已消耗,但最终是否退款由苹果决定,这里稍后描述)
步骤6:通知类型为 REFUND ,表示苹果已经同意退款,用户已经完成退款,商户服务端收到通知后处理扣除权益的逻辑
废话不多说,这里以代码为例 备注:(信息已脱敏)
@SneakyThrows
@PostMapping("/apple")
@ApiOperation(value = "苹果事件回调")
public String appleNotify(@RequestBody String strBody) {
log.info("收到苹果事件回调通知 {}", strBody);
Object payloadObj = JSONPath.extract(strBody, "$.signedPayload");
log.info("校验Token是否有效");
JSONObject jsonObject = ApplePayTokenUtil.verifyAndGet(payloadObj.toString());
ApplePayRefundNotifyResponseVO refundNotifyResponseVO = JSON.parseObject(jsonObject.toString(), ApplePayRefundNotifyResponseVO.class);
log.info("退款响应对象:{}", refundNotifyResponseVO);
List<String> applePayEvens = Arrays.asList(ApplePayEventEnum.CONSUMPTION_REQUEST.getName(), ApplePayEventEnum.REFUND.getName());
if (!applePayEvens.contains(refundNotifyResponseVO.getNotificationType())) {
log.info("当前苹果推送事件非退款事件,当前事件:{}", refundNotifyResponseVO.getNotificationType());
return "";
}
ApplePayRefundNotifyResponseVO.ApplePayRefundNotifyDataVO refundNotifyDataVO = JSON.parseObject(refundNotifyResponseVO.getData().toString(), ApplePayRefundNotifyResponseVO.ApplePayRefundNotifyDataVO.class);
log.info("原订单交易信息概览:{}", refundNotifyDataVO);
if (!"Production".equals(refundNotifyDataVO.getEnvironment())) {
log.info("当前苹果推送事件非生产环境事件,直接返回,请求负载信息:{}", refundNotifyDataVO.getEnvironment());
return "";
}
String signedTransactionInfo = refundNotifyDataVO.getSignedTransactionInfo();
JWT jwt1 = JWTUtil.parseToken(signedTransactionInfo);
ApplePayTransactionResponseVO transactionResponseVO = JSON.parseObject(jwt1.getPayloads().toString(), ApplePayTransactionResponseVO.class);
log.info("原始交易订单详情:{}", transactionResponseVO);
if (ApplePayEventEnum.CONSUMPTION_REQUEST.getName().equals(refundNotifyResponseVO.getNotificationType())) {
log.info("当前用户发起订单退款,苹果订单号:{}", transactionResponseVO.getTransactionId());
weChatRobotClient.sendTextMessage("雷神APP用户 发起了订单退款(发起退款),苹果订单号 ".concat(transactionResponseVO.getTransactionId()));
return "";
}
log.info("发起对业务系统回调,苹果订单号:{}",transactionResponseVO.getTransactionId());
//weChatRobotClient.sendTextMessage("雷神APP用户 订单退款成功(退款成功),苹果订单号 ".concat(transactionResponseVO.getTransactionId()));
RefundNotifyReq notifyReq = new RefundNotifyReq();
notifyReq.setBundleId(transactionResponseVO.getBundleId());
notifyReq.setAppAppleId(refundNotifyDataVO.getAppAppleId());
notifyReq.setNotifyUuid(refundNotifyResponseVO.getNotificationUUID());
notifyReq.setBundleVersion(refundNotifyDataVO.getBundleVersion());
notifyReq.setEnvironment(refundNotifyDataVO.getEnvironment());
notifyReq.setRefundSnapshot(strBody);
notifyReq.setDecodeSnapshot(JSON.toJSONString(transactionResponseVO));
notifyReq.setRefundState(ChannelRefundStateEnum.REFUND_SUCCE.getValue());
notifyReq.setRefundNo(transactionResponseVO.getTransactionId()); //苹果支付没有这个单号,暂时和trxId保持保持一致
notifyReq.setChannelRefundNo(transactionResponseVO.getTransactionId());
notifyReq.setChannelEnName(AccountConstant.CHANNEL_APPLE);
notifyReq.setAppleProductId(transactionResponseVO.getProductId());
notifyReq.setBizType(AppleRefundBizTypeEnum.LEIGOD.getValue());
channelNotifyService.refundNoty(notifyReq);
return "";
}
苹果回调通知的接口文档地址
https://developer.apple.com/documentation/appstoreservernotifications/app_store_server_notifications_v2
苹果回调过来的是一串原始的字符串(JWS,基于JWT规范的实现,JWS/JWT区别参考:https://blog.csdn.net/qq_31772441/article/details/126564514)
原始字符串
{"signedPayload":"eyJhbGciOiJFUzI1NiIsIng1YyI6WyJNSUlFTURDQ0E3YWdBd0lCQWdJUWZUbGZkMGZOdkZXdnpDMVlJQU5zWGpBS0JnZ3Foa2pPUFFRREF6QjFNVVF3UWdZRFZRUURERHRCY0hCc1pTQlhiM0pzWkhkcFpHVWdSR1YyWld4dmNHVnlJRkpsYkdGMGFXOXVjeUJEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURUxNQWtHQTFVRUN3d0NSell4RXpBUkJnTlZCQW9NQ2tGd2NHeGxJRWx1WXk0eEN6QUpCZ05WQkFZVEFsVlRNQjRYRFRJek1Ea3hNakU1TlRFMU0xb1hEVEkxTVRBeE1URTVOVEUxTWxvd2daSXhRREErQmdOVkJBTU1OMUJ5YjJRZ1JVTkRJRTFoWXlCQmNIQWdVM1J2Y21VZ1lXNWtJR2xVZFc1bGN5QlRkRzl5WlNCU1pXTmxhWEIwSUZOcFoyNXBibWN4TERBcUJnTlZCQXNNSTBGd2NHeGxJRmR2Y214a2QybGtaU0JFWlhabGJHOXdaWElnVW1Wc1lYUnBiMjV6TVJNd0VRWURWUVFLREFwQmNIQnNaU0JKYm1NdU1Rc3dDUVlEVlFRR0V3SlZVekJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCRUZFWWUvSnFUcXlRdi9kdFhrYXVESENTY1YxMjlGWVJWLzB4aUIyNG5DUWt6UWYzYXNISk9OUjVyMFJBMGFMdko0MzJoeTFTWk1vdXZ5ZnBtMjZqWFNqZ2dJSU1JSUNCREFNQmdOVkhSTUJBZjhFQWpBQU1COEdBMVVkSXdRWU1CYUFGRDh2bENOUjAxREptaWc5N2JCODVjK2xrR0taTUhBR0NDc0dBUVVGQndFQkJHUXdZakF0QmdnckJnRUZCUWN3QW9ZaGFIUjBjRG92TDJObGNuUnpMbUZ3Y0d4bExtTnZiUzkzZDJSeVp6WXVaR1Z5TURFR0NDc0dBUVVGQnpBQmhpVm9kSFJ3T2k4dmIyTnpjQzVoY0hCc1pTNWpiMjB2YjJOemNEQXpMWGQzWkhKbk5qQXlNSUlCSGdZRFZSMGdCSUlCRlRDQ0FSRXdnZ0VOQmdvcWhraUc5Mk5rQlFZQk1JSCtNSUhEQmdnckJnRUZCUWNDQWpDQnRneUJzMUpsYkdsaGJtTmxJRzl1SUhSb2FYTWdZMlZ5ZEdsbWFXTmhkR1VnWW5rZ1lXNTVJSEJoY25SNUlHRnpjM1Z0WlhNZ1lXTmpaWEIwWVc1alpTQnZaaUIwYUdVZ2RHaGxiaUJoY0hCc2FXTmhZbXhsSUhOMFlXNWtZWEprSUhSbGNtMXpJR0Z1WkNCamIyNWthWFJwYjI1eklHOW1JSFZ6WlN3Z1kyVnlkR2xtYVdOaGRHVWdjRzlzYVdONUlHRnVaQ0JqWlhKMGFXWnBZMkYwYVc5dUlIQnlZV04wYVdObElITjBZWFJsYldWdWRITXVNRFlHQ0NzR0FRVUZCd0lCRmlwb2RIUndPaTh2ZDNkM0xtRndjR3hsTG1OdmJTOWpaWEowYVdacFkyRjBaV0YxZEdodmNtbDBlUzh3SFFZRFZSME9CQllFRkFNczhQanM2VmhXR1FsekUyWk9FK0dYNE9vL01BNEdBMVVkRHdFQi93UUVBd0lIZ0RBUUJnb3Foa2lHOTJOa0Jnc0JCQUlGQURBS0JnZ3Foa2pPUFFRREF3Tm9BREJsQWpFQTh5Uk5kc2twNTA2REZkUExnaExMSndBdjVKOGhCR0xhSThERXhkY1BYK2FCS2pqTzhlVW85S3BmcGNOWVVZNVlBakFQWG1NWEVaTCtRMDJhZHJtbXNoTnh6M05uS20rb3VRd1U3dkJUbjBMdmxNN3ZwczJZc2xWVGFtUllMNGFTczVrPSIsIk1JSURGakNDQXB5Z0F3SUJBZ0lVSXNHaFJ3cDBjMm52VTRZU3ljYWZQVGp6Yk5jd0NnWUlLb1pJemowRUF3TXdaekViTUJrR0ExVUVBd3dTUVhCd2JHVWdVbTl2ZENCRFFTQXRJRWN6TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd0hoY05NakV3TXpFM01qQXpOekV3V2hjTk16WXdNekU1TURBd01EQXdXakIxTVVRd1FnWURWUVFERER0QmNIQnNaU0JYYjNKc1pIZHBaR1VnUkdWMlpXeHZjR1Z5SUZKbGJHRjBhVzl1Y3lCRFpYSjBhV1pwWTJGMGFXOXVJRUYxZEdodmNtbDBlVEVMTUFrR0ExVUVDd3dDUnpZeEV6QVJCZ05WQkFvTUNrRndjR3hsSUVsdVl5NHhDekFKQmdOVkJBWVRBbFZUTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUVic1FLQzk0UHJsV21aWG5YZ3R4emRWSkw4VDBTR1luZ0RSR3BuZ24zTjZQVDhKTUViN0ZEaTRiQm1QaENuWjMvc3E2UEYvY0djS1hXc0w1dk90ZVJoeUo0NXgzQVNQN2NPQithYW85MGZjcHhTdi9FWkZibmlBYk5nWkdoSWhwSW80SDZNSUgzTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0h3WURWUjBqQkJnd0ZvQVV1N0Rlb1ZnemlKcWtpcG5ldnIzcnI5ckxKS3N3UmdZSUt3WUJCUVVIQVFFRU9qQTRNRFlHQ0NzR0FRVUZCekFCaGlwb2RIUndPaTh2YjJOemNDNWhjSEJzWlM1amIyMHZiMk56Y0RBekxXRndjR3hsY205dmRHTmhaek13TndZRFZSMGZCREF3TGpBc29DcWdLSVltYUhSMGNEb3ZMMk55YkM1aGNIQnNaUzVqYjIwdllYQndiR1Z5YjI5MFkyRm5NeTVqY213d0hRWURWUjBPQkJZRUZEOHZsQ05SMDFESm1pZzk3YkI4NWMrbGtHS1pNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVFCZ29xaGtpRzkyTmtCZ0lCQkFJRkFEQUtCZ2dxaGtqT1BRUURBd05vQURCbEFqQkFYaFNxNUl5S29nTUNQdHc0OTBCYUI2NzdDYUVHSlh1ZlFCL0VxWkdkNkNTamlDdE9udU1UYlhWWG14eGN4ZmtDTVFEVFNQeGFyWlh2TnJreFUzVGtVTUkzM3l6dkZWVlJUNHd4V0pDOTk0T3NkY1o0K1JHTnNZRHlSNWdtZHIwbkRHZz0iLCJNSUlDUXpDQ0FjbWdBd0lCQWdJSUxjWDhpTkxGUzVVd0NnWUlLb1pJemowRUF3TXdaekViTUJrR0ExVUVBd3dTUVhCd2JHVWdVbTl2ZENCRFFTQXRJRWN6TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd0hoY05NVFF3TkRNd01UZ3hPVEEyV2hjTk16a3dORE13TVRneE9UQTJXakJuTVJzd0dRWURWUVFEREJKQmNIQnNaU0JTYjI5MElFTkJJQzBnUnpNeEpqQWtCZ05WQkFzTUhVRndjR3hsSUVObGNuUnBabWxqWVhScGIyNGdRWFYwYUc5eWFYUjVNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVFzd0NRWURWUVFHRXdKVlV6QjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkpqcEx6MUFjcVR0a3lKeWdSTWMzUkNWOGNXalRuSGNGQmJaRHVXbUJTcDNaSHRmVGpqVHV4eEV0WC8xSDdZeVlsM0o2WVJiVHpCUEVWb0EvVmhZREtYMUR5eE5CMGNUZGRxWGw1ZHZNVnp0SzUxN0lEdll1VlRaWHBta09sRUtNYU5DTUVBd0hRWURWUjBPQkJZRUZMdXczcUZZTTRpYXBJcVozcjY5NjYvYXl5U3JNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTURBMmdBTUdVQ01RQ0Q2Y0hFRmw0YVhUUVkyZTN2OUd3T0FFWkx1Tit5UmhIRkQvM21lb3locG12T3dnUFVuUFdUeG5TNGF0K3FJeFVDTUcxbWloREsxQTNVVDgyTlF6NjBpbU9sTTI3amJkb1h0MlFmeUZNbStZaGlkRGtMRjF2TFVhZ002QmdENTZLeUtBPT0iXX0.eyJub3RpZmljYXRpb25UeXBlIjoiUkVGVU5EIiwibm90aWZpY2F0aW9uVVVJRCI6IjVkYTJhOGE1LTFiMTQtNGFmYy05MTlmLWY3ZWVhZWM2MTM1MCIsImRhdGEiOnsiYXBwQXBwbGVJZCI6MTYxMzUwNjE0NSwiYnVuZGxlSWQiOiJjb20uYW9sYWZ1LmxlaXNoZW4iLCJidW5kbGVWZXJzaW9uIjoiMTAwODE2MTciLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJzaWduZWRUcmFuc2FjdGlvbkluZm8iOiJleUpoYkdjaU9pSkZVekkxTmlJc0luZzFZeUk2V3lKTlNVbEZUVVJEUTBFM1lXZEJkMGxDUVdkSlVXWlViR1prTUdaT2RrWlhkbnBETVZsSlFVNXpXR3BCUzBKblozRm9hMnBQVUZGUlJFRjZRakZOVlZGM1VXZFpSRlpSVVVSRVJIUkNZMGhDYzFwVFFsaGlNMHB6V2toa2NGcEhWV2RTUjFZeVdsZDRkbU5IVm5sSlJrcHNZa2RHTUdGWE9YVmplVUpFV2xoS01HRlhXbkJaTWtZd1lWYzVkVWxGUmpGa1IyaDJZMjFzTUdWVVJVeE5RV3RIUVRGVlJVTjNkME5TZWxsNFJYcEJVa0puVGxaQ1FXOU5RMnRHZDJOSGVHeEpSV3gxV1hrMGVFTjZRVXBDWjA1V1FrRlpWRUZzVmxSTlFqUllSRlJKZWsxRWEzaE5ha1UxVGxSRk1VMHhiMWhFVkVreFRWUkJlRTFVUlRWT1ZFVXhUV3h2ZDJkYVNYaFJSRUVyUW1kT1ZrSkJUVTFPTVVKNVlqSlJaMUpWVGtSSlJURm9XWGxDUW1OSVFXZFZNMUoyWTIxVloxbFhOV3RKUjJ4VlpGYzFiR041UWxSa1J6bDVXbE5DVTFwWFRteGhXRUl3U1VaT2NGb3lOWEJpYldONFRFUkJjVUpuVGxaQ1FYTk5TVEJHZDJOSGVHeEpSbVIyWTIxNGEyUXliR3RhVTBKRldsaGFiR0pIT1hkYVdFbG5WVzFXYzFsWVVuQmlNalY2VFZKTmQwVlJXVVJXVVZGTFJFRndRbU5JUW5OYVUwSktZbTFOZFUxUmMzZERVVmxFVmxGUlIwVjNTbFpWZWtKYVRVSk5SMEo1Y1VkVFRUUTVRV2RGUjBORGNVZFRUVFE1UVhkRlNFRXdTVUZDUlVaRldXVXZTbkZVY1hsUmRpOWtkRmhyWVhWRVNFTlRZMVl4TWpsR1dWSldMekI0YVVJeU5HNURVV3Q2VVdZellYTklTazlPVWpWeU1GSkJNR0ZNZGtvME16Sm9lVEZUV2sxdmRYWjVabkJ0TWpacVdGTnFaMmRKU1UxSlNVTkNSRUZOUW1kT1ZraFNUVUpCWmpoRlFXcEJRVTFDT0VkQk1WVmtTWGRSV1UxQ1lVRkdSRGgyYkVOT1VqQXhSRXB0YVdjNU4ySkNPRFZqSzJ4clIwdGFUVWhCUjBORGMwZEJVVlZHUW5kRlFrSkhVWGRaYWtGMFFtZG5ja0puUlVaQ1VXTjNRVzlaYUdGSVVqQmpSRzkyVERKT2JHTnVVbnBNYlVaM1kwZDRiRXh0VG5aaVV6a3paREpTZVZwNldYVmFSMVo1VFVSRlIwTkRjMGRCVVZWR1FucEJRbWhwVm05a1NGSjNUMms0ZG1JeVRucGpRelZvWTBoQ2MxcFROV3BpTWpCMllqSk9lbU5FUVhwTVdHUXpXa2hLYms1cVFYbE5TVWxDU0dkWlJGWlNNR2RDU1VsQ1JsUkRRMEZTUlhkblowVk9RbWR2Y1docmFVYzVNazVyUWxGWlFrMUpTQ3ROU1VoRVFtZG5ja0puUlVaQ1VXTkRRV3BEUW5SbmVVSnpNVXBzWWtkc2FHSnRUbXhKUnpsMVNVaFNiMkZZVFdkWk1sWjVaRWRzYldGWFRtaGtSMVZuV1c1cloxbFhOVFZKU0VKb1kyNVNOVWxIUm5wak0xWjBXbGhOWjFsWFRtcGFXRUl3V1ZjMWFscFRRblphYVVJd1lVZFZaMlJIYUd4aWFVSm9ZMGhDYzJGWFRtaFpiWGhzU1VoT01GbFhOV3RaV0VwclNVaFNiR050TVhwSlIwWjFXa05DYW1JeU5XdGhXRkp3WWpJMWVrbEhPVzFKU0ZaNldsTjNaMWt5Vm5sa1IyeHRZVmRPYUdSSFZXZGpSemx6WVZkT05VbEhSblZhUTBKcVdsaEtNR0ZYV25CWk1rWXdZVmM1ZFVsSVFubFpWMDR3WVZkT2JFbElUakJaV0ZKc1lsZFdkV1JJVFhWTlJGbEhRME56UjBGUlZVWkNkMGxDUm1sd2IyUklVbmRQYVRoMlpETmtNMHh0Um5kalIzaHNURzFPZG1KVE9XcGFXRW93WVZkYWNGa3lSakJhVjBZeFpFZG9kbU50YkRCbFV6aDNTRkZaUkZaU01FOUNRbGxGUmtGTmN6aFFhbk0yVm1oWFIxRnNla1V5V2s5RkswZFlORTl2TDAxQk5FZEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJVVUpuYjNGb2EybEhPVEpPYTBKbmMwSkNRVWxHUVVSQlMwSm5aM0ZvYTJwUFVGRlJSRUYzVG05QlJFSnNRV3BGUVRoNVVrNWtjMnR3TlRBMlJFWmtVRXhuYUV4TVNuZEJkalZLT0doQ1IweGhTVGhFUlhoa1kxQllLMkZDUzJwcVR6aGxWVzg1UzNCbWNHTk9XVlZaTlZsQmFrRlFXRzFOV0VWYVRDdFJNREpoWkhKdGJYTm9Ubmg2TTA1dVMyMHJiM1ZSZDFVM2RrSlViakJNZG14Tk4zWndjekpaYzJ4V1ZHRnRVbGxNTkdGVGN6VnJQU0lzSWsxSlNVUkdha05EUVhCNVowRjNTVUpCWjBsVlNYTkhhRkozY0RCak1tNTJWVFJaVTNsallXWlFWR3A2WWs1amQwTm5XVWxMYjFwSmVtb3dSVUYzVFhkYWVrVmlUVUpyUjBFeFZVVkJkM2RUVVZoQ2QySkhWV2RWYlRsMlpFTkNSRkZUUVhSSlJXTjZUVk5aZDBwQldVUldVVkZNUkVJeFFtTklRbk5hVTBKRVdsaEtNR0ZYV25CWk1rWXdZVmM1ZFVsRlJqRmtSMmgyWTIxc01HVlVSVlJOUWtWSFFURlZSVU5uZDB0UldFSjNZa2RWWjFOWE5XcE1ha1ZNVFVGclIwRXhWVVZDYUUxRFZsWk5kMGhvWTA1TmFrVjNUWHBGTTAxcVFYcE9la1YzVjJoalRrMTZXWGROZWtVMVRVUkJkMDFFUVhkWGFrSXhUVlZSZDFGbldVUldVVkZFUkVSMFFtTklRbk5hVTBKWVlqTktjMXBJWkhCYVIxVm5Va2RXTWxwWGVIWmpSMVo1U1VaS2JHSkhSakJoVnpsMVkzbENSRnBZU2pCaFYxcHdXVEpHTUdGWE9YVkpSVVl4WkVkb2RtTnRiREJsVkVWTVRVRnJSMEV4VlVWRGQzZERVbnBaZUVWNlFWSkNaMDVXUWtGdlRVTnJSbmRqUjNoc1NVVnNkVmw1TkhoRGVrRktRbWRPVmtKQldWUkJiRlpVVFVoWmQwVkJXVWhMYjFwSmVtb3dRMEZSV1VaTE5FVkZRVU5KUkZsblFVVmljMUZMUXprMFVISnNWMjFhV0c1WVozUjRlbVJXU2t3NFZEQlRSMWx1WjBSU1IzQnVaMjR6VGpaUVZEaEtUVVZpTjBaRWFUUmlRbTFRYUVOdVdqTXZjM0UyVUVZdlkwZGpTMWhYYzB3MWRrOTBaVkpvZVVvME5YZ3pRVk5RTjJOUFFpdGhZVzg1TUdaamNIaFRkaTlGV2taaWJtbEJZazVuV2tkb1NXaHdTVzgwU0RaTlNVZ3pUVUpKUjBFeFZXUkZkMFZDTDNkUlNVMUJXVUpCWmpoRFFWRkJkMGgzV1VSV1VqQnFRa0puZDBadlFWVjFOMFJsYjFabmVtbEtjV3RwY0c1bGRuSXpjbkk1Y2t4S1MzTjNVbWRaU1V0M1dVSkNVVlZJUVZGRlJVOXFRVFJOUkZsSFEwTnpSMEZSVlVaQ2VrRkNhR2x3YjJSSVVuZFBhVGgyWWpKT2VtTkROV2hqU0VKeldsTTFhbUl5TUhaaU1rNTZZMFJCZWt4WFJuZGpSM2hzWTIwNWRtUkhUbWhhZWsxM1RuZFpSRlpTTUdaQ1JFRjNUR3BCYzI5RGNXZExTVmx0WVVoU01HTkViM1pNTWs1NVlrTTFhR05JUW5OYVV6VnFZakl3ZGxsWVFuZGlSMVo1WWpJNU1Ga3lSbTVOZVRWcVkyMTNkMGhSV1VSV1VqQlBRa0paUlVaRU9IWnNRMDVTTURGRVNtMXBaemszWWtJNE5XTXJiR3RIUzFwTlFUUkhRVEZWWkVSM1JVSXZkMUZGUVhkSlFrSnFRVkZDWjI5eGFHdHBSemt5VG10Q1owbENRa0ZKUmtGRVFVdENaMmR4YUd0cVQxQlJVVVJCZDA1dlFVUkNiRUZxUWtGWWFGTnhOVWw1UzI5blRVTlFkSGMwT1RCQ1lVSTJOemREWVVWSFNsaDFabEZDTDBWeFdrZGtOa05UYW1sRGRFOXVkVTFVWWxoV1dHMTRlR040Wm10RFRWRkVWRk5RZUdGeVdsaDJUbkpyZUZVelZHdFZUVWt6TTNsNmRrWldWbEpVTkhkNFYwcERPVGswVDNOa1kxbzBLMUpIVG5OWlJIbFNOV2R0WkhJd2JrUkhaejBpTENKTlNVbERVWHBEUTBGamJXZEJkMGxDUVdkSlNVeGpXRGhwVGt4R1V6VlZkME5uV1VsTGIxcEplbW93UlVGM1RYZGFla1ZpVFVKclIwRXhWVVZCZDNkVFVWaENkMkpIVldkVmJUbDJaRU5DUkZGVFFYUkpSV042VFZOWmQwcEJXVVJXVVZGTVJFSXhRbU5JUW5OYVUwSkVXbGhLTUdGWFduQlpNa1l3WVZjNWRVbEZSakZrUjJoMlkyMXNNR1ZVUlZSTlFrVkhRVEZWUlVObmQwdFJXRUozWWtkVloxTlhOV3BNYWtWTVRVRnJSMEV4VlVWQ2FFMURWbFpOZDBob1kwNU5WRkYzVGtSTmQwMVVaM2hQVkVFeVYyaGpUazE2YTNkT1JFMTNUVlJuZUU5VVFUSlhha0p1VFZKemQwZFJXVVJXVVZGRVJFSktRbU5JUW5OYVUwSlRZakk1TUVsRlRrSkpRekJuVW5wTmVFcHFRV3RDWjA1V1FrRnpUVWhWUm5kalIzaHNTVVZPYkdOdVVuQmFiV3hxV1ZoU2NHSXlOR2RSV0ZZd1lVYzVlV0ZZVWpWTlVrMTNSVkZaUkZaUlVVdEVRWEJDWTBoQ2MxcFRRa3BpYlUxMVRWRnpkME5SV1VSV1VWRkhSWGRLVmxWNlFqSk5Ra0ZIUW5seFIxTk5ORGxCWjBWSFFsTjFRa0pCUVdsQk1rbEJRa3BxY0V4Nk1VRmpjVlIwYTNsS2VXZFNUV016VWtOV09HTlhhbFJ1U0dOR1FtSmFSSFZYYlVKVGNETmFTSFJtVkdwcVZIVjRlRVYwV0M4eFNEZFplVmxzTTBvMldWSmlWSHBDVUVWV2IwRXZWbWhaUkV0WU1VUjVlRTVDTUdOVVpHUnhXR3cxWkhaTlZucDBTelV4TjBsRWRsbDFWbFJhV0hCdGEwOXNSVXROWVU1RFRVVkJkMGhSV1VSV1VqQlBRa0paUlVaTWRYY3pjVVpaVFRScFlYQkpjVm96Y2pZNU5qWXZZWGw1VTNKTlFUaEhRVEZWWkVWM1JVSXZkMUZHVFVGTlFrRm1PSGRFWjFsRVZsSXdVRUZSU0M5Q1FWRkVRV2RGUjAxQmIwZERRM0ZIVTAwME9VSkJUVVJCTW1kQlRVZFZRMDFSUTBRMlkwaEZSbXcwWVZoVVVWa3laVE4yT1VkM1QwRkZXa3gxVGl0NVVtaElSa1F2TTIxbGIzbG9jRzEyVDNkblVGVnVVRmRVZUc1VE5HRjBLM0ZKZUZWRFRVY3hiV2xvUkVzeFFUTlZWRGd5VGxGNk5qQnBiVTlzVFRJM2FtSmtiMWgwTWxGbWVVWk5iU3RaYUdsa1JHdE1SakYyVEZWaFowMDJRbWRFTlRaTGVVdEJQVDBpWFgwLmV5SjBjbUZ1YzJGamRHbHZia2xrSWpvaU56QXdNREU1T1RRME9EazFNVEFpTENKdmNtbG5hVzVoYkZSeVlXNXpZV04wYVc5dVNXUWlPaUkzTURBd01UazVORFE0T1RVeE1DSXNJbUoxYm1Sc1pVbGtJam9pWTI5dExtRnZiR0ZtZFM1c1pXbHphR1Z1SWl3aWNISnZaSFZqZEVsa0lqb2lNekF3TURJaUxDSndkWEpqYUdGelpVUmhkR1VpT2pFM01EY3hNRGMyTnpjd01EQXNJbTl5YVdkcGJtRnNVSFZ5WTJoaGMyVkVZWFJsSWpveE56QTNNVEEzTmpjM01EQXdMQ0p4ZFdGdWRHbDBlU0k2TVN3aWRIbHdaU0k2SWtOdmJuTjFiV0ZpYkdVaUxDSnBia0Z3Y0U5M2JtVnljMmhwY0ZSNWNHVWlPaUpRVlZKRFNFRlRSVVFpTENKemFXZHVaV1JFWVhSbElqb3hOekEzTVRnNE9UQTBOVFE0TENKeVpYWnZZMkYwYVc5dVVtVmhjMjl1SWpveExDSnlaWFp2WTJGMGFXOXVSR0YwWlNJNk1UY3dOekU0TnprNU9UQXdNQ3dpWlc1MmFYSnZibTFsYm5RaU9pSlFjbTlrZFdOMGFXOXVJaXdpZEhKaGJuTmhZM1JwYjI1U1pXRnpiMjRpT2lKUVZWSkRTRUZUUlNJc0luTjBiM0psWm5KdmJuUWlPaUpEU0U0aUxDSnpkRzl5WldaeWIyNTBTV1FpT2lJeE5ETTBOalVpTENKd2NtbGpaU0k2TVRJek1EQXdMQ0pqZFhKeVpXNWplU0k2SWtOT1dTSjkuY2RwOHI0U3B3OFE1NlloV3JFc2hrSGtwS01IMXoxQXVteTVuOWFlbXJGVjE3elY1RVlKaWVrMFBTSFJQY0pjS0VaMFU5YTlveGIyN21hYUstWTNHckEifSwidmVyc2lvbiI6IjIuMCIsInNpZ25lZERhdGUiOjE3MDcxODg5MDQ1NzR9.-ZoSI0u1vbV7OrGoyAEacAIDM8Mac_vMg0MvR2UvsXC9OybqdfLh13UTnLu63ZemgO_Ck0208HaELH4QqwxNTg"}
解析Payload部分后具有以下部分
{notificationType: "REFUND",notificationUUID: "5da2a8a5-1b14-4afc-919f-f7eeaec61350",data: {appAppleId: 1613506145,bundleId: com.aolafu.leishen,bundleVersion: "10081617",environment: "Production",signedTransactionInfo: eyJhbGciOiJFUzI1NiIsIng1YyI6WyJNSUlFTURDQ0E3YWdBd0lCQWdJUWZUbGZkMGZOdkZXdnpDMVlJQU5zWGpBS0JnZ3Foa2pPUFFRREF6QjFNVVF3UWdZRFZRUURERHRCY0hCc1pTQlhiM0pzWkhkcFpHVWdSR1YyWld4dmNHVnlJRkpsYkdGMGFXOXVjeUJEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURUxNQWtHQTFVRUN3d0NSell4RXpBUkJnTlZCQW9NQ2tGd2NHeGxJRWx1WXk0eEN6QUpCZ05WQkFZVEFsVlRNQjRYRFRJek1Ea3hNakU1TlRFMU0xb1hEVEkxTVRBeE1URTVOVEUxTWxvd2daSXhRREErQmdOVkJBTU1OMUJ5YjJRZ1JVTkRJRTFoWXlCQmNIQWdVM1J2Y21VZ1lXNWtJR2xVZFc1bGN5QlRkRzl5WlNCU1pXTmxhWEIwSUZOcFoyNXBibWN4TERBcUJnTlZCQXNNSTBGd2NHeGxJRmR2Y214a2QybGtaU0JFWlhabGJHOXdaWElnVW1Wc1lYUnBiMjV6TVJNd0VRWURWUVFLREFwQmNIQnNaU0JKYm1NdU1Rc3dDUVlEVlFRR0V3SlZVekJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCRUZFWWUvSnFUcXlRdi9kdFhrYXVESENTY1YxMjlGWVJWLzB4aUIyNG5DUWt6UWYzYXNISk9OUjVyMFJBMGFMdko0MzJoeTFTWk1vdXZ5ZnBtMjZqWFNqZ2dJSU1JSUNCREFNQmdOVkhSTUJBZjhFQWpBQU1COEdBMVVkSXdRWU1CYUFGRDh2bENOUjAxREptaWc5N2JCODVjK2xrR0taTUhBR0NDc0dBUVVGQndFQkJHUXdZakF0QmdnckJnRUZCUWN3QW9ZaGFIUjBjRG92TDJObGNuUnpMbUZ3Y0d4bExtTnZiUzkzZDJSeVp6WXVaR1Z5TURFR0NDc0dBUVVGQnpBQmhpVm9kSFJ3T2k4dmIyTnpjQzVoY0hCc1pTNWpiMjB2YjJOemNEQXpMWGQzWkhKbk5qQXlNSUlCSGdZRFZSMGdCSUlCRlRDQ0FSRXdnZ0VOQmdvcWhraUc5Mk5rQlFZQk1JSCtNSUhEQmdnckJnRUZCUWNDQWpDQnRneUJzMUpsYkdsaGJtTmxJRzl1SUhSb2FYTWdZMlZ5ZEdsbWFXTmhkR1VnWW5rZ1lXNTVJSEJoY25SNUlHRnpjM1Z0WlhNZ1lXTmpaWEIwWVc1alpTQnZaaUIwYUdVZ2RHaGxiaUJoY0hCc2FXTmhZbXhsSUhOMFlXNWtZWEprSUhSbGNtMXpJR0Z1WkNCamIyNWthWFJwYjI1eklHOW1JSFZ6WlN3Z1kyVnlkR2xtYVdOaGRHVWdjRzlzYVdONUlHRnVaQ0JqWlhKMGFXWnBZMkYwYVc5dUlIQnlZV04wYVdObElITjBZWFJsYldWdWRITXVNRFlHQ0NzR0FRVUZCd0lCRmlwb2RIUndPaTh2ZDNkM0xtRndjR3hsTG1OdmJTOWpaWEowYVdacFkyRjBaV0YxZEdodmNtbDBlUzh3SFFZRFZSME9CQllFRkFNczhQanM2VmhXR1FsekUyWk9FK0dYNE9vL01BNEdBMVVkRHdFQi93UUVBd0lIZ0RBUUJnb3Foa2lHOTJOa0Jnc0JCQUlGQURBS0JnZ3Foa2pPUFFRREF3Tm9BREJsQWpFQTh5Uk5kc2twNTA2REZkUExnaExMSndBdjVKOGhCR0xhSThERXhkY1BYK2FCS2pqTzhlVW85S3BmcGNOWVVZNVlBakFQWG1NWEVaTCtRMDJhZHJtbXNoTnh6M05uS20rb3VRd1U3dkJUbjBMdmxNN3ZwczJZc2xWVGFtUllMNGFTczVrPSIsIk1JSURGakNDQXB5Z0F3SUJBZ0lVSXNHaFJ3cDBjMm52VTRZU3ljYWZQVGp6Yk5jd0NnWUlLb1pJemowRUF3TXdaekViTUJrR0ExVUVBd3dTUVhCd2JHVWdVbTl2ZENCRFFTQXRJRWN6TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd0hoY05NakV3TXpFM01qQXpOekV3V2hjTk16WXdNekU1TURBd01EQXdXakIxTVVRd1FnWURWUVFERER0QmNIQnNaU0JYYjNKc1pIZHBaR1VnUkdWMlpXeHZjR1Z5SUZKbGJHRjBhVzl1Y3lCRFpYSjBhV1pwWTJGMGFXOXVJRUYxZEdodmNtbDBlVEVMTUFrR0ExVUVDd3dDUnpZeEV6QVJCZ05WQkFvTUNrRndjR3hsSUVsdVl5NHhDekFKQmdOVkJBWVRBbFZUTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUVic1FLQzk0UHJsV21aWG5YZ3R4emRWSkw4VDBTR1luZ0RSR3BuZ24zTjZQVDhKTUViN0ZEaTRiQm1QaENuWjMvc3E2UEYvY0djS1hXc0w1dk90ZVJoeUo0NXgzQVNQN2NPQithYW85MGZjcHhTdi9FWkZibmlBYk5nWkdoSWhwSW80SDZNSUgzTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0h3WURWUjBqQkJnd0ZvQVV1N0Rlb1ZnemlKcWtpcG5ldnIzcnI5ckxKS3N3UmdZSUt3WUJCUVVIQVFFRU9qQTRNRFlHQ0NzR0FRVUZCekFCaGlwb2RIUndPaTh2YjJOemNDNWhjSEJzWlM1amIyMHZiMk56Y0RBekxXRndjR3hsY205dmRHTmhaek13TndZRFZSMGZCREF3TGpBc29DcWdLSVltYUhSMGNEb3ZMMk55YkM1aGNIQnNaUzVqYjIwdllYQndiR1Z5YjI5MFkyRm5NeTVqY213d0hRWURWUjBPQkJZRUZEOHZsQ05SMDFESm1pZzk3YkI4NWMrbGtHS1pNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVFCZ29xaGtpRzkyTmtCZ0lCQkFJRkFEQUtCZ2dxaGtqT1BRUURBd05vQURCbEFqQkFYaFNxNUl5S29nTUNQdHc0OTBCYUI2NzdDYUVHSlh1ZlFCL0VxWkdkNkNTamlDdE9udU1UYlhWWG14eGN4ZmtDTVFEVFNQeGFyWlh2TnJreFUzVGtVTUkzM3l6dkZWVlJUNHd4V0pDOTk0T3NkY1o0K1JHTnNZRHlSNWdtZHIwbkRHZz0iLCJNSUlDUXpDQ0FjbWdBd0lCQWdJSUxjWDhpTkxGUzVVd0NnWUlLb1pJemowRUF3TXdaekViTUJrR0ExVUVBd3dTUVhCd2JHVWdVbTl2ZENCRFFTQXRJRWN6TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd0hoY05NVFF3TkRNd01UZ3hPVEEyV2hjTk16a3dORE13TVRneE9UQTJXakJuTVJzd0dRWURWUVFEREJKQmNIQnNaU0JTYjI5MElFTkJJQzBnUnpNeEpqQWtCZ05WQkFzTUhVRndjR3hsSUVObGNuUnBabWxqWVhScGIyNGdRWFYwYUc5eWFYUjVNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVFzd0NRWURWUVFHRXdKVlV6QjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkpqcEx6MUFjcVR0a3lKeWdSTWMzUkNWOGNXalRuSGNGQmJaRHVXbUJTcDNaSHRmVGpqVHV4eEV0WC8xSDdZeVlsM0o2WVJiVHpCUEVWb0EvVmhZREtYMUR5eE5CMGNUZGRxWGw1ZHZNVnp0SzUxN0lEdll1VlRaWHBta09sRUtNYU5DTUVBd0hRWURWUjBPQkJZRUZMdXczcUZZTTRpYXBJcVozcjY5NjYvYXl5U3JNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTURBMmdBTUdVQ01RQ0Q2Y0hFRmw0YVhUUVkyZTN2OUd3T0FFWkx1Tit5UmhIRkQvM21lb3locG12T3dnUFVuUFdUeG5TNGF0K3FJeFVDTUcxbWloREsxQTNVVDgyTlF6NjBpbU9sTTI3amJkb1h0MlFmeUZNbStZaGlkRGtMRjF2TFVhZ002QmdENTZLeUtBPT0iXX0.eyJ0cmFuc2FjdGlvbklkIjoiNzAwMDE5OTQ0ODk1MTAiLCJvcmlnaW5hbFRyYW5zYWN0aW9uSWQiOiI3MDAwMTk5NDQ4OTUxMCIsImJ1bmRsZUlkIjoiY29tLmFvbGFmdS5sZWlzaGVuIiwicHJvZHVjdElkIjoiMzAwMDIiLCJwdXJjaGFzZURhdGUiOjE3MDcxMDc2NzcwMDAsIm9yaWdpbmFsUHVyY2hhc2VEYXRlIjoxNzA3MTA3Njc3MDAwLCJxdWFudGl0eSI6MSwidHlwZSI6IkNvbnN1bWFibGUiLCJpbkFwcE93bmVyc2hpcFR5cGUiOiJQVVJDSEFTRUQiLCJzaWduZWREYXRlIjoxNzA3MTg4OTA0NTQ4LCJyZXZvY2F0aW9uUmVhc29uIjoxLCJyZXZvY2F0aW9uRGF0ZSI6MTcwNzE4Nzk5OTAwMCwiZW52aXJvbm1lbnQiOiJQcm9kdWN0aW9uIiwidHJhbnNhY3Rpb25SZWFzb24iOiJQVVJDSEFTRSIsInN0b3JlZnJvbnQiOiJDSE4iLCJzdG9yZWZyb250SWQiOiIxNDM0NjUiLCJwcmljZSI6MTIzMDAwLCJjdXJyZW5jeSI6IkNOWSJ9.cdp8r4Spw8Q56YhWrEshkHkpKMH1z1Aumy5n9aemrFV17zV5EYJiek0PSHRPcJcKEZ0U9a9oxb27maaK-Y3GrA},version: 2.0,signedDate: 1707188904574}
Payload中具有通知类型,包名,环境等公共参数,再次使用JWT解析 signedTransactionInfo 字段,可以获取到订单相关的详情
{transactionId: "70001994489510",originalTransactionId: "70001994489510",bundleId: com.aolafu.xxxxx,productId: "30002",purchaseDate: 1707107677000,originalPurchaseDate: 1707107677000,quantity: 1,type: "Consumable",inAppOwnershipType: "PURCHASED",signedDate: 1707188904548,revocationReason: 1,revocationDate: 1707187999000,environment: "Production",transactionReason: "PURCHASE",storefront: "CHN",storefrontId: "143465",price: 123000,currency: "CNY"}
这里可以拿到退款商品ID,金额,数量,苹果订单号(与支付验签接口的返回的苹果订单号一致)
拿到订单号后,可以追溯到当前这笔订单的系统内的订单号,然后做对应的扣权益操作
注意,这里有一种特殊情况,即后端没有收到支付流程完成后,客户端传递过来的支付凭证,但是却收到了用户发起退款和退款成功的通知,目前我这里方案是,在收到苹果退款成功通知后,会拿transactionId/originalTransactionId 去查询是否有成功支付的订单
如果有支付成功的订单,保存退款记录,执行扣除权益
如果没有支付成功的订单,保存退款记录,如果后续有收到客户端的支付请求,可以在支付流程中直接将改请求拦截,提示无效的支付凭证或其他,目的是补个用户增加权益
2.决策系统上报
依上文描述,在收到CONSUMPTION_REQUEST回调请求后,服务端有48小时去收集信息告诉苹果的决策系统该笔订单的状态和消耗情况
苹果支付的具体的接口文档地址
https://developer.apple.com/documentation/appstoreserverapi/consumptionrequest
重点关注的字段:
appAccountToken(这个需要IOS客户端在支付时传过去)
customerConsented,true或的布尔值false,指示客户是否同意提供消费数据。
注意对接该接口需要加密,加密代码如下:
org.springframework.core.io.Resource resource = applicationContext.getResource(keyPath);
File file = resource.getFile();
Map<String, Object> headers = new HashMap<>();
// apple指定ES256算法
headers.put("alg", "ES256");
// 密钥ID
headers.put("kid", kid);
// jwt格式
headers.put("typ", "JWT");
return JWT.create().withHeader(headers)
// issId:见apple connect后台右上角
.withIssuer(issId)
// 签名日期
.withIssuedAt(new Date())
// 失效日期:最晚一个小时,否则报错401
.withExpiresAt(DateUtils.addHours(new Date(), 1))
// 目标接收者,固定值
.withAudience("appstoreconnect-v1")
// 包名,bundleId
.withClaim("bid", bundleId)
// 签名密钥,需要用到apple connect下载p8文件
.sign(Algorithm.ECDSA256(null, (ECPrivateKey) getPrivateKey(file.getPath())));
其中对几个关键参数说明
KeyPath:这个是苹果的秘钥证书地址,p8格式,在开发者后台 apple connet下载
Kid:这是苹果的秘钥id
issId:在开发者后台 apple connet右上角
接口请求完成后:苹果会根据决策系统来判断是否最终进行退款(备注:也就是会参考商户的信息,目前有概率性仍然会进行退款)
三.参考链接
- 退货与退款 https://www.apple.com.cn/cn/shop/help/returns_refund
- 销售与退款条款和条件 https://www.apple.com.cn/shop/browse/open/salespolicies
- 苹果开发者后台 https://developer.apple.com 和 https://appstoreconnect.apple.com/login
- 苹果内购支付文档 https://developer.apple.com/cn/documentation/storekit/original_api_for_in-app_purchase/
- 苹果支付凭证校验 https://developer.apple.com/documentation/appstorereceipts/verifyreceipt
- 苹果退款通知文档 https://developer.apple.com/documentation/appstoreservernotifications/app_store_server_notifications_v2
- 苹果决策系统文档 https://developer.apple.com/documentation/appstoreserverapi/consumptionrequest
- 苹果获取历史退款订单接口(用来处理历史数据) https://developer.apple.com/documentation/appstoreserverapi/creating_api_keys_to_authorize_api_requests

浙公网安备 33010602011771号