วิธีตรวจสอบการซื้อแอป Android ในฝั่งเซิร์ฟเวอร์ (Google Play ในการเรียกเก็บเงินแอป v3)


108

ฉันมีแอพง่ายๆ (ต้องการการเข้าสู่ระบบของผู้ใช้ด้วยบัญชี) ฉันมีคุณสมบัติพิเศษสำหรับผู้ใช้แบบชำระเงินเช่นเนื้อหาข่าวเพิ่มเติม

ฉันต้องการบันทึกว่าผู้ใช้ซื้อรายการนี้ในฐานข้อมูลเซิร์ฟเวอร์ของฉันหรือไม่ เมื่อฉันให้เนื้อหาข้อมูลไปยังอุปกรณ์ของผู้ใช้ฉันสามารถตรวจสอบสถานะของผู้ใช้และระบุเนื้อหาที่แตกต่างกันสำหรับผู้ใช้ที่ชำระเงิน

ฉันตรวจสอบตัวอย่าง Trivialdrive อย่างเป็นทางการที่ Google จัดหาให้แล้วมันไม่ได้ให้รหัสตัวอย่างใด ๆ สำหรับการยืนยันฝั่งเซิร์ฟเวอร์นี่คือคำถามของฉัน

  1. ฉันพบว่าตัวอย่างใช้คีย์สาธารณะของแอปของฉันในการตรวจสอบการซื้อมันดูไม่ดีฉันคิดว่าฉันสามารถย้ายกระบวนการตรวจสอบไปยังเซิร์ฟเวอร์ของฉันรวมกับข้อมูลรับรองการเข้าสู่ระบบของผู้ใช้เพื่อดูว่าการซื้อของผู้ใช้เสร็จสมบูรณ์หรือไม่จากนั้นอัปเดตฐานข้อมูล
  2. นอกจากนี้ยังมีAPI การซื้อที่ฉันสามารถใช้เพื่อสอบถามได้สิ่งที่ฉันต้องการคือการส่ง purchaseToken ของผู้ใช้ไปยังเซิร์ฟเวอร์

ฉันไม่แน่ใจว่าฉันควรใช้วิธีใดในการตรวจสอบการซื้อของผู้ใช้และทำเครื่องหมายสถานะของผู้ใช้ในฐานข้อมูลของฉันอาจจะทั้งสองอย่าง?

และฉันกลัวว่าจะมีสถานการณ์เกิดขึ้นหากผู้ใช้ซื้อรายการนี้จาก Google Play แต่ด้วยเหตุผลบางอย่างในช่วงเวลานั้นเมื่อแอปของฉันเปิดการตรวจสอบไปยังเซิร์ฟเวอร์ของฉันการเชื่อมต่อเครือข่ายไม่ทำงานหรือเซิร์ฟเวอร์ของฉันหยุดทำงาน ผู้ใช้เพิ่งชำระเงินใน Google Play แต่ฉันไม่ได้บันทึกการซื้อในเซิร์ฟเวอร์ของฉัน? ฉันควรทำอย่างไรฉันจะจัดการกับสถานการณ์นี้ได้อย่างไร


คำตอบ:


167

ดูเหมือนว่าสิ่งที่คุณกำลังมองหาคือวิธีตรวจสอบว่าผู้ใช้เปิดใช้งานคุณสมบัติพิเศษในบัญชีของตนหรือไม่ดังนั้นฉันจะเริ่มต้น

ตรวจสอบให้แน่ใจว่ามีแฟล็กบางประเภทบนฐานข้อมูลของคุณที่ระบุว่าผู้ใช้มีคุณสมบัติพิเศษหรือไม่และรวมสิ่งนั้นไว้ในเพย์โหลดการตอบกลับ API เมื่อขอข้อมูลบัญชี ค่าสถานะนี้จะเป็นอำนาจหลักของคุณสำหรับ "คุณลักษณะพิเศษ"

เมื่อผู้ใช้ทำการซื้อในแอปให้แคชรายละเอียด (โทเค็นรหัสคำสั่งซื้อและรหัสผลิตภัณฑ์) ไว้ในเครื่องไคลเอนต์ (เช่นแอป) จากนั้นส่งไปยัง API ของคุณ

จากนั้น API ของคุณควรส่งpurchaseTokenไปยังGoogle Play Developer APIเพื่อตรวจสอบความถูกต้อง

อาจมีบางสิ่งเกิดขึ้นจากที่นี่:

  1. ใบเสร็จถูกต้อง API ของคุณตอบกลับลูกค้าด้วยรหัสสถานะ 200 Ok
  2. ใบเสร็จรับเงินไม่ถูกต้อง API ของคุณตอบกลับลูกค้าด้วยรหัสสถานะคำขอไม่ถูกต้อง 400 รายการ
  3. Google Play API หยุดทำงาน API ของคุณตอบสนองด้วยรหัสสถานะ 502 Bad Gateway

ในกรณีของ 1. หรือ 2. (รหัสสถานะ 2xx หรือ 4xx) ไคลเอ็นต์ของคุณจะล้างแคชของรายละเอียดการซื้อเนื่องจากไม่จำเป็นต้องใช้อีกต่อไปเนื่องจาก API ระบุว่าได้รับแล้ว

เมื่อตรวจสอบความถูกต้องสำเร็จ (กรณี 1. ) คุณควรตั้งค่าpremiumแฟล็กเป็นจริงสำหรับผู้ใช้

ในกรณีของ 3. (รหัสสถานะ 5xx) หรือการหมดเวลาของเครือข่ายไคลเอ็นต์ควรพยายามต่อไปจนกว่าจะได้รับรหัสสถานะ 2xx หรือ 4xx จาก API ของคุณ

ขึ้นอยู่กับความต้องการของคุณคุณสามารถรอสองสามวินาทีก่อนที่จะส่งอีกครั้งหรือเพียงแค่ส่งรายละเอียดไปยัง API ของคุณเมื่อมีการเปิดตัวแอปอีกครั้งหรือไม่อยู่เบื้องหลังหากรายละเอียดการซื้ออยู่ในแคชของแอป

แนวทางนี้ควรดูแลการหมดเวลาของเครือข่ายเซิร์ฟเวอร์ไม่พร้อมใช้งาน ฯลฯ

ขณะนี้มีคำถามสองสามข้อที่คุณต้องพิจารณา:

จะเกิดอะไรขึ้นทันทีหลังจากการซื้อ? แอปควรรอจนกว่าการตรวจสอบความถูกต้องจะสำเร็จก่อนที่จะให้บริการเนื้อหาพรีเมียมหรือควรให้สิทธิ์การเข้าถึงโดยไม่เป็นทางการและนำออกไปหากการตรวจสอบล้มเหลว

การให้สิทธิ์การเข้าถึงคุณลักษณะพรีเมียมเบื้องต้นจะทำให้กระบวนการสำหรับผู้ใช้ส่วนใหญ่เป็นไปอย่างราบรื่น แต่คุณจะให้สิทธิ์การเข้าถึงแก่ผู้ใช้ที่หลอกลวงจำนวนมากด้วยในขณะที่ API ของคุณตรวจสอบความถูกต้องของpurchaseToken.

หากต้องการนำไปใช้ในทางอื่น: การซื้อจะใช้ได้จนกว่าจะพิสูจน์ได้ว่าเป็นการฉ้อโกงหรือ; หลอกลวงจนกว่าจะพิสูจน์ได้ว่าถูกต้อง?

เพื่อที่จะระบุว่าผู้ใช้ยังคงมีการสมัครสมาชิกใช้งานได้เมื่อระยะเวลาการสมัครของพวกเขาขึ้นมาสำหรับการต่ออายุคุณจะต้องกำหนดเวลาการตรวจสอบอีกครั้งในpurchaseTokenการทำงานในexpiryTimeMillisที่ถูกส่งกลับในผล

หากexpiryTimeMillisเป็นอดีตคุณสามารถตั้งค่าpremiumสถานะเป็นเท็จได้ expiryTimeMillisถ้าเป็นในอนาคตอีกครั้งกำหนดการอีกครั้งสำหรับใหม่

สุดท้ายนี้เพื่อให้แน่ใจว่าผู้ใช้มีสิทธิ์การเข้าถึงระดับพรีเมียม (หรือไม่) แอปของคุณควรสอบถาม API ของคุณเพื่อดูรายละเอียดผู้ใช้เกี่ยวกับการเปิดตัวแอปหรือเมื่อมีการใช้งานเบื้องหลัง


สำหรับแอปที่ต้องซื้อฉันจะรับใบเสร็จจาก Google ได้อย่างไร
Merbin Joe

2
ไฮ! ไม่มีวิธีเข้าถึงประวัติการสมัครสมาชิกที่ google? จะป้องกันไม่ให้สูญเสียความจริงที่ใช้ cubscription ที่ซื้อไปแล้วในกรณีที่แอปขัดข้องในขณะจัดเก็บ buyToken ได้อย่างไร
scythargon

2
ฉันมีปัญหาที่คล้ายกัน .. แทนที่จะปล่อยให้แอปส่งโทเค็นไปยัง api จะไม่น่าเชื่อถือกว่าที่จะสั่งให้เซิร์ฟเวอร์นักพัฒนาของ Google ทำเช่นนั้นด้วยการแจ้งเตือนแบบพุชตรงไปยัง API ของฉัน
Gianluca Ghettini

สำหรับการสมัครที่ถูกยกเลิก Google Play Developer API จะยังคงส่งคืน 200 หลังจากการยกเลิกหากมีการใช้โทเค็นการซื้อแบบเดิมในการตรวจสอบความถูกต้อง
Cezar Cobuz

ดังนั้นสำหรับการสมัครสมาชิกคุณขอแนะนำว่าหลังจากการโทรครั้งแรกบนเซิร์ฟเวอร์เราจะจัดเก็บโทเค็นการซื้อและ ID ผลิตภัณฑ์และกำหนดเวลาการเรียกตรวจสอบอื่น ๆ (เรียกใช้คำขอเดียวกันอีกครั้ง) เมื่อหมดอายุ TimeMillis? นั่นเป็นวิธีที่เราควรตรวจสอบความถูกต้องของการสมัครสมาชิกหรือไม่? มีแนวทางจาก Android ในการทำเช่นนั้นหรือไม่? Apple มีวิดีโอ WWDC เกี่ยวกับเรื่องนี้ซึ่งอธิบายถึงแนวทางปฏิบัติที่ดีของวิดีโอนี้อย่างชัดเจน แต่หาข้อมูลเกี่ยวกับ Play Store ไม่ได้มากนัก
schankam

32

เอกสารเกี่ยวกับเรื่องนี้ทำให้สับสนและใช้คำอธิบายอย่างแปลกประหลาดกับสิ่งที่เกือบจะไม่สำคัญในขณะที่ทิ้งเอกสารสำคัญจริง ๆ ไว้เกือบจะไม่ได้เชื่อมโยงและหายากมาก สิ่งนี้ควรใช้งานได้ดีบนแพลตฟอร์มเซิร์ฟเวอร์ยอดนิยมที่สามารถเรียกใช้ไลบรารีไคลเอนต์ google api รวมถึง Java, Python, .Net และ NodeJS เป็นต้น หมายเหตุ: ฉันได้ทดสอบเฉพาะไคลเอนต์ Python api ดังที่แสดงด้านล่าง

ขั้นตอนที่จำเป็น:

  1. สร้างโครงการ API จากลิงก์การเข้าถึง API ในคอนโซล Google Play ของคุณ

  2. สร้างบัญชีบริการใหม่บันทึกคีย์ส่วนตัว JSON ที่สร้างขึ้น คุณจะต้องนำไฟล์นี้ไปที่เซิร์ฟเวอร์ของคุณ

  3. กดเสร็จสิ้นในส่วนบัญชีบริการของ Play Console เพื่อรีเฟรชจากนั้นให้สิทธิ์เข้าถึงบัญชีบริการ

  4. ไปรับไลบรารีไคลเอนต์ google api สำหรับแพลตฟอร์มเซิร์ฟเวอร์ของคุณจากhttps://developers.google.com/api-client-library

  5. ใช้ไลบรารีไคลเอ็นต์ของแพลตฟอร์มเฉพาะของคุณเพื่อสร้างอินเทอร์เฟซบริการและอ่านผลการตรวจสอบการซื้อของคุณโดยตรง

คุณไม่จำเป็นต้องกังวลกับขอบเขตการอนุญาตการโทรตามคำขอที่กำหนดเองการรีเฟรชโทเค็นการเข้าถึง ฯลฯ ไลบรารีไคลเอ็นต์ api จะดูแลทุกอย่าง นี่คือตัวอย่างการใช้งานไลบรารี python เพื่อยืนยันการสมัครสมาชิก:

ขั้นแรกให้ติดตั้งไคลเอนต์ google api ใน pipenv ของคุณดังนี้:

$ pipenv install google-api-python-client

จากนั้นคุณสามารถตั้งค่าข้อมูลรับรองไคลเอ็นต์ api โดยใช้ไฟล์ json คีย์ส่วนตัวสำหรับการพิสูจน์ตัวตนบัญชีบริการ

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

ตอนนี้คุณสามารถตรวจสอบการซื้อการสมัครสมาชิกหรือการซื้อผลิตภัณฑ์โดยใช้ไลบรารีได้โดยตรง

#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}

เอกสารสำหรับอินเทอร์เฟซบริการแพลตฟอร์มสำหรับ API ของนักพัฒนาซอฟต์แวร์ Play ไม่ได้เชื่อมโยงในรูปแบบที่ง่ายต่อการค้นหาสำหรับบางส่วนนั้นหายากมาก นี่คือลิงค์สำหรับแพลตฟอร์มยอดนิยมที่ฉันพบ:

Python | Java | .NET | PHP | NodeJS (Github TS) | ไป (Github JSON)


7
เห็นด้วยค่ะเอกสารแย่มาก ... มีความคิดอย่างไรกับฟังก์ชัน Firebase (Firestore) และ Cloud เป็นแบ็กเอนด์
Jeff Padgett

หากฟังก์ชัน Cloud ของคุณอยู่ใน NodeJS คุณอาจใช้ลิงค์ NodeJS ด้านบนเพื่อให้ไลบรารีไคลเอ็นต์ API ทำงานได้หรือไม่
Dhiraj Gupta

18

ตัวอย่างที่สมบูรณ์ของการใช้Google API Client Library สำหรับ PHP :

  1. การตั้งค่าของคุณโครงการของ Googleและการเข้าถึงGoogle Playสำหรับบัญชีผู้ใช้บริการตามที่อธิบายไว้ในคำตอบของ Marc นี่https://stackoverflow.com/a/35138885/1046909

  2. ติดตั้งไลบรารี: https://developers.google.com/api-client-library/php/start/installation

  3. ตอนนี้คุณสามารถตรวจสอบใบเสร็จของคุณได้ด้วยวิธีต่อไปนี้:

    $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);
    

    หลังจากนั้น $ purchase เป็นตัวอย่างของGoogle_Service_AndroidPublisher_SubscriptionPurchase

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

สิ่งนี้ใช้ไม่ได้ฉันได้รับ (401) การเข้าสู่ระบบที่จำเป็นและ setAuthConfig ไม่ยอมรับข้อมูลรับรองบัญชีบริการ json
Raulnd

อันนี้ใช้ได้สำหรับฉัน putenv ('GOOGLE_APPLICATION_CREDENTIALS = credentials.json'); $ client = Google_Client ใหม่ (); $ client-> useApplicationDefaultCredentials (); $ client-> addScope (' googleapis.com/auth/androidpublisher' ); $ service = Google_Service_AndroidPublisher ใหม่ ($ client); $ purchase = $ service-> purchase_products-> get ($ packageName, $ productId, $ token); var_dump (ซื้อ $);
Raulnd

สิ่งนี้เป็นกรณีของการเรียกเก็บเงินที่ไม่เหมาะสม จะเกิดอะไรขึ้นถ้าฉันต้องการรับ orderId ไปยังฐานข้อมูลของฉันเมื่อใดก็ตามที่ผู้ใช้ซื้อแอพของฉันจาก play store แทนที่จะเป็นไม่เกี่ยวข้อง
Ankesh kumar Jaisansaria

stackoverflow.com/questions/48662787/… โปรดดูคำถามนี้ ฉันกำลังมองหาคำตอบสำหรับคำถามนี้ สิ่งนี้มีค่าหัวเช่นกัน
Ankesh kumar Jaisansaria

@MingalevME จะเกิดอะไรขึ้นหากรูปแบบโทเค็นไม่ถูกต้องและ PHP ได้รับข้อผิดพลาดร้ายแรงฉันจะตรวจจับข้อผิดพลาดนี้ได้อย่างไร
alexx0186

12

คุณสามารถลองใช้การซื้อการสมัครสมาชิก: รับฝั่งเซิร์ฟเวอร์ มันต้องใช้เวลา packageName, subscriptionId และโทเค็นเป็น PARAMATERS และต้องมีการอนุมัติ

ตรวจสอบว่าการซื้อการสมัครสมาชิกของผู้ใช้นั้นถูกต้องหรือไม่และคืนเวลาหมดอายุ

หากสำเร็จเมธอดนี้จะส่งคืนรีซอร์สการซื้อการสมัครสมาชิกในเนื้อหาการตอบกลับ


9
ฉันมีปัญหาร้ายแรงในการขออนุมัติ

9
อย่างจริงจัง. สำหรับการซื้อที่สำคัญสำหรับแอพบางตัวการสนับสนุนและเอกสารประกอบนั้นไม่มีประโยชน์ นี่คือสิ่งที่คุณต้องทำบนเซิร์ฟเวอร์: github.com/google/… . ข้อมูลเพิ่มเติมที่นี่: stackoverflow.com/questions/35127086/…
ผู้ใช้

0

ฉันตอบข้อกังวลนี้

การเชื่อมต่อเครือข่ายหยุดทำงานหรือเซิร์ฟเวอร์ของฉันหยุดทำงานผู้ใช้เพิ่งชำระเงินใน Google Play แต่ฉันไม่ได้บันทึกการซื้อในเซิร์ฟเวอร์ของฉัน? ฉันควรทำอย่างไรฉันจะจัดการกับสถานการณ์นี้ได้อย่างไร

สถานการณ์คือ:

ผู้ใช้ซื้อสินค้า 'abc' โดยใช้บริการ Google Play -> ส่งคืนตกลง -> ไม่สามารถยืนยันกับเซิร์ฟเวอร์ด้วยเหตุผลบางประการเช่นไม่มีการเชื่อมต่ออินเทอร์เน็ต

วิธีแก้ไขคือ:

ในฝั่งไคลเอ็นต์ก่อนที่จะแสดงปุ่ม "Google Wallet" ให้คุณตรวจสอบว่ามีรายการ "abc" อยู่แล้วหรือไม่

  • ถ้าใช่ให้ตรวจสอบกับเซิร์ฟเวอร์อีกครั้ง
  • หากไม่มีให้แสดงปุ่ม "Google Wallet"

ซื้อซื้อ = 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
ฉันไม่เข้าใจว่าทำไมการตรวจสอบความถูกต้องบนเซิร์ฟเวอร์จึงปลอดภัยกว่าการตรวจสอบบนแอป ในตอนท้ายของวันแอปนี้จะปลดล็อกคุณลักษณะดังนั้นจึงยังคงสามารถลบหรือกลับรหัสในแอปได้ซึ่งจะตรวจสอบว่าการตอบสนองของเซิร์ฟเวอร์ "ตกลง" หรือไม่
Gianluca Ghettini

3
@GianlucaGhettini เนื่องจากบางครั้งเซิร์ฟเวอร์เป็นสิ่งที่ให้บริการที่ซื้อมาไม่ใช่แอปนอกจากนี้แอปอาจถูกออกแบบทางวิศวกรรมย้อนกลับจากนั้นด้วยการต่อสู้บางอย่างกระบวนการตรวจสอบอาจถูกแฮ็ก
Mohyaddin Alaoddin

0

คำตอบของ Marc Greenstock นั้นให้ความกระจ่างอย่างแน่นอนมีบางสิ่งที่ต้องให้ความสนใจแม้ว่าฉันจะใช้เวลานานในการคิดออก (อย่างน้อยก็มีเวลามากกว่าที่ฉันคาดไว้):

  1. ฉันต้องเลือก "เปิดใช้การมอบสิทธิ์ G Suite ทั่วทั้งโดเมน" ในการตั้งค่าบัญชีบริการ หากไม่มีสิ่งนี้ฉันก็ยังคงได้รับข้อผิดพลาดนี้: "ผู้ใช้ปัจจุบันมีสิทธิ์ไม่เพียงพอที่จะดำเนินการตามที่ร้องขอ" เลือกตัวเลือกเปิดใช้ G Suite ทั่วทั้งโดเมน

  2. สำหรับวัตถุประสงค์ในการทดสอบคุณสามารถสร้างโทเค็น JWT สำหรับบัญชีบริการของคุณได้ที่นี่อย่าลืมเลือกอัลกอริทึม RS256

  3. คีย์สาธารณะคือ "private_key_id" จากไฟล์ JSON ที่คุณดาวน์โหลด นอกจากนี้ยังมีรูปแบบต่อไปนี้:

    ----- BEGIN PUBLIC KEY ----- {private_key_id} ----- END PUBLIC KEY -----

  4. คีย์ส่วนตัวคือ "private_key" จากไฟล์ JSON ที่ดาวน์โหลดมา

  5. การเรียกร้องที่จำเป็นสำหรับการสร้าง JWT จะมีคำอธิบายที่นี่

  6. สับสนเกี่ยวกับ JWT Token คืออะไรและประกอบอย่างไร? อย่าละอายใจตรวจสอบลิงค์นี้ คุณเป็นเหมือนฉันและใช้เวลานานในการมองหาว่ามันคืออะไรมัน (วิธี) ง่ายกว่าที่คิด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.