תהליך פיתוח כרטיס ל-Google Wallet

Google Wallet API מספק קבוצה מוגדרת מראש של סוגי כרטיסים שמותאמים לתרחישי שימוש ספציפיים, כמו כרטיסי מתנה, כרטיסי עלייה למטוס, כרטיסים לאירועים ועוד. יש גם סוג כרטיס גנרי שמיועד למקרים שבהם סוג כרטיס מסוים לא זמין.

המאמר הזה נועד להציג את השלבים הבסיסיים הנדרשים ליצירה ולהנפקה של כרטיס באמצעות Google Wallet API. יש כמה דרכים לבצע חלק מהשלבים שמפורטים בהמשך, אבל ברמה גבוהה כל סוגי הכרטיסים נוצרים לפי אותו תהליך פיתוח בסיסי.

להדרכה מפורטת בנושא יצירת כרטיס, אפשר לעיין במדריכים לאינטרנט, לאימייל ול-SMS או לאפליקציות ל-Android.

למה זה מיועד

קטגוריית כרטיסים מגדירה קבוצה של מאפיינים שמשותפים לכמה כרטיסים, בדומה לתבנית. לדוגמה, אם אתם מנפיקים כרטיסים לאירוע, הקטגוריה 'כרטיסים' תגדיר שדות זהים בכל הכרטיסים, למשל שם האירוע, התאריך והשעה.

כל כרטיס שמנפיקים חייב להתייחס למחלקה של כרטיסים. בנוסף, צריך להקצות מזהה ייחודי לכל מחלקה של כרטיסים שאתם יוצרים. המזהה הזה ישמש להפניה אל יצירת הכרטיסים.

איך עושים את זה

מחלקת כרטיסים מוגדרת בפורמט JSON ואפשר ליצור אותה באמצעות ה-API ל-REST של Google Wallet, Android SDK או באמצעות ה-Business Console של Google Wallet.

הצגת מחלקת כרטיסים לדוגמה

{
  "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"
      }
    }
  }
}
    

למה זה מיועד

אובייקט 'כרטיסים' מגדיר את המאפיינים של כרטיס ייחודי שיונפק למשתמש ספציפי. לדוגמה, האובייקט 'כרטיסים' של כרטיס לאירוע יגדיר שדות ייחודיים לכרטיס מסוים, כמו מספר המושב או קוד ה-QR של הכרטיס הזה.

כשאובייקט 'כרטיסים' נוצר, Google Wallet API מאחסן כרטיס חדש ומשייך אותו לחשבון המנפיק שלכם. הכרטיס המאוחסן הזה הוא שילוב של המאפיינים הייחודיים של אובייקט הכרטיסים ומאפייני התבנית של קטגוריית הכרטיסים המשויכת.

בנוסף, עליכם להקצות לכל אובייקט 'כרטיסים' מזהה ייחודי שישמש כהפניה אליו בהנפקת הכרטיס.

איך עושים את זה

אובייקט Passes מוגדר בפורמט JSON, ואפשר ליצור אותו באמצעות ה-API ל-REST של Google Wallet או 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": ""
  }
}
    

למה זה מיועד

כדי להנפיק כרטיס למשתמש, אובייקט מסוג Passes Class ו-Passes חייב להיות מקודד באסימון אינטרנט מסוג JSON (JWT). פורמט JWT הוא סטנדרט נפוץ ופתוח לייצוג הצהרות בין שני צדדים. במקרה של הנפקת כרטיסים באמצעות Google Wallet API, אסימוני JWT משמשים לשליחת הצהרה על כך שלמשתמש יש זכות לגשת לכרטיס ספציפי שמשויך לחשבון המנפיק שלכם.

כשקוד JWT נשלח ל-Google Wallet API, הנתונים המקודדים משמשים לזיהוי כרטיס ספציפי ולהנפקת אותו למשתמש. אם הכרטיס כבר הונפק, הנתונים האלה גם מאפשרים ל-Google Wallet API לזהות שהכרטיס כפול כך שלא יתווסף ל-Google Wallet של המשתמש יותר מפעם אחת.

איך עושים את זה

אסימוני JWT מוגדרים בפורמט JSON על סמך מפרט JWT. כדי להגדיר JWT להנפקת כרטיס באמצעות Google Wallet API, עליך לספק את המידע לגבי הכרטיס שברצונך להנפיק בנכס payload של ה-JWT.

הצגת JWT לדוגמה

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

למה זה מיועד

כל אסימוני ה-JWT שנשלחים אל Google Wallet API להנפקת כרטיס חייבים להיות חתומים עם פרטי הכניסה שסיפקת בעבר במסוף העסקי של Google Wallet. במסגרת החתימה, נעשה שימוש בפרטי הכניסה שלך כדי להצפין את ה-JWT כדי שהכרטיסים יישארו מאובטחים, וכדי לאפשר ל-Google Wallet API לאמת שפרטי הכרטיס שקודדו בו תקפים ומשויכים לחשבון המנפיק שלכם.

איך עושים את זה

ספריות הלקוח של Google Wallet ו-Android SDK מספקות שיטות נוחות לחתימה על אסימוני JWT. יש גם ספריות רבות של קוד פתוח זמינות שמטפלות במורכבות של חתימת קוד, שמתוכן תוכלו לבחור.

אם אתם משתמשים ב-API ל-REST של Google Wallet כדי להנפיק כרטיסים, ה-JWT נחתם באמצעות מפתח לחשבון שירות של Google Cloud. למשתמשי Google Wallet Android SDK, ערכת ה-SDK מטפלת באופן אוטומטי בחתימה על ה-JWT באמצעות טביעת האצבע SHA-1 של האישור לחתימת האפליקציה.

כדי להגן על פרטי הכניסה שלך, אסימוני JWT צריכים להיות חתומים רק בשרת שלך או להשתמש ב-Android SDK של Google Wallet באפליקציה שלך.

הצגת חתימת קוד לדוגמה

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 Wallet. כדי לעשות זאת, מוצגת למשתמש האפשרות 'הוספה ל-Google Wallet'. לחצן או קישור. כשמשתמש לוחץ על הלחצן או על ההיפר-קישור, ה-JWT החתום נשלח ל-Google Wallet API, ואז מפענח אותו באמצעות פרטי הכניסה שנשמרו. לאחר שחתימת ה-JWT מאומתת, הכרטיס יונפק למשתמש כדי לשמור אותו ב-Google Wallet.

איך עושים את זה

כדי ליצור 'הוספה ל-Google Wallet' עבור אפליקציה ל-Android, השתמשו ב-Android SDK של Google Wallet, שמספק שיטות ליצירת הלחצן. לכל שאר הפלטפורמות, כולל אינטרנט, אימייל והודעת טקסט, יוצרים היפר-קישור בפורמט https://pay.google.com/gp/v/save/<signed_jwt>. כשהדבר אפשרי, מומלץ לספק את הקישור הזה למשתמש בתור 'הוספה ל-Google Wallet'. לחצן.

לקבלת מידע נוסף על השימוש בתכונה 'הוספה ל-Google Wallet' הלחצן, עיין בהנחיות המותג של 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 Wallet שלו עם כל הכרטיסים האחרים שהוא שמר.

יצירת אובייקטים של כרטיסים וסיווגים של כרטיסים ב-JWT

אפשר ליצור אובייקטים של 'כיתות' ו'כרטיסים' מראש באמצעות ה-API ל-REST של Google Wallet או Android SDK. לאחר יצירתם, הם ישמשו להנפקת כרטיסים באמצעות ציון המזהה שלהם.

לחלופין, אפשר גם ליצור אובייקטים של 'סיווגים' ו'כרטיסים' 'בדיוק בזמן'. על ידי הטמעת קובץ ה-JSON ישירות ב-JWT שמשמש להנפקת הכרטיס למשתמש. בשיטה הזו, האובייקטים של הכיתות והכרטיסים נוצרים על ידי Google Wallet API כשה-JWT החתום נשלח באמצעות 'הוספה ל-Google Wallet' לחצן או קישור.

לדוגמה, למטה מוצג JWT עם קטגוריית כרטיסים חדשה ואובייקט כרטיסים חדשים שהוגדרו באמצעות המאפיינים payload.eventTicketClasses ו-payload.eventTicketObjects. שימו לב שהמאפיינים האלה הם מערכים, ולכן הם יכולים לקבל אובייקט אחד או יותר של מחלקות או אובייקטים של כרטיסים. אפשר גם לציין רק אובייקט כרטיסים חדש ב-JWT שמפנה לסיווג כרטיסים קיים לפי המזהה שלו.

הצגת 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": ""
        }
      }]
    }
  }