苹果IOS内购验单完整流程,in_app购买收据处理

苹果IOS内购验单完整流程,in_app购买收据处理

// 收据格式处理

val data = JsonObject()

data.addProperty("receipt-data", receipt.replace(" ", "+"))

val entity = StringEntity(data.toString())

entity.setContentEncoding("UTF-8")

entity.setContentType("application/json")

// 发送苹果校验

val request = if HttpPost(PURCHASE_CALLBACK_APPSTORE)

request.entity = entity

val client = HttpClientBuilder.create().build()

// 解析校验结果

val response = JsonParser().parse(EntityUtils.toString(client.execute(request).entity, "UTF-8")).asJsonObject

client.close()

if(response["status"].asInt==0){

val re = response["receipt"].asJsonObject

val inApp = re["in_app"].asJsonArray

// 判定inApp是否为空 inApp为空认为订单无效

if (inApp.size() == 0) return false

// 循环验证inAPP内的购买收据

inApp.forEach {

// 判定productId是否符合项目中的内购ID

val productId = it.asJsonObject["product_id"].asString

// 项目中不存在该内购ID收据无效,跳过本次校验

val product = mProductRepo.findByIapId(productId) ?: return@forEach

// 判断transactionId是否验证过

val transactionId = it.asJsonObject["transaction_id"].asString

val tradeLog = mTradeLogRepo.findByTransactionId(transactionId)

// transactionId校验过,跳过本次校验

if (tradeLog != null) return@forEach

try { // 购买异常处理

// 购买逻辑,内部校验服务订单内的商品ID是否和购买收据内的ID匹配

purchaseSuccess(number, product.id)

// 记录验单结果,以便跟踪

addTradeLog(userId, number, receipt, response.toString(), transactionId, 0)

} catch (e: Exception) {

// 记录内部校验失败的记录,以便跟踪

addTradeLog(userId, number, receipt, response.toString(), transactionId, 1)

return@forEach

}

}

}else{

// 记录验证失败的收据

mRedisRepo.put(RedisRepo.KeyType.REJECT_RECEIPT, number, receipt)

}

目前网上大部分内购验单是粗暴的检验收据是否通过苹果校验,容易产生恶意刷单和漏单的情况,本人开发过程中也踩了不少坑。总结了自己认为较为完善的内购验单流程,由于技术有限,流程仅供参考,内部方法,类之类的就不贴出来了,如果有遗漏或者错误的地方,欢迎指正。

相关推荐