diff --git a/apple/cert.go b/apple/cert.go index 812cfe46..59040476 100644 --- a/apple/cert.go +++ b/apple/cert.go @@ -13,7 +13,7 @@ func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) { // Parse PEM block var block *pem.Block if block, _ = pem.Decode(key); block == nil { - return nil, errors.New("ErrKeyMustBePEMEncoded") + return nil, errors.New("decode private key error") } // Parse the key var parsedKey interface{} @@ -24,7 +24,7 @@ func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) { } pkey, ok := parsedKey.(*ecdsa.PrivateKey) if !ok { - return nil, errors.New("ErrNotECPrivateKey") + return nil, errors.New("private key must be ECP private key") } return pkey, nil } diff --git a/apple/notification_v2.go b/apple/notification_v2.go index 632f05cc..e2b7e0b0 100644 --- a/apple/notification_v2.go +++ b/apple/notification_v2.go @@ -34,8 +34,7 @@ func DecodeSignedPayload(signedPayload string) (payload *NotificationV2Payload, return nil, fmt.Errorf("signedPayload is empty") } payload = &NotificationV2Payload{} - _, err = ExtractClaims(signedPayload, payload) - if err != nil { + if err = ExtractClaims(signedPayload, payload); err != nil { return nil, err } return diff --git a/apple/notification_v2_model.go b/apple/notification_v2_model.go index da7477d8..21fb3782 100644 --- a/apple/notification_v2_model.go +++ b/apple/notification_v2_model.go @@ -64,8 +64,7 @@ func (d *NotificationV2Payload) DecodeRenewalInfo() (ri *RenewalInfo, err error) return nil, fmt.Errorf("data.signedRenewalInfo is empty") } ri = &RenewalInfo{} - _, err = ExtractClaims(d.Data.SignedRenewalInfo, ri) - if err != nil { + if err = ExtractClaims(d.Data.SignedRenewalInfo, ri); err != nil { return nil, err } return @@ -79,8 +78,7 @@ func (d *NotificationV2Payload) DecodeTransactionInfo() (ti *TransactionInfo, er return nil, fmt.Errorf("data.signedTransactionInfo is empty") } ti = &TransactionInfo{} - _, err = ExtractClaims(d.Data.SignedTransactionInfo, ti) - if err != nil { + if err = ExtractClaims(d.Data.SignedTransactionInfo, ti); err != nil { return nil, err } return @@ -135,8 +133,11 @@ type TransactionInfo struct { SignedDate int64 `json:"signedDate"` // Auto-Renewable Subscription: An auto-renewable subscription. Non-Consumable: A non-consumable in-app purchase. Consumable: A consumable in-app purchase. Non-Renewing Subscription: A non-renewing subcription. SubscriptionGroupIdentifier string `json:"subscriptionGroupIdentifier"` TransactionId string `json:"transactionId"` + TransactionReason string `json:"transactionReason"` Type string `json:"type"` WebOrderLineItemId string `json:"webOrderLineItemId"` + Storefront string `json:"storefront"` + StorefrontId string `json:"storefrontId"` } type NotificationHistoryRsp struct { diff --git a/apple/subscription_model.go b/apple/subscription_model.go index 5ab4ba9e..0ece89c5 100644 --- a/apple/subscription_model.go +++ b/apple/subscription_model.go @@ -27,8 +27,7 @@ func (d *LastTransactionsItem) DecodeRenewalInfo() (ri *RenewalInfo, err error) return nil, fmt.Errorf("SignedRenewalInfo is empty") } ri = &RenewalInfo{} - _, err = ExtractClaims(d.SignedRenewalInfo, ri) - if err != nil { + if err = ExtractClaims(d.SignedRenewalInfo, ri); err != nil { return nil, err } return ri, nil @@ -39,8 +38,7 @@ func (d *LastTransactionsItem) DecodeTransactionInfo() (ti *TransactionInfo, err return nil, fmt.Errorf("signedTransactionInfo is empty") } ti = &TransactionInfo{} - _, err = ExtractClaims(d.SignedTransactionInfo, ti) - if err != nil { + if err = ExtractClaims(d.SignedTransactionInfo, ti); err != nil { return nil, err } return ti, nil diff --git a/apple/transaction_model.go b/apple/transaction_model.go index 5da6cab9..356df93f 100644 --- a/apple/transaction_model.go +++ b/apple/transaction_model.go @@ -45,8 +45,7 @@ func (s *SignedTransaction) DecodeSignedTransaction() (ti *TransactionsItem, err return nil, fmt.Errorf("signedTransactions is empty") } ti = &TransactionsItem{} - _, err = ExtractClaims(string(*s), ti) - if err != nil { + if err = ExtractClaims(string(*s), ti); err != nil { return nil, err } return ti, nil @@ -63,8 +62,7 @@ func (t *TransactionInfoRsp) DecodeSignedTransaction() (ti *TransactionsItem, er return nil, fmt.Errorf("signedTransactionInfo is empty") } ti = &TransactionsItem{} - _, err = ExtractClaims(t.SignedTransactionInfo, ti) - if err != nil { + if err = ExtractClaims(t.SignedTransactionInfo, ti); err != nil { return nil, err } return ti, nil diff --git a/apple/unsign_jwt.go b/apple/unsign_jwt.go index 7f8258c9..e313a494 100644 --- a/apple/unsign_jwt.go +++ b/apple/unsign_jwt.go @@ -7,32 +7,39 @@ import ( "encoding/json" "errors" "fmt" + "reflect" "strings" "github.com/go-pay/gopay/pkg/jwt" ) // ExtractClaims 解析jws格式数据 -func ExtractClaims(signedPayload string, tran jwt.Claims) (interface{}, error) { +// signedPayload:jws格式数据 +// tran:指针类型的结构体,用于接收解析后的数据 +func ExtractClaims(signedPayload string, tran jwt.Claims) (err error) { + valueOf := reflect.ValueOf(tran) + if valueOf.Kind() != reflect.Ptr { + return errors.New("tran must be ptr struct") + } tokenStr := signedPayload rootCertStr, err := extractHeaderByIndex(tokenStr, 2) if err != nil { - return nil, err + return err } intermediaCertStr, err := extractHeaderByIndex(tokenStr, 1) if err != nil { - return nil, err + return err } if err = verifyCert(rootCertStr, intermediaCertStr); err != nil { - return nil, err + return err } _, err = jwt.ParseWithClaims(tokenStr, tran, func(token *jwt.Token) (interface{}, error) { return extractPublicKeyFromToken(tokenStr) }) if err != nil { - return nil, err + return err } - return tran, nil + return nil } // Per doc: https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.6 diff --git a/apple/unsign_jwt_test.go b/apple/unsign_jwt_test.go index 5b80e23c..7caef40e 100644 --- a/apple/unsign_jwt_test.go +++ b/apple/unsign_jwt_test.go @@ -32,3 +32,39 @@ func TestExample(t *testing.T) { valid := ecdsa.VerifyASN1(&privateKey.PublicKey, hash[:], sig) fmt.Println("signature verified:", valid) } + +func TestExtractClaims(t *testing.T) { + signedPayload := "eyJhbGciOiJFUzI1NiIsIng1YyI6WyJNSUlFTURDQ0E3YWdBd0lCQWdJUWFQb1BsZHZwU29FSDBsQnJqRFB2OWpBS0JnZ3Foa2pPUFFRREF6QjFNVVF3UWdZRFZRUURERHRCY0hCc1pTQlhiM0pzWkhkcFpHVWdSR1YyWld4dmNHVnlJRkpsYkdGMGFXOXVjeUJEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURUxNQWtHQTFVRUN3d0NSell4RXpBUkJnTlZCQW9NQ2tGd2NHeGxJRWx1WXk0eEN6QUpCZ05WQkFZVEFsVlRNQjRYRFRJeE1EZ3lOVEF5TlRBek5Gb1hEVEl6TURreU5EQXlOVEF6TTFvd2daSXhRREErQmdOVkJBTU1OMUJ5YjJRZ1JVTkRJRTFoWXlCQmNIQWdVM1J2Y21VZ1lXNWtJR2xVZFc1bGN5QlRkRzl5WlNCU1pXTmxhWEIwSUZOcFoyNXBibWN4TERBcUJnTlZCQXNNSTBGd2NHeGxJRmR2Y214a2QybGtaU0JFWlhabGJHOXdaWElnVW1Wc1lYUnBiMjV6TVJNd0VRWURWUVFLREFwQmNIQnNaU0JKYm1NdU1Rc3dDUVlEVlFRR0V3SlZVekJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCT29UY2FQY3BlaXBOTDllUTA2dEN1N3BVY3dkQ1hkTjh2R3FhVWpkNThaOHRMeGlVQzBkQmVBK2V1TVlnZ2gxLzVpQWsrRk14VUZtQTJhMXI0YUNaOFNqZ2dJSU1JSUNCREFNQmdOVkhSTUJBZjhFQWpBQU1COEdBMVVkSXdRWU1CYUFGRDh2bENOUjAxREptaWc5N2JCODVjK2xrR0taTUhBR0NDc0dBUVVGQndFQkJHUXdZakF0QmdnckJnRUZCUWN3QW9ZaGFIUjBjRG92TDJObGNuUnpMbUZ3Y0d4bExtTnZiUzkzZDJSeVp6WXVaR1Z5TURFR0NDc0dBUVVGQnpBQmhpVm9kSFJ3T2k4dmIyTnpjQzVoY0hCc1pTNWpiMjB2YjJOemNEQXpMWGQzWkhKbk5qQXlNSUlCSGdZRFZSMGdCSUlCRlRDQ0FSRXdnZ0VOQmdvcWhraUc5Mk5rQlFZQk1JSCtNSUhEQmdnckJnRUZCUWNDQWpDQnRneUJzMUpsYkdsaGJtTmxJRzl1SUhSb2FYTWdZMlZ5ZEdsbWFXTmhkR1VnWW5rZ1lXNTVJSEJoY25SNUlHRnpjM1Z0WlhNZ1lXTmpaWEIwWVc1alpTQnZaaUIwYUdVZ2RHaGxiaUJoY0hCc2FXTmhZbXhsSUhOMFlXNWtZWEprSUhSbGNtMXpJR0Z1WkNCamIyNWthWFJwYjI1eklHOW1JSFZ6WlN3Z1kyVnlkR2xtYVdOaGRHVWdjRzlzYVdONUlHRnVaQ0JqWlhKMGFXWnBZMkYwYVc5dUlIQnlZV04wYVdObElITjBZWFJsYldWdWRITXVNRFlHQ0NzR0FRVUZCd0lCRmlwb2RIUndPaTh2ZDNkM0xtRndjR3hsTG1OdmJTOWpaWEowYVdacFkyRjBaV0YxZEdodmNtbDBlUzh3SFFZRFZSME9CQllFRkNPQ21NQnEvLzFMNWltdlZtcVgxb0NZZXFyTU1BNEdBMVVkRHdFQi93UUVBd0lIZ0RBUUJnb3Foa2lHOTJOa0Jnc0JCQUlGQURBS0JnZ3Foa2pPUFFRREF3Tm9BREJsQWpFQWw0SkI5R0pIaXhQMm51aWJ5VTFrM3dyaTVwc0dJeFBNRTA1c0ZLcTdoUXV6dmJleUJ1ODJGb3p6eG1ienBvZ29BakJMU0ZsMGRaV0lZbDJlalBWK0RpNWZCbktQdThteW1CUXRvRS9IMmJFUzBxQXM4Yk51ZVUzQ0JqamgxbHduRHNJPSIsIk1JSURGakNDQXB5Z0F3SUJBZ0lVSXNHaFJ3cDBjMm52VTRZU3ljYWZQVGp6Yk5jd0NnWUlLb1pJemowRUF3TXdaekViTUJrR0ExVUVBd3dTUVhCd2JHVWdVbTl2ZENCRFFTQXRJRWN6TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd0hoY05NakV3TXpFM01qQXpOekV3V2hjTk16WXdNekU1TURBd01EQXdXakIxTVVRd1FnWURWUVFERER0QmNIQnNaU0JYYjNKc1pIZHBaR1VnUkdWMlpXeHZjR1Z5SUZKbGJHRjBhVzl1Y3lCRFpYSjBhV1pwWTJGMGFXOXVJRUYxZEdodmNtbDBlVEVMTUFrR0ExVUVDd3dDUnpZeEV6QVJCZ05WQkFvTUNrRndjR3hsSUVsdVl5NHhDekFKQmdOVkJBWVRBbFZUTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUVic1FLQzk0UHJsV21aWG5YZ3R4emRWSkw4VDBTR1luZ0RSR3BuZ24zTjZQVDhKTUViN0ZEaTRiQm1QaENuWjMvc3E2UEYvY0djS1hXc0w1dk90ZVJoeUo0NXgzQVNQN2NPQithYW85MGZjcHhTdi9FWkZibmlBYk5nWkdoSWhwSW80SDZNSUgzTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0h3WURWUjBqQkJnd0ZvQVV1N0Rlb1ZnemlKcWtpcG5ldnIzcnI5ckxKS3N3UmdZSUt3WUJCUVVIQVFFRU9qQTRNRFlHQ0NzR0FRVUZCekFCaGlwb2RIUndPaTh2YjJOemNDNWhjSEJzWlM1amIyMHZiMk56Y0RBekxXRndjR3hsY205dmRHTmhaek13TndZRFZSMGZCREF3TGpBc29DcWdLSVltYUhSMGNEb3ZMMk55YkM1aGNIQnNaUzVqYjIwdllYQndiR1Z5YjI5MFkyRm5NeTVqY213d0hRWURWUjBPQkJZRUZEOHZsQ05SMDFESm1pZzk3YkI4NWMrbGtHS1pNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVFCZ29xaGtpRzkyTmtCZ0lCQkFJRkFEQUtCZ2dxaGtqT1BRUURBd05vQURCbEFqQkFYaFNxNUl5S29nTUNQdHc0OTBCYUI2NzdDYUVHSlh1ZlFCL0VxWkdkNkNTamlDdE9udU1UYlhWWG14eGN4ZmtDTVFEVFNQeGFyWlh2TnJreFUzVGtVTUkzM3l6dkZWVlJUNHd4V0pDOTk0T3NkY1o0K1JHTnNZRHlSNWdtZHIwbkRHZz0iLCJNSUlDUXpDQ0FjbWdBd0lCQWdJSUxjWDhpTkxGUzVVd0NnWUlLb1pJemowRUF3TXdaekViTUJrR0ExVUVBd3dTUVhCd2JHVWdVbTl2ZENCRFFTQXRJRWN6TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd0hoY05NVFF3TkRNd01UZ3hPVEEyV2hjTk16a3dORE13TVRneE9UQTJXakJuTVJzd0dRWURWUVFEREJKQmNIQnNaU0JTYjI5MElFTkJJQzBnUnpNeEpqQWtCZ05WQkFzTUhVRndjR3hsSUVObGNuUnBabWxqWVhScGIyNGdRWFYwYUc5eWFYUjVNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVFzd0NRWURWUVFHRXdKVlV6QjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkpqcEx6MUFjcVR0a3lKeWdSTWMzUkNWOGNXalRuSGNGQmJaRHVXbUJTcDNaSHRmVGpqVHV4eEV0WC8xSDdZeVlsM0o2WVJiVHpCUEVWb0EvVmhZREtYMUR5eE5CMGNUZGRxWGw1ZHZNVnp0SzUxN0lEdll1VlRaWHBta09sRUtNYU5DTUVBd0hRWURWUjBPQkJZRUZMdXczcUZZTTRpYXBJcVozcjY5NjYvYXl5U3JNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTURBMmdBTUdVQ01RQ0Q2Y0hFRmw0YVhUUVkyZTN2OUd3T0FFWkx1Tit5UmhIRkQvM21lb3locG12T3dnUFVuUFdUeG5TNGF0K3FJeFVDTUcxbWloREsxQTNVVDgyTlF6NjBpbU9sTTI3amJkb1h0MlFmeUZNbStZaGlkRGtMRjF2TFVhZ002QmdENTZLeUtBPT0iXX0.eyJub3RpZmljYXRpb25UeXBlIjoiQ09OU1VNUFRJT05fUkVRVUVTVCIsIm5vdGlmaWNhdGlvblVVSUQiOiJjYmZmNjk4Ny1iOGQ5LTQzZDgtYjFkYy0wN2ZhOGM5ZmQ5NDUiLCJkYXRhIjp7ImFwcEFwcGxlSWQiOjE2MDE4MzA4MTQsImJ1bmRsZUlkIjoiY29tLmpyamoua2V5c25zIiwiYnVuZGxlVmVyc2lvbiI6IjEiLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJzaWduZWRUcmFuc2FjdGlvbkluZm8iOiJleUpoYkdjaU9pSkZVekkxTmlJc0luZzFZeUk2V3lKTlNVbEZUVVJEUTBFM1lXZEJkMGxDUVdkSlVXRlFiMUJzWkhad1UyOUZTREJzUW5KcVJGQjJPV3BCUzBKblozRm9hMnBQVUZGUlJFRjZRakZOVlZGM1VXZFpSRlpSVVVSRVJIUkNZMGhDYzFwVFFsaGlNMHB6V2toa2NGcEhWV2RTUjFZeVdsZDRkbU5IVm5sSlJrcHNZa2RHTUdGWE9YVmplVUpFV2xoS01HRlhXbkJaTWtZd1lWYzVkVWxGUmpGa1IyaDJZMjFzTUdWVVJVeE5RV3RIUVRGVlJVTjNkME5TZWxsNFJYcEJVa0puVGxaQ1FXOU5RMnRHZDJOSGVHeEpSV3gxV1hrMGVFTjZRVXBDWjA1V1FrRlpWRUZzVmxSTlFqUllSRlJKZUUxRVozbE9WRUY1VGxSQmVrNUdiMWhFVkVsNlRVUnJlVTVFUVhsT1ZFRjZUVEZ2ZDJkYVNYaFJSRUVyUW1kT1ZrSkJUVTFPTVVKNVlqSlJaMUpWVGtSSlJURm9XWGxDUW1OSVFXZFZNMUoyWTIxVloxbFhOV3RKUjJ4VlpGYzFiR041UWxSa1J6bDVXbE5DVTFwWFRteGhXRUl3U1VaT2NGb3lOWEJpYldONFRFUkJjVUpuVGxaQ1FYTk5TVEJHZDJOSGVHeEpSbVIyWTIxNGEyUXliR3RhVTBKRldsaGFiR0pIT1hkYVdFbG5WVzFXYzFsWVVuQmlNalY2VFZKTmQwVlJXVVJXVVZGTFJFRndRbU5JUW5OYVUwSktZbTFOZFUxUmMzZERVVmxFVmxGUlIwVjNTbFpWZWtKYVRVSk5SMEo1Y1VkVFRUUTVRV2RGUjBORGNVZFRUVFE1UVhkRlNFRXdTVUZDVDI5VVkyRlFZM0JsYVhCT1REbGxVVEEyZEVOMU4zQlZZM2RrUTFoa1RqaDJSM0ZoVldwa05UaGFPSFJNZUdsVlF6QmtRbVZCSzJWMVRWbG5aMmd4THpWcFFXc3JSazE0VlVadFFUSmhNWEkwWVVOYU9GTnFaMmRKU1UxSlNVTkNSRUZOUW1kT1ZraFNUVUpCWmpoRlFXcEJRVTFDT0VkQk1WVmtTWGRSV1UxQ1lVRkdSRGgyYkVOT1VqQXhSRXB0YVdjNU4ySkNPRFZqSzJ4clIwdGFUVWhCUjBORGMwZEJVVlZHUW5kRlFrSkhVWGRaYWtGMFFtZG5ja0puUlVaQ1VXTjNRVzlaYUdGSVVqQmpSRzkyVERKT2JHTnVVbnBNYlVaM1kwZDRiRXh0VG5aaVV6a3paREpTZVZwNldYVmFSMVo1VFVSRlIwTkRjMGRCVVZWR1FucEJRbWhwVm05a1NGSjNUMms0ZG1JeVRucGpRelZvWTBoQ2MxcFROV3BpTWpCMllqSk9lbU5FUVhwTVdHUXpXa2hLYms1cVFYbE5TVWxDU0dkWlJGWlNNR2RDU1VsQ1JsUkRRMEZTUlhkblowVk9RbWR2Y1docmFVYzVNazVyUWxGWlFrMUpTQ3ROU1VoRVFtZG5ja0puUlVaQ1VXTkRRV3BEUW5SbmVVSnpNVXBzWWtkc2FHSnRUbXhKUnpsMVNVaFNiMkZZVFdkWk1sWjVaRWRzYldGWFRtaGtSMVZuV1c1cloxbFhOVFZKU0VKb1kyNVNOVWxIUm5wak0xWjBXbGhOWjFsWFRtcGFXRUl3V1ZjMWFscFRRblphYVVJd1lVZFZaMlJIYUd4aWFVSm9ZMGhDYzJGWFRtaFpiWGhzU1VoT01GbFhOV3RaV0VwclNVaFNiR050TVhwSlIwWjFXa05DYW1JeU5XdGhXRkp3WWpJMWVrbEhPVzFKU0ZaNldsTjNaMWt5Vm5sa1IyeHRZVmRPYUdSSFZXZGpSemx6WVZkT05VbEhSblZhUTBKcVdsaEtNR0ZYV25CWk1rWXdZVmM1ZFVsSVFubFpWMDR3WVZkT2JFbElUakJaV0ZKc1lsZFdkV1JJVFhWTlJGbEhRME56UjBGUlZVWkNkMGxDUm1sd2IyUklVbmRQYVRoMlpETmtNMHh0Um5kalIzaHNURzFPZG1KVE9XcGFXRW93WVZkYWNGa3lSakJhVjBZeFpFZG9kbU50YkRCbFV6aDNTRkZaUkZaU01FOUNRbGxGUmtOUFEyMU5RbkV2THpGTU5XbHRkbFp0Y1ZneGIwTlpaWEZ5VFUxQk5FZEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJVVUpuYjNGb2EybEhPVEpPYTBKbmMwSkNRVWxHUVVSQlMwSm5aM0ZvYTJwUFVGRlJSRUYzVG05QlJFSnNRV3BGUVd3MFNrSTVSMHBJYVhoUU1tNTFhV0o1VlRGck0zZHlhVFZ3YzBkSmVGQk5SVEExYzBaTGNUZG9VWFY2ZG1KbGVVSjFPREpHYjNwNmVHMWllbkJ2WjI5QmFrSk1VMFpzTUdSYVYwbFpiREpsYWxCV0swUnBOV1pDYmt0UWRUaHRlVzFDVVhSdlJTOUlNbUpGVXpCeFFYTTRZazUxWlZVelEwSnFhbWd4YkhkdVJITkpQU0lzSWsxSlNVUkdha05EUVhCNVowRjNTVUpCWjBsVlNYTkhhRkozY0RCak1tNTJWVFJaVTNsallXWlFWR3A2WWs1amQwTm5XVWxMYjFwSmVtb3dSVUYzVFhkYWVrVmlUVUpyUjBFeFZVVkJkM2RUVVZoQ2QySkhWV2RWYlRsMlpFTkNSRkZUUVhSSlJXTjZUVk5aZDBwQldVUldVVkZNUkVJeFFtTklRbk5hVTBKRVdsaEtNR0ZYV25CWk1rWXdZVmM1ZFVsRlJqRmtSMmgyWTIxc01HVlVSVlJOUWtWSFFURlZSVU5uZDB0UldFSjNZa2RWWjFOWE5XcE1ha1ZNVFVGclIwRXhWVVZDYUUxRFZsWk5kMGhvWTA1TmFrVjNUWHBGTTAxcVFYcE9la1YzVjJoalRrMTZXWGROZWtVMVRVUkJkMDFFUVhkWGFrSXhUVlZSZDFGbldVUldVVkZFUkVSMFFtTklRbk5hVTBKWVlqTktjMXBJWkhCYVIxVm5Va2RXTWxwWGVIWmpSMVo1U1VaS2JHSkhSakJoVnpsMVkzbENSRnBZU2pCaFYxcHdXVEpHTUdGWE9YVkpSVVl4WkVkb2RtTnRiREJsVkVWTVRVRnJSMEV4VlVWRGQzZERVbnBaZUVWNlFWSkNaMDVXUWtGdlRVTnJSbmRqUjNoc1NVVnNkVmw1TkhoRGVrRktRbWRPVmtKQldWUkJiRlpVVFVoWmQwVkJXVWhMYjFwSmVtb3dRMEZSV1VaTE5FVkZRVU5KUkZsblFVVmljMUZMUXprMFVISnNWMjFhV0c1WVozUjRlbVJXU2t3NFZEQlRSMWx1WjBSU1IzQnVaMjR6VGpaUVZEaEtUVVZpTjBaRWFUUmlRbTFRYUVOdVdqTXZjM0UyVUVZdlkwZGpTMWhYYzB3MWRrOTBaVkpvZVVvME5YZ3pRVk5RTjJOUFFpdGhZVzg1TUdaamNIaFRkaTlGV2taaWJtbEJZazVuV2tkb1NXaHdTVzgwU0RaTlNVZ3pUVUpKUjBFeFZXUkZkMFZDTDNkUlNVMUJXVUpCWmpoRFFWRkJkMGgzV1VSV1VqQnFRa0puZDBadlFWVjFOMFJsYjFabmVtbEtjV3RwY0c1bGRuSXpjbkk1Y2t4S1MzTjNVbWRaU1V0M1dVSkNVVlZJUVZGRlJVOXFRVFJOUkZsSFEwTnpSMEZSVlVaQ2VrRkNhR2x3YjJSSVVuZFBhVGgyWWpKT2VtTkROV2hqU0VKeldsTTFhbUl5TUhaaU1rNTZZMFJCZWt4WFJuZGpSM2hzWTIwNWRtUkhUbWhhZWsxM1RuZFpSRlpTTUdaQ1JFRjNUR3BCYzI5RGNXZExTVmx0WVVoU01HTkViM1pNTWs1NVlrTTFhR05JUW5OYVV6VnFZakl3ZGxsWVFuZGlSMVo1WWpJNU1Ga3lSbTVOZVRWcVkyMTNkMGhSV1VSV1VqQlBRa0paUlVaRU9IWnNRMDVTTURGRVNtMXBaemszWWtJNE5XTXJiR3RIUzFwTlFUUkhRVEZWWkVSM1JVSXZkMUZGUVhkSlFrSnFRVkZDWjI5eGFHdHBSemt5VG10Q1owbENRa0ZKUmtGRVFVdENaMmR4YUd0cVQxQlJVVVJCZDA1dlFVUkNiRUZxUWtGWWFGTnhOVWw1UzI5blRVTlFkSGMwT1RCQ1lVSTJOemREWVVWSFNsaDFabEZDTDBWeFdrZGtOa05UYW1sRGRFOXVkVTFVWWxoV1dHMTRlR040Wm10RFRWRkVWRk5RZUdGeVdsaDJUbkpyZUZVelZHdFZUVWt6TTNsNmRrWldWbEpVTkhkNFYwcERPVGswVDNOa1kxbzBLMUpIVG5OWlJIbFNOV2R0WkhJd2JrUkhaejBpTENKTlNVbERVWHBEUTBGamJXZEJkMGxDUVdkSlNVeGpXRGhwVGt4R1V6VlZkME5uV1VsTGIxcEplbW93UlVGM1RYZGFla1ZpVFVKclIwRXhWVVZCZDNkVFVWaENkMkpIVldkVmJUbDJaRU5DUkZGVFFYUkpSV042VFZOWmQwcEJXVVJXVVZGTVJFSXhRbU5JUW5OYVUwSkVXbGhLTUdGWFduQlpNa1l3WVZjNWRVbEZSakZrUjJoMlkyMXNNR1ZVUlZSTlFrVkhRVEZWUlVObmQwdFJXRUozWWtkVloxTlhOV3BNYWtWTVRVRnJSMEV4VlVWQ2FFMURWbFpOZDBob1kwNU5WRkYzVGtSTmQwMVVaM2hQVkVFeVYyaGpUazE2YTNkT1JFMTNUVlJuZUU5VVFUSlhha0p1VFZKemQwZFJXVVJXVVZGRVJFSktRbU5JUW5OYVUwSlRZakk1TUVsRlRrSkpRekJuVW5wTmVFcHFRV3RDWjA1V1FrRnpUVWhWUm5kalIzaHNTVVZPYkdOdVVuQmFiV3hxV1ZoU2NHSXlOR2RSV0ZZd1lVYzVlV0ZZVWpWTlVrMTNSVkZaUkZaUlVVdEVRWEJDWTBoQ2MxcFRRa3BpYlUxMVRWRnpkME5SV1VSV1VWRkhSWGRLVmxWNlFqSk5Ra0ZIUW5seFIxTk5ORGxCWjBWSFFsTjFRa0pCUVdsQk1rbEJRa3BxY0V4Nk1VRmpjVlIwYTNsS2VXZFNUV016VWtOV09HTlhhbFJ1U0dOR1FtSmFSSFZYYlVKVGNETmFTSFJtVkdwcVZIVjRlRVYwV0M4eFNEZFplVmxzTTBvMldWSmlWSHBDVUVWV2IwRXZWbWhaUkV0WU1VUjVlRTVDTUdOVVpHUnhXR3cxWkhaTlZucDBTelV4TjBsRWRsbDFWbFJhV0hCdGEwOXNSVXROWVU1RFRVVkJkMGhSV1VSV1VqQlBRa0paUlVaTWRYY3pjVVpaVFRScFlYQkpjVm96Y2pZNU5qWXZZWGw1VTNKTlFUaEhRVEZWWkVWM1JVSXZkMUZHVFVGTlFrRm1PSGRFWjFsRVZsSXdVRUZSU0M5Q1FWRkVRV2RGUjAxQmIwZERRM0ZIVTAwME9VSkJUVVJCTW1kQlRVZFZRMDFSUTBRMlkwaEZSbXcwWVZoVVVWa3laVE4yT1VkM1QwRkZXa3gxVGl0NVVtaElSa1F2TTIxbGIzbG9jRzEyVDNkblVGVnVVRmRVZUc1VE5HRjBLM0ZKZUZWRFRVY3hiV2xvUkVzeFFUTlZWRGd5VGxGNk5qQnBiVTlzVFRJM2FtSmtiMWgwTWxGbWVVWk5iU3RaYUdsa1JHdE1SakYyVEZWaFowMDJRbWRFTlRaTGVVdEJQVDBpWFgwLmV5SjBjbUZ1YzJGamRHbHZia2xrSWpvaU5URXdNREF4TWpZeE1EY3lPVEl4SWl3aWIzSnBaMmx1WVd4VWNtRnVjMkZqZEdsdmJrbGtJam9pTlRFd01EQXhNall4TURjeU9USXhJaXdpWW5WdVpHeGxTV1FpT2lKamIyMHVhbkpxYWk1clpYbHpibk1pTENKd2NtOWtkV04wU1dRaU9pSmpiMjB1YTJWNWMyNXpMa3BTTVRJd01DSXNJbkIxY21Ob1lYTmxSR0YwWlNJNk1UWTROekl6T1RBek5qQXdNQ3dpYjNKcFoybHVZV3hRZFhKamFHRnpaVVJoZEdVaU9qRTJPRGN5TXprd016WXdNREFzSW5GMVlXNTBhWFI1SWpveExDSjBlWEJsSWpvaVEyOXVjM1Z0WVdKc1pTSXNJbWx1UVhCd1QzZHVaWEp6YUdsd1ZIbHdaU0k2SWxCVlVrTklRVk5GUkNJc0luTnBaMjVsWkVSaGRHVWlPakUyT0RjNU5ERTFNVEkxTnpNc0ltVnVkbWx5YjI1dFpXNTBJam9pVUhKdlpIVmpkR2x2YmlJc0luUnlZVzV6WVdOMGFXOXVVbVZoYzI5dUlqb2lVRlZTUTBoQlUwVWlMQ0p6ZEc5eVpXWnliMjUwSWpvaVEwaE9JaXdpYzNSdmNtVm1jbTl1ZEVsa0lqb2lNVFF6TkRZMUluMC5hM09PRTNGcGxPdF9UQV9nQURzNW1rM2JRNWdKUDJubFdWX2hfN2xKRUMtcjNCZDh0d2ItSzFuQm5KR3hGVW9OeVRibWp3YXZOcDhPUHM5bGw4cGhfZyJ9LCJ2ZXJzaW9uIjoiMi4wIiwic2lnbmVkRGF0ZSI6MTY4Nzk0MTUxMjU2MH0.Tz4bvMOb-AT88is_pobjyOBZxwIKDkyugOQ4BqfTbhrlRNgKaZ-upGRTJlydJrUM9aRfdezRc0-1ekmMwcndcA" + np := &NotificationV2Payload{} + err = ExtractClaims(signedPayload, np) + if err != nil { + xlog.Error(err) + return + } + xlog.Infof("np:%+v", np) + xlog.Infof("np.data:%+v", np.Data) + ti, err := np.DecodeTransactionInfo() + if err != nil { + xlog.Error(err) + return + } + xlog.Infof("ti:%+v", ti.TransactionId) + /* + { + "transactionId": "510001261072921", + "originalTransactionId": "510001261072921", + "bundleId": "com.jrjj.keysns", + "productId": "com.keysns.JR1200", + "purchaseDate": 1687239036000, + "originalPurchaseDate": 1687239036000, + "quantity": 1, + "type": "Consumable", + "inAppOwnershipType": "PURCHASED", + "signedDate": 1687941512573, + "environment": "Production", + "transactionReason": "PURCHASE", + "storefront": "CHN", + "storefrontId": "143465" + } + */ +}