2024-04-25 11:37:07 +09:00
|
|
|
package iap
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
b64 "encoding/base64"
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"io/ioutil"
|
|
|
|
|
"net/http"
|
|
|
|
|
"os"
|
|
|
|
|
|
2024-05-17 09:52:12 +09:00
|
|
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
2024-04-25 11:37:07 +09:00
|
|
|
|
|
|
|
|
"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
|
|
|
|
|
}
|