1.需要在苹果后台配置通知地址,选v2版本协议
2.相关地址
用来解析调试接收到的signedPayload
新版通知协议地址 responseBodyV2DecodedPayloadhttps://developer.apple.com/documentation/appstoreservernotifications/responsebodyv2decodedpayload
3.上代码
pom引用,用来解析苹果的jws数据
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
工具类
@Component
public class JwsUtil {
private Logger logger = LoggerFactory.getLogger(this.getClass());
public Jws<Claims> verifyJWT(String x5c, String jws){
try {
X509Certificate cert = getCert(x5c);
if (!cert.getSubjectDN().getName().contains("Apple Inc")){
logger.info("not apple cert . name = {}", cert.getIssuerX500Principal().getName());
return null;
}
return Jwts.parser().setSigningKey(cert.getPublicKey()).parseClaimsJws(jws);
}catch (JwtException exc){
logger.info("jws verify failure.", exc);
return null;
} catch (Exception exc){
logger.info("jws verify error.", exc);
return null;
}
}
public static X509Certificate getCert(String x5c) throws CertificateException {
String stripped = x5c.replaceAll("-----BEGIN (.*)-----", "");
stripped = stripped.replaceAll("-----END (.*)----", "");
stripped = stripped.replaceAll("\r\n", "");
stripped = stripped.replaceAll("\n", "");
stripped.trim();
byte[] keyBytes = Base64.getDecoder().decode(stripped);
CertificateFactory fact = CertificateFactory.getInstance("X.509");
return (X509Certificate) fact.generateCertificate(new ByteArrayInputStream(keyBytes));
}
}
接收参数实体类
@Data
public class RefundIosDto {
private String signedPayload;
}
接口代码
@PostMapping("/notification")
public BaseResponse notification(@RequestBody RefundIosDto refundIosDto) {
//记录每次的苹果通知请求
AppleNotificationInfo appleNotificationInfo=new AppleNotificationInfo();
appleNotificationInfo.setCreatetime(new Date());
appleNotificationInfo.setContent(refundIosDto.getSignedPayload());
appleNotificationService.insert(appleNotificationInfo);
//解析苹果请求的数据
String signedPayload=new String(com.google.api.client.util.Base64.decodeBase64(refundIosDto.getSignedPayload().split("\\.")[0]));
// String result2=java.util.Base64.getUrlDecoder().decode(refundIosDto.getSignedPayload()).toString();
JSONObject jsonObject=JSONObject.parseObject(signedPayload);
;
Jws<Claims> result=jwsUtil.verifyJWT(jsonObject.getJSONArray("x5c").get(0).toString(),refundIosDto.getSignedPayload());
System.out.println(result.toString());
String notificationType=result.getBody().get("notificationType").toString();
Claims map=result.getBody();
HashMap<String,Object> envmap=map.get("data",HashMap.class);
String env=envmap.get("environment").toString();
String resulttran=new String(com.google.api.client.util.Base64.decodeBase64(envmap.get("signedTransactionInfo").toString().split("\\.")[0]));
JSONObject jsonObjecttran=JSONObject.parseObject(resulttran);
Jws<Claims> result3=jwsUtil.verifyJWT(jsonObjecttran.getJSONArray("x5c").get(0).toString(),envmap.get("signedTransactionInfo").toString());
System.out.println(result3.getBody().toString());
// HashMap<String,Object> orderMap=result3.getBody().("data",HashMap.class);
logger.info("苹果通知类型:"+notificationType+"环境:"+env);
if(notificationType.equals("DID_RENEW")) {
//查找原始订单的memberuid
// VipOrder vipOrderinsert=new VipOrder();
String transactionId = result3.getBody().get("transactionId").toString();
String productId = result3.getBody().get("productId").toString();
String originalTransactionId = result3.getBody().get("originalTransactionId").toString();
VipOrder vipOrder = vipOrdrService.getOne(originalTransactionId, productId, "ios");
if (Objects.nonNull(vipOrder)&&StringUtils.isNotBlank(productId) && StringUtils.isNotBlank(transactionId)) {//判重,避免重复分发内购商品。
//逻辑代码
}
}
else if(notificationType.equals("REFUND")) {
String originalTransactionId= result3.getBody().get("originalTransactionId").toString();
String productId = result3.getBody().get("productId").toString();
//逻辑代码
}
else {
logger.info("notificationType未处理:" + notificationType);
}
// result.toLowerCase();
return ReturnResponseUtil.Success(ReturnResponseUtil.SUCCESS, "success");
}