Google 钱包卡券开发流程

Google Wallet API 提供了一组预定义的卡券类型,这些卡券类型针对特定用例(例如礼品卡、登机牌、活动门票等)进行了优化。此外,还有一种通用卡券类型,适用于无法使用特定卡券类型的用例。

本文旨在帮助您熟悉使用 Google Wallet API 创建和签发卡券所需的基本步骤。您可以通过多种方式完成下文详述的某些步骤,但大体上讲,所有卡券类型都是按照相同的基本开发流程创建的。

如需查看卡券创建的详细演示,请参阅适用于网页、电子邮件和短信Android 应用的指南。

用途

卡券类定义一组在多个卡券中通用的属性,与模板类似。例如,如果您要签发活动门票,卡券类将定义所有门票都相同的字段,例如活动名称、日期和时间。

您发出的每个卡券都必须引用一个卡券类。您还必须为您创建的每个卡券类分配一个唯一 ID,用于在创建卡券时引用该类。

实现方式

卡券类以 JSON 格式定义,可以通过 Google Wallet REST API、Android SDK 或 Google 钱包业务控制台创建。

显示卡券类示例

{
  "id": "ISSUER_ID.EVENT_CLASS_ID",
  "issuerName": "[TEST ONLY] Heraldic Event",
  "localizedIssuerName": {
    "defaultValue": {
      "language": "en-US",
      "value": "[TEST ONLY] Heraldic Event"
    }
  },
  "logo": {
    "sourceUri": {
      "uri": "https://images.unsplash.com/photo-1475721027785-f74eccf877e2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=660&h=660"
    },
    "contentDescription": {
      "defaultValue": {
        "language": "en-US",
        "value": "LOGO_IMAGE_DESCRIPTION"
      }
    }
  },
  "eventName": {
    "defaultValue": {
      "language": "en-US",
      "value": "Google Live"
    }
  },
  "venue": {
    "name": {
      "defaultValue": {
        "language": "en-US",
        "value": "Shoreline Amphitheater"
      }
    },
    "address": {
      "defaultValue": {
        "language": "en-US",
        "value": "ADDRESS_OF_THE_VENUE"
      }
    }
  },
  "dateTime": {
    "start": "2023-04-12T11:30"
  },
  "reviewStatus": "UNDER_REVIEW",
  "hexBackgroundColor": "#264750",
  "heroImage": {
    "sourceUri": {
      "uri": "https://images.unsplash.com/photo-1501281668745-f7f57925c3b4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1032&h=336"
    },
    "contentDescription": {
      "defaultValue": {
        "language": "en-US",
        "value": "HERO_IMAGE_DESCRIPTION"
      }
    }
  }
}
    

用途

卡券对象定义了将签发给特定用户的唯一卡券的属性。例如,活动门票的卡券对象会定义特定门票所独有的字段,如该门票的座位号或二维码。

创建卡券对象后,Google Wallet API 会存储新的卡券,并将其与您的发卡机构帐号相关联。此存储的卡券结合了卡券对象的唯一属性和关联卡券类的模板属性。

您还必须为每个卡券对象分配一个唯一 ID,以便在签发卡券时引用它。

实现方式

卡券对象是定义的 JSON 格式,可通过 Google Wallet REST API 或 Android SDK 创建。

显示卡券对象示例

{
  "id": "ISSUER_ID.OBJECT_ID",
  "classId": "ISSUER_ID.EVENT_CLASS_ID",
  "state": "ACTIVE",
  "seatInfo": {
    "seat": {
      "defaultValue": {
        "language": "en-us",
        "value": "5"
      }
    },
    "row": {
      "defaultValue": {
        "language": "en-us",
        "value": "G"
      }
    },
    "section": {
      "defaultValue": {
        "language": "en-us",
        "value": "40"
      }
    },
    "gate": {
      "defaultValue": {
        "language": "en-us",
        "value": "3A"
      }
    }
  },
  "barcode": {
    "type": "QR_CODE",
    "value": "BARCODE_VALUE",
    "alternateText": ""
  }
}
    

用途

如需向用户颁发卡券,卡券类和卡券对象必须以 JSON Web 令牌 (JWT) 编码。JWT 格式是表示双方之间的声明的通用开放标准。在使用 Google Wallet API 签发卡券时,JWT 用于发送声明,表明用户有权访问与您的发卡机构帐号相关联的特定卡券。

将 JWT 发送到 Google Wallet API 时,编码数据将用于标识特定卡券,并将其发放给用户。如果卡券已签发,Google Wallet API 可通过此数据确定卡券是重复卡券,这样它就不会重复添加到用户的 Google 钱包中。

实现方式

JWT 是根据 JWT 规范以 JSON 格式定义的。如需定义使用 Google Wallet API 颁发卡券的 JWT,请在 JWT 的 payload 属性中提供与要签发的卡券相关的信息。

显示示例 JWT

{
  "iss": "issuer@example.com",
  "aud": "google",
  "typ": "savetowallet",
  "iat": 1696877738,
  "origins": [
    "www.example.com"
  ],
  "payload": {
    "eventTicketObjects": [
      {
        "id": "ISSUER_ID.LOYALTY_OBJECT_SUFFIX"
      }
    ]
  }
}
    

用途

发送到 Google Wallet API 以颁发卡券的所有 JWT 都必须使用您之前在 Google Wallet Business Console 中提供的凭据签名。签名功能会使用您的凭据来加密 JWT,以确保您的凭证保持安全,并允许 Google Wallet API 进行身份验证,确保编码在凭证中的凭证详情有效且与您的发卡机构帐号相关联。

实现方式

Google 电子钱包客户端库和 Android SDK 提供了为 JWT 签名的各种便捷方法。此外,还有大量的开源库可以处理代码签名的复杂性,供您从中选择。

对于使用 Google Wallet REST API 颁发卡券的用户,JWT 将使用 Google Cloud 服务账号密钥为 JWT 签名。对于使用 Google 钱包 Android SDK 的用户,该 SDK 会自动使用应用签名证书的 SHA-1 指纹为 JWT 签名。

为了保护您的凭据,请仅在您的服务器上为 JWT 签名,或在您的应用中使用 Google 钱包 Android SDK。

显示代码签名示例代码

Java

  // Create the JWT as a HashMap object
  HashMap claims = new HashMap();
  claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail());
  claims.put("aud", "google");
  claims.put("origins", Arrays.asList("www.example.com"));
  claims.put("typ", "savetowallet");

  // Create the Google Wallet payload and add to the JWT
  HashMap payload = new HashMap();
  payload.put("eventTicketObjects", Arrays.asList(newObject));
  claims.put("payload", payload);

  // Google Cloud service account credentials are used to sign the JWT
  Algorithm algorithm =
      Algorithm.RSA256(
          null, (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey());
  String token = JWT.create().withPayload(claims).sign(algorithm);
        

Node.JS

  // Create the JWT claims
  let claims = {
    iss: this.credentials.client_email,
    aud: 'google',
    origins: ['www.example.com'],
    typ: 'savetowallet',
    payload: {
      eventTicketObjects: [newObject]
    },
  };

  // The service account credentials are used to sign the JWT
  let token = jwt.sign(claims, this.credentials.private_key, { algorithm: 'RS256' });
        

Python

  # Create the JWT claims
  claims = {
      'iss': self.credentials.service_account_email,
      'aud': 'google',
      'origins': ['www.example.com'],
      'typ': 'savetowallet',
      'payload': {
          # The listed classes and objects will be created
          'eventTicketObjects': [new_object]
      }
  }

  # The service account credentials are used to sign the JWT
  signer = crypt.RSASigner.from_service_account_file(self.key_file_path)
  token = jwt.encode(signer, claims).decode('utf-8')
        

用途

创建已签名的 JWT 后,您就可以向 Google 钱包用户颁发卡券了!为此,请向用户显示“添加到 Google 钱包”按钮或链接。当用户点击该按钮或超链接时,系统会将已签名的 JWT 发送到 Google Wallet API,然后由 Google Wallet API 使用您保存的凭据对其进行解密。JWT 签名经过身份验证后,系统会将卡券发放给用户,以将其保存在 Google 钱包中。

实现方式

要为 Android 应用创建“添加到 Google 钱包”按钮,请使用 Google Wallet Android SDK,其中提供了生成该按钮的方法。对于所有其他平台(包括网页、电子邮件和短信),请创建 https://pay.google.com/gp/v/save/<signed_jwt> 格式的超链接。尽可能以“添加到 Google 电子钱包”按钮的形式向用户发送此链接。

如需详细了解如何使用“添加到 Google 钱包”按钮,请参阅 Google Wallet API 品牌推广指南

显示示例代码

  https://pay.google.com/gp/v/save/<signed_jwt>
        

Android SDK

  private lateinit var walletClient: PayClient
  private val addToGoogleWalletRequestCode = 1000
  private lateinit var addToGoogleWalletButton: View

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    walletClient = Pay.getClient(this)
    addToGoogleWalletButton.setOnClickListener {
      walletClient.savePasses(newObjectJson, this, addToGoogleWalletRequestCode)
    }
  }
        

用户保存签发的卡券后,该卡券将与保存的任何其他卡券一起显示在用户的 Google 钱包应用中。

在 JWT 中创建卡券对象和卡券类

卡券类和卡券对象可以使用 Google Wallet REST API 或 Android SDK 提前创建。创建后,系统会通过引用其 ID 来使用卡券发放卡券。

或者,您也可以“及时”创建卡券类和卡券对象,方法是将其 JSON 直接嵌入用于向用户发布卡券的 JWT 中。在此方法中,当使用“添加到 Google 钱包”按钮或链接发送已签名的 JWT 时,Google Wallet API 会创建卡券类和卡券对象。

例如,下面显示的 JWT 具有使用 payload.eventTicketClassespayload.eventTicketObjects 属性定义的新卡券类和卡券对象。请注意,这些属性是数组,因此它们可以接受一个或多个卡券类或卡券对象。您也可以仅在 JWT 中指定通过 ID 引用现有卡券类的新卡券对象。

显示示例 JWT

  {
    "iss": "issuer@example.com",
    "aud": "google",
    "typ": "savetowallet",
    "iat": 1696877738,
    "origins": [
      "www.example.com"
    ],
    "payload": {
      "eventTicketClasses": [{
        "id": "ISSUER_ID.EVENT_CLASS_ID",
        "issuerName": "[TEST ONLY] Heraldic Event",
        "localizedIssuerName": {
          "defaultValue": {
            "language": "en-US",
            "value": "[TEST ONLY] Heraldic Event"
          }
        },
        "logo": {
          "sourceUri": {
            "uri": "https://images.unsplash.com/photo-1475721027785-f74eccf877e2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=660&h=660"
          },
          "contentDescription": {
            "defaultValue": {
              "language": "en-US",
              "value": "LOGO_IMAGE_DESCRIPTION"
            }
          }
        },
        "eventName": {
          "defaultValue": {
            "language": "en-US",
            "value": "Google Live"
          }
        },
        "venue": {
          "name": {
            "defaultValue": {
              "language": "en-US",
              "value": "Shoreline Amphitheater"
            }
          },
          "address": {
            "defaultValue": {
              "language": "en-US",
              "value": "ADDRESS_OF_THE_VENUE"
            }
          }
        },
        "dateTime": {
          "start": "2023-04-12T11:30"
        },
        "reviewStatus": "UNDER_REVIEW",
        "hexBackgroundColor": "#264750",
        "heroImage": {
          "sourceUri": {
            "uri": "https://images.unsplash.com/photo-1501281668745-f7f57925c3b4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1032&h=336"
          },
          "contentDescription": {
            "defaultValue": {
              "language": "en-US",
              "value": "HERO_IMAGE_DESCRIPTION"
            }
          }
        }
      }],
      "eventTicketObjects": [{
        "id": "ISSUER_ID.OBJECT_ID",
        "classId": "ISSUER_ID.EVENT_CLASS_ID",
        "state": "ACTIVE",
        "seatInfo": {
          "seat": {
            "defaultValue": {
              "language": "en-us",
              "value": "5"
            }
          },
          "row": {
            "defaultValue": {
              "language": "en-us",
              "value": "G"
            }
          },
          "section": {
            "defaultValue": {
              "language": "en-us",
              "value": "40"
            }
          },
          "gate": {
            "defaultValue": {
              "language": "en-us",
              "value": "3A"
            }
          }
        },
        "barcode": {
          "type": "QR_CODE",
          "value": "BARCODE_VALUE",
          "alternateText": ""
        }
      }]
    }
  }