Tout d'abord, il y a quelques erreurs de frappe dans le code affiché. Essayez ceci. (Disclaimer : Refactoring et. al est laissé comme un exercice pour le lectorat !)
- (BOOL)verifyReceipt:(SKPaymentTransaction *)transaction {
NSString *jsonObjectString = [self encode:(uint8_t *)transaction.transactionReceipt.bytes length:transaction.transactionReceipt.length];
NSString *completeString = [NSString stringWithFormat:@"http://url-for-your-php?receipt=%@", jsonObjectString];
NSURL *urlForValidation = [NSURL URLWithString:completeString];
NSMutableURLRequest *validationRequest = [[NSMutableURLRequest alloc] initWithURL:urlForValidation];
[validationRequest setHTTPMethod:@"GET"];
NSData *responseData = [NSURLConnection sendSynchronousRequest:validationRequest returningResponse:nil error:nil];
[validationRequest release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding: NSUTF8StringEncoding];
NSInteger response = [responseString integerValue];
[responseString release];
return (response == 0);
}
- (NSString *)encode:(const uint8_t *)input length:(NSInteger)length {
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData *data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t *output = (uint8_t *)data.mutableBytes;
for (NSInteger i = 0; i < length; i += 3) {
NSInteger value = 0;
for (NSInteger j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
NSInteger index = (i / 3) * 4;
output[index + 0] = table[(value >> 18) & 0x3F];
output[index + 1] = table[(value >> 12) & 0x3F];
output[index + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
output[index + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
}
return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
}
Vous pouvez créer ces méthodes internes sur la classe qui gère votre SKPaymentTransactionObserver messages :
@interface YourStoreClass (Internal)
- (BOOL)verifyReceipt:(SKPaymentTransaction *)transaction;
- (NSString *)encode:(const uint8_t *)input length:(NSInteger)length;
@end
Remarque : Vous pourrait utiliser quelque chose comme libcrypto pour gérer l'encodage base64, mais il faut alors tenir compte des restrictions à l'exportation et des étapes supplémentaires au moment de l'approbation de l'application. Mais je m'égare...
Ensuite, quel que soit l'endroit où vous avez l'intention de lancer l'enregistrement de la transaction sur votre serveur distant, appelez vérifier le reçu : avec votre transaction et assurez-vous qu'elle revienne positive.
Pendant ce temps, sur votre serveur, voici du PHP simplifié pour gérer les choses :
$receipt = json_encode(array("receipt-data" => $_GET["receipt"]));
// NOTE: use "buy" vs "sandbox" in production.
$url = "https://sandbox.itunes.apple.com/verifyReceipt";
$response_json = call-your-http-post-here($url, $receipt);
$response = json_decode($response_json);
// Save the data here!
echo $response->status;
Où appelez-votre-poste-http-ici est votre mécanisme d'affichage HTTP préféré. ( cURL est un choix possible. YMMV. PHP.net a le scoop !)
Une chose qui m'inquiète un peu est la longueur de la charge utile dans l'URL allant de l'application au serveur (via GET). Je ne sais plus s'il y a un problème de longueur dans les RFC. Peut-être que c'est correct, ou peut-être que c'est spécifique au serveur. (Lecteurs : vos conseils sont les bienvenus sur ce point !)
Il se peut également qu'il y ait des réticences à faire de cette demande une demande synchrone. Vous voudrez peut-être la poster de manière asynchrone et mettre en place le bon vieil UIActivityIndicatorView ou un autre HUD. Un exemple concret : Ce initWithData:encodage : L'appel prend un loooooong temps pour moi. Quelques secondes, ce qui est une petite éternité au pays de l'iPhone (ou partout ailleurs en ligne, d'ailleurs). L'affichage d'une sorte d'indicateur de progression indéterminé pourrait être conseillé.