package iap import ( "context" b64 "encoding/base64" "encoding/json" "io/ioutil" "net/http" "os" "go-ayo/logger" "github.com/awa/go-iap/appstore/api" "github.com/awa/go-iap/playstore" ) var PlayStorePublicKey string var PlayStorePackageName string var PlayStoreClient *playstore.Client type PlayStoreReceiptInfo struct { OrderId string `json:"orderId"` PackageName string `json:"packageName"` ProductId string `json:"productId"` PurchaseTime int `json:"purchaseTime"` PurchaseState int `json:"purchaseState"` PurchaseToken string `json:"purchaseToken"` Quantity int `json:"quantity"` Acknowledged bool `json:"acknowledged"` } func PlayStoreInit(packageName string, publickey string) { jsonKey, err := ioutil.ReadFile("playstore-iap-kingdom.json") if err != nil { logger.Fatal(err) return } PlayStoreClient, err = playstore.New(jsonKey) if err != nil { logger.Fatal(err) return } PlayStorePublicKey = publickey PlayStorePackageName = packageName } func PlayStoreVerifyReceipt(receptData string, signature string) (isVerified bool, receiptInfo PlayStoreReceiptInfo) { var info PlayStoreReceiptInfo uDec, _ := b64.URLEncoding.DecodeString(receptData) bOk, err := playstore.VerifySignature(PlayStorePublicKey, []byte(uDec), signature) if bOk == false || err != nil { logger.Println("playstore - VerifySignature fail :" + err.Error()) return bOk, info } json.Unmarshal(uDec, &info) return bOk, info } func PlayStoreVerifyProduct(info PlayStoreReceiptInfo) (bool, int, int) { productPurchases, err := PlayStoreClient.VerifyProduct(context.Background(), PlayStorePackageName, info.ProductId, info.PurchaseToken) if err != nil { logger.Println("playstore - PlayStoreVerifyProduct fail :" + err.Error()) return false, -1, -1 } // fmt.Println(productPurchases) // fmt.Println("================") // fmt.Println(productPurchases.PurchaseState) // fmt.Println(productPurchases.ConsumptionState) // fmt.Println("================") return true, int(productPurchases.PurchaseState), int(productPurchases.ConsumptionState) } func PlayStoreConsumeProduct(info PlayStoreReceiptInfo) bool { err := PlayStoreClient.ConsumeProduct(context.Background(), PlayStorePackageName, info.ProductId, info.PurchaseToken) if err != nil { logger.Error("playstore - PlayStoreConsumeProduct fail :" + err.Error()) return false } return true } var AppStoreClient *api.StoreClient func AppStoreInit(keyPath string, configFilePath string) { keyContentBytes, err := os.ReadFile(keyPath) if err != nil { logger.Fatal(err) return } configBytes, err := os.ReadFile(configFilePath) if err != nil { logger.Fatal(err) return } var configMap map[string]any err = json.Unmarshal(configBytes, &configMap) config := &api.StoreConfig{ KeyContent: keyContentBytes, KeyID: configMap["KeyID"].(string), BundleID: configMap["BundleID"].(string), Issuer: configMap["Issuer"].(string), Sandbox: configMap["Sandbox"].(bool), } AppStoreClient = api.NewStoreClient(config) if config.Sandbox { logger.Println("IPA - Appstore : Use Sandbox") } else { logger.Println("IPA - Appstore : Normal") } } func AppStoreVerifyReceipt(transactionId string) (bool, *api.JWSTransaction) { res, err := AppStoreClient.GetTransactionInfo(context.Background(), transactionId) if err != nil { logger.Error(err) return false, nil } transaction, err := AppStoreClient.ParseSignedTransaction(res.SignedTransactionInfo) if err != nil { logger.Error(err) return false, nil } if transaction.TransactionID != transactionId { return false, nil } if len(transaction.OriginalTransactionId) == 0 { return false, nil } return true, transaction } func AppStoreConsumeProduct(transaction *api.JWSTransaction) bool { //https://developer.apple.com/documentation/appstoreserverapi/consumptionrequest consumeReqBody := api.ConsumptionRequestBody{ AccountTenure: 0, AppAccountToken: transaction.AppAccountToken, ConsumptionStatus: 3, CustomerConsented: true, DeliveryStatus: 0, LifetimeDollarsPurchased: 0, LifetimeDollarsRefunded: 0, Platform: 1, PlayTime: 0, SampleContentProvided: false, UserStatus: 1, } statusCode, err := AppStoreClient.SendConsumptionInfo(context.Background(), transaction.OriginalTransactionId, consumeReqBody) if statusCode != http.StatusAccepted { return false } if err != nil { logger.Error(err) return false } return true }