Xamarin.iOS의 트랜잭션 및 확인

과거 트랜잭션 복원

애플리케이션에서 복원 가능한 제품 유형을 지원하는 경우 사용자가 해당 구매를 복원할 수 있도록 일부 사용자 인터페이스 요소를 포함해야 합니다. 이 기능을 사용하면 고객이 앱을 초기화하거나 앱을 제거하거나 다시 설치한 후 제품을 추가 디바이스에 추가하거나 동일한 디바이스로 복원할 클린 수 있습니다. 복원 가능한 제품 유형은 다음과 같습니다.

  • 소모성이 없는 제품
  • 자동 재생 가능 구독
  • 무료 구독

복원 프로세스는 제품을 이행하기 위해 디바이스에 보관하는 레코드를 업데이트해야 합니다. 고객은 언제든지 디바이스에서 복원하도록 선택할 수 있습니다. 복원 프로세스는 해당 사용자에 대한 모든 이전 트랜잭션을 다시 보냅니다. 애플리케이션 코드는 해당 정보를 사용하여 수행할 작업을 결정해야 합니다(예: 디바이스에 이미 구매 레코드가 있는 경우 검사, 그렇지 않은 경우 구매 레코드를 만들고 사용자를 위해 제품을 사용하도록 설정).

복원 구현

사용자 인터페이스 복원 단추는 다음 메서드를 호출하여 RestoreCompletedTransactions를 SKPaymentQueue트리거합니다.

public void Restore()
{
   // theObserver will be notified of when the restored transactions start arriving <- AppStore
   SKPaymentQueue.DefaultQueue.RestoreCompletedTransactions();​​​
}

StoreKit는 Apple 서버에 비동기적으로 복원 요청을 보냅니다.

CustomPaymentObserver 트랜잭션 관찰자로 등록되므로 Apple 서버가 응답할 때 메시지를 받습니다. 응답에는 이 사용자가 이 애플리케이션에서 수행한 모든 트랜잭션(모든 디바이스에서)이 포함됩니다. 코드는 각 트랜잭션을 반복하고, 복원된 상태를 검색하고, 아래와 같이 메서드를 호출 UpdatedTransactions 하여 처리합니다.

// called when the transaction status is updated
public override void UpdatedTransactions (SKPaymentQueue queue, SKPaymentTransaction[] transactions)
{
   foreach (SKPaymentTransaction transaction in transactions)
   {
       switch (transaction.TransactionState)
       {
       case SKPaymentTransactionState.Purchased:
          theManager.CompleteTransaction(transaction);
           break;
       case SKPaymentTransactionState.Failed:
          theManager.FailedTransaction(transaction);
           break;
       case SKPaymentTransactionState.Restored:
           theManager.RestoreTransaction(transaction);
           break;
​default:
           break;
       }
   }
}

사용자 UpdatedTransactions 에 대한 복원 가능한 제품이 없으면 호출되지 않습니다.

샘플에서 지정된 트랜잭션을 복원하는 가장 간단한 코드는 제품 ID에 액세스하는 데 속성이 사용된다는 점을 OriginalTransaction 제외하고 구매가 발생할 때와 동일한 작업을 수행합니다.

public void RestoreTransaction (SKPaymentTransaction transaction)
{
   // Restored Transactions always have an 'original transaction' attached
   var productId = transaction.OriginalTransaction.Payment.ProductIdentifier;
   // Register the purchase, so it is remembered for next time
   PhotoFilterManager.Purchase(productId); // it's as though it was purchased again
   FinishTransaction(transaction, true);
}

보다 정교한 구현은 원래 날짜 및 영수증 번호와 같은 다른 transaction.OriginalTransaction 속성을 검사 수 있습니다. 이 정보는 일부 제품 유형(예: 구독)에 유용합니다.

복원 완료

CustomPaymentObserver 복원 프로세스가 완료될 때(성공적으로 또는 오류가 있는 경우) StoreKit에서 호출되는 두 가지 추가 메서드가 있습니다.

public override void PaymentQueueRestoreCompletedTransactionsFinished (SKPaymentQueue queue)
{
   Console.WriteLine(" ** RESTORE Finished ");
}
public override void RestoreCompletedTransactionsFailedWithError (SKPaymentQueue queue, NSError error)
{
   Console.WriteLine(" ** RESTORE FailedWithError " + error.LocalizedDescription);
}

예제에서 이러한 메서드는 아무 작업도 수행하지 않습니다. 그러나 실제 애플리케이션은 사용자에게 메시지를 구현하거나 다른 기능을 구현하도록 선택할 수 있습니다.

구매 보안

이 문서의 두 예제는 구매를 추적하는 데 사용합니다 NSUserDefaults .

소모품 – 신용 구매의 '잔액'은 각 구매에 따라 증가되는 간단한 NSUserDefaults 정수 값입니다.

소모품이 아닙니다. 각 사진 필터 구매는 키-값 쌍으로 저장됩니다 NSUserDefaults.

예제 코드를 사용하면 NSUserDefaults 간단하게 유지되지만 기술적으로 생각하는 사용자가 설정을 업데이트할 수 있으므로 매우 안전한 솔루션을 제공하지는 않습니다(결제 메커니즘 무시).

참고: 실제 애플리케이션은 사용자 변조의 대상이 아닌 구매한 콘텐츠를 저장하기 위한 보안 메커니즘을 채택해야 합니다. 여기에는 암호화 및/또는 원격 서버 인증을 포함한 기타 기술이 포함될 수 있습니다.

또한 iOS, iTunes 및 iCloud의 기본 제공 백업 및 복구 기능을 활용하도록 메커니즘을 설계해야 합니다. 이렇게 하면 사용자가 백업을 복원한 후 이전 구매를 즉시 사용할 수 있습니다.

더 많은 iOS 관련 지침은 Apple의 보안 코딩 가이드를 참조하세요.

영수증 확인 및 서버 배달 제품

지금까지 이 문서의 예제는 앱에 이미 코딩된 기능 또는 기능을 잠금 해제하는 구매 트랜잭션을 수행하기 위해 App Store 서버와 직접 통신하는 애플리케이션으로만 구성되었습니다.

Apple은 구매 영수증을 다른 서버에서 독립적으로 확인할 수 있도록 하여 추가적인 수준의 구매 보안을 제공합니다. 이는 구매의 일부로 디지털 콘텐츠를 배달하기 전에 요청의 유효성을 검사하는 데 유용할 수 있습니다(예: 디지털 책 또는 잡지).

기본 제공 제품 – 이 문서의 예제와 마찬가지로 구매 중인 제품은 애플리케이션과 함께 제공되는 기능으로 존재합니다. 앱에서 구매하면 사용자가 기능에 액세스할 수 있습니다. 제품 ID는 하드 코딩됩니다.

서버 배달 제품 – 이 제품은 트랜잭션이 성공하면 콘텐츠를 다운로드할 때까지 원격 서버에 저장된 다운로드 가능한 콘텐츠로 구성됩니다. 예를 들어 책이나 잡지 문제가 있을 수 있습니다. 제품 ID는 일반적으로 외부 서버(제품 콘텐츠도 호스팅되는 위치)에서 공급됩니다. 애플리케이션은 트랜잭션이 완료될 때 강력한 기록 방법을 구현해야 하므로 콘텐츠 다운로드가 실패할 경우 사용자를 혼동하지 않고 다시 시도할 수 있습니다.

서버 제공 제품

구매 프로세스 중에 책과 잡지(또는 게임 수준)와 같은 일부 제품의 콘텐츠를 원격 서버에서 다운로드해야 합니다. 즉, 제품 콘텐츠를 구매한 후 저장하고 배달하려면 추가 서버가 필요합니다.

서버 제공 제품의 가격 가져오기

제품이 원격으로 배달되기 때문에 더 많은 책이나 잡지의 새로운 문제를 추가하는 등 시간이 지남에 따라 (앱 코드를 업데이트하지 않고) 더 많은 제품을 추가할 수도 있습니다. 애플리케이션에서 이러한 뉴스 제품을 검색하고 사용자에게 표시할 수 있도록 추가 서버는 이 정보를 저장하고 제공해야 합니다.

Getting Prices for Server-Delivered Products

  1. 제품 정보는 서버 및 iTunes 커넥트 여러 위치에 저장해야 합니다. 또한 각 제품에는 연결된 콘텐츠 파일이 있습니다. 이러한 파일은 성공적으로 구매한 후에 배달됩니다.

  2. 사용자가 제품을 구매하려는 경우 애플리케이션은 사용 가능한 제품을 결정해야 합니다. 이 정보는 캐시될 수 있지만 제품의 마스터 목록이 저장된 원격 서버에서 전달해야 합니다.

  3. 서버는 구문 분석할 애플리케이션에 대한 제품 ID 목록을 반환합니다.

  4. 그런 다음 애플리케이션은 가격 및 설명을 검색하기 위해 StoreKit에 보낼 제품 ID를 결정합니다.

  5. StoreKit은 제품 ID 목록을 Apple의 서버로 보냅니다.

  6. iTunes 서버는 유효한 제품 정보(설명 및 현재 가격)로 응답합니다.

  7. 애플리케이션 SKProductsRequestDelegate 은 사용자에게 표시할 제품 정보를 전달합니다.

서버 배달 제품 구매

원격 서버에는 콘텐츠 요청이 유효한지 확인하는 방법이 필요하기 때문에(예: 지불된 경우) 인증을 위해 영수증 정보가 전달됩니다. 원격 서버는 확인을 위해 해당 데이터를 iTunes에 전달하고, 성공하면 애플리케이션에 대한 응답에 제품 콘텐츠를 포함합니다.

Purchasing Server-Delivered Products

  1. 앱은 큐에 SKPayment 추가합니다. 필요한 경우 사용자에게 Apple ID를 묻는 메시지가 표시되고 결제를 확인하라는 메시지가 표시됩니다.

  2. StoreKit는 처리를 위해 서버에 요청을 보냅니다.

  3. 트랜잭션이 완료되면 서버가 트랜잭션 영수증으로 응답합니다.

  4. SKPaymentTransactionObserver 서브클래스는 영수증을 받고 처리합니다. 제품을 서버에서 다운로드해야 하므로 애플리케이션은 원격 서버에 대한 네트워크 요청을 시작합니다.

  5. 다운로드 요청에는 영수증 데이터가 함께 제공되므로 원격 서버가 콘텐츠에 액세스할 수 있는 권한이 있는지 확인할 수 있습니다. 애플리케이션의 네트워크 클라이언트는 이 요청에 대한 응답을 기다립니다.

  6. 서버는 콘텐츠 요청을 받으면 영수증 데이터를 구문 분석하고 iTunes 서버에 직접 요청을 보내 영수증이 유효한 트랜잭션인지 확인합니다. 서버는 일부 논리를 사용하여 프로덕션 또는 샌드박스 URL에 요청을 보낼지 여부를 결정해야 합니다. Apple은 21007(프로덕션 서버로 전송된 샌드박스 영수증)상태 받는 경우 항상 프로덕션 URL을 사용하고 샌드박스로 전환하는 것이 좋습니다. 자세한 내용은 Apple의 영수증 유효성 검사 프로그래밍 가이드 를 참조하세요.

  7. iTunes는 영수증을 검사 유효한 경우 0의 상태 반환합니다.

  8. 서버는 iTunes의 응답을 기다립니다. 유효한 응답을 받으면 코드는 애플리케이션에 대한 응답에 포함할 연결된 제품 콘텐츠 파일을 찾아야 합니다.

  9. 애플리케이션은 응답을 수신하고 구문 분석하여 제품 콘텐츠를 디바이스의 파일 시스템에 저장합니다.

  10. 애플리케이션은 제품을 사용하도록 설정한 다음 StoreKit를 FinishTransaction호출합니다. 그러면 애플리케이션에서 필요에 따라 구매한 콘텐츠를 표시할 수 있습니다(예: 구매한 책 또는 잡지 문제의 첫 번째 페이지 표시).

매우 큰 제품 콘텐츠 파일에 대한 대체 구현에는 트랜잭션을 신속하게 완료할 수 있도록 9단계에서 트랜잭션 영수증을 저장하고 나중에 실제 제품 콘텐츠를 다운로드할 수 있는 사용자 인터페이스를 제공하는 것이 포함될 수 있습니다. 후속 다운로드 요청은 저장된 영수증을 다시 전송하여 필요한 제품 콘텐츠 파일에 액세스할 수 있습니다.

서버 쪽 영수증 확인 코드 작성

워크플로 다이어그램에서 5~8단계를 포함하는 간단한 HTTP POST 요청/응답을 사용하여 서버 쪽 코드에서 영수증의 유효성을 검사할 수 있습니다.

앱에서 SKPaymentTansaction.TransactionReceipt 속성을 추출합니다. 확인을 위해 iTunes로 보내야 하는 데이터입니다(5단계).

Base64-트랜잭션 영수증 데이터(5단계 또는 #6)를 인코딩합니다.

다음과 같이 간단한 JSON 페이로드를 만듭니다.

{
   "receipt-data" : "(base-64 encoded receipt here)"
}

프로덕션 또는 https://sandbox.itunes.apple.com/verifyReceipt 테스트를 위해 JSON을 https://buy.itunes.apple.com/verifyReceipt HTTP POST합니다.

JSON 응답에는 다음 키가 포함됩니다.

{
   "status" : 0,
   "receipt" : { (receipt repeated here) }
}

상태 0은 유효한 영수증을 나타냅니다. 서버에서 구매한 제품의 콘텐츠를 계속 처리할 수 있습니다. 영수증 키에는 앱에서 받은 개체와 동일한 속성을 SKPaymentTransaction 가진 JSON 사전이 포함되어 있으므로 서버 코드는 이 사전을 쿼리하여 구매의 product_id 및 수량과 같은 정보를 검색할 수 있습니다.

자세한 내용은 Apple의 영수증 유효성 검사 프로그래밍 가이드 설명서를 참조하세요.