API گوگل پی برای جت‌پک کامپوز در اندروید

۱. مقدمه

آنچه خواهید ساخت

با تکمیل این آزمایشگاه کد، شما یک برنامه Jetpack Compose حداقلی و قابل اجرا با ادغام Google Pay برای اندروید خواهید داشت. این پروژه یک توکن پرداخت را بازیابی می‌کند که ممکن است برای پردازش به یک ارائه‌دهنده خدمات پرداخت ارسال شود.

آنچه یاد خواهید گرفت

  • نحوه نصب و پیکربندی کتابخانه Compose جت‌پک گوگل پی
  • نحوه نمایش دکمه Google Pay و مدیریت کلیک‌ها
  • نحوه درخواست توکن پرداخت از گوگل پی

آنچه نیاز دارید

  • اندروید استودیو (آخرین نسخه پایدار) نصب شده است.
  • کیت توسعه نرم‌افزار اندروید (SDK) و یک شبیه‌ساز یا دستگاه که در اندروید استودیو راه‌اندازی شده باشد.
  • برای تولید، به یک شناسه تجاری گوگل پی (Google Pay merchantId ) نیاز دارید. ثبت نام در کنسول گوگل پی و کیف پول (Google Pay & Wallet Console) فقط یک دقیقه طول می‌کشد، پس بهتر است همین الان این کار را انجام دهید.

۲. پروژه Jetpack Compose را ایجاد کنید

ایجاد فایل‌های پروژه

  1. یک پروژه جدید Jetpack Compose در اندروید استودیو با نام gpay-compose ایجاد کنید:
    • اندروید استودیو را باز کنید و گزینه New Project انتخاب کنید.
    • الگوی Empty Activity (Jetpack Compose) را انتخاب کنید.
    • نام: gpay-compose ، نام بسته: com.example.gpay .
    • زبان: کاتلین، حداقل SDK: API 21+.
    • برای تولید پروژه، کار را تمام کنید.
  2. وابستگی دکمه نوشتن Google Pay را اضافه کنید. در فایل app/build.gradle(.kts) خود، موارد زیر را اضافه کنید:
    dependencies {
        implementation("com.google.pay.button:compose-pay-button:1.0.0")
    }
    
    گرووی دی‌اس‌ال:
    dependencies {
        implementation 'com.google.pay.button:compose-pay-button:1.0.0'
    }
    
  3. وابستگی کیف پول خدمات گوگل پلی را اضافه کنید (برای باز کردن برگه Google Pay): در فایل app/build.gradle(.kts) خود، وابستگی زیر را اضافه کنید:
    dependencies {
        implementation("com.google.android.gms:play-services-wallet:19.3.0")
    }
    
    اگر پروژه شما از Groovy DSL استفاده می‌کند، از موارد زیر استفاده کنید:
    dependencies {
        implementation 'com.google.android.gms:play-services-wallet:19.3.0'
    }
    
  4. MainActivity.kt در اندروید استودیو باز کنید و محتویات آن را با ساختار برنامه Compose مینیمال زیر جایگزین کنید (در مرحله بعد دکمه را سیم‌کشی خواهیم کرد):
    package com.example.gpay
    
    import android.os.Bundle
    import androidx.activity.ComponentActivity
    import androidx.activity.compose.setContent
    import androidx.compose.foundation.layout.Box
    import androidx.compose.foundation.layout.fillMaxSize
    import androidx.compose.material3.MaterialTheme
    import androidx.compose.material3.Surface
    import androidx.compose.ui.Alignment
    import androidx.compose.ui.Modifier
    
    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
                    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                        // Google Pay button added in the next section
                    }
                }
            }
        }
    }
    

۳. پیکربندی گوگل پی

یک درخواست پرداخت گوگل پی به یک شیء درخواست نیاز دارد. شیء تعریف شده در اینجا به عنوان baseGooglePayRequest شامل حداقل تنظیمات مشترک برای همه درخواست‌ها است. تنظیمات اضافی بسته به درخواست انجام شده اضافه خواهند شد که در این آزمایشگاه کد بررسی خواهیم کرد.

ثابت‌های پیکربندی Google Pay را به MainActivity.kt اضافه کنید (در مرحله بعدی از آنها دوباره استفاده خواهید کرد):

private const val merchantId = "12345678901234567890"

// This is the base configuration for all Google Pay payment data requests.
private val baseGooglePayRequest = """
    {
      "apiVersion": 2,
      "apiVersionMinor": 0,
      "allowedPaymentMethods": [
        {
          "type": "CARD",
          "parameters": {
            "allowedAuthMethods": [
              "PAN_ONLY", "CRYPTOGRAM_3DS"
            ],
            "allowedCardNetworks": [
              "AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"
            ]
          },
          "tokenizationSpecification": {
            "type": "PAYMENT_GATEWAY",
            "parameters": {
              "gateway": "example",
              "gatewayMerchantId": "exampleGatewayMerchantId"
            }
          }
        }
      ],
      "merchantInfo": {
        "merchantId": "$merchantId"
      }
    }
""".trimIndent()

منابع

  • مرجع API : مستندات اشیاء درخواست API گوگل پی
  • مرجع API : برای اطلاعات بیشتر در مورد روش‌های مجوزدهی مجاز، شبکه‌های کارتی مجاز و مشخصات توکن‌سازی از جمله مقدار مناسب درگاه، به PaymentMethod مراجعه کنید.

۴. دکمه گوگل پی را اضافه کنید

از دکمه‌ی «نوشتن پرداخت» برای رندر کردن یک دکمه‌ی بومی گوگل پی و از API کیف پول برای باز کردن برگه‌ی گوگل پی استفاده کنید.

کل محتوای MainActivity.kt را با مثال کامل زیر (شامل پیکربندی + دکمه + جریان پرداخت) جایگزین کنید:

package com.example.gpay

import android.os.Bundle
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.google.android.gms.common.api.CommonStatusCodes
import com.google.android.gms.tasks.Task
import com.google.android.gms.wallet.contract.TaskResultContracts.GetPaymentDataResult
import com.google.android.gms.wallet.*
import com.google.pay.button.ButtonTheme
import com.google.pay.button.ButtonType
import com.google.pay.button.PayButton
import org.json.JSONObject

private const val merchantId = "12345678901234567890"

// Base Google Pay request used for both the button and the Wallet request
private val baseGooglePayRequest = """
    {
      "apiVersion": 2,
      "apiVersionMinor": 0,
      "allowedPaymentMethods": [
        {
          "type": "CARD",
          "parameters": {
            "allowedAuthMethods": [
              "PAN_ONLY", "CRYPTOGRAM_3DS"
            ],
            "allowedCardNetworks": [
              "AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"
            ]
          },
          "tokenizationSpecification": {
            "type": "PAYMENT_GATEWAY",
            "parameters": {
              "gateway": "example",
              "gatewayMerchantId": "exampleGatewayMerchantId"
            }
          }
        }
      ],
      "merchantInfo": {
        "merchantId": "$merchantId"
      }
    }
""".trimIndent()

class MainActivity : ComponentActivity() {
  private val paymentDataLauncher = registerForActivityResult(GetPaymentDataResult()) { taskResult ->
    when (taskResult.status.statusCode) {
      CommonStatusCodes.SUCCESS -> {
        handlePaymentData(taskResult.result!!)
      }
      //CommonStatusCodes.CANCELED -> The user canceled
      //CommonStatusCodes.DEVELOPER_ERROR -> The API returned an error (it.status: Status)
      //else -> Handle internal and other unexpected errors
    }
  }
  private lateinit var paymentsClient: PaymentsClient

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Create the PaymentsClient
    paymentsClient = Wallet.getPaymentsClient(
      this,
      Wallet.WalletOptions.Builder()
        .setEnvironment(WalletConstants.ENVIRONMENT_TEST) // Switch to PRODUCTION when ready
        .build()
    )

    // Derive allowedPaymentMethods for the button from baseGooglePayRequest
    val allowedPaymentMethods = JSONObject(baseGooglePayRequest)
      .getJSONArray("allowedPaymentMethods")
      .toString()

    setContent {
      Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        PayButton(
          onClick = { requestPayment(paymentDataLauncher) },
          allowedPaymentMethods = allowedPaymentMethods,
          type = ButtonType.Pay,
          theme = ButtonTheme.Light
        )
      }
    }
  }

  private fun requestPayment(launcher: ActivityResultLauncher<Task<PaymentData>>) {
    // Build a PaymentDataRequest from the base request by adding transaction info
    val requestJson = JSONObject(baseGooglePayRequest).apply {
      put("transactionInfo", JSONObject().apply {
        put("totalPrice", "14.95")
        put("totalPriceStatus", "FINAL")
        put("countryCode", "US")
        put("currencyCode", "USD")
      })
    }
    val request = PaymentDataRequest.fromJson(requestJson.toString())
    val task = paymentsClient.loadPaymentData(request)
    task.addOnCompleteListener(paymentDataLauncher::launch)
  }

  private fun handlePaymentData(paymentData: PaymentData?) {
    val json = paymentData?.toJson() ?: return
    val paymentMethodData = JSONObject(json).getJSONObject("paymentMethodData")
    val tokenizationData = paymentMethodData.getJSONObject("tokenizationData")
    val token = tokenizationData.getString("token")
    // Send 'token' to your payment service provider (PSP)
    println("Payment token: $token")
  }
}

۵. درخواست پرداخت بدهید

وقتی دکمه‌ی Google Pay فشرده می‌شود، requestPayment(...) با اضافه کردن transactionInfo به baseGooglePayRequest شما، یک PaymentDataRequest می‌سازد، برگه‌ی Google Pay را باز می‌کند و یک توکن پرداخت برمی‌گرداند.

نکات کلیدی

  • دکمه: PayButton دکمه بومی Google Pay را رندر می‌کند.
  • کلاینت: PaymentsClient با TEST یا PRODUCTION پیکربندی شده است.
  • راه‌اندازی: loadPaymentData استفاده کنید و در صورت لزوم با یک IntentSender آن را حل کنید.
  • توکن: برای استخراج paymentMethodData.tokenizationData.token و ارسال آن به PSP خود، PaymentData.toJson() را تجزیه کنید.

۶. نتیجه‌گیری

تبریک می‌گویم که این Codelab را به پایان رساندید! شما یاد گرفتید که چگونه API گوگل پی را در یک برنامه Jetpack Compose برای اندروید ادغام کنید.

اجرای پروژه

پروژه را از اندروید استودیو ( Run > Run 'app' ) اجرا کنید تا برنامه شما شروع به کار کند.

از اینجا به کجا برویم؟

منابع اضافی