- vừa được xem lúc

Android - Tích hợp Google Pay

0 0 22

Người đăng: Nguyễn Đức Mạnh

Theo Viblo Asia

Như mọi người đã biết, Từ 15/11/2022 Google Pay chính thức hoạt động ở Việt Nam. Google Pay (hay còn được gọi là Google Wallet) là một giải pháp thanh toán di động được cung cấp bởi Google cho phép người dùng thanh toán trực tuyến hoặc trong các cửa hàng với sử dụng thiết bị di động của họ. Nó cung cấp một cách đơn giản và tiện lợi cho người dùng thanh toán bằng cách sử dụng thông tin thanh toán đã lưu trữ trong tài khoản Google của họ.

Thông tin các ngân hàng ở Việt hỗ trợ tích hợp và thanh toán bằng Google Pay mọi người có thể tham khảo tại : https://support.google.com/wallet/answer/12315406?hl=en

Ở bài viết này, mình xin chia sẻ các bước để bạn có thể tích hợp thanh toán Google Pay trong ứng dụng Android

I. Cấu hình project

1. Yêu cầu ban đầu

2. Cấu hình Gradle, AndroidManifest

Bước đầu để tích hợp Google Pay, chúng ta cần implement thư viện Google Pay Api

build.gradle

buildscript { repositories { google() mavenCentral() }
} allprojects { repositories { google() mavenCentral() }
}

app/build.gradle

implementation 'com.google.android.gms:play-services-wallet:**.*.*'
implementation 'com.google.android.gms:play-services-identity:**.*.*'

Thêm quyền truy cập vào file AndroidManifest.xml

<meta-data android:name="com.google.android.gms.wallet.api.enabled" android:value="true" />

II. Triển khai Code

1. Cấu hình Google Pay Api

  1. Define your Google Pay API version
private val baseRequest = JSONObject().apply { put("apiVersion", 2) put("apiVersionMinor", 0) }
  1. Request Payment Token
private fun gatewayTokenizationSpecification(): JSONObject { return JSONObject().apply { put("type", "PAYMENT_GATEWAY") put("parameters", JSONObject(mapOf( "gateway" to "example", "gatewayMerchantId" to "exampleGatewayMerchantId"))) }
}

Thay thế "example" và "exampleGatewayMerchantId" bằng các giá trị thích hợp cho nhà cung cấp dịch vụ thanh toán của bạn

  • gateway : Xác định cho 1 cổng mà được Google support
  • gatewayMerchantId: ID duy nhất liên kêt người bán với cổng đã cho
  1. Define supported payment card networks:

Định nghĩa 1 số thẻ được chấp nhận thanh toán

 private val allowedCardNetworks = JSONArray(Constants.SUPPORTED_NETWORKS)

hiện 1 số thẻ được hỗ trợ là: val SUPPORTED_NETWORKS = listOf( "AMEX", "DISCOVER", "JCB", "MASTERCARD", "VISA") Tiếp theo cần định nghĩa phương thức xác thực được chấp nhận trong giao dịch

private val allowedCardAuthMethods = JSONArray(Constants.SUPPORTED_METHODS)

hiện các phương thức được hỗ trợ là val SUPPORTED_METHODS = listOf( "PAN_ONLY", "CRYPTOGRAM_3DS")

  • PAN_ONLY là một loại PaymentMethod mà chỉ chấp nhận thông tin thẻ tín dụng hoặc thẻ ghi nợ (PAN, hoặc Primary Account Number) nhưng không chấp nhận thông tin bảo mật khác như mã CVV hoặc ngày hết hạn.
  • CRYPTOGRAM_3DS là một loại PaymentMethod mà chứa một mã mã hoá (cryptogram) được tạo ra bởi ngân hàng phát hành thẻ tín dụng hoặc thẻ ghi nợ, và được sử dụng trong quá trình xác minh giao dịch. Mã mã hoá này được sử dụng để xác minh rằng giao dịch được thực hiện bởi người sở hữu thật của thẻ, và không phải là một giao dịch giả mạo hoặc trái phép.

Cả hai loại PaymentMethod này đều được sử dụng trong Google Pay API để xác định cách thanh toán sẽ được thực hiện trong một giao dịch. Tuy nhiên, hãy lưu ý rằng các điều khoản và điều lệ về việc sử dụng các loại PaymentMethod này có thể khác nhau tùy theo quốc gia hoặc khu vực.

  1. Describe your allowed payment methods Cấu hình phương thức thanh toán qua các định nghĩa bên trên
 private fun baseCardPaymentMethod(): JSONObject { return JSONObject().apply { val parameters = JSONObject().apply { put("allowedAuthMethods", allowedCardAuthMethods) put("allowedCardNetworks", allowedCardNetworks) put("billingAddressRequired", true) put("billingAddressParameters", JSONObject().apply { put("format", "FULL") }) } put("type", "CARD") put("parameters", parameters) } }
 private fun cardPaymentMethod(): JSONObject { val cardPaymentMethod = baseCardPaymentMethod() cardPaymentMethod.put("tokenizationSpecification", gatewayTokenizationSpecification()) return cardPaymentMethod }

2. Khởi tạo PaymentClient

Để khởi tạo Google Pay Api, chúng ta cần khởi tạo 1 PaymentClient

 fun createPaymentsClient(context: Context): PaymentsClient { val walletOptions = Wallet.WalletOptions.Builder() .setEnvironment(WalletConstants.ENVIRONMENT_TEST) .build() return Wallet.getPaymentsClient(context, walletOptions) }

Chúng ta có thể cấu hình môi trường test hoặc Product bằng cách setEnvironmentWalletConstants.ENVIRONMENT_TEST hoặc WalletConstants.ENVIRONMENT_PRODUCTION

  • ENVIRONMENT_PRODUCTION: Đây là môi trường sản xuất thực tế, tức là người dùng sẽ thực sự thanh toán tiền bằng cách sử dụng Google Pay trong ứng dụng của bạn.
  • ENVIRONMENT_TEST: Đây là môi trường thử nghiệm, tức là người dùng sẽ không thực sự thanh toán tiền bằng cách sử dụng Google Pay trong ứng dụng của bạn. Môi trường này được sử dụng để kiểm tra xem ứng dụng của bạn có tích hợp đúng với Google Pay không. Bạn chỉ có thể sử dụng các thẻ thanh toán có sẵn trong bảng "Card Test" của Google Pay Developer documentation. (Tìm hiểu thêm thông tin về Card Test tại: https://developers.google.com/pay/api/android/guides/resources/test-card-suite?hl=vi)

Bạn nên sử dụng môi trường ENVIRONMENT_TEST trong quá trình phát triển và kiểm tra, rồi chuyển sang môi trường ENVIRONMENT_PRODUCTION khi ứng dụng của bạn đã sẵn sàng được phát hành.

Để có thể sử dụng môi trường product, bạn cần đăng ký quyền truy cập tại: https://g.co/pay/sign-up

3. Xác định GooglePay có sẵn sàng để sử dụng hay chưa?

Sau khi đã cấu hình xong Google Pay Api, bước tiếp theo chúng ta cần kiểm tra xem thiết bị có sẵn sàng để thanh toán bằng Google Pay hay không

fun isReadyToPayRequest(): JSONObject? { return try { baseRequest.apply { put("allowedPaymentMethods", JSONArray().put(baseCardPaymentMethod())) } } catch (e: JSONException) { null } }
private fun fetchCanUseGooglePay() { val isReadyToPayJson = PaymentsUtil.isReadyToPayRequest() if (isReadyToPayJson == null) _canUseGooglePay.value = false val request = IsReadyToPayRequest.fromJson(isReadyToPayJson.toString()) val task = paymentsClient.isReadyToPay(request) task.addOnCompleteListener { completedTask -> try { _canUseGooglePay.value = completedTask.getResult(ApiException::class.java) } catch (exception: ApiException) { Log.w("isReadyToPay failed", exception) _canUseGooglePay.value = false } } }

Nếu _canUseGooglePay return false nghĩa là thiết bị/ người dùng đang không thể sử dụng Google Pay để thanh toán. Theo khuyến nghị của Google, trong trường hợph đó bạn ko nên hiển thị button Google Pay

4. Xác định thông tin giao dịch bằng PaymentDataRequest

PaymentDataRequest là một đối tượng trong Google Pay API, mà được sử dụng để xác định các thông tin cần thiết cho một giao dịch thanh toán bằng Google Pay. Đối tượng này bao gồm các thông tin như loại PaymentMethod mà người dùng muốn sử dụng, tổng số tiền cần thanh toán, tiền tệ sử dụng, và các thông tin khác như tên người mua và địa chỉ giao hàng.

Khởi tạo thông tin giao dịch: const val COUNTRY_CODE = "US" , const val CURRENCY_CODE = "USD" ( Trong trường hợp ở Việt Nam là "VN" - "VND", của Nhật bản là "JP" - "JPY")

private fun getTransactionInfo(price: String): JSONObject { return JSONObject().apply { put("totalPrice", price) put("totalPriceStatus", "FINAL") put("countryCode", Constants.COUNTRY_CODE) put("currencyCode", Constants.CURRENCY_CODE) } }

(Tham khảo thêm về các thông tin của TransactionInfo tại: https://developers.google.com/pay/api/android/reference/request-objects#TransactionInfo)

Khởi tạo thông tin của merchant

private val merchantInfo: JSONObject = JSONObject().put("merchantName", "Example Merchant")

Khởi taọ PaymentDataRequest

fun getPaymentDataRequest(priceCemts: Long): JSONObject { return baseRequest.apply { put("allowedPaymentMethods", JSONArray().put(cardPaymentMethod())) put("transactionInfo", getTransactionInfo(priceCemts.centsToString())) put("merchantInfo", merchantInfo) // An optional shipping address requirement is a top-level property of the // PaymentDataRequest JSON object. val shippingAddressParameters = JSONObject().apply { put("phoneNumberRequired", false) put("allowedCountryCodes", JSONArray(listOf("US", "GB"))) } put("shippingAddressParameters", shippingAddressParameters) put("shippingAddressRequired", true) } }

(Tham khảo về các thông tin của PaymentDataRequets tại: https://developers.google.com/pay/api/android/reference/request-objects#PaymentDataRequest)

5. Thanh toán

Thực hiện giao dịch thanh toán khi Click vào Button Google Pay

 googlePayButton.setOnClickListener { requestPayment() }
private fun requestPayment() { // Disables the button to prevent multiple clicks. googlePayButton.isClickable = false // The price provided to the API should include taxes and shipping. // This price is not displayed to the user. val dummyPriceCents = 100L val shippingCostCents = 900L val task = model.getLoadPaymentDataTask(dummyPriceCents + shippingCostCents) task.addOnCompleteListener { completedTask -> if (completedTask.isSuccessful) { completedTask.result.let(::handlePaymentSuccess) } else { when (val exception = completedTask.exception) { is ResolvableApiException -> { resolvePaymentForResult.launch( IntentSenderRequest.Builder(exception.resolution).build() ) } is ApiException -> { handleError(exception.statusCode, exception.message) } else -> { handleError( CommonStatusCodes.INTERNAL_ERROR, "Unexpected non API" + " exception when trying to deliver the task result to an activity!" ) } } } // Re-enables the Google Pay payment button. googlePayButton.isClickable = true } }
 private fun handlePaymentSuccess(paymentData: PaymentData) { val paymentInformation = paymentData.toJson() try { // Token will be null if PaymentDataRequest was not constructed using fromJson(String). val paymentMethodData = JSONObject(paymentInformation).getJSONObject("paymentMethodData") val billingName = paymentMethodData.getJSONObject("info") .getJSONObject("billingAddress").getString("name") Log.d("BillingName", billingName) Toast.makeText(this, getString(R.string.payments_show_name, billingName), Toast.LENGTH_LONG).show() // Logging token string. Log.d("Google Pay token", paymentMethodData .getJSONObject("tokenizationData") .getString("token")) } catch (error: JSONException) { Log.e("handlePaymentSuccess", "Error: $error") } }

ViewModel:

fun getLoadPaymentDataTask(priceCents: Long): Task<PaymentData> { val paymentDataRequestJson = PaymentsUtil.getPaymentDataRequest(priceCents) val request = PaymentDataRequest.fromJson(paymentDataRequestJson.toString()) return paymentsClient.loadPaymentData(request) }

6. Xử lý kết quả thanh toán

Sau khi hoàn thành thanh toán, kết quả sẽ được trả về tại onActivityResult kèm với thông tin PaymentData

// Handle potential conflict from calling loadPaymentData private val resolvePaymentForResult = registerForActivityResult(StartIntentSenderForResult()) { result: ActivityResult -> when (result.resultCode) { RESULT_OK -> result.data?.let { intent -> PaymentData.getFromIntent(intent)?.let(::handlePaymentSuccess) } RESULT_CANCELED -> { // The user cancelled the payment attempt } } }
private fun handlePaymentSuccess(paymentData: PaymentData) { val paymentInformation = paymentData.toJson() try { // Token will be null if PaymentDataRequest was not constructed using fromJson(String). val paymentMethodData = JSONObject(paymentInformation).getJSONObject("paymentMethodData") val billingName = paymentMethodData.getJSONObject("info") .getJSONObject("billingAddress").getString("name") Log.d("BillingName", billingName) Toast.makeText(this, getString(R.string.payments_show_name, billingName), Toast.LENGTH_LONG).show() // Logging token string. Log.d("Google Pay token", paymentMethodData .getJSONObject("tokenizationData") .getString("token")) } catch (error: JSONException) { Log.e("handlePaymentSuccess", "Error: $error") } }

III. Quy định về Brand

Để sử dụng và hiển thị button Google Play, bạn cần tuân thủ về chính sách và quy định về brand của Google

  • Chỉ sử dụng các nút Google Pay do Google cung cấp.
  • Sử dụng các nút Google Pay để bắt đầu quy trình thanh toán.
  • Sử dụng cùng một kiểu nút trên toàn bộ trang web của bạn.
  • Đảm bảo rằng kích thước của các nút Google Pay bằng hoặc lớn hơn các nút khác.

Không được

  • Tạo các nút Google Pay của riêng bạn hoặc thay đổi phông chữ, màu sắc, phần đệm trong nút theo bất kỳ cách nào.
  • Sử dụng các nút thanh toán của Google Pay để bắt đầu bất kỳ hành động nào ngoài quy trình thanh toán.
  • Làm cho nút Google Pay nhỏ hơn các nút khác.

1 số quy định khác:

  • Viết hoa các chữ cái "G" và "P"
  • Không được viết tắt Google Pay
  • Phù hợp với style UI trong ứng dụng
  • Không dịch "Google Pay"
  • Sử dụng trademark symbol (™) trong hoạt động truyền thông tiếp thị

Tham khảo thêm về Brand Guidelines: https://developers.google.com/pay/api/android/guides/brand-guidelines

IV. Tổng kết

Với xu thế thanh toán không dùng tiền mặt ở Việt Nam và thế giới ngày càng tăng cao, với sự xuất hiện của các ví điện tử kèm các kênh thanh toán mới, Google Pay hứa hẹn là 1 giải pháp thanh toán thông minh và an toàn trên các thiết bị smart phone


Tham khảo: https://www.youtube.com/watch?v=SZorG5Hqjzc https://developers.google.com/pay/api/android/overview https://github.com/google-pay/android-quickstart

Bình luận

Bài viết tương tự

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 1: Làm quen cô nàng Flutter

Lời mở đầu. Gần đây, Flutter nổi lên và được Google PR như một xu thế của lập trình di động vậy.

0 0 281

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 3: Lột trần cô nàng Flutter, BuildContext là gì?

Lời mở đầu. Màn làm quen cô nàng FLutter ở Phần 1 đã gieo rắc vào đầu chúng ta quá nhiều điều bí ẩn về nàng Flutter.

0 0 206

- vừa được xem lúc

[Android] Hiển thị Activity trên màn hình khóa - Show Activity over lock screen

Xin chào các bạn, Hôm nay là 30 tết rồi, ngồi ngắm trời chờ đón giao thừa, trong lúc rảnh rỗi mình quyết định ngồi viết bài sau 1 thời gian vắng bóng. .

0 0 107

- vừa được xem lúc

Tìm hiểu Proguard trong Android

1. Proguard là gì . Cụ thể nó giúp ứng dụng của chúng ta:. .

0 0 98

- vừa được xem lúc

Làm ứng dụng học toán đơn giản với React Native - Phần 6

Chào các bạn một năm mới an khang thịnh vượng, dồi dào sức khỏe. Lại là mình đây Đây là link app mà các bạn đang theo dõi :3 https://play.google.com/store/apps/details?id=com.

0 0 68

- vừa được xem lúc

20 Plugin hữu ích cho Android Studio

1. CodeGlance. Plugin này sẽ nhúng một minimap vào editor cùng với thanh cuộn cũng khá là lớn. Nó sẽ giúp chúng ta xem trước bộ khung của code và cho phép điều hướng đến đoạn code mà ta mong muốn một cách nhanh chóng.

0 0 315