修改路径
This commit is contained in:
40
package/pay/playstore/InAppProduct_utils.go
Normal file
40
package/pay/playstore/InAppProduct_utils.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package playstore
|
||||
|
||||
// GetStatus 获取产品的状态,例如产品是否处于活跃状态。
|
||||
//
|
||||
// 返回值 EProductStatus 代表产品状态。
|
||||
// 可能的状态包括:
|
||||
//
|
||||
// ProductStatus_Unspecified // 未指定状态。
|
||||
// ProductStatus_active // 产品已发布且在商店中处于活跃状态。
|
||||
// ProductStatus_inactive // 产品未发布,因此在商店中处于非活跃状态。
|
||||
func (iap InAppProduct) GetStatus() EProductStatus {
|
||||
return EProductStatus(iap.AndroidPublisherInAppProduct.Status)
|
||||
}
|
||||
|
||||
// GetSubscriptionPeriod 获取订阅的周期。
|
||||
//
|
||||
// 返回值 ESubscriptionPeriod 代表订阅周期。
|
||||
// 可能的周期包括:
|
||||
//
|
||||
// SubscriptionPeriod_Invalid : 无效的订阅(可能是消耗品)。
|
||||
// SubscriptionPeriod_OneWeek (一周)。
|
||||
// SubscriptionPeriod_OneMonth (一个月)。
|
||||
// SubscriptionPeriod_ThreeMonths (三个月)。
|
||||
// SubscriptionPeriod_SixMonths (六个月)。
|
||||
// SubscriptionPeriod_OneYear (一年)。
|
||||
func (iap InAppProduct) GetSubscriptionPeriod() ESubscriptionPeriod {
|
||||
return ESubscriptionPeriod(iap.AndroidPublisherInAppProduct.SubscriptionPeriod)
|
||||
}
|
||||
|
||||
// GetPurchaseType 获取产品的购买类型。
|
||||
//
|
||||
// 返回值 EPurchaseType 代表产品的购买类型。
|
||||
// 可能的类型包括:
|
||||
//
|
||||
// EPurchaseType_Unspecified (未指定购买类型)。
|
||||
// EPurchaseType_ManagedUser 可以被单次或多次购买(消耗品、非消耗品)。
|
||||
// EPurchaseType_Subscription (应用内产品,具有周期性消费)。
|
||||
func (iap InAppProduct) GetPurchaseType() EPurchaseType {
|
||||
return EPurchaseType(iap.AndroidPublisherInAppProduct.PurchaseType)
|
||||
}
|
||||
34
package/pay/playstore/enums.go
Normal file
34
package/pay/playstore/enums.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package playstore
|
||||
|
||||
// EProductStatus 定义了产品的状态,例如产品是否处于活跃状态。
|
||||
type EProductStatus string
|
||||
|
||||
// 定义了产品可能的状态常量。
|
||||
const (
|
||||
ProductStatus_Unspecified EProductStatus = "statusUnspecified" // 未指定状态。
|
||||
ProductStatus_active EProductStatus = "active" // 产品已发布且在商店中处于活跃状态。
|
||||
ProductStatus_inactive EProductStatus = "inactive" // 产品未发布,因此在商店中处于非活跃状态。
|
||||
)
|
||||
|
||||
// ESubscriptionPeriod 定义了订阅的周期。
|
||||
type ESubscriptionPeriod string
|
||||
|
||||
// 定义了订阅可能的周期常量。
|
||||
const (
|
||||
SubscriptionPeriod_Invalid ESubscriptionPeriod = "" // 无效的订阅(可能是消耗品)。
|
||||
SubscriptionPeriod_OneWeek ESubscriptionPeriod = "P1W" // 一周。
|
||||
SubscriptionPeriod_OneMonth ESubscriptionPeriod = "P1M" // 一个月。
|
||||
SubscriptionPeriod_ThreeMonths ESubscriptionPeriod = "P3M" // 三个月。
|
||||
SubscriptionPeriod_SixMonths ESubscriptionPeriod = "P6M" // 六个月。
|
||||
SubscriptionPeriod_OneYear ESubscriptionPeriod = "P1Y" // 一年。
|
||||
)
|
||||
|
||||
// EPurchaseType 定义了产品的购买类型,例如周期性订阅。
|
||||
type EPurchaseType string
|
||||
|
||||
// 定义了产品可能的购买类型常量。
|
||||
const (
|
||||
EPurchaseType_Unspecified EPurchaseType = "purchaseTypeUnspecified" // 未指定购买类型。
|
||||
EPurchaseType_ManagedUser EPurchaseType = "managedUser" // 默认的产品类型 - 可以单次或多次购买(消耗品、非消耗品)。
|
||||
EPurchaseType_Subscription EPurchaseType = "subscription" // 应用内具有周期性的产品。
|
||||
)
|
||||
80
package/pay/playstore/models.go
Normal file
80
package/pay/playstore/models.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package playstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"google.golang.org/api/androidpublisher/v3"
|
||||
)
|
||||
|
||||
// IABProduct 接口定义了商品服务的基本操作。
|
||||
type IABProduct interface {
|
||||
// VerifyProduct 验证指定的内购产品购买信息。
|
||||
// ctx: 上下文,用于控制请求的取消、超时等。
|
||||
// packageName: 应用包名。
|
||||
// productId: 内购商品ID。
|
||||
// purchaseToken: 购买凭证。
|
||||
// 返回经过验证的购买信息和可能的错误。
|
||||
VerifyProduct(context.Context, string, string, string) (*androidpublisher.ProductPurchase, error)
|
||||
|
||||
// AcknowledgeProduct 确认指定的内购产品的购买。
|
||||
// ctx: 上下文。
|
||||
// packageName: 应用包名。
|
||||
// productId: 内购商品ID。
|
||||
// purchaseToken: 购买凭证。
|
||||
// orderId: 订单ID。
|
||||
// 返回可能发生的错误。
|
||||
AcknowledgeProduct(context.Context, string, string, string, string) error
|
||||
}
|
||||
|
||||
// IABSubscription 接口定义了订阅服务的基本操作。
|
||||
type IABSubscription interface {
|
||||
// AcknowledgeSubscription 确认指定订阅的购买。
|
||||
// ctx: 上下文。
|
||||
// packageName: 应用包名。
|
||||
// subscriptionId: 订阅ID。
|
||||
// purchaseToken: 购买凭证。
|
||||
// acknowledgeRequest: 确认请求参数。
|
||||
// 返回可能发生的错误。
|
||||
AcknowledgeSubscription(context.Context, string, string, string, *androidpublisher.SubscriptionPurchasesAcknowledgeRequest) error
|
||||
|
||||
// VerifySubscription 验证指定订阅的购买信息。
|
||||
// ctx: 上下文。
|
||||
// packageName: 应用包名。
|
||||
// subscriptionId: 订阅ID。
|
||||
// purchaseToken: 购买凭证。
|
||||
// 返回经过验证的订阅购买信息和可能的错误。
|
||||
VerifySubscription(context.Context, string, string, string) (*androidpublisher.SubscriptionPurchase, error)
|
||||
|
||||
// CancelSubscription 取消指定的订阅。
|
||||
// ctx: 上下文。
|
||||
// packageName: 应用包名。
|
||||
// subscriptionId: 订阅ID。
|
||||
// purchaseToken: 购买凭证。
|
||||
// 返回可能发生的错误。
|
||||
CancelSubscription(context.Context, string, string, string) error
|
||||
|
||||
// RefundSubscription 为指定的订阅办理退款。
|
||||
// ctx: 上下文。
|
||||
// packageName: 应用包名。
|
||||
// subscriptionId: 订阅ID。
|
||||
// purchaseToken: 购买凭证。
|
||||
// 返回可能发生的错误。
|
||||
RefundSubscription(context.Context, string, string, string) error
|
||||
|
||||
// RevokeSubscription 撤销指定的订阅。
|
||||
// ctx: 上下文。
|
||||
// packageName: 应用包名。
|
||||
// subscriptionId: 订阅ID。
|
||||
// purchaseToken: 购买凭证。
|
||||
// 返回可能发生的错误。
|
||||
RevokeSubscription(context.Context, string, string, string) error
|
||||
}
|
||||
|
||||
// Client 结构体实现了 IABSubscription 接口,提供了具体的操作实现。
|
||||
type Client struct {
|
||||
service *androidpublisher.Service
|
||||
}
|
||||
|
||||
// InAppProduct 结构体封装了 androidpublisher.InAppProduct,并提供了一些辅助方法。
|
||||
type InAppProduct struct {
|
||||
AndroidPublisherInAppProduct *androidpublisher.InAppProduct
|
||||
}
|
||||
62
package/pay/playstore/notification.go
Normal file
62
package/pay/playstore/notification.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package playstore
|
||||
|
||||
// SubscriptionNotificationType 定义了订阅通知的类型。
|
||||
type SubscriptionNotificationType int
|
||||
|
||||
// 预定义的订阅通知类型。
|
||||
const (
|
||||
SubscriptionNotificationTypeRecovered SubscriptionNotificationType = iota + 1 // 订阅已恢复
|
||||
SubscriptionNotificationTypeRenewed // 订阅已续订
|
||||
SubscriptionNotificationTypeCanceled // 订阅已取消
|
||||
SubscriptionNotificationTypePurchased // 订阅已购买
|
||||
SubscriptionNotificationTypeAccountHold // 订阅账户暂停
|
||||
SubscriptionNotificationTypeGracePeriod // 宽限期通知
|
||||
SubscriptionNotificationTypeRestarted // 订阅已重新开始
|
||||
SubscriptionNotificationTypePriceChangeConfirmed // 订阅价格变更已确认
|
||||
SubscriptionNotificationTypeDeferred // 订阅延迟
|
||||
SubscriptionNotificationTypePaused // 订阅已暂停
|
||||
SubscriptionNotificationTypePauseScheduleChanged // 暂停计划已更改
|
||||
SubscriptionNotificationTypeRevoked // 订阅已撤销
|
||||
SubscriptionNotificationTypeExpired // 订阅已过期
|
||||
)
|
||||
|
||||
// OneTimeProductNotificationType 定义了一次性产品通知的类型。
|
||||
type OneTimeProductNotificationType int
|
||||
|
||||
// 预定义的一次性产品通知类型。
|
||||
const (
|
||||
OneTimeProductNotificationTypePurchased OneTimeProductNotificationType = iota + 1 // 一次性产品已购买
|
||||
OneTimeProductNotificationTypeCanceled // 一次性产品已取消
|
||||
)
|
||||
|
||||
// DeveloperNotification 是通过 Pub/Sub 主题发送给开发者的通知。
|
||||
// 详细描述请参见:https://developer.android.com/google/play/billing/rtdn-reference#json_specification
|
||||
type DeveloperNotification struct {
|
||||
Version string `json:"version"` // 版本号
|
||||
PackageName string `json:"packageName"` // 应用包名
|
||||
EventTimeMillis string `json:"eventTimeMillis"` // 事件发生时间(毫秒)
|
||||
SubscriptionNotification SubscriptionNotification `json:"subscriptionNotification,omitempty"` // 订阅通知
|
||||
OneTimeProductNotification OneTimeProductNotification `json:"oneTimeProductNotification,omitempty"` // 一次性产品通知
|
||||
TestNotification TestNotification `json:"testNotification,omitempty"` // 测试通知
|
||||
}
|
||||
|
||||
// SubscriptionNotification 包含订阅状态通知类型、token 和订阅ID,用于通过Google Android Publisher API确认状态。
|
||||
type SubscriptionNotification struct {
|
||||
Version string `json:"version"` // 版本号
|
||||
NotificationType SubscriptionNotificationType `json:"notificationType,omitempty"` // 通知类型
|
||||
PurchaseToken string `json:"purchaseToken,omitempty"` // 购买token
|
||||
SubscriptionID string `json:"subscriptionId,omitempty"` // 订阅ID
|
||||
}
|
||||
|
||||
// OneTimeProductNotification 包含一次性产品状态通知类型、token 和产品ID(SKU),用于通过Google Android Publisher API确认状态。
|
||||
type OneTimeProductNotification struct {
|
||||
Version string `json:"version"` // 版本号
|
||||
NotificationType OneTimeProductNotificationType `json:"notificationType,omitempty"` // 通知类型
|
||||
PurchaseToken string `json:"purchaseToken,omitempty"` // 购买token
|
||||
SKU string `json:"sku,omitempty"` // 产品ID(SKU)
|
||||
}
|
||||
|
||||
// TestNotification 是仅通过Google Play开发者控制台发送的测试发布通知。
|
||||
type TestNotification struct {
|
||||
Version string `json:"version"` // 版本号
|
||||
}
|
||||
118
package/pay/playstore/playstore.go
Normal file
118
package/pay/playstore/playstore.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package playstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/androidpublisher/v3"
|
||||
"google.golang.org/api/option"
|
||||
)
|
||||
|
||||
// New 创建并返回一个包含访问androidpublisher API所需凭证的http客户端。
|
||||
//
|
||||
// @Description: 通过提供的JSON密钥创建一个配置好的Client实例,可用于与Google Play Store API交互。
|
||||
// @param jsonKey 用于构建JWT配置的JSON密钥字节切片。
|
||||
// @return *Client 返回初始化好的Client实例。
|
||||
// @return error 如果在创建过程中遇到任何错误,则返回非nil的error。
|
||||
func New(jsonKey []byte) (*Client, error) {
|
||||
// 设置http客户端超时时间为10秒
|
||||
c := &http.Client{Timeout: 10 * time.Second}
|
||||
// 为context设置HTTP客户端,以便在OAuth2流程中使用
|
||||
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, c)
|
||||
|
||||
// 使用JSON密钥和所需范围配置JWT
|
||||
conf, err := google.JWTConfigFromJSON(jsonKey, androidpublisher.AndroidpublisherScope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 验证JWT配置是否正确,并获取访问令牌
|
||||
val := conf.Client(ctx).Transport.(*oauth2.Transport)
|
||||
_, err = val.Source.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 使用配置的HTTP客户端初始化androidpublisher服务
|
||||
service, err := androidpublisher.NewService(ctx, option.WithHTTPClient(conf.Client(ctx)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 返回初始化好的Client实例
|
||||
return &Client{service}, err
|
||||
}
|
||||
|
||||
// NewWithClient returns http client which includes the custom http client.
|
||||
// 使用自定义的http客户端创建并返回一个包含访问androidpublisher API所需凭证的http客户端。
|
||||
func NewWithClient(jsonKey []byte, cli *http.Client) (*Client, error) {
|
||||
if cli == nil {
|
||||
return nil, fmt.Errorf("client is nil")
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, cli)
|
||||
|
||||
conf, err := google.JWTConfigFromJSON(jsonKey, androidpublisher.AndroidpublisherScope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
service, err := androidpublisher.NewService(ctx, option.WithHTTPClient(conf.Client(ctx)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{service}, err
|
||||
}
|
||||
|
||||
// VerifySignature 验证应用内购买的签名。
|
||||
// 您需要为您的 Android 应用的内购准备公钥,可在 https://play.google.com/apps/publish/ 上完成。
|
||||
// 参数:
|
||||
//
|
||||
// base64EncodedPublicKey string - 经过 Base64 编码的公钥字符串。
|
||||
// receipt []byte - 购买收据的字节数据。
|
||||
// signature string - 购买收据的签名字符串。
|
||||
//
|
||||
// 返回值:
|
||||
//
|
||||
// isValid bool - 标识签名是否验证成功。
|
||||
// err error - 验证过程中遇到的错误。
|
||||
func VerifySignature(base64EncodedPublicKey string, receipt []byte, signature string) (isValid bool, err error) {
|
||||
// 准备公钥
|
||||
decodedPublicKey, err := base64.StdEncoding.DecodeString(base64EncodedPublicKey)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to decode public key")
|
||||
}
|
||||
publicKeyInterface, err := x509.ParsePKIXPublicKey(decodedPublicKey)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to parse public key")
|
||||
}
|
||||
publicKey, _ := publicKeyInterface.(*rsa.PublicKey)
|
||||
|
||||
// 从收据生成哈希值
|
||||
hasher := sha1.New()
|
||||
hasher.Write(receipt)
|
||||
hashedReceipt := hasher.Sum(nil)
|
||||
|
||||
// 解码签名
|
||||
decodedSignature, err := base64.StdEncoding.DecodeString(signature)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to decode signature")
|
||||
}
|
||||
|
||||
// 验证签名
|
||||
if err := rsa.VerifyPKCS1v15(publicKey, crypto.SHA1, hashedReceipt, decodedSignature); err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
64
package/pay/playstore/product.go
Normal file
64
package/pay/playstore/product.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package playstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"google.golang.org/api/androidpublisher/v3"
|
||||
)
|
||||
|
||||
// VerifyProduct 验证产品状态
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文,用于控制请求的生命周期。
|
||||
// - packageName: 应用的包名(例如,'com.some.thing')。
|
||||
// - productID: 内购产品的SKU(例如,'com.some.thing.inapp1')。
|
||||
// - token: 用户购买内购产品时设备上提供的令牌。
|
||||
//
|
||||
// 返回值:
|
||||
// - *androidpublisher.ProductPurchase: 验证购买后的详细信息。
|
||||
// - error: 执行过程中出现的错误。
|
||||
func (c *Client) VerifyProduct(ctx context.Context, packageName string, productID string, token string) (*androidpublisher.ProductPurchase, error) {
|
||||
ps := androidpublisher.NewPurchasesProductsService(c.service)
|
||||
result, err := ps.Get(packageName, productID, token).Context(ctx).Do()
|
||||
return result, err
|
||||
}
|
||||
|
||||
// AcknowledgeProduct 确认内购商品购买
|
||||
//
|
||||
// 注意!此函数必须在购买后的约24小时内对所有购买调用,否则购买将被自动撤销。
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文,用于控制请求的生命周期。
|
||||
// - packageName: 应用的包名(例如,'com.some.thing')。
|
||||
// - productId: 内购产品的SKU(例如,'com.some.thing.inapp1')。
|
||||
// - token: 用户购买内购产品时设备上提供的令牌。
|
||||
// - developerPayload: 开发者自定义信息。
|
||||
//
|
||||
// 返回值:
|
||||
// - error: 执行过程中出现的错误。
|
||||
func (c *Client) AcknowledgeProduct(ctx context.Context, packageName, productID, token, developerPayload string) error {
|
||||
ps := androidpublisher.NewPurchasesProductsService(c.service)
|
||||
acknowledgeRequest := &androidpublisher.ProductPurchasesAcknowledgeRequest{DeveloperPayload: developerPayload}
|
||||
err := ps.Acknowledge(packageName, productID, token, acknowledgeRequest).Context(ctx).Do()
|
||||
return err
|
||||
}
|
||||
|
||||
// ConsumeProduct 消费购买应用内商品。
|
||||
func (c *Client) ConsumeProduct(ctx context.Context, packageName, productID, token string) error {
|
||||
ps := androidpublisher.NewPurchasesProductsService(c.service)
|
||||
//acknowledgeRequest := &androidpublisher.PurchasesProductsConsumeCall{DeveloperPayload: developerPayload}
|
||||
//err := ps.Consume(packageName, productID, token).Context(ctx).Do()
|
||||
_, err := ps.Get(packageName, productID, token).Context(ctx).Do()
|
||||
return err
|
||||
}
|
||||
|
||||
// Voidedpurchases 获取已撤销的购买列表
|
||||
//
|
||||
// 参数:
|
||||
// - packageName: 应用的包名(例如,'com.some.thing')。
|
||||
//
|
||||
// 返回值:
|
||||
// - *androidpublisher.VoidedPurchasesListResponse: 已撤销购买的列表响应。
|
||||
// - error: 执行过程中出现的错误。
|
||||
func (c *Client) Voidedpurchases(packageName string) (*androidpublisher.VoidedPurchasesListResponse, error) {
|
||||
return androidpublisher.NewPurchasesVoidedpurchasesService(c.service).List(packageName).Do()
|
||||
}
|
||||
63
package/pay/playstore/subscription.go
Normal file
63
package/pay/playstore/subscription.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package playstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"google.golang.org/api/androidpublisher/v3"
|
||||
)
|
||||
|
||||
// AcknowledgeSubscription acknowledges a subscription purchase.
|
||||
// 功能:确认订阅购买。
|
||||
// 参数:packageName(应用包名),subscriptionID(订阅ID),token(购买令牌),req(确认请求对象)。
|
||||
// 实现:使用PurchasesSubscriptionsService服务的Acknowledge方法来确认指定订阅。
|
||||
func (c *Client) AcknowledgeSubscription(ctx context.Context, packageName string, subscriptionID string, token string,
|
||||
req *androidpublisher.SubscriptionPurchasesAcknowledgeRequest) error {
|
||||
ps := androidpublisher.NewPurchasesSubscriptionsService(c.service)
|
||||
err := ps.Acknowledge(packageName, subscriptionID, token, req).Context(ctx).Do()
|
||||
return err
|
||||
}
|
||||
|
||||
// VerifySubscription verifies subscription status
|
||||
// 功能:验证订阅状态。
|
||||
// 参数:packageName(应用包名),subscriptionID(订阅ID),token(购买令牌)。
|
||||
// 实现:使用PurchasesSubscriptionsService的Get方法来获取订阅的当前状态。
|
||||
// 返回值:SubscriptionPurchase对象,包含订阅详情。
|
||||
func (c *Client) VerifySubscription(ctx context.Context, packageName string, subscriptionID string, token string) (*androidpublisher.SubscriptionPurchase, error) {
|
||||
ps := androidpublisher.NewPurchasesSubscriptionsService(c.service)
|
||||
result, err := ps.Get(packageName, subscriptionID, token).Context(ctx).Do()
|
||||
return result, err
|
||||
}
|
||||
|
||||
// CancelSubscription cancels a user's subscription purchase.
|
||||
// 功能:取消用户的订阅购买。
|
||||
// 参数:packageName(应用包名),subscriptionID(订阅ID),token(购买令牌)。
|
||||
// 实现:使用PurchasesSubscriptionsService的Cancel方法来取消订阅。
|
||||
func (c *Client) CancelSubscription(ctx context.Context, packageName string, subscriptionID string, token string) error {
|
||||
ps := androidpublisher.NewPurchasesSubscriptionsService(c.service)
|
||||
err := ps.Cancel(packageName, subscriptionID, token).Context(ctx).Do()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// RefundSubscription refunds a user's subscription purchase, but the subscription remains valid
|
||||
// until its expiration time and it will continue to recur.
|
||||
// 功能:退款用户的订阅购买,但订阅在到期前仍有效,并且会继续递延。
|
||||
// 参数:packageName(应用包名),subscriptionID(订阅ID),token(购买令牌)。
|
||||
// 实现:使用PurchasesSubscriptionsService的Refund方法来退款,但不取消订阅。
|
||||
func (c *Client) RefundSubscription(ctx context.Context, packageName string, subscriptionID string, token string) error {
|
||||
ps := androidpublisher.NewPurchasesSubscriptionsService(c.service)
|
||||
err := ps.Refund(packageName, subscriptionID, token).Context(ctx).Do()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// RevokeSubscription refunds and immediately revokes a user's subscription purchase.
|
||||
// Access to the subscription will be terminated immediately and it will stop recurring.
|
||||
// 功能:退款并立即撤销用户的订阅购买。订阅将立即终止,并停止递延。
|
||||
// 参数:packageName(应用包名),subscriptionID(订阅ID),token(购买令牌)。
|
||||
// 实现:使用PurchasesSubscriptionsService的Revoke方法来退款并撤销订阅。
|
||||
func (c *Client) RevokeSubscription(ctx context.Context, packageName string, subscriptionID string, token string) error {
|
||||
ps := androidpublisher.NewPurchasesSubscriptionsService(c.service)
|
||||
err := ps.Revoke(packageName, subscriptionID, token).Context(ctx).Do()
|
||||
|
||||
return err
|
||||
}
|
||||
33
package/pay/playstore/utils.go
Normal file
33
package/pay/playstore/utils.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package playstore
|
||||
|
||||
import "context"
|
||||
|
||||
// GetProduct 获取应用内商品信息,该商品可以是管理型商品或订阅。
|
||||
//
|
||||
// - packageName: 应用的包名。
|
||||
// - productID: 应用内商品的唯一标识符(SKU)。
|
||||
//
|
||||
// 返回值为InAppProduct类型的商品信息和可能出现的错误。
|
||||
func (c *Client) GetProduct(ctx context.Context, packageName string, productID string) (*InAppProduct, error) {
|
||||
// 通过Google Play 商店API获取指定商品的信息
|
||||
var iap, err = c.service.Inappproducts.Get(packageName, productID).Context(ctx).Do()
|
||||
return &InAppProduct{iap}, err
|
||||
}
|
||||
|
||||
// ConvertRegionPrices 将商品的价格区域配置转换为指定货币单位。
|
||||
//
|
||||
// - ctx: 上下文,用于控制请求的取消、超时等。
|
||||
// - packageName: 应用的包名。
|
||||
// - productID: 应用内商品的唯一标识符。
|
||||
// - inAppProduct: 需要转换价格区域的InAppProduct对象。
|
||||
//
|
||||
// 返回转换后的InAppProduct对象和可能出现的错误。
|
||||
//
|
||||
// 注:此函数暂未实现。
|
||||
//func (c *Client) ConvertRegionPrices(ctx context.Context, packageName string, productID string, inAppProduct InAppProduct) (*InAppProduct, error) {
|
||||
// // TODO: 实现商品价格区域转换逻辑
|
||||
// // c.service.
|
||||
//
|
||||
// // 返回未实现的错误
|
||||
// return &InAppProduct{iap}, err
|
||||
//}
|
||||
Reference in New Issue
Block a user