Skip to content

Instantly share code, notes, and snippets.

@sandyxu
Forked from sauloarruda/receipt
Last active December 30, 2015 05:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sandyxu/7783761 to your computer and use it in GitHub Desktop.
Save sandyxu/7783761 to your computer and use it in GitHub Desktop.
Verify in-app payment data on App store & Android market
ewoJInNpZ25hdHVyZSIgPSAiQXBNVUJDODZBbHpOaWtWNVl0clpBTWlKUWJLOEVk
ZVhrNjNrV0JBWHpsQzhkWEd1anE0N1puSVlLb0ZFMW9OL0ZTOGNYbEZmcDlZWHQ5
aU1CZEwyNTBsUlJtaU5HYnloaXRyeVlWQVFvcmkzMlc5YVIwVDhML2FZVkJkZlcr
T3kvUXlQWkVtb05LeGhudDJXTlNVRG9VaFo4Wis0cFA3MHBlNWtVUWxiZElWaEFB
QURWekNDQTFNd2dnSTdvQU1DQVFJQ0NHVVVrVTNaV0FTMU1BMEdDU3FHU0liM0RR
RUJCUVVBTUg4eEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUtEQXBCY0hCc1pT
QkpibU11TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlF
RjFkR2h2Y21sMGVURXpNREVHQTFVRUF3d3FRWEJ3YkdVZ2FWUjFibVZ6SUZOMGIz
SmxJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1CNFhEVEE1TURZeE5U
SXlNRFUxTmxvWERURTBNRFl4TkRJeU1EVTFObG93WkRFak1DRUdBMVVFQXd3YVVI
VnlZMmhoYzJWU1pXTmxhWEIwUTJWeWRHbG1hV05oZEdVeEd6QVpCZ05WQkFzTUVr
RndjR3hsSUdsVWRXNWxjeUJUZEc5eVpURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NX
NWpMakVMTUFrR0ExVUVCaE1DVlZNd2daOHdEUVlKS29aSWh2Y05BUUVCQlFBRGdZ
MEFNSUdKQW9HQkFNclJqRjJjdDRJclNkaVRDaGFJMGc4cHd2L2NtSHM4cC9Sd1Yv
cnQvOTFYS1ZoTmw0WElCaW1LalFRTmZnSHNEczZ5anUrK0RyS0pFN3VLc3BoTWRk
S1lmRkU1ckdYc0FkQkVqQndSSXhleFRldngzSExFRkdBdDFtb0t4NTA5ZGh4dGlJ
ZERnSnYyWWFWczQ5QjB1SnZOZHk2U01xTk5MSHNETHpEUzlvWkhBZ01CQUFHamNq
QndNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVVOaDNvNHAyQzBn
RVl0VEpyRHRkREM1RllRem93RGdZRFZSMFBBUUgvQkFRREFnZUFNQjBHQTFVZERn
UVdCQlNwZzRQeUdVakZQaEpYQ0JUTXphTittVjhrOVRBUUJnb3Foa2lHOTJOa0Jn
VUJCQUlGQURBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQUVhU2JQanRtTjRDL0lC
M1FFcEszMlJ4YWNDRFhkVlhBZVZSZVM1RmFaeGMrdDg4cFFQOTNCaUF4dmRXLzNl
VFNNR1k1RmJlQVlMM2V0cVA1Z204d3JGb2pYMGlreVZSU3RRKy9BUTBLRWp0cUIw
N2tMczlRVWU4Y3pSOFVHZmRNMUV1bVYvVWd2RGQ0TndOWXhMUU1nNFdUUWZna1FR
Vnk4R1had1ZIZ2JFL1VDNlk3MDUzcEdYQms1MU5QTTN3b3hoZDNnU1JMdlhqK2xv
SHNTdGNURXFlOXBCRHBtRzUrc2s0dHcrR0szR01lRU41LytlMVFUOW5wL0tsMW5q
K2FCdzdDMHhzeTBiRm5hQWQxY1NTNnhkb3J5L0NVdk02Z3RLc21uT09kcVRlc2Jw
MGJzOHNuNldxczBDOWRnY3hSSHVPTVoydG04bnBMVW03YXJnT1N6UT09IjsKCSJw
dXJjaGFzZS1pbmZvIiA9ICJld29KSW05eWFXZHBibUZzTFhCMWNtTm9ZWE5sTFdS
aGRHVXRjSE4wSWlBOUlDSXlNREV5TFRBMExUTXdJREE0T2pBMU9qVTFJRUZ0WlhK
cFkyRXZURzl6WDBGdVoyVnNaWE1pT3dvSkltOXlhV2RwYm1Gc0xYUnlZVzV6WVdO
MGFXOXVMV2xrSWlBOUlDSXhNREF3TURBd01EUTJNVGM0T0RFM0lqc0tDU0ppZG5K
eklpQTlJQ0l5TURFeU1EUXlOeUk3Q2draWRISmhibk5oWTNScGIyNHRhV1FpSUQw
Z0lqRXdNREF3TURBd05EWXhOemc0TVRjaU93b0pJbkYxWVc1MGFYUjVJaUE5SUNJ
eElqc0tDU0p2Y21sbmFXNWhiQzF3ZFhKamFHRnpaUzFrWVhSbExXMXpJaUE5SUNJ
eE16TTFOems0TXpVMU9EWTRJanNLQ1NKd2NtOWtkV04wTFdsa0lpQTlJQ0pqYjIw
dWJXbHVaRzF2WW1Gd2NDNWtiM2R1Ykc5aFpDSTdDZ2tpYVhSbGJTMXBaQ0lnUFNB
aU5USXhNVEk1T0RFeUlqc0tDU0ppYVdRaUlEMGdJbU52YlM1dGFXNWtiVzlpWVhC
d0xrMXBibVJOYjJJaU93b0pJbkIxY21Ob1lYTmxMV1JoZEdVdGJYTWlJRDBnSWpF
ek16VTNPVGd6TlRVNE5qZ2lPd29KSW5CMWNtTm9ZWE5sTFdSaGRHVWlJRDBnSWpJ
d01USXRNRFF0TXpBZ01UVTZNRFU2TlRVZ1JYUmpMMGROVkNJN0Nna2ljSFZ5WTJo
aGMyVXRaR0YwWlMxd2MzUWlJRDBnSWpJd01USXRNRFF0TXpBZ01EZzZNRFU2TlRV
Z1FXMWxjbWxqWVM5TWIzTmZRVzVuWld4bGN5STdDZ2tpYjNKcFoybHVZV3d0Y0hW
eVkyaGhjMlV0WkdGMFpTSWdQU0FpTWpBeE1pMHdOQzB6TUNBeE5Ub3dOVG8xTlNC
RmRHTXZSMDFVSWpzS2ZRPT0iOwoJImVudmlyb25tZW50IiA9ICJTYW5kYm94IjsK
CSJwb2QiID0gIjEwMCI7Cgkic2lnbmluZy1zdGF0dXMiID0gIjAiOwp9
{
"receipt": {
"original_purchase_date_pst": "2012-04-30 08:05:55 America/Los_Angeles",
"original_transaction_id": "1000000046178817",
"original_purchase_date_ms": "1335798355868",
"transaction_id": "1000000046178817",
"quantity": "1",
"product_id": "br.com.jera.Example",
"bvrs": "20120427",
"purchase_date_ms": "1335798355868",
"purchase_date": "2012-04-30 15:05:55 Etc/GMT",
"original_purchase_date": "2012-04-30 15:05:55 Etc/GMT",
"purchase_date_pst": "2012-04-30 08:05:55 America/Los_Angeles",
"bid": "br.com.jera.Example",
"item_id": "521129812"
},
"status": 0
}
/* 2014-09-23 */
{"receipt"=>
{"original_purchase_date_pst"=>"2014-08-23 02:41:58 America/Los_Angeles",
"unique_identifier"=>"bd07c727b484155cf23415b4d2f01e9f3e89638d",
"original_transaction_id"=>"240000108530732",
"bvrs"=>"1.10.6",
"app_item_id"=>"820775657",
"transaction_id"=>"240000108530732",
"quantity"=>"1",
"unique_vendor_identifier"=>"6E2A1F82-BFF9-482D-BC2F-55CF6CCD4E6C",
"product_id"=>"cn.accessbright.rod.new.0001",
"item_id"=>"820775781",
"version_external_identifier"=>"552312833",
"bid"=>"cn.accessbright.rod.new",
"purchase_date_ms"=>"1408786918295",
"purchase_date"=>"2014-08-23 09:41:58 Etc/GMT",
"purchase_date_pst"=>"2014-08-23 02:41:58 America/Los_Angeles",
"original_purchase_date"=>"2014-08-23 09:41:58 Etc/GMT",
"original_purchase_date_ms"=>"1408786918295"},
"status"=>0}
-----BEGIN PUBLIC KEY-----
NIIIjANBgkqhkiG9w0BAQEFAAOCA12AMIIBCgKCAQEAm30EgLzmT0wGF71ecnHQ
B6TAZZR2s6tNRTHrXz6NSldO5MhkvrPyE2rgedUelBS8TIYnJuv24SJb9AOumQDk
+fNUkYX2GwswZEc5iZ5KUHEpPSag1N4F0Fh//Eo7OVHD4YCchmTA6nNRo++GgQB4
DGFov2boLT8/QkjyN7GgRTQKAIXqXwFGSZI67rN0fgH12LhexOfWMjOv8tokK7ay
dimEyffpL1lCaGyr49ik/Ufkzd/Wu27Zwa9z7OtLqyd9+aY7RWEjStm0PQyEq11l
cAWYnY1EPoB2A+txep3WSG/Xu2OrYsUvmEv0mBPesxvNKzipEM3frlqQKbPKrda7
FQIDAQAA
-----END PUBLIC KEY-----
require 'rubygems'
require 'openssl'
require 'base64'
def main
# 注意 receipt是String类型
receipt = '{"orderId":"12999763169054705758.1304279243034704","packageName":"net.ty.android.pf.greeapp57501.xg","productId":"stone_3770","purchaseTime":1418115851461,"purchaseState":0,"developerPayload":"google14181158390582684418630128","purchaseToken":"jdpbjbbfipfjcemhonfhehfe.AO-J1Owb3bs4xcUswTi9AwTButThMyNpGEu2lUz_CD5J_OxwMLozAmypfyfKkNIffNY6F07YiHxkX89F0m7He4LRWaIf1HKzNHAnYdKYzCa_uYzuBl45aIo7FtZqxhUNgkYYYV84ddr7"}'
signature = "Ybzp0rAwKpfr9M40CMCw3UZaAHnJqnlZfZfaPwX+ALUWy5tprrIA8qYQcxZSU2PMstNvGU3AN6SFAGcYLOaWdFCrrulSEkyYwMBi+7Ya7f3t673SHzfKARLR5q7LACStE/pMMfMkfldcUG35DtA2m6IVarLsJuStglJVpwG+ReksBXon/ecjAV410nKcWlTdJdc7ocSj4bM9oh+OzkMwDKnIvuH5PCqCCEAzkdyEV342RWFmpQVc5QrWMZIo9MYwKIt6Bl1cLz2NU7ZmSrPcL8leYMMTjHOD1gdhu/AEekbmXjp4ZNIkDpd1BudxgmTSZfWM+xXT7dXWw4kkVosp9w=="
public_key = OpenSSL::PKey::RSA.new read_file(ARGV[0])
#verify the signature digest was encrypted with priv key & matches digest for receipt string
verified = public_key.verify( OpenSSL::Digest::SHA1.new, Base64.decode64(signature), receipt)
print "Wow... thats #{verified} amazing\n"
end
def read_file(file_name)
file = File.open(file_name, "r")
data = file.read
file.close
return data
end
# ruby verify-_oogle_market_in_app.rb 'my-public-key.pem'
main
# This code call the apple sandbox in app purchase server to validate a receipt using Ruby Code.
# Run this using "ruby verifyReceipt.rb"
# By @sauloarruda (http://twitter.com/sauloarruda)
require 'net/http'
# This core reads an file called receipt (see an example bellow)
params_json = "{ \"receipt-data\": \"#{open("./receipt").read}\" }"
# Use net/http to post to apple sandbox server
uri = URI("https://sandbox.itunes.apple.com") # Use "https://buy.itunes.apple.com" for production
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
response = http.post('/verifyReceipt', params_json)
# Puts the result! (see an example below - result.json)
puts response.body
end
1) my-public-key.pem : 以 -----BEGIN PUBLIC KEY----- 开头,以 -----END PUBLIC KEY----- 结尾;每行长度64个字符(\n)表示换行。
***我这里pem是一个伪造的demo,请以自己申请的为准***
2)verify-_google_market_in_app.rb 使用 openssl的验证方式确认Google play购买是否有效。
verified = public_key.verify( OpenSSL::Digest::SHA1.new, Base64.decode64(signature), receipt)
receipt 参数为String,如果是json时注意顺序。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment