Google Pay API menampilkan metode pembayaran dalam payload PaymentMethodToken yang ditandatangani dan dienkripsi. Metode pembayaran yang ditampilkan adalah kartu yang
terdiri dari PAN, atau kartu yang ditokenisasi yang terdiri dari PAN perangkat dan kriptogram.
Payload berisi kolom bernama protocolVersion yang memberi tahu penerima payload tentang primitif kriptografis yang digunakan dan format yang diharapkan.
Panduan ini memberikan informasi tentang cara membuat kunci publik untuk meminta token metode pembayaran yang ditandatangani dan dienkripsi oleh Google, serta menjelaskan langkah-langkah yang harus dilakukan untuk memverifikasi dan mendekripsi token.
Panduan ini hanya berlaku untuk protocolVersion = ECv2.
Karena Anda menerima informasi kartu pembayaran secara langsung, pastikan aplikasi Anda mematuhi PCI DSS dan server Anda memiliki infrastruktur yang diperlukan untuk menangani kredensial pembayaran pengguna dengan aman sebelum melanjutkan.
Langkah-langkah berikut menguraikan hal yang harus dilakukan integrator untuk menggunakan payload ECv2 PaymentMethodToken Google Pay API:
- Ambil kunci penandatanganan root Google.
- Pastikan tanda tangan kunci penandatanganan perantara valid oleh salah satu kunci penandatanganan root yang belum habis masa berlakunya.
- Pastikan kunci penandatanganan perantara payload belum habis masa berlakunya.
- Pastikan tanda tangan payload valid menurut kunci penandatanganan perantara.
- Dekripsi konten payload setelah Anda memverifikasi tanda tangan.
- Pastikan masa berlaku pesan belum berakhir. Hal ini mengharuskan Anda memeriksa bahwa waktu saat ini
kurang dari kolom
messageExpirationdalam konten yang didekripsi. - Gunakan metode pembayaran dalam konten yang didekripsi dan tagih.
Kode contoh di library Tink kami menjalankan langkah 1–6.
Struktur token metode pembayaran
Pesan yang ditampilkan oleh Google dalam respons PaymentData adalah objek JSON yang dienkode UTF-8 dan diserialisasi dengan kunci yang ditentukan dalam tabel berikut:
| Nama | Jenis | Deskripsi |
|---|---|---|
protocolVersion |
String | Mengidentifikasi skema enkripsi atau penandatanganan yang digunakan untuk membuat pesan. Hal ini memungkinkan protokol berkembang seiring waktu, jika diperlukan. |
signature |
String | Memverifikasi bahwa pesan berasal dari Google. Kunci ini dienkode base64, dan dibuat dengan ECDSA oleh kunci penandatanganan perantara. |
intermediateSigningKey |
Objek | Objek JSON yang berisi kunci penandatanganan perantara dari Google. File ini berisi
signedKey dengan keyValue, keyExpiration, dan
signatures. Kunci ini diserialisasi untuk menyederhanakan proses verifikasi tanda tangan kunci penandatanganan perantara. |
signedMessage |
String | Objek JSON yang diserialisasi sebagai string yang aman untuk HTML yang berisi
encryptedMessage, ephemeralPublicKey, dan tag. Data ini
diserialisasi untuk menyederhanakan proses verifikasi tanda tangan. |
Contoh
Berikut adalah respons token metode pembayaran dalam JSON:
{ "protocolVersion":"ECv2", "signature":"MEQCIH6Q4OwQ0jAceFEkGF0JID6sJNXxOEi4r+mA7biRxqBQAiAondqoUpU/bdsrAOpZIsrHQS9nwiiNwOrr24RyPeHA0Q\u003d\u003d", "intermediateSigningKey":{ "signedKey": "{\"keyExpiration\":\"1542323393147\",\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\\u003d\\u003d\"}", "signatures": ["MEYCIQCO2EIi48s8VTH+ilMEpoXLFfkxAwHjfPSCVED/QDSHmQIhALLJmrUlNAY8hDQRV/y1iKZGsWpeNmIP+z+tCQHQxP0v"] }, "signedMessage":"{\"tag\":\"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\\u003d\",\"ephemeralPublicKey\":\"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\\u003d\",\"encryptedMessage\":\"mKOoXwi8OavZ\"}" }
Kunci penandatanganan perantara
intermediateSigningKey adalah objek JSON yang dienkode UTF-8 dan diserialisasi yang berisi
nilai berikut:
| Nama | Jenis | Deskripsi |
|---|---|---|
signedKey |
String | Pesan berenkode base64 yang berisi deskripsi pembayaran kunci. |
signatures |
String | Memverifikasi bahwa kunci penandatanganan perantara berasal dari Google. Kunci ini dienkode base64, dan dibuat dengan ECDSA. |
Kunci bertanda tangan
signedKey adalah objek JSON yang dienkode UTF-8 dan diserialisasi yang berisi nilai berikut:
| Nama | Jenis | Deskripsi |
|---|---|---|
keyValue |
String | Versi base64 dari kunci yang dienkode dalam jenis ASN.1. SubjectPublicKeyInfo ditentukan dalam standar X.509. |
keyExpiration |
String | Tanggal dan waktu saat kunci perantara berakhir sebagai milidetik UTC sejak epoch. Integrator menolak kunci apa pun yang sudah tidak berlaku. |
Pesan yang ditandatangani
signedMessage adalah objek JSON yang dienkode UTF-8 dan diserialisasi yang berisi nilai berikut:
| Nama | Jenis | Deskripsi |
|---|---|---|
encryptedMessage |
String | Pesan terenkripsi berenkode base64 yang berisi informasi pembayaran dan beberapa kolom keamanan tambahan. |
ephemeralPublicKey |
String | Kunci publik sementara berenkode base64 yang terkait dengan kunci pribadi untuk mengenkripsi pesan dalam format titik yang tidak dikompresi. Untuk mengetahui informasi selengkapnya, lihat Format kunci publik enkripsi. |
tag |
String | MAC berenkode base64 dari encryptedMessage. |
Pesan terenkripsi
encryptedMessage yang didekripsi adalah objek JSON yang diserialisasi dan dienkode UTF-8. JSON berisi dua tingkat. Tingkat luar berisi metadata dan kolom yang disertakan untuk keamanan, sedangkan
tingkat dalam adalah objek JSON lain yang mewakili kredensial pembayaran yang sebenarnya.
Untuk mengetahui detail selengkapnya tentang encryptedMessage, lihat tabel dan contoh objek JSON berikut:
| Nama | Jenis | Deskripsi |
|---|---|---|
messageExpiration |
String | Tanggal dan waktu saat pesan berakhir sebagai milidetik UTC sejak epoch. Integrator harus menolak pesan yang telah habis masa berlakunya. |
messageId |
String | ID unik yang mengidentifikasi pesan jika perlu dicabut atau ditemukan di lain waktu. |
paymentMethod |
String | Jenis kredensial pembayaran.
Saat ini, hanya CARD yang didukung.
|
paymentMethodDetails |
Objek | Kredensial pembayaran itu sendiri. Format objek ini ditentukan oleh
paymentMethod dan dijelaskan dalam tabel berikut. |
Kartu
Properti berikut membentuk kredensial pembayaran untuk metode pembayaran CARD:
| Nama | Jenis | Deskripsi |
|---|---|---|
pan |
String | Nomor rekening pribadi yang dikenai biaya. String ini hanya berisi digit. |
expirationMonth |
Angka | Bulan habis masa berlaku kartu, dengan 1 mewakili Januari, 2 mewakili Februari, dan seterusnya. |
expirationYear |
Angka | Empat digit tahun habis masa berlaku kartu, misalnya 2020. |
authMethod |
String | Metode autentikasi transaksi kartu. |
merchantTokenId |
String | ID token penjual dari transaksi kartu. Kolom opsional ini hanya ditampilkan jika semua kondisi berikut terpenuhi:
|
PAN_ONLY
Cuplikan JSON berikut adalah contoh encryptedMessage lengkap untuk
CARD paymentMethod
dengan PAN_ONLY authMethod.
{ "paymentMethod": "CARD", "paymentMethodDetails": { "authMethod": "PAN_ONLY", "pan": "1111222233334444", "expirationMonth": 10, "expirationYear": 2025 }, "gatewayMerchantId": "some-merchant-id", "messageId": "some-message-id", "messageExpiration": "1759309000000" }
CRYPTOGRAM_3DS
CARD yang diautentikasi dengan penggunaan kriptogram 3-D Secure,
CRYPTOGRAM_3DS authMethod. Ini mencakup kolom tambahan berikut:
| Nama | Jenis | Deskripsi |
|---|---|---|
cryptogram |
String | Kriptogram 3-D Secure. |
eciIndicator |
String | String ini tidak selalu ada. Token ini hanya ditampilkan untuk transaksi token perangkat yang diautentikasi di Android (CRYPTOGRAM_3DS). Nilai ini harus diteruskan ke alur pemrosesan pembayaran. |
Cuplikan JSON berikut adalah contoh encryptedMessage lengkap untuk
CARD paymentMethod dengan
CRYPTOGRAM_3DS authMethod:
{
"paymentMethod": "CARD",
"paymentMethodDetails": {
"authMethod": "CRYPTOGRAM_3DS",
"pan": "1111222233334444",
"expirationMonth": 10,
"expirationYear": 2025,
"cryptogram": "AAAAAA...",
"eciIndicator": "eci indicator",
"merchantTokenId": "merchant-token-id",
},
"messageId": "some-message-id",
"messageExpiration": "1759309000000"
}eciIndicator
Jaringan kartu mungkin memberikan eciIndicator untuk transaksi token perangkat yang diautentikasi (CRYPTOGRAM_3DS).
Anda harus meneruskan nilai eciIndicator pada transaksi otorisasi tanpa mengubah atau melakukan hardcode; jika tidak, transaksi akan gagal. Tabel berikut menjelaskan nilai eciIndicator.
| Nilai eciIndicator | Jaringan Kartu | Pihak yang Bertanggung Jawab | authMethod |
|---|---|---|---|
""(empty) |
Mastercard | Penjual/Pemroses | CRYPTOGRAM_3DS |
02 |
Mastercard | Penerbit kartu | CRYPTOGRAM_3DS |
06 |
Mastercard | Penjual/Pemroses | CRYPTOGRAM_3DS |
05 |
Visa | Penerbit kartu | CRYPTOGRAM_3DS |
07 |
Visa | Penjual/Pemroses | CRYPTOGRAM_3DS |
""(empty) |
Jaringan lain | Penjual/Pemroses | CRYPTOGRAM_3DS |
Nilai ECI lainnya untuk VISA dan Mastercard yang tidak ada dalam tabel ini tidak akan ditampilkan.
Verifikasi tanda tangan
Untuk memverifikasi tanda tangan, yang mencakup kunci perantara dan tanda tangan pesan, item berikut diperlukan:
- Algoritma yang digunakan untuk membuat tanda tangan
- String byte yang digunakan untuk membuat tanda tangan
- Kunci publik yang sesuai dengan kunci pribadi yang digunakan untuk membuat tanda tangan
- Tanda tangan itu sendiri
Algoritma tanda tangan
Google menggunakan Algoritma Tanda Tangan Digital Kurva Eliptik (ECDSA) untuk menandatangani pesan dengan parameter berikut: ECDSA melalui NIST P-256 dengan SHA-256 sebagai fungsi hash, seperti yang ditentukan dalam FIPS 186-4.
Tanda tangan
Tanda tangan disertakan dalam tingkat terluar pesan. Kunci ini dienkode dengan base64 dalam format byte ASN.1. Untuk informasi selengkapnya tentang ASN.1, lihat Lampiran A Alat IETF. Tanda tangan terdiri dari bilangan bulat r dan s ECDSA. Untuk mengetahui informasi selengkapnya, lihat Algoritma pembuatan tanda tangan.
Berikut adalah contoh format byte ASN.1 yang ditentukan, yang merupakan format standar yang dihasilkan oleh implementasi ECDSA Java Cryptography Extension (JCE).
ECDSA-Sig-Value :: = SEQUENCE {
r INTEGER,
s INTEGER
}Cara membuat string byte untuk tanda tangan kunci penandatanganan perantara
Untuk memvalidasi tanda tangan kunci penandatanganan perantara dalam contoh token metode pembayaran, buat
signedStringForIntermediateSigningKeySignature dengan formula berikut:
signedStringForIntermediateSigningKeySignature = length_of_sender_id || sender_id || length_of_protocol_version || protocol_version || length_of_signed_key || signed_key
Notasi "||" berarti penyambungan. Setiap komponen—sender_id,
protocolVersion, signedKey—harus dienkode UTF-8. signedKey harus berupa string intermediateSigningKey.signedKey.
Panjang byte setiap komponen adalah 4 byte dalam format little-endian.
Contoh
Contoh ini menggunakan contoh token metode pembayaran berikut:
{
"protocolVersion":"ECv2",
"signature":"MEQCIH6Q4OwQ0jAceFEkGF0JID6sJNXxOEi4r+mA7biRxqBQAiAondqoUpU/bdsrAOpZIsrHQS9nwiiNwOrr24RyPeHA0Q\u003d\u003d",
"intermediateSigningKey":{
"signedKey": "{\"keyExpiration\":\"1542323393147\",\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\\u003d\\u003d\"}",
"signatures": ["MEYCIQCO2EIi48s8VTH+ilMEpoXLFfkxAwHjfPSCVED/QDSHmQIhALLJmrUlNAY8hDQRV/y1iKZGsWpeNmIP+z+tCQHQxP0v"]
},
"signedMessage":"{\"tag\":\"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\\u003d\",\"ephemeralPublicKey\":\"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\\u003d\",\"encryptedMessage\":\"mKOoXwi8OavZ\"}"
}sender_id selalu Google dan protocol_version adalah
ECv2.
Jika sender_id adalah Google, signedString akan muncul seperti yang ditunjukkan dalam contoh berikut:
signedStringForIntermediateSigningKeySignature =
\x06\x00\x00\x00 || Google || | \x04\x00\x00\x00 || ECv2 || \xb5\x00\x00\x00 || {"keyExpiration":"1542323393147","keyValue":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\u003d\u003d"}Cara memverifikasi tanda tangan di signedStringForIntermediateSigningKeySignature
Algoritma verifikasi ECDSA standar digunakan saat string yang ditandatangani untuk tanda tangan kunci penandatanganan perantara disusun. Untuk protokol ECv2, Anda perlu melakukan iterasi pada semua tanda tangan
di intermediateSigningKey.signatures dan mencoba memvalidasi setiap tanda tangan dengan
kunci penandatanganan Google yang belum habis masa berlakunya di keys.json. Jika setidaknya satu validasi tanda tangan
berhasil, anggap verifikasi selesai. Gunakan
intermediateSigningKey.signedKey.keyValue nanti untuk memverifikasi
signedStringForMessageSignature. Google sangat menyarankan Anda menggunakan library kriptografi yang ada, bukan kode verifikasi Anda sendiri.
Cara membuat string byte untuk tanda tangan pesan
Untuk memvalidasi tanda tangan dalam contoh token metode pembayaran, buat
signedStringForMessageSignature dengan formula berikut:
signedStringForMessageSignature = length_of_sender_id || sender_id || length_of_recipient_id || recipient_id || length_of_protocolVersion || protocolVersion || length_of_signedMessage || signedMessage
Notasi "||" berarti penyambungan. Setiap komponen—sender_id,
recipient_id, protocolVersion, signedMessage—harus dienkode
UTF-8. Panjang byte setiap komponen adalah 4 byte dalam format little-endian. Saat Anda membuat
string byte, jangan mengurai atau mengubah signedMessage. Misalnya, jangan ganti
\u003d dengan karakter =.
Contoh
Berikut adalah contoh token metode pembayaran:
{
"protocolVersion":"ECv2",
"signature":"MEQCIH6Q4OwQ0jAceFEkGF0JID6sJNXxOEi4r+mA7biRxqBQAiAondqoUpU/bdsrAOpZIsrHQS9nwiiNwOrr24RyPeHA0Q\u003d\u003d",
"intermediateSigningKey":{
"signedKey": "{\"keyExpiration\":\"1542323393147\",\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\\u003d\\u003d\"}",
"signatures": ["MEYCIQCO2EIi48s8VTH+ilMEpoXLFfkxAwHjfPSCVED/QDSHmQIhALLJmrUlNAY8hDQRV/y1iKZGsWpeNmIP+z+tCQHQxP0v"]
},
"signedMessage":"{\"tag\":\"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\\u003d\",\"ephemeralPublicKey\":\"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\\u003d\",\"encryptedMessage\":\"mKOoXwi8OavZ\"}"
}sender_id selalu Google dan recipient_id adalah
merchant:merchantId. merchantId cocok dengan nilai yang ditemukan di
Konsol Google Pay & Wallet untuk penjual dengan akses produksi.
Jika sender_id adalah Google dan recipient_id
adalah merchant:12345, signedString akan muncul seperti dalam contoh
berikut:
signedStringForMessageSignature =
\x06\x00\x00\x00 || Google || \x0e\x00\x00\x00 || merchant:12345 || | \x04\x00\x00\x00 || ECv2 || \xd2\x00\x00\x00 || {"tag":"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\u003d","ephemeralPublicKey":"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\u003d","encryptedMessage":"mKOoXwi8OavZ"}Cara memverifikasi tanda tangan di signedStringForMessageSignature
Algoritma verifikasi ECDSA standar digunakan saat string yang ditandatangani disusun. intermediateSigningKey.signedKey.keyValue yang diverifikasi pada langkah sebelumnya digunakan untuk memverifikasi signedMessage. Google sangat menyarankan Anda menggunakan library kriptografi yang ada, bukan kode verifikasi Anda sendiri.
Spesifikasi skema enkripsi
Google menggunakan Elliptic Curve Integrated Encryption Scheme (ECIES) untuk mengamankan token metode pembayaran yang ditampilkan dalam respons API Google Pay. Skema enkripsi menggunakan parameter berikut:
| Parameter | Definisi |
|---|---|
| Metode enkapsulasi kunci | ECIES-KEM, sebagaimana ditentukan dalam ISO 18033-2.
|
| Fungsi derivasi kunci | Berbasis HMAC dengan SHA-256 (
|
| Algoritma enkripsi simetris |
DEM2, sebagaimana ditentukan dalam ISO 18033-2 Algoritma enkripsi: AES-256-CTR dengan IV nol dan tanpa padding. |
| Algoritma MAC | HMAC_SHA256 dengan kunci 256-bit seperti yang diperoleh dari fungsi derivasi kunci. |
Format kunci publik enkripsi
Kunci publik enkripsi dan ephemeralPublicKey yang ditampilkan dalam payload Google diformat dengan representasi base64 dari kunci dalam format titik yang tidak dikompresi. Terdiri dari
dua elemen berikut:
- Satu nomor ajaib yang menentukan format (0x04).
- Dua bilangan bulat besar 32 byte yang mewakili koordinat X dan Y dalam Kurva Eliptis.
Format ini dijelaskan secara lebih mendetail dalam "Kriptografi Kunci Publik Untuk Industri Jasa Keuangan: Algoritma Tanda Tangan Digital Kurva Eliptik (ECDSA)," ANSI X9.62, 1998.
Menggunakan OpenSSL untuk membuat kunci publik
Langkah 1: Buat kunci pribadi
Contoh berikut menghasilkan kunci pribadi Kurva Eliptik yang cocok untuk digunakan dengan NIST P-256
dan menulisnya ke key.pem:
openssl ecparam -name prime256v1 -genkey -noout -out key.pem
Opsional: Melihat kunci pribadi dan publik
Gunakan perintah berikut untuk melihat kunci pribadi dan publik:
openssl ec -in key.pem -pubout -text -noout
Perintah ini menghasilkan output yang mirip dengan berikut ini:
read EC key
Private-Key: (256 bit)
priv:
08:f4:ae:16:be:22:48:86:90:a6:b8:e3:72:11:cf:
c8:3b:b6:35:71:5e:d2:f0:c1:a1:3a:4f:91:86:8a:
f5:d7
pub:
04:e7:68:5c:ff:bd:02:ae:3b:dd:29:c6:c2:0d:c9:
53:56:a2:36:9b:1d:f6:f1:f6:a2:09:ea:e0:fb:43:
b6:52:c6:6b:72:a3:f1:33:df:fa:36:90:34:fc:83:
4a:48:77:25:48:62:4b:42:b2:ae:b9:56:84:08:0d:
64:a1:d8:17:66
ASN1 OID: prime256v1
Langkah 2: Buat kunci publik berenkode base64
Kunci pribadi dan publik yang dihasilkan dalam contoh langkah opsional sebelumnya dienkode dalam format heksadesimal. Untuk mendapatkan kunci publik berenkode base64 dalam format titik yang tidak dikompresi, gunakan perintah berikut:
openssl ec -in key.pem -pubout -text -noout 2> /dev/null | grep "pub:" -A5 | sed 1d | xxd -r -p | base64 | paste -sd "\0" - | tr -d '\n\r ' > publicKey.txt
Perintah ini menghasilkan file publicKey.txt yang kontennya, yaitu versi base64 dari kunci dalam format titik yang tidak dikompresi, menyerupai berikut ini:
BOdoXP+9Aq473SnGwg3JU1aiNpsd9vH2ognq4PtDtlLGa3Kj8TPf+jaQNPyDSkh3JUhiS0KyrrlWhAgNZKHYF2Y=
Konten file tidak boleh memiliki spasi kosong atau enter tambahan. Untuk memverifikasi hal ini, jalankan perintah berikut di Linux atau MacOS:
od -bc publicKey.txt
Langkah 3: Buat kunci pribadi berenkode base64 dalam format PKCS #8
Library Tink mengharapkan kunci pribadi Anda dienkode base64 dalam format PKCS #8. Gunakan perintah berikut untuk membuat kunci pribadi dalam format ini dari kunci pribadi yang dibuat pada langkah pertama:
openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -nocrypt | base64 | paste -sd "\0" -
Perintah ini menghasilkan output yang mirip dengan berikut ini:
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWV4oK8c/MZkCLk4qSCNjW0Zm6H0CBCtSYxkXkC9FBHehRANCAAQPldOnhO2/oXjdJD1dwlFPiNs6fcdoRgFu3/Z0iKj24SjTGyLRGAtYWLGXBZcDdPj3T2bJRHRVhE8Bc2AjkT7n
Cara mendekripsi token metode pembayaran
Ikuti langkah-langkah berikut untuk mendekripsi token:
- Gunakan kunci pribadi Anda dan
ephemeralPublicKeyyang diberikan untuk mendapatkan kunci bersama sepanjang 512 bit yang menggunakan ECIES-KEM. Gunakan parameter berikut: - Kurva eliptis: NIST P-256, juga dikenal di OpenSSL sebagai prime256v1.
CheckMode,OldCofactorMode,SingleHashMode, danCofactorModeadalah0.- Fungsi encoding: Format titik yang tidak dikompresi.
- Fungsi derivasi kunci: HKDFwithSHA256, seperti yang dijelaskan dalam RFC 5869, dengan parameter berikut:
- Salt tidak boleh diberikan. Sesuai dengan RFC, ini harus setara dengan salt 32 byte yang di-nol-kan.
- Pisahkan kunci yang dihasilkan menjadi dua kunci sepanjang 256 bit:
symmetricEncryptionKeydanmacKey. Pastikan kolom
tagadalah MAC yang valid untukencryptedMessage.Untuk membuat MAC yang diharapkan, gunakan HMAC (RFC 5869) dengan fungsi hash SHA256 dan
macKeyyang diperoleh di Langkah 2.Dekripsi
encryptedMessagedengan menggunakan mode AES-256-CTR, dan dengan hal berikut:- IV nol.
- Tidak diisi.
symmetricEncryptionKeyyang diperoleh di Langkah 2.
Pengelolaan kunci
Kunci enkripsi penjual
Penjual membuat kunci publik sesuai dengan spesifikasi yang diuraikan dalam Spesifikasi skema enkripsi.
Kunci penandatanganan root Google
Google memublikasikan kumpulan kunci publik penandatanganan root yang saat ini valid dan dapat diambil dari URL publik. Kunci tersebut valid selama header cache HTTP yang ditampilkan oleh URL menunjukkannya. Kunci tersebut di-cache hingga masa berlakunya habis, yang ditentukan oleh kolom keyExpiration. Sebaiknya saat pengambilan berakhir, ambil kunci dari URL publik lagi untuk menerima daftar kunci valid saat ini.
Pengecualian untuk protokol ECv2: Jika Anda tidak dapat mengambil kunci dari Google saat runtime, ambil
keys.json dari URL produksi kami, simpan ke sistem Anda, dan muat ulang secara berkala
secara manual. Dalam keadaan normal, Google menerbitkan kunci penandatanganan root baru untuk ECv2 lima tahun
sebelum kunci dengan tanggal habis masa berlaku terlama berakhir. Jika terjadi penyusupan kunci, Google
akan memberi tahu semua penjual melalui informasi kontak yang diberikan di portal layanan mandiri untuk
meminta pemuatan ulang keys.json yang lebih cepat. Untuk memastikan Anda tidak melewatkan
rotasi reguler, sebaiknya penjual yang memilih untuk menyimpan kunci Google dalam konten
keys.json melakukan pembaruan setiap tahun sebagai bagian dari rotasi kunci tahunan mereka sendiri.
Kunci yang disediakan melalui URL publik dipetakan dalam format berikut:
{ "keys": [ { "keyValue": "encoded public key", "protocolVersion": "ECv2" "keyExpiration":"2000000000000" }, { "keyValue": "encoded public key", "protocolVersion": "ECv2" "keyExpiration":"3000000000000" } ] }
keyValue adalah versi base64, tidak digabungkan atau diisi, dari kunci yang dienkode dalam jenis SubjectPublicKeyInfo ASN.1 yang ditentukan dalam standar X.509. Di Java, encoding ASN.1 yang dirujuk diwakili oleh class X509EncodedKeySpec.
Token ini dapat diperoleh dengan ECPublicKey.getEncoded().
URL untuk lingkungan pengujian dan produksi disediakan melalui link berikut:
- Uji:
https://payments.developers.google.com/paymentmethodtoken/test/keys.json - Produksi:
https://payments.developers.google.com/paymentmethodtoken/keys.json
Rotasi kunci
Jika Anda mendekripsi token metode pembayaran langsung di server Anda dengan integrasi langsung, Anda harus merotasi kunci setiap tahun.
Selesaikan langkah-langkah berikut untuk merotasi kunci enkripsi:
- Gunakan OpenSSL untuk membuat pasangan kunci baru.
- Buka Konsol Google Pay & Wallet saat login dengan Akun Google yang sebelumnya Anda gunakan untuk mendaftar sebagai developer Google Pay.
- Di tab Google Pay API, di panel Integrasi langsung, klik Kelola di samping kunci publik yang ada. Klik Tambahkan kunci lain.
- Pilih kolom input teks Public encryption key dan tambahkan kunci publik yang baru dibuat yang dienkode base64 dalam format titik yang tidak dikompresi.
- Klik Simpan kunci enkripsi.
Untuk memastikan rotasi kunci yang lancar, dukung dekripsi kunci pribadi baru dan lama saat Anda mentransisikan kunci.
Jika Anda menggunakan library Tink untuk mendekripsi token, gunakan kode Java berikut untuk mendukung beberapa kunci pribadi:
String decryptedMessage = new PaymentMethodTokenRecipient.Builder() .addRecipientPrivateKey(newPrivateKey) .addRecipientPrivateKey(oldPrivateKey);
Pastikan kode untuk dekripsi di-deploy ke produksi dan Anda memantau dekripsi yang berhasil.
Ubah kunci publik yang digunakan dalam kode Anda.
Ganti nilai atribut
publicKeydi propertiPaymentMethodTokenizationSpecificationparameters:const tokenizationSpecification = { "type": "DIRECT", "parameters": { "protocolVersion": "ECv2", "publicKey": "BOdoXP1aiNp.....kh3JUhiSZKHYF2Y=" } }
- Deploy kode dari langkah 4 ke produksi. Setelah kode di-deploy, transaksi enkripsi dan dekripsi akan menggunakan pasangan kunci baru.
Pastikan kunci publik lama tidak lagi digunakan untuk mengenkripsi transaksi apa pun.
- Hapus kunci pribadi lama.
- Buka Konsol Google Pay & Wallet saat login dengan Akun Google yang sebelumnya Anda gunakan untuk mendaftar sebagai developer dengan Google Pay.
- Di tab Google Pay API, di panel Integrasi langsung, klik Kelola di samping kunci publik yang ada. Klik Hapus di samping kunci publik lama Anda, lalu klik Simpan kunci enkripsi.
Google menggunakan kunci yang ditentukan dalam properti publicKey dalam objek PaymentMethodTokenizationSpecification parameters, seperti yang ditunjukkan dalam contoh berikut:
{
"protocolVersion": "ECv2",
"publicKey": "BOdoXP+9Aq473SnGwg3JU1..."
}Menggunakan library Tink untuk mengelola respons terenkripsi
Untuk melakukan verifikasi tanda tangan dan dekripsi pesan, gunakan library paymentmethodtoken Tink. Library ini hanya tersedia di Java. Untuk menggunakannya, selesaikan langkah-langkah berikut:
Di
pom.xml, tambahkan aplikasi Tinkpaymentmethodtokensebagai dependensi:<dependencies> <!-- other dependencies ... --> <dependency> <groupId>com.google.crypto.tink</groupId> <artifactId>apps-paymentmethodtoken</artifactId> <version>1.9.1</version> <!-- or latest version --> </dependency> </dependencies>Saat server dimulai, ambil kunci penandatanganan Google terlebih dahulu agar kunci tersedia di memori. Hal ini mencegah tampilan pengguna dari latensi jaringan apa pun saat proses dekripsi mengambil kunci.
GooglePaymentsPublicKeysManager.INSTANCE_PRODUCTION.refreshInBackground();
Dekripsi pesan dengan kode berikut, yang mengasumsikan
paymentMethodTokendisimpan dalam variabelencryptedMessage, dan ganti bagian yang dicetak tebal sesuai dengan skenario Anda.Untuk pengujian non-produksi, ganti
INSTANCE_PRODUCTIONdenganINSTANCE_TEST, dan jika integrasi Anda tidak aktif atau tidak memiliki kunci enkripsi yang dikonfigurasi, ganti [YOUR MERCHANT ID] dengan12345678901234567890.- Aktif
- Mengaktifkan integrasi DIRECT
- Memiliki kunci enkripsi yang dikonfigurasi
jangan ganti [YOUR MERCHANT ID].
String decryptedMessage = new PaymentMethodTokenRecipient.Builder() .fetchSenderVerifyingKeysWith( GooglePaymentsPublicKeysManager.INSTANCE_PRODUCTION) .recipientId("merchant:[YOUR MERCHANT ID]") // This guide applies only to protocolVersion = ECv2 .protocolVersion("ECv2") // Multiple private keys can be added to support graceful // key rotations. .addRecipientPrivateKey(PrivateKey1) .addRecipientPrivateKey(PrivateKey2) .build() .unseal(encryptedMessage);
Ganti
PrivateKey1dengan nilai kunci pribadi yang sesuai yang terkait dengan nilai kunci publik yang terdaftar di Google dari Menyiapkan kunci dan mendaftar ke Google. Anda dapat menambahkan beberapa nilai kunci pribadi lainnya nanti saat diminta untuk Merotasi kunci dengan Google. Variabel dapat berupa string PKCS8 berenkode base64 atau objekECPrivateKey. Untuk mengetahui informasi selengkapnya tentang cara membuat kunci pribadi PKCS8 berenkode base64, lihat Menyiapkan kunci dan mendaftar ke Google.Jika Anda tidak dapat memanggil server Google setiap kali mendekripsi kunci, dekripsi dengan kode berikut dan ganti bagian yang dicetak tebal sesuai dengan skenario Anda.
String decryptedMessage = new PaymentMethodTokenRecipient.Builder() .addSenderVerifyingKey("ECv2 key fetched from test or production url") .recipientId("merchant:[YOUR MERCHANT ID]") // This guide applies only to protocolVersion = ECv2 .protocolVersion("ECv2") // Multiple private keys can be added to support graceful // key rotations. .addRecipientPrivateKey(PrivateKey1) .addRecipientPrivateKey(PrivateKey2) .build() .unseal(encryptedMessage);
Kunci saat ini di lingkungan produksi berlaku hingga 14/04/2038 dalam keadaan normal, kecuali jika kunci tersebut disusupi. Jika terjadi penyusupan kunci, Google akan memberi tahu semua penjual melalui informasi kontak yang diberikan di portal layanan mandiri untuk meminta pemuatan ulang
keys.jsonyang lebih cepat.Cuplikan kode menangani detail keamanan berikut sehingga Anda dapat berfokus pada penggunaan payload:
- Kunci penandatanganan Google diambil dan di-cache dalam memori
- Verifikasi tanda tangan
- Dekripsi