Skip to content

Instantly share code, notes, and snippets.

@hechien
Created October 11, 2012 06:39
Show Gist options
  • Select an option

  • Save hechien/3870614 to your computer and use it in GitHub Desktop.

Select an option

Save hechien/3870614 to your computer and use it in GitHub Desktop.
iAP Server verify with Ruby

關於這份文件

之所以會寫這份文件是因為想要記錄一下弄了好幾天的iAP Server驗證終於做出來了,後來才發現其實好簡單 …

廢話不多說,就直接開始吧

  1. 先有一個iAP的流程,反正就是要可以買就是了,然後在購買成功的時候會呼叫- (void)completeTransaction:(SKPaymentTransaction*)transaction才對,而整個流程就是在這個裡面處理。
  2. Apple送過來的東西基本上要轉成Base64才可以work,而轉換的程式碼是:
- (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];
}
  1. 接著,在completeTransaction中得到的變數中可以取得交易後的資料,然後交給上面提到的Code去轉成Base64 [self encode:((uint8_t*)[[transaction transactionReceipt] bytes]) length:[transaction transactionReceipt].length]
  2. 然後取到的Base64 code就可以丟給Ruby去做驗證。由於我們現在要用測試環境去驗證,所以我們要連到sandbox.itunes.apple.com這台主機,然後要扔到https通道內。
  3. 該做的事情是在Ruby收到了data後要塞到一個JSON內,而且這個data不需要先透過Base64 decode的動作(我卡在這邊卡一小陣子)。
  4. 然後丟到Apple那邊去,回來的東西如果有顯示{status: 0} 這樣就表示此筆交易有效。

必須注意的是,送給Apple的東西必須是JSON,所以Content-Type也要為application/json

Ruby Code如下:

#encoding: utf-8
#!/usr/bin/env ruby

require 'rest-client'
require 'yajl'
require 'json'
require 'pry'
require 'pry-nav'
require 'base64'

code = "ewoJInNpZ25hdHVyZSIgPSAiQXJxaXFVTG83Q3duVG9XU3pOS25TbDFPSUJrbjRDWmdaVHNza2syb2ZTVmZwcEVPM1lZWTNIU2x6TW9tLzhLWG1KTnJBcnp2QTdxbG5zOCs4SVJKcjN1NFRudWpUcDRqQ0wwaHlOSGVCRDY3UldCc2w3ekM4UzBCWTIraDBnZ0Y3eEM0TnJtY0VTNCs2RUxzUFd4Ui9ZdnF0ZlBGQlZkSVVDUFZQY3FjY25KM0FBQURWekNDQTFNd2dnSTdvQU1DQVFJQ0NHVVVrVTNaV0FTMU1BMEdDU3FHU0liM0RRRUJCUVVBTUg4eEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURXpNREVHQTFVRUF3d3FRWEJ3YkdVZ2FWUjFibVZ6SUZOMGIzSmxJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1CNFhEVEE1TURZeE5USXlNRFUxTmxvWERURTBNRFl4TkRJeU1EVTFObG93WkRFak1DRUdBMVVFQXd3YVVIVnlZMmhoYzJWU1pXTmxhWEIwUTJWeWRHbG1hV05oZEdVeEd6QVpCZ05WQkFzTUVrRndjR3hsSUdsVWRXNWxjeUJUZEc5eVpURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd2daOHdEUVlKS29aSWh2Y05BUUVCQlFBRGdZMEFNSUdKQW9HQkFNclJqRjJjdDRJclNkaVRDaGFJMGc4cHd2L2NtSHM4cC9Sd1YvcnQvOTFYS1ZoTmw0WElCaW1LalFRTmZnSHNEczZ5anUrK0RyS0pFN3VLc3BoTWRkS1lmRkU1ckdYc0FkQkVqQndSSXhleFRldngzSExFRkdBdDFtb0t4NTA5ZGh4dGlJZERnSnYyWWFWczQ5QjB1SnZOZHk2U01xTk5MSHNETHpEUzlvWkhBZ01CQUFHamNqQndNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVVOaDNvNHAyQzBnRVl0VEpyRHRkREM1RllRem93RGdZRFZSMFBBUUgvQkFRREFnZUFNQjBHQTFVZERnUVdCQlNwZzRQeUdVakZQaEpYQ0JUTXphTittVjhrOVRBUUJnb3Foa2lHOTJOa0JnVUJCQUlGQURBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQUVhU2JQanRtTjRDL0lCM1FFcEszMlJ4YWNDRFhkVlhBZVZSZVM1RmFaeGMrdDg4cFFQOTNCaUF4dmRXLzNlVFNNR1k1RmJlQVlMM2V0cVA1Z204d3JGb2pYMGlreVZSU3RRKy9BUTBLRWp0cUIwN2tMczlRVWU4Y3pSOFVHZmRNMUV1bVYvVWd2RGQ0TndOWXhMUU1nNFdUUWZna1FRVnk4R1had1ZIZ2JFL1VDNlk3MDUzcEdYQms1MU5QTTN3b3hoZDNnU1JMdlhqK2xvSHNTdGNURXFlOXBCRHBtRzUrc2s0dHcrR0szR01lRU41LytlMVFUOW5wL0tsMW5qK2FCdzdDMHhzeTBiRm5hQWQxY1NTNnhkb3J5L0NVdk02Z3RLc21uT09kcVRlc2JwMGJzOHNuNldxczBDOWRnY3hSSHVPTVoydG04bnBMVW03YXJnT1N6UT09IjsKCSJwdXJjaGFzZS1pbmZvIiA9ICJld29KSW05eWFXZHBibUZzTFhCMWNtTm9ZWE5sTFdSaGRHVXRjSE4wSWlBOUlDSXlNREV5TFRFd0xURXdJREl4T2pFek9qTTFJRUZ0WlhKcFkyRXZURzl6WDBGdVoyVnNaWE1pT3dvSkluVnVhWEYxWlMxcFpHVnVkR2xtYVdWeUlpQTlJQ0kyTldJeFlqTmhOR0l5TWpoaU1tWTVOR1ZsWVdJMFpqa3dNVEppTmpOalkyTmlZakE0TXpWaklqc0tDU0p2Y21sbmFXNWhiQzEwY21GdWMyRmpkR2x2YmkxcFpDSWdQU0FpTVRBd01EQXdNREExTmprMU5qY3hPU0k3Q2draVluWnljeUlnUFNBaU1TNHdJanNLQ1NKMGNtRnVjMkZqZEdsdmJpMXBaQ0lnUFNBaU1UQXdNREF3TURBMU5qazFOamN4T1NJN0Nna2ljWFZoYm5ScGRIa2lJRDBnSWpFaU93b0pJbTl5YVdkcGJtRnNMWEIxY21Ob1lYTmxMV1JoZEdVdGJYTWlJRDBnSWpFek5EazVNamc0TVRVMk5ERWlPd29KSW5WdWFYRjFaUzEyWlc1a2IzSXRhV1JsYm5ScFptbGxjaUlnUFNBaVJEQkdNVEpDUVRJdFFrVTBNaTAwTjBRNExVRTVOa1V0T0RCRk1qTXdORFZCTmpWRElqc0tDU0p3Y205a2RXTjBMV2xrSWlBOUlDSmpiMjB1YTJSaGJtMXZZbWxzWlM1bWIyOWthV1YwYUdWaWRXZGZhVzVoY0hCZlltVmhNU0k3Q2draWFYUmxiUzFwWkNJZ1BTQWlOVEEwTlRNME56ZzNJanNLQ1NKaWFXUWlJRDBnSW1OdmJTNXRaV2RoWTNWaWFXTXVabTl2WkdsbGRHaGxZblZuSWpzS0NTSndkWEpqYUdGelpTMWtZWFJsTFcxeklpQTlJQ0l4TXpRNU9USTRPREUxTmpReElqc0tDU0p3ZFhKamFHRnpaUzFrWVhSbElpQTlJQ0l5TURFeUxURXdMVEV4SURBME9qRXpPak0xSUVWMFl5OUhUVlFpT3dvSkluQjFjbU5vWVhObExXUmhkR1V0Y0hOMElpQTlJQ0l5TURFeUxURXdMVEV3SURJeE9qRXpPak0xSUVGdFpYSnBZMkV2VEc5elgwRnVaMlZzWlhNaU93b0pJbTl5YVdkcGJtRnNMWEIxY21Ob1lYTmxMV1JoZEdVaUlEMGdJakl3TVRJdE1UQXRNVEVnTURRNk1UTTZNelVnUlhSakwwZE5WQ0k3Q24wPSI7CgkiZW52aXJvbm1lbnQiID0gIlNhbmRib3giOwoJInBvZCIgPSAiMTAwIjsKCSJzaWduaW5nLXN0YXR1cyIgPSAiMCI7Cn0="
json = {'receipt-data' => code}
rep = RestClient.post 'https://sandbox.itunes.apple.com/verifyReceipt', json.to_json, {content_type: :json}

binding.pry
#encoding: utf-8
$LOAD_PATH << '.'
require 'uri'
require 'yajl'
DEBUG = true
_uri = ''
if DEBUG
_uri = 'https://sandbox.itunes.apple.com'
else
_uri = 'https://buy.itunes.apple.com'
end
ITUNES_URL = URI.parse(_uri)
require 'sinatra'
require 'net/http'
helpers do
def verify_status(data)
Net::HTTP.start(ITUNES_URL.host, ITUNES_URL.port, use_ssl: true) do |http|
puts data
return (http.post('/verifyReceipt', data)).body
end
end
end
post '/verify' do
verify_status(Yajl::Encoder.encode({'receipt-data' => params[:code]}))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment