Cách xác minh giao dịch mua cho ứng dụng android ở phía máy chủ (google play trong ứng dụng thanh toán v3)


95

Tôi có một ứng dụng đơn giản (cần người dùng đăng nhập bằng tài khoản). Tôi cung cấp một số tính năng cao cấp cho người dùng trả phí, như nhiều nội dung tin tức hơn.

Tôi cần ghi lại nếu người dùng đã mua mặt hàng này trong cơ sở dữ liệu máy chủ của tôi. Khi tôi cung cấp nội dung dữ liệu cho thiết bị của người dùng, tôi có thể kiểm tra trạng thái của người dùng và cung cấp nội dung khác cho người dùng trả phí.

Tôi đã kiểm tra mẫu Trivialdrive chính thức do Google cung cấp, nó không cung cấp bất kỳ mã mẫu nào để xác minh phía máy chủ, đây là câu hỏi của tôi.

  1. Tôi thấy mẫu sử dụng khóa công khai của ứng dụng bên trong để xác minh giao dịch mua, nó có vẻ không ổn, tôi nghĩ tôi có thể chỉ cần di chuyển quy trình xác minh đến máy chủ của mình kết hợp với thông tin đăng nhập của người dùng để xem liệu giao dịch mua của người dùng đã hoàn tất hay chưa rồi cập nhật cơ sở dữ liệu.
  2. Ngoài ra, có API mua hàng mà tôi có thể sử dụng để truy vấn, những gì tôi cần là chuyển buyToken của người dùng vào máy chủ.

Tôi không chắc mình nên thực hiện phương pháp nào để xác minh giao dịch mua của người dùng và đánh dấu trạng thái của người dùng trong cơ sở dữ liệu của mình, có thể là cả hai?

Và tôi sợ có trường hợp xảy ra, nếu người dùng mua mặt hàng này từ google play, nhưng vì lý do nào đó, ngay lúc đó, khi ứng dụng của tôi khởi chạy xác minh đến máy chủ của tôi, kết nối mạng bị ngắt hoặc máy chủ của chính tôi bị lỗi , người dùng vừa thanh toán tiền trong google play nhưng tôi không ghi lại giao dịch mua trong máy chủ của mình? Tôi phải làm gì, Làm thế nào tôi có thể đối phó với tình huống này.


Bạn có thể nên xóa cờ ios khỏi câu hỏi này.
Gustavo Guevara

Câu trả lời:


159

Có vẻ như những gì bạn đang tìm kiếm là một cách để kiểm tra xem người dùng có bật các tính năng cao cấp trên tài khoản của họ hay không, vì vậy đây là nơi tôi sẽ bắt đầu;

Đảm bảo có một cờ nào đó trên cơ sở dữ liệu của bạn cho biết liệu người dùng có các tính năng cao cấp hay không và đưa tính năng đó vào tải trọng phản hồi API khi yêu cầu thông tin tài khoản. Cờ này sẽ là cơ quan chính của bạn cho "tính năng cao cấp".

Khi người dùng thực hiện mua hàng trong ứng dụng, hãy lưu vào bộ nhớ cache các chi tiết (mã thông báo, id đơn hàng và id sản phẩm) cục bộ trên máy khách (tức là ứng dụng), sau đó gửi đến API của bạn.

Sau đó, API của bạn sẽ gửi purchaseTokenđến API nhà phát triển trên Google Play để xác thực.

Một số điều có thể xảy ra từ đây:

  1. Biên nhận hợp lệ, API của bạn phản hồi khách hàng bằng mã trạng thái 200 Ok
  2. Biên nhận không hợp lệ, API của bạn phản hồi khách hàng với mã trạng thái 400 Yêu cầu không hợp lệ
  3. API Google Play không hoạt động, API của bạn phản hồi với mã trạng thái 502 Bad Gateway

Trong trường hợp 1. hoặc 2. (mã trạng thái 2xx hoặc 4xx) khách hàng của bạn xóa bộ nhớ cache của chi tiết mua hàng vì nó không cần nó nữa vì API cho biết rằng nó đã được nhận.

Sau khi xác thực thành công (trường hợp 1.), bạn nên đặt premiumcờ thành true cho người dùng.

Trong trường hợp 3. (mã trạng thái 5xx) hoặc mạng hết thời gian chờ, khách hàng nên tiếp tục thử cho đến khi nhận được mã trạng thái 2xx hoặc 4xx từ API của bạn.

Tùy thuộc vào yêu cầu của bạn, bạn có thể đợi một vài giây trước khi gửi lại hoặc chỉ gửi thông tin chi tiết đến API của bạn khi ứng dụng được khởi chạy lại hoặc thoát ra nền nếu chi tiết mua hàng có trên bộ nhớ cache của ứng dụng.

Cách tiếp cận này sẽ quan tâm đến thời gian chờ của mạng, máy chủ không khả dụng, v.v.

Bây giờ có một số câu hỏi bạn cần xem xét:

Điều gì sẽ xảy ra ngay sau khi mua hàng? Ứng dụng có nên đợi cho đến khi xác thực thành công trước khi cung cấp nội dung cao cấp hay nên tạm thời cấp quyền truy cập và lấy đi nếu quá trình xác thực không thành công?

Việc cấp quyền truy cập dự kiến ​​vào các tính năng cao cấp sẽ làm suôn sẻ quy trình cho đa số người dùng của bạn, nhưng bạn cũng sẽ cấp quyền truy cập cho một số người dùng gian lận trong khi API của bạn xác thực purchaseToken.

Nói cách khác: Giao dịch mua có giá trị cho đến khi được chứng minh là gian lận hoặc; gian lận cho đến khi được chứng minh hợp lệ?

Để xác định xem người dùng có còn đăng ký hợp lệ hay không khi thời hạn đăng ký của họ đến ngày gia hạn, bạn sẽ cần lên lịch xác thực lại purchaseTokenđể chạy tại kết quảexpiryTimeMillis được trả về .

Nếu expiryTimeMillislà quá khứ, bạn có thể đặt premiumcờ thành false. Nếu đó là trong tương lai, hãy lên lịch lại lần nữa cho cái mới expiryTimeMillis.

Cuối cùng, để đảm bảo người dùng có quyền truy cập cao cấp (hoặc không), ứng dụng của bạn nên truy vấn API của bạn để biết thông tin chi tiết về người dùng khi khởi chạy ứng dụng hoặc khi ứng dụng chạy nền.


Đối với ứng dụng trả phí, tôi sẽ nhận biên lai từ google như thế nào?
Merbin Joe

2
Chào! Không có cách nào để truy cập lịch sử đăng ký tại google? Làm thế nào để ngăn chặn việc mất thông tin thực tế đã sử dụng cubscription đã mua trong trường hợp nếu ứng dụng gặp sự cố tại thời điểm lưu trữ buyToken?
scythargon

2
Tôi gặp sự cố tương tự .. thay vì để ứng dụng gửi mã thông báo đến api sẽ không đáng tin cậy hơn để hướng dẫn máy chủ nhà phát triển google làm như vậy bằng một thông báo đẩy thẳng đến api của tôi?
Gianluca Ghettini

Đối với các đăng ký đã bị hủy, API nhà phát triển trên Google Play sẽ vẫn trả về 200 sau khi hủy, nếu cùng một mã thông báo mua cũ được sử dụng để xác thực.
Cezar Cobuz

Vì vậy, đối với một đăng ký, bạn đề xuất rằng sau cuộc gọi đầu tiên trên máy chủ, chúng tôi lưu trữ mã thông báo mua hàng và ID sản phẩm, đồng thời lên lịch một cuộc gọi xác minh khác (chạy lại cùng một yêu cầu) khi hết hạn Đó có phải là cách chúng tôi phải xác minh tính hợp lệ của đăng ký không? Có bất kỳ hướng dẫn nào từ Android về cách thực hiện điều đó không? Apple đã có một video WWDC về nó giải thích khá rõ ràng về cách làm tốt của nó, nhưng không thể tìm thấy nhiều thông tin về Play Store.
schankam

26

Tài liệu về vấn đề này thật khó hiểu và dài dòng một cách kỳ lạ với những thứ gần như không quan trọng trong khi để tài liệu thực sự quan trọng gần như không được liên kết và rất khó tìm. Điều này sẽ hoạt động tốt trên nền tảng máy chủ phổ biến nhất có thể chạy các thư viện ứng dụng khách google api, bao gồm Java, Python, .Net và NodeJS, trong số các thư viện khác. Lưu ý: Tôi chỉ thử nghiệm ứng dụng api Python như được hiển thị bên dưới.

Các bước cần thiết:

  1. Tạo một dự án API, từ liên kết Truy cập API trong bảng điều khiển Google Play của bạn

  2. Tạo tài khoản dịch vụ mới, lưu khóa cá nhân JSON được tạo. Bạn sẽ cần đưa tệp này đến máy chủ của mình.

  3. Nhấn Xong trong phần tài khoản dịch vụ của Play Console để làm mới rồi cấp quyền truy cập vào tài khoản dịch vụ

  4. Truy cập thư viện ứng dụng khách google api cho nền tảng máy chủ của bạn từ https://developers.google.com/api-client-library

  5. Sử dụng thư viện khách hàng của nền tảng cụ thể của bạn để xây dựng giao diện dịch vụ và trực tiếp đọc kết quả xác minh mua hàng của bạn.

Bạn không cần phải bận tâm đến phạm vi ủy quyền, thực hiện các cuộc gọi yêu cầu tùy chỉnh, làm mới mã thông báo truy cập, v.v. thư viện ứng dụng khách api sẽ đảm nhận mọi thứ. Đây là ví dụ sử dụng thư viện python để xác minh đăng ký:

Trước tiên, cài đặt ứng dụng google api trong pipenv của bạn như sau:

$ pipenv install google-api-python-client

Sau đó, bạn có thể thiết lập thông tin đăng nhập ứng dụng khách bằng cách sử dụng tệp json khóa cá nhân để xác thực tài khoản dịch vụ.

credentials = service_account.Credentials.from_service_account_file("service_account.json")

Giờ đây, bạn có thể trực tiếp xác minh các giao dịch mua đăng ký hoặc mua sản phẩm bằng thư viện.

#Build the "service" interface to the API you want
service = googleapiclient.discovery.build("androidpublisher", "v3", credentials=credentials)

#Use the token your API got from the app to verify the purchase
result = service.purchases().subscriptions().get(packageName="your.app.package.id", subscriptionId="sku.name", token="token-from-app").execute()
#result is a python object that looks like this ->
# {'kind': 'androidpublisher#subscriptionPurchase', 'startTimeMillis': '1534326259450', 'expiryTimeMillis': '1534328356187', 'autoRenewing': False, 'priceCurrencyCode': 'INR', 'priceAmountMicros': '70000000', 'countryCode': 'IN', 'developerPayload': '', 'cancelReason': 1, 'orderId': 'GPA.1234-4567-1234-1234..5', 'purchaseType': 0}

Tài liệu về giao diện dịch vụ nền tảng cho API nhà phát triển trò chơi không được liên kết theo cách dễ tìm, đối với một số người thì rất khó tìm . Dưới đây là các liên kết cho các nền tảng phổ biến mà tôi đã tìm thấy:

Con trăn | Java | .NET | PHP | NodeJS (Github TS) | Đi (Github JSON)


5
Đồng ý, tài liệu thật kinh khủng ... Bạn có ý tưởng nào về cách thực hiện điều này với Firebase (Firestore) và Cloud hoạt động như một chương trình phụ trợ không?
Jeff Padgett

Nếu các chức năng Đám mây của bạn nằm trong NodeJS thì bạn có thể sử dụng liên kết NodeJS ở trên để làm cho thư viện Ứng dụng khách API hoạt động?
Dhiraj Gupta

17

Toàn bộ ví dụ về việc sử dụng Thư viện ứng dụng API Google cho PHP :

  1. Thiết lập Dự án Google của bạn và truy cập vào Google Play cho tài khoản dịch vụ của bạn như được mô tả trong câu trả lời của Marc tại đây https://stackoverflow.com/a/35138885/1046909 .

  2. Cài đặt thư viện: https://developers.google.com/api-client-library/php/start/installation .

  3. Bây giờ bạn có thể xác minh biên nhận của mình theo cách sau:

    $client = new \Google_Client();
    $client->setAuthConfig('/path/to/service/account/credentials.json');
    $client->addScope('https://www.googleapis.com/auth/androidpublisher');
    $service = new \Google_Service_AndroidPublisher($client);
    $purchase = $service->purchases_subscriptions->get($packageName, $productId, $token);

    Sau lần mua $ đó là phiên bản của Google_Service_AndroidPublisher_SubscriptionPurchase

    $purchase->getAutoRenewing();
    $purchase->getCancelReason();
    ...

Điều này không hoạt động, tôi tiếp tục nhận được (401) Đăng nhập Bắt buộc và setAuthConfig không chấp nhận thông tin đăng nhập tài khoản dịch vụ json
Raulnd

Cái này phù hợp với tôi putenv ('GOOGLE_APPLICATION_CREDENTIALS = credentials.json'); $ client = new Google_Client (); $ client-> useApplicationDefaultCredentials (); $ client-> addScope (' googleapis.com/auth/androidpublisher' ); $ service = new Google_Service_AndroidPublisher ($ client); $ buy = $ service-> Purcha_products-> get ($ packageName, $ productId, $ token); var_dump ($ mua);
Raulnd

Điều này là trong trường hợp thanh toán inapp. Điều gì sẽ xảy ra nếu tôi muốn nhận orderId vào cơ sở dữ liệu của mình bất cứ khi nào người dùng mua ứng dụng của tôi từ cửa hàng Play thay vì inapp?
Ankesh kumar Jaisansaria

stackoverflow.com/questions/48662787/… Vui lòng xem câu hỏi này. Tôi đang tìm kiếm câu trả lời cho câu hỏi này. Đây có tiền thưởng tích cực cũng
Ankesh kumar Jaisansaria

@MingalevME Điều gì xảy ra nếu định dạng mã thông báo không hợp lệ và PHP gặp lỗi nghiêm trọng, làm cách nào để bắt lỗi này?
alexx0186

12

Bạn có thể thử sử dụng Purchases.subscriptions: lấy phía máy chủ. Nó sử dụng packageName, subscriptionId và mã thông báo làm thông số và yêu cầu ủy quyền .

Kiểm tra xem giao dịch mua đăng ký của người dùng có hợp lệ hay không và trả về thời gian hết hạn của nó.

Nếu thành công, phương pháp này trả về tài nguyên Purchases.subscriptions trong phần nội dung phản hồi.


9
Tôi đang gặp sự cố nghiêm trọng để ủy quyền hoạt động.

8
Nghiêm túc. Đối với mức độ quan trọng của việc mua hàng đối với một số ứng dụng, hỗ trợ và tài liệu không có. Đây là những gì bạn cần làm trên máy chủ: github.com/google/… . Thông tin thêm tại đây: stackoverflow.com/questions/35127086/…
người dùng

0

Tôi trả lời cho mối quan tâm này

kết nối mạng bị ngắt hoặc máy chủ của tôi bị lỗi, người dùng vừa thanh toán tiền trong google play nhưng tôi không ghi lại giao dịch mua trong máy chủ của mình? Tôi phải làm gì, Làm thế nào tôi có thể đối phó với tình huống này.

Tình hình là:

Người dùng mua mặt hàng 'abc' bằng dịch vụ google play -> trả về OK -> không xác minh được với máy chủ vì một số lý do như không có kết nối Internet.

Giải pháp là:

Về phía khách hàng, trước khi hiển thị nút 'Google Wallet', bạn kiểm tra xem mục 'abc' đã được sở hữu chưa.

  • nếu có, hãy xác minh lại với máy chủ
  • nếu không, hãy hiển thị nút 'Google Wallet'.

Mua mua = mInventory.getPurchase ('abc');

if (purchase != null) // Verify with server 

else // show Google Wallet button

https://developer.android.com/google/play/billing/billing_reference.html#getSkuDetails


4
Tôi không hiểu tại sao xác thực trên máy chủ lại an toàn hơn xác thực trên ứng dụng. Vào cuối ngày đó là ứng dụng mở ra các tính năng nên nó vẫn có thể loại bỏ hoặc nghịch mã trong ứng dụng rằng séc nếu phản ứng máy chủ là "OK"
Gianluca Ghettini

2
@GianlucaGhettini bởi vì, đôi khi máy chủ là thứ cung cấp dịch vụ đã mua chứ không phải ứng dụng bên cạnh đó, ứng dụng có thể được thiết kế ngược và sau đó với một số khó khăn, quá trình xác minh có thể bị tấn công.
Mohyaddin Alaoddin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.