Google Pay API روشهای پرداخت را در یک بار داده
PaymentMethodToken امضاشده و رمزگذاریشده برمیگرداند. روشهای پرداخت برگرداندهشده یا کارتهایی هستند که
شامل PAN هستند، یا کارتهای نشانگذاریشدهای هستند که شامل PAN دستگاه و رمزنگاری هستند.
بار داده حاوی فیلدی بهنام protocolVersion است که به گیرنده بار داده میگوید کدام اصول رمزنگاری درحال استفاده است و قالب موردانتظار چیست.
این راهنما اطلاعاتی درباره نحوه تولید کلید عمومی برای درخواست کردن یک کد روش پرداخت رمزگذاریشده و امضاشده توسط Google ارائه میدهد و مراحل لازم برای درستیسنجی و رمزگشایی کد را شرح میدهد.
این راهنما فقط برای protocolVersion = ECv2 اعمال میشود.
چون اطلاعات کارت پرداخت را مستقیماً دریافت میکنید، قبلاز ادامه دادن مطمئن شوید که برنامهتان با PCI DSS مطابقت دارد و سرورهایتان زیرساخت لازم را برای مدیریت ایمن اطلاعات کاربری پرداخت کاربر دارند.
مراحل زیر کارهایی را که یکپارچهساز باید برای مصرف کردن بار داده Google Pay API
ECv2 PaymentMethodToken انجام دهد بهطور خلاصه بیان میکند:
- کلیدهای امضای ریشه Google را واکشی کنید.
- بررسی کنید که امضای کلید امضای واسط با هرکدام از کلیدهای امضای ریشه منقضینشده معتبر باشد.
- تأیید کنید که کلید امضای واسط بار داده منقضی نشده باشد.
- تأیید کنید که امضای پایهبار با کلید امضای واسط معتبر است.
- پساز درستیسنجی امضا، محتوای بار مفید را رمزگشایی کنید.
- بررسی کنید که پیام منقضی نشده باشد. برای این کار باید بررسی کنید که زمان فعلی کمتر از فیلد
messageExpirationدر محتوای رمزگشاییشده باشد. - از روش پرداخت موجود در محتوای رمزگشاییشده استفاده کنید و آن را شارژ کنید.
کد نمونه در کتابخانه Tink ما مراحل ۱ تا ۶ را انجام میدهد.
ساختار کد روش پرداخت
پیامی که Google در پاسخ PaymentData برمیگرداند، یک شیء JSON سریالیشده با کدبندی UTF-8 است که کلیدهای آن در جدول زیر مشخص شده است:
| نام | نوع | شرح |
|---|---|---|
protocolVersion |
رشته | طرح رمزگذاری یا امضا را که پیام تحت آن ایجاد شده است شناسایی میکند. این کار به پروتکل اجازه میدهد درصورت نیاز درطول زمان تکامل یابد. |
signature |
رشته | تأیید میکند که پیام از Google ارسال شده است. این امضا با کدبندی ۶۴پایهای و با ECDSA توسط کلید امضای واسط ایجاد شده است. |
intermediateSigningKey |
شیء | شیء JSON که حاوی کلید امضای واسطه از Google است. این فایل حاوی
signedKey با keyValue، keyExpiration، و
signatures است. این گواهی برای ساده کردن فرایند درستیسنجی امضای کلید امضای واسط، سریالی شده است. |
signedMessage |
رشته | شیء JSON که بهصورت رشتهای ایمن برای HTML سریالسازی شده است و حاوی
encryptedMessage، ephemeralPublicKey، و tag است. این کلید برای سادهسازی فرایند درستیسنجی امضا، سریالی شده است. |
مثال
در زیر پاسخ کد روش پرداخت در 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\"}" }
کلید امضای واسط
intermediateSigningKey یک شیء JSON سریالیشده با کدگذاری UTF-8 است که حاوی
مقادیر زیر است:
| نام | نوع | شرح |
|---|---|---|
signedKey |
رشته | پیام کدبندیشده با base64 که حاوی شرح پرداخت کلید است. |
signatures |
رشته | تأیید میکند که کلید امضای واسط از Google آمده است. این کلید با کدبندی base64 و با ECDSA ایجاد شده است. |
کلید امضاشده
signedKey یک شیء JSON سریالیشده با کدبندی UTF-8 است که شامل
مقادیر زیر است:
| نام | نوع | شرح |
|---|---|---|
keyValue |
رشته | نسخه ۶۴پایهای کلید کدبندیشده در نوع ASN.1. SubjectPublicKeyInfo در استاندارد X.509 تعریف شده است. |
keyExpiration |
رشته | تاریخ و زمانی که کلید واسطه منقضی میشود برحسب میلیثانیه UTC از تاریخ. یکپارچهسازها هر کلیدی را که منقضی شده باشد رد میکنند. |
پیام امضاشده
signedMessage یک شیء JSON سریالیشده با کدبندی UTF-8 است که شامل
مقادیر زیر است:
| نام | نوع | شرح |
|---|---|---|
encryptedMessage |
رشته | پیام رمزگذاریشده با کدبندی base64 که حاوی اطلاعات پرداخت و برخی فیلدهای امنیتی اضافی است. |
ephemeralPublicKey |
رشته | کلید عمومی موقت کدبندیشده با base64 مرتبط با کلید خصوصی برای رمزگذاری پیام در قالب نقطه فشردهنشده. برای اطلاعات بیشتر، به قالب کلید عمومی رمزگذاری مراجعه کنید. |
tag |
رشته | یک MAC کدبندیشده با base64 از encryptedMessage. |
پیام رمزگذاریشده
encryptedMessage رمزگشاییشده یک شیء JSON سریالیشده با کدبندی UTF-8 است. JSON
دو سطح دارد. سطح بیرونی حاوی فراداده و فیلدهایی است که برای امنیت گنجانده شدهاند، درحالیکه
سطح درونی شیء JSON دیگری است که اعتبارنامه پرداخت واقعی را نشان میدهد.
برای جزئیات بیشتر درباره encryptedMessage، جدولهای زیر و
نمونههای شیء JSON را ببینید:
| نام | نوع | شرح |
|---|---|---|
messageExpiration |
رشته | تاریخ و زمانی که پیام منقضی میشود برحسب میلیثانیه UTC از تاریخ. یکپارچهسازها باید هر پیامی را که منقضی شده است رد کنند. |
messageId |
رشته | شناسه یکتایی که پیام را شناسایی میکند تا درصورت نیاز بعداً لغو یا پیدا شود. |
paymentMethod |
رشته | نوع اعتبارنامه پرداخت.
درحالحاضر، فقط از CARD پشتیبانی میشود.
|
paymentMethodDetails |
شیء | خود اعتبارنامه پرداخت. قالب این شیء توسط paymentMethod تعیین میشود و در جدولهای زیر شرح داده شده است. |
کارت
مشخصههای زیر اعتبارنامه پرداخت را برای روش پرداخت CARD تشکیل میدهند:
| نام | نوع | شرح |
|---|---|---|
pan |
رشته | شماره حساب شخصی که هزینه از آن کسر شده است. این رشته فقط حاوی رقم است. |
expirationMonth |
عدد | ماه انقضای کارت، که ۱ نشاندهنده ژانویه، ۲ نشاندهنده فوریه، و غیره است. |
expirationYear |
عدد | سال انقضای چهار رقمی کارت، مثلاً ۲۰۲۰. |
authMethod |
رشته | روش اصالتسنجی تراکنش کارت. |
merchantTokenId |
رشته | شناسه ژتون فروشنده تراکنش کارت. این فیلد اختیاری فقط درصورتی برگردانده میشود که همه شرایط زیر برآورده شده باشد:
|
PAN_ONLY
تکهکد JSON زیر نمونهای از encryptedMessage کامل برای
CARD paymentMethod
با 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 بااستفاده از رمزنگاری 3-D Secure اصالتسنجی شد،
CRYPTOGRAM_3DS authMethod. این فیلدها شامل فیلدهای اضافی زیر است:
| نام | نوع | شرح |
|---|---|---|
cryptogram |
رشته | رمزنگار 3-D Secure. |
eciIndicator |
رشته | این رشته همیشه وجود ندارد. این خطا فقط برای تراکنشهای با کد اصالتسنجیشده دستگاه در Android برگردانده میشود (CRYPTOGRAM_3DS). این مقدار باید به جریان پردازش پرداخت منتقل شود. |
تکهکد JSON زیر نمونهای از encryptedMessage کامل برای
CARD paymentMethod با
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
شبکه کارت ممکن است eciIndicator را برای تراکنشهای توکن دستگاه اصالتسنجیشده (CRYPTOGRAM_3DS) ارائه دهد.
باید مقدار eciIndicator را در تراکنش مجوزدهی بدون تغییر یا کدگذاری سخت ارسال کنید؛ درغیراینصورت، تراکنش ناموفق خواهد بود. جدول زیر جزئیات مقادیر eciIndicator را نشان میدهد.
| مقدار eciIndicator | شبکه کارت | طرف مسئول | authMethod |
|---|---|---|---|
""(empty) |
Mastercard | فروشنده/خریدار | CRYPTOGRAM_3DS |
02 |
Mastercard | صادرکننده کارت | CRYPTOGRAM_3DS |
06 |
Mastercard | فروشنده/خریدار | CRYPTOGRAM_3DS |
05 |
Visa | صادرکننده کارت | CRYPTOGRAM_3DS |
07 |
Visa | فروشنده/خریدار | CRYPTOGRAM_3DS |
""(empty) |
شبکههای دیگر | فروشنده/خریدار | CRYPTOGRAM_3DS |
هر مقدار ECI دیگری برای VISA و Mastercard که در این جدول وجود نداشته باشد برگردانده نخواهد شد.
درستیسنجی امضا
برای تأیید امضاها، که شامل امضاهای کلید واسط و پیام است، موارد زیر لازم است:
- الگوریتم استفادهشده برای ایجاد امضا
- رشته بایتی که برای ایجاد امضا استفاده شده است
- کلید عمومی که با کلید خصوصی استفادهشده برای ایجاد امضا مطابقت دارد
- خود امضا
الگوریتم امضا
Google از «الگوریتم امضای دیجیتال منحنی بیضوی» (ECDSA) برای امضای پیامها با پارامترهای زیر استفاده میکند: ECDSA روی NIST P-256 با SHA-256 بهعنوان تابع درهمسازی، همانطور که در FIPS 186-4 تعریف شده است.
امضا
امضا در بیرونیترین سطح پیام گنجانده شده است. این کلید با base64 در قالب بایت ASN.1 کدبندی شده است. برای اطلاعات بیشتر درباره ASN.1، پیوست الف ابزارهای IETF را ببینید. امضا شامل اعداد صحیح r و s در ECDSA است. برای اطلاعات بیشتر، الگوریتم تولید امضا را ببینید.
در زیر نمونهای از قالب بایت ASN.1 مشخصشده آورده شده است که قالب استاندارد تولیدشده توسط پیادهسازیهای Java Cryptography Extension (JCE) ECDSA است.
ECDSA-Sig-Value :: = SEQUENCE {
r INTEGER,
s INTEGER
}نحوه ساخت رشته بایت برای امضای کلید امضای واسطه
برای اعتبارسنجی امضای کلید امضای واسط در نمونه کد روش پرداخت،
signedStringForIntermediateSigningKeySignature را با فرمول زیر بسازید:
signedStringForIntermediateSigningKeySignature = length_of_sender_id || sender_id || length_of_protocol_version || protocol_version || length_of_signed_key || signed_key
نماد «||» بهمعنای الحاق است. هر مؤلفه—sender_id،
protocolVersion، signedKey—باید کدبندی UTF-8 داشته باشد. signedKey باید رشته intermediateSigningKey.signedKey باشد.
طول بایت هر مؤلفه ۴ بایت در قالب لیتل اندین است.
مثال
این مثال از کد روش پرداخت نمونه زیر استفاده میکند:
{
"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 همیشه Google و protocol_version
ECv2 است.
اگر sender_id Google باشد، signedString بهصورت زیر نشان داده میشود:
signedStringForIntermediateSigningKeySignature =
\x06\x00\x00\x00 || Google || | \x04\x00\x00\x00 || ECv2 || \xb5\x00\x00\x00 || {"keyExpiration":"1542323393147","keyValue":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\u003d\u003d"}نحوه درستیسنجی امضا در signedStringForIntermediateSigningKeySignature
هنگام مونتاژ رشته امضاشده برای امضای کلید امضای واسطه، از الگوریتم درستیسنجی استاندارد ECDSA استفاده میشود. برای پروتکل ECv2، باید همه امضاها را در intermediateSigningKey.signatures تکرار کنید و هرکدام را با کلیدهای امضای منقضینشده Google در keys.json اعتبارسنجی کنید. اگر حداقل یک اعتبارسنجی امضا
کار کند، درستیسنجی را کامل درنظر بگیرید. بعداً از
intermediateSigningKey.signedKey.keyValue برای درستیسنجی
signedStringForMessageSignature استفاده کنید. Google اکیداً توصیه میکند بهجای کد درستیسنجی خودتان، از کتابخانه رمزنگاری موجود استفاده کنید.
نحوه ساختن رشته بایت برای امضای پیام
برای اعتبارسنجی امضا در نمونه کد روش پرداخت،
signedStringForMessageSignature را با فرمول زیر بسازید:
signedStringForMessageSignature = length_of_sender_id || sender_id || length_of_recipient_id || recipient_id || length_of_protocolVersion || protocolVersion || length_of_signedMessage || signedMessage
نماد «||» بهمعنای الحاق است. هر مؤلفه—sender_id،
recipient_id، protocolVersion، signedMessage—باید با UTF-8
کدبندی شود. طول بایت هر مؤلفه ۴ بایت در قالب لیتل اندین است. وقتی رشته بایت را میسازید،
signedMessage را تجزیه یا اصلاح نکنید. برای مثال،
\u003d را با نویسه = جایگزین نکنید.
مثال
نمونه زیر یک نمونه از کد روش پرداخت است:
{
"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 همیشه Google و recipient_id
merchant:merchantId است. merchantId با مقدار موجود در
کنسول کیف پول و Google Pay برای فروشندگان دارای دسترسی تولید مطابقت دارد.
اگر sender_id برابر با Google و recipient_id
برابر با merchant:12345 باشد، signedString بهصورت زیر نشان داده میشود:
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"}نحوه درستیسنجی امضا در signedStringForMessageSignature
هنگام مونتاژ رشته امضاشده، از الگوریتم درستیسنجی استاندارد ECDSA استفاده میشود. intermediateSigningKey.signedKey.keyValue
تأییدشده در مرحله قبلی برای
تأیید signedMessage استفاده میشود. Google اکیداً توصیه میکند بهجای کد درستیسنجی خودتان، از کتابخانه رمزنگاری موجود استفاده کنید.
مشخصات طرح رمزگذاری
Google از «طرح رمزگذاری یکپارچه منحنی بیضوی» (ECIES) برای ایمنسازی ژتون روش پرداخت برگرداندهشده در پاسخ Google Pay API استفاده میکند. طرح رمزگذاری از پارامترهای زیر استفاده میکند:
| پارامتر | تعریف |
|---|---|
| روش کپسولهسازی کلید | ECIES-KEM، همانطور که در ISO 18033-2 تعریف شده است.
|
| تابع استخراج کلید | مبتنی بر HMAC با SHA-256 (
|
| الگوریتم رمزگذاری متقارن |
DEM2، همانطور که در ISO 18033-2 تعریف شده است الگوریتم رمزگذاری: AES-256-CTR با IV صفر و بدون لایه. |
| الگوریتم کد اصالتسنجی پیام | HMAC_SHA256 با کلید ۲۵۶ بیتی که از تابع مشتق کلید مشتق شده است. |
قالب کلید عمومی رمزگذاری
کلید عمومی رمزگذاری و ephemeralPublicKey که در پایهبارهای Google برگردانده شدهاند
با نمایش ۶۴پایهای کلید در قالب نقطه غیرفشرده قالببندی شدهاند. این شناسه از دو عنصر زیر تشکیل شده است:
- یک عدد جادویی که قالب را مشخص میکند (0x04).
- دو عدد صحیح بزرگ ۳۲ بایتی که مختصات X و Y را در «منحنی بیضوی» نشان میدهند.
این قالب با جزئیات بیشتر در «رمزنگاری کلید عمومی برای صنعت خدمات مالی: الگوریتم امضای دیجیتال منحنی بیضوی (ECDSA)»، ANSI X9.62، ۱۹۹۸ شرح داده شده است.
استفاده کردن از OpenSSL برای تولید کلید عمومی
مرحله ۱: تولید کلید خصوصی
نمونه زیر کلید خصوصی «منحنی بیضوی» مناسب برای استفاده با NIST P-256 را تولید میکند
و آن را در key.pem مینویسد:
openssl ecparam -name prime256v1 -genkey -noout -out key.pem
اختیاری: مشاهده کلیدهای خصوصی و عمومی
از فرمان زیر برای مشاهده کلید خصوصی و عمومی استفاده کنید:
openssl ec -in key.pem -pubout -text -noout
این فرمان بروندادی مشابه زیر تولید میکند:
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
مرحله ۲: تولید کلید عمومی کدگذاریشده با base64
کلید خصوصی و عمومی که در مثال مرحله اختیاری قبلی تولید شده است، بهصورت شانزدهشانزدهی کدگذاری شده است. برای دریافت کلید عمومی کدبندیشده با base64 در قالب نقطه فشردهنشده، از فرمان زیر استفاده کنید:
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
این فرمان فایل publicKey.txt را تولید میکند که محتوای آن، نسخه ۶۴پایهای
کلید در قالب نقطه فشردهنشده، شبیه به موارد زیر است:
BOdoXP+9Aq473SnGwg3JU1aiNpsd9vH2ognq4PtDtlLGa3Kj8TPf+jaQNPyDSkh3JUhiS0KyrrlWhAgNZKHYF2Y=
محتوای فایل نباید فاصله خالی اضافی یا بازگشت نورد داشته باشد. برای تأیید این موضوع، فرمان زیر را در Linux یا MacOS اجرا کنید:
od -bc publicKey.txt
مرحله ۳: تولید کلید خصوصی کدبندیشده با base64 در قالب PKCS #8
کتابخانه Tink انتظار دارد کلید خصوصی شما در قالب PKCS #8 با کدبندی base64 باشد. از فرمان زیر برای تولید کلید خصوصی در این قالب از کلید خصوصی تولیدشده در مرحله اول استفاده کنید:
openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -nocrypt | base64 | paste -sd "\0" -
این فرمان بروندادی مشابه زیر تولید میکند:
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWV4oK8c/MZkCLk4qSCNjW0Zm6H0CBCtSYxkXkC9FBHehRANCAAQPldOnhO2/oXjdJD1dwlFPiNs6fcdoRgFu3/Z0iKj24SjTGyLRGAtYWLGXBZcDdPj3T2bJRHRVhE8Bc2AjkT7n
نحوه رمزگشایی کردن کد روش پرداخت
برای رمزگشایی کردن توکن، این مراحل را دنبال کنید:
- از کلید خصوصیتان و
ephemeralPublicKeyارائهشده برای بهدست آوردن کلید مشترک ۵۱۲ بیتی استفاده کنید که از ECIES-KEM استفاده میکند. از پارامترهای زیر استفاده کنید: - منحنی بیضوی: NIST P-256، که در OpenSSL با نام prime256v1 نیز شناخته میشود.
-
CheckMode،OldCofactorMode،SingleHashMode، وCofactorMode0هستند. - تابع کدبندی: قالب نقطه فشردهنشده.
- تابع استخراج کلید: HKDFwithSHA256، همانطور که در RFC 5869 شرح داده شده است، با پارامتر زیر:
- Salt نباید ارائه شود. طبق RFC، این باید معادل یک سالت ۳۲ بایت صفرشده باشد.
- کلید تولیدشده را به دو کلید ۲۵۶ بیتی تقسیم کنید:
symmetricEncryptionKeyوmacKey. بررسی کنید که فیلد
tagیک MAC معتبر برایencryptedMessageباشد.برای تولید MAC موردانتظار، از HMAC (RFC 5869) با تابع چکیدهساز SHA256 و
macKeyبهدستآمده در مرحله ۲ استفاده کنید.encryptedMessageرا بااستفاده از حالت AES-256-CTR و با موارد زیر رمزگشایی کنید:- بردار مقداردهی اولیه صفر.
- بدون لایه محافظ.
symmetricEncryptionKeyمشتقشده در مرحله ۲.
مدیریت کلید
کلیدهای رمزگذاری فروشنده
فروشندگان طبق مشخصات ذکرشده در مشخصات طرح رمزگذاری، کلید عمومی تولید میکنند.
کلیدهای امضای ریشه Google
Google مجموعهای از کلیدهای عمومی امضای ریشه را که درحالحاضر معتبر هستند و از نشانی وب عمومی قابلواکشی هستند منتشر میکند. کلیدها تا زمانی معتبر هستند که سرصفحههای حافظه پنهان HTTP که توسط نشانی وب برگردانده میشوند نشان میدهند. این کلیدها تا زمان انقضا که توسط فیلد keyExpiration تعیین میشود، در حافظه نهان ذخیره میشوند. توصیه میکنیم وقتی واکشی منقضی میشود، کلیدها را دوباره از نشانی وب عمومی واکشی کنید تا فهرست فعلی کلیدهای معتبر را دریافت کنید.
استثنا برای پروتکل ECv2: اگر نمیتوانید کلیدها را در زمان اجرا از Google واکشی کنید،
keys.json را از نشانی وب تولید ما واکشی کنید، آن را در سیستم خود ذخیره کنید، و بهطور دورهای
بهصورت دستی بازآوری کنید. در شرایط عادی، Google کلید امضای ریشه جدیدی برای ECv2 پنج سال
قبلاز منقضی شدن کلید با طولانیترین تاریخ انقضا صادر میکند. درصورت لو رفتن کلید، Google
ازطریق اطلاعات تماس ارائهشده در درگاه خودیاری به همه فروشندگان اطلاع میدهد تا
بارگیری مجدد سریعتر keys.json را درخواست کند. برای اطمینان از اینکه چرخش منظم را ازدست نمیدهید، توصیه میکنیم فروشندگانی که انتخاب میکنند کلیدهای Google را در محتوای keys.json ذخیره کنند، سالانه بهعنوان بخشی از چرخش کلید سالانه خود، بازآوری کنند.
کلیدهای ارائهشده ازطریق نشانی وب عمومی در قالب زیر نگاشت میشوند:
{ "keys": [ { "keyValue": "encoded public key", "protocolVersion": "ECv2" "keyExpiration":"2000000000000" }, { "keyValue": "encoded public key", "protocolVersion": "ECv2" "keyExpiration":"3000000000000" } ] }
keyValue نسخه base64، بدون پوشش یا حاشیه، از کلید کدبندیشده در نوع SubjectPublicKeyInfo ASN.1 است که در استاندارد X.509 تعریف شده است. در جاوا، کدگذاری ASN.1 ارجاعشده با
کلاس X509EncodedKeySpec نمایش داده میشود.
میتوان آن را با ECPublicKey.getEncoded() دریافت کرد.
نشانیهای وب برای هر دو محیط آزمایشی و تولیدی در پیوندهای زیر ارائه شده است:
- آزمایش:
https://payments.developers.google.com/paymentmethodtoken/test/keys.json - تولید:
https://payments.developers.google.com/paymentmethodtoken/keys.json
چرخش کلید
اگر با ادغام مستقیم، یک روش پرداخت را مستقیماً در سرورهایتان رمزگشایی میکنید، باید کلیدها را سالانه بچرخانید.
برای چرخاندن کلیدهای رمزگذاری، مراحل زیر را تکمیل کنید:
- از OpenSSL برای تولید جفت کلید جدید استفاده کنید.
- کنسول کیف پول و Google Pay را باز کنید و با «حساب Google» که قبلاً برای مدیریت برنامهتان با Google Play استفاده میشد.
- در برگه Google Pay API، در زیر قاب ادغام مستقیم، روی مدیریت در کنار کلید عمومی موجود خود کلیک کنید. روی افزودن کلید دیگر کلیک کنید.
- فیلد ورودی نوشتار کلید رمزگذاری عمومی را انتخاب کنید و کلید عمومی جدیداً تولیدشدهتان را که با base64 در قالب نقطه غیرفشرده کدبندی شده است اضافه کنید.
- روی ذخیره کلیدهای رمزگذاری کلیک کنید.
برای اطمینان از چرخش یکپارچه کلید، درطول انتقال کلیدها، از رمزگشایی کلیدهای خصوصی جدید و قدیمی پشتیبانی کنید.
اگر از کتابخانه Tink برای رمزگشایی کردن توکن استفاده میکنید، از کد Java زیر برای پشتیبانی از چندین کلید خصوصی استفاده کنید:
String decryptedMessage = new PaymentMethodTokenRecipient.Builder() .addRecipientPrivateKey(newPrivateKey) .addRecipientPrivateKey(oldPrivateKey);
مطمئن شوید که کد رمزگشایی در تولید مستقر شده است و رمزگشاییهای موفق را پایش میکنید.
کلید عمومی استفادهشده در کدتان را تغییر دهید.
مقدار مشخصه
publicKeyرا در خصوصیتPaymentMethodTokenizationSpecificationparametersجایگزین کنید:/** * @param publicKey public key retrieved from your server */ private static JSONObject getTokenizationSpecification(String publicKey) { JSONObject tokenizationSpecification = new JSONObject(); tokenizationSpecification.put("type", "DIRECT"); tokenizationSpecification.put( "parameters", new JSONObject() .put("protocolVersion", "ECv2") .put("publicKey", publicKey)); return tokenizationSpecification; }
- کد مرحله ۴ را در محیط تولید مستقر کنید. وقتی کد مستقر شد، تراکنشهای رمزگذاری و رمزگشایی از جفت کلیدهای جدید استفاده میکنند.
تأیید کنید که کلید عمومی قدیمی دیگر برای رمزگذاری تراکنشها استفاده نمیشود.
- کلید خصوصی قدیمی را بردارید.
- کنسول Pay و کیف پول Google را باز کنید و با همان «حساب Google» که قبلاً برای ثبتنام بهعنوان توسعهدهنده در Google Pay استفاده کردهاید به سیستم وارد شوید.
- در برگه Google Pay API، در زیر قاب ادغام مستقیم، روی مدیریت در کنار کلید عمومی موجود کلیک کنید. روی حذف در کنار کلید عمومی قدیمیتان کلیک کنید و روی ذخیره کلیدهای رمزگذاری کلیک کنید.
Google از کلید مشخصشده در ویژگی publicKey در شیء PaymentMethodTokenizationSpecification parameters استفاده میکند، همانطور که در مثال زیر نشان داده شده است:
{
"protocolVersion": "ECv2",
"publicKey": "BOdoXP+9Aq473SnGwg3JU1..."
}از کتابخانه Tink برای مدیریت پاسخ رمزگذاریشده استفاده کنید
برای انجام درستیسنجی امضا و رمزگشایی پیام، از کتابخانه Tink paymentmethodtoken استفاده کنید. این کتابخانه فقط در Java دردسترس است. برای استفاده از آن، مراحل زیر را تکمیل کنید:
در
pom.xml، برنامه Tinkpaymentmethodtokenرا بهعنوان وابستگی اضافه کنید:<dependencies> <!-- other dependencies ... --> <dependency> <groupId>com.google.crypto.tink</groupId> <artifactId>apps-paymentmethodtoken</artifactId> <version>1.9.1</version> <!-- or latest version --> </dependency> </dependencies>هنگام راهاندازی سرور، کلیدهای امضای Google را پیشواکشی کنید تا کلید در حافظه دردسترس قرار گیرد. این کار از مشاهده هرگونه تأخیر شبکه توسط کاربر درحین واکشی کلیدها توسط فرایند رمزگشایی جلوگیری میکند.
GooglePaymentsPublicKeysManager.INSTANCE_PRODUCTION.refreshInBackground();
پیام را با کد زیر رمزگشایی کنید، که فرض میکند
paymentMethodTokenدر متغیرencryptedMessageذخیره شده است، و بخشهای پررنگ را مطابق با سناریو خود جایگزین کنید.برای آزمایشهای غیرتولیدی،
INSTANCE_PRODUCTIONرا باINSTANCE_TESTجایگزین کنید و اگر ادغام شما غیرفعال است یا کلید رمزگذاری پیکربندیشده ندارد، [YOUR MERCHANT ID] را باجایگزین کنید.- فعال
- ادغام DIRECT فعال است
- کلید رمزگذاری پیکربندیشده دارد
[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);
PrivateKey1را با مقدار کلید خصوصی مناسبی که با مقدار کلید عمومی ثبتشده با Google از آمادهسازی کلیدها و ثبتنام با Google مرتبط است جایگزین کنید. بعداً وقتی لازم شد کلیدها را با Google بچرخانید، میتوانید چندین مقدار کلید خصوصی دیگر اضافه کنید. متغیرها میتوانند رشته PKCS8 کدبندیشده با base64 یا شیءECPrivateKeyباشند. برای اطلاعات بیشتر درباره نحوه تولید کردن کلید خصوصی PKCS8 کدگذاریشده با base64، به آماده کردن کلیدها و ثبتنام در Google مراجعه کنید.اگر نمیتوانید هربار که کلیدها را رمزگشایی میکنید با سرور Google تماس بگیرید، با کد زیر رمزگشایی کنید و بخشهای پررنگ را مطابق با سناریو خود جایگزین کنید.
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);
کلید فعلی در محیط تولید تا تاریخ ۲۰۳۸/۰۴/۱۴ تحت شرایط عادی معتبر است، مگر اینکه کلید لو برود. درصورت لو رفتن کلید، Google ازطریق اطلاعات تماس ارائهشده در درگاه خودخدمتی به همه فروشندگان اطلاع میدهد تا درخواست بار کردن مجدد سریعتر
keys.jsonرا بدهد.تکهکد جزئیات امنیتی زیر را مدیریت میکند تا بتوانید روی مصرف بار مفید تمرکز کنید:
- کلیدهای امضای Google واکشی و در حافظه پنهان ذخیره شد
- درستیسنجی امضا
- رمزگشایی