### Verify Purchase Token Response (JSON) Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md Example JSON response from the purchase token verification endpoint. It includes a response code, purchase token data (InAppPurchaseData), a data signature, and the signature algorithm. The purchaseTokenData contains detailed information about the purchase. ```json { "responseCode": "0", "purchaseTokenData": "{\"autoRenewing\":false,\"orderId\":\"202008172303339595b1212421.123456\",\"packageName\":\"com.huawei.packagename\",\"applicationId\":123456,\"kind\":0,\"productId\":\"3\",\"productName\":\"商品名称\",\"purchaseTime\":1597676623000,\"purchaseTimeMillis\":1597676623000,\"purchaseState\":0,\"developerPayload\":\"payload data\",\"purchaseToken\":\"00000173741056a37...\",\"consumptionState\":0,\"confirmed\":0,\"currency\":\"CNY\",\"price\":\"100\",\"country\":\"CN\",\"payOrderId\":\"WX123456789ce8e23ee927\",\"payType\":\"17\"}", "dataSignature": "FiJJZYRdVIFgEzDA...", "signatureAlgorithm": "SHA256WithRSA" } ``` -------------------------------- ### Confirm Purchase Response (JSON) Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md Example JSON response from the purchase confirmation endpoint. It indicates success or failure with a response code and an optional response message. A '0' response code signifies a successful confirmation. ```json { "responseCode": "0", "responseMessage": "consume success" } ``` -------------------------------- ### 确认华为 IAP 购买(消耗型商品)(Bash) Source: https://context7.com/huanggze/channeldocs/llms.txt 对于消耗型商品,在发货成功后调用此接口通知华为 IAP 服务器更新商品发货状态,否则用户将无法再次购买。此接口等同于客户端的 `IapClient.consumeOwnedPurchase` 方法,应在验证通过并发货成功后立即调用。 ```bash # 确认购买(消耗商品) ROOT_URL="https://orders-drcn.iap.dbankcloud.cn" curl -X POST "${ROOT_URL}/applications/v2/purchases/confirm" \ -H "Content-Type: application/json; charset=UTF-8" \ -H "Authorization: Basic QVBQQVQ6Q0Z5SjFsVFNyMGh5OVE0QnZsdk5EcXgxUjRrdDNmeEVKVEp0UWdBQUFBQQ==" \ -d '{ "purchaseToken": "00000173741056a37eef310dff9c6a86abc123def456", "productId": "gem_100" }' # 成功响应示例 # { # "responseCode": "0", # "responseMessage": "consume success" # } # 错误响应示例 # { # "responseCode": "6", # "responseMessage": "purchase token invalid" # } ``` -------------------------------- ### POST /applications/purchases/tokens/verify Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md 验证客户端支付结果中的购买令牌,确认支付结果的准确性。 ```APIDOC ## POST {rootUrl}/applications/purchases/tokens/verify ### Description 向华为 IAP 服务器校验支付结果中的购买令牌,仅针对非订阅型商品。 ### Method POST ### Endpoint {rootUrl}/applications/purchases/tokens/verify ### Parameters #### Request Header - **Authorization** (String) - Required - Basic {Base64("APPAT:{access_token}")} ### Response #### Success Response (200) - **purchaseTokenData** (String) - 购买数据 - **dataSignature** (String) - 签名数据 #### Response Example { "purchaseTokenData": "{\"productId\":\"...\",\"purchaseState\":0}", "dataSignature": "..." } ``` -------------------------------- ### POST /applications/v2/purchases/confirm Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md 消耗型商品发货成功后,通知华为 IAP 服务器更新商品发货状态。 ```APIDOC ## POST {rootUrl}/applications/v2/purchases/confirm ### Description 确认消耗型商品已发货。若不调用此接口,用户将无法再次购买该商品。 ### Method POST ### Endpoint {rootUrl}/applications/v2/purchases/confirm ### Parameters #### Request Header - **Authorization** (String) - Required - Basic {Base64("APPAT:{access_token}")} ### Response #### Success Response (200) - **responseCode** (String) - 确认结果状态码 ``` -------------------------------- ### Initialize and Process Huawei IAP Payment Source: https://context7.com/huanggze/channeldocs/llms.txt Demonstrates how to initialize the HuaweiIAPService with credentials and public keys, and how to process a payment token reported by the client. It includes validation of expected price and application ID to ensure transaction integrity. ```python import json if __name__ == "__main__": IAP_PUBLIC_KEY = """-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA... -----END PUBLIC KEY-----""" iap_service = HuaweiIAPService( client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", iap_public_key=IAP_PUBLIC_KEY ) result = iap_service.process_payment( purchase_token="00000173741056a37eef310dff9c6a86abc123def456", product_id="gem_100", expected_price=600, expected_app_id=123456 ) print(json.dumps(result, ensure_ascii=False, indent=2)) ``` -------------------------------- ### POST /applications/v2/purchases/confirm Source: https://context7.com/huanggze/channeldocs/llms.txt 确认消耗型商品的购买状态,通知华为服务器更新发货状态。 ```APIDOC ## POST /applications/v2/purchases/confirm ### Description 对于消耗型商品,发货成功后必须调用此接口通知华为 IAP 服务器更新商品发货状态,否则用户将无法再次购买。 ### Method POST ### Endpoint https://orders-drcn.iap.dbankcloud.cn/applications/v2/purchases/confirm ### Parameters #### Request Body - **purchaseToken** (string) - Required - 购买令牌 - **productId** (string) - Required - 商品 ID ### Request Example { "purchaseToken": "00000173741056a37eef310dff9c6a86abc123def456", "productId": "gem_100" } ### Response #### Success Response (200) - **responseCode** (string) - 响应码,0 表示成功 - **responseMessage** (string) - 响应描述 #### Response Example { "responseCode": "0", "responseMessage": "consume success" } ``` -------------------------------- ### POST /oauth2/v3/token Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md 获取调用华为服务端 API 所需的应用级 Access Token(App AT)。 ```APIDOC ## POST https://oauth-login.cloud.huawei.com/oauth2/v3/token ### Description 获取应用级 Access Token 用于后续 API 调用的鉴权。建议在收到 401 错误时重新申请。 ### Method POST ### Endpoint https://oauth-login.cloud.huawei.com/oauth2/v3/token ### Parameters #### Request Body (Form Data) - **grant_type** (String) - Required - 固定值:client_credentials - **client_id** (String) - Required - 应用 ID - **client_secret** (String) - Required - 应用密钥 ### Request Example ```http POST https://oauth-login.cloud.huawei.com/oauth2/v3/token Content-Type: application/x-www-form-urlencoded; charset=UTF-8 grant_type=client_credentials&client_id=1234567&client_secret=appsecret ``` ### Response #### Success Response (200) - **access_token** (String) - 应用级 Access Token - **token_type** (String) - Token 类型,固定为 Bearer - **expires_in** (Integer) - 有效期(秒) #### Response Example { "access_token": "CFyJ...", "token_type": "Bearer", "expires_in": 3600 } ``` -------------------------------- ### 验证华为 IAP 购买 Token (Bash) Source: https://context7.com/huanggze/channeldocs/llms.txt 使用此命令向华为 IAP 服务器校验支付结果中的购买令牌,适用于非订阅型商品。验证通过后,开发者应进行发货并调用确认购买接口。`purchaseTokenData` 包含订单信息,需使用 IAP 公钥验签。 ```bash # 验证购买 Token # rootUrl 根据站点不同而不同,中国站点为:https://orders-drcn.iap.dbankcloud.cn ROOT_URL="https://orders-drcn.iap.dbankcloud.cn" curl -X POST "${ROOT_URL}/applications/purchases/tokens/verify" \ -H "Content-Type: application/json; charset=UTF-8" \ -H "Authorization: Basic QVBQQVQ6Q0Z5SjFsVFNyMGh5OVE0QnZsdk5EcXgxUjRrdDNmeEVKVEp0UWdBQUFBQQ==" \ -d '{ "purchaseToken": "00000173741056a37eef310dff9c6a86abc123def456", "productId": "gem_100" }' # 成功响应示例 # { # "responseCode": "0", # "purchaseTokenData": "{\"autoRenewing\":false,\"orderId\":\"202008172303339595b1212421.123456\",\"packageName\":\"com.example.game\",\"applicationId\":123456,\"kind\":0,\"productId\":\"gem_100\",\"productName\":\"100颗宝石\",\"purchaseTime\":1597676623000,\"purchaseTimeMillis\":1597676623000,\"purchaseState\":0,\"developerPayload\":\"order_12345\",\"purchaseToken\":\"00000173741056a37...\",\"consumptionState\":0,\"confirmed\":0,\"currency\":\"CNY\",\"price\":\"600\",\"country\":\"CN\",\"payOrderId\":\"WX123456789ce8e23ee927\",\"payType\":\"17\"}", # "dataSignature": "FiJJZYRdVIFgEzDA...", # "signatureAlgorithm": "SHA256WithRSA" # } # 关键字段说明: # - purchaseState: 0=成功, 1=已取消, 2=已退款, 3=待处理 # - consumptionState: 0=未消耗, 1=已消耗 # - kind: 0=消耗型, 1=非消耗型 # - price: 实际价格×100(600表示6.00元) ``` -------------------------------- ### 获取华为 IAP 应用级 Access Token (Bash) Source: https://context7.com/huanggze/channeldocs/llms.txt 调用此命令获取应用级 Access Token,用于鉴权华为服务端 API。Token 有效期为 3600 秒,建议在收到 401 响应时重新申请。Client ID 和 Client Secret 可在 AppGallery Connect 中获取。 ```bash # 获取 Access Token curl -X POST "https://oauth-login.cloud.huawei.com/oauth2/v3/token" \ -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \ -d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET" # 响应示例 # { # "access_token": "CFyJ1lTSr0hy9Q4BvlvNDqx1R4kt3fxEJTJtQgAAAAA...", # "token_type": "Bearer", # "expires_in": 3600 # } # 构造 Authorization Header(用于后续 API 调用) # Authorization: Basic {Base64("APPAT:{access_token}")} # 示例: ACCESS_TOKEN="CFyJ1lTSr0hy9Q4BvlvNDqx1R4kt3fxEJTJtQgAAAAA" AUTH_HEADER=$(echo -n "APPAT:${ACCESS_TOKEN}" | base64) echo "Authorization: Basic ${AUTH_HEADER}" ``` -------------------------------- ### POST /applications/purchases/tokens/verify Source: https://context7.com/huanggze/channeldocs/llms.txt 验证购买令牌的合法性,确认支付结果的准确性,适用于消耗型和非消耗型商品。 ```APIDOC ## POST /applications/purchases/tokens/verify ### Description 向华为 IAP 服务器校验支付结果中的购买令牌。建议在发货前调用此接口验证,响应包含加密的订单信息。 ### Method POST ### Endpoint https://orders-drcn.iap.dbankcloud.cn/applications/purchases/tokens/verify ### Parameters #### Request Body - **purchaseToken** (string) - Required - 客户端获取的购买令牌 - **productId** (string) - Required - 商品 ID ### Request Example { "purchaseToken": "00000173741056a37eef310dff9c6a86abc123def456", "productId": "gem_100" } ### Response #### Success Response (200) - **responseCode** (string) - 响应码,0 表示成功 - **purchaseTokenData** (string) - JSON 格式的订单详情字符串 - **dataSignature** (string) - 签名数据 #### Response Example { "responseCode": "0", "purchaseTokenData": "{\"orderId\":\"202008172303339595b1212421.123456\",\"productId\":\"gem_100\"}", "dataSignature": "FiJJZYRdVIFgEzDA..." } ``` -------------------------------- ### POST /oauth2/v3/token Source: https://context7.com/huanggze/channeldocs/llms.txt 获取应用级 Access Token,用于后续调用华为 IAP 服务端 API 的身份鉴权。 ```APIDOC ## POST /oauth2/v3/token ### Description 获取应用级 Access Token (App AT)。该 Token 用于后续 API 调用的鉴权,有效期通常为 3600 秒。 ### Method POST ### Endpoint https://oauth-login.cloud.huawei.com/oauth2/v3/token ### Parameters #### Request Body - **grant_type** (string) - Required - 固定值: client_credentials - **client_id** (string) - Required - 应用的 Client ID - **client_secret** (string) - Required - 应用的 Client Secret ### Request Example { "grant_type": "client_credentials", "client_id": "YOUR_CLIENT_ID", "client_secret": "YOUR_CLIENT_SECRET" } ### Response #### Success Response (200) - **access_token** (string) - 鉴权令牌 - **token_type** (string) - 令牌类型 - **expires_in** (integer) - 有效期(秒) #### Response Example { "access_token": "CFyJ1lTSr0hy9Q4BvlvNDqx1R4kt3fxEJTJtQgAAAAA", "token_type": "Bearer", "expires_in": 3600 } ``` -------------------------------- ### Huawei IAP Payment Verification Flow (Python) Source: https://context7.com/huanggze/channeldocs/llms.txt This Python class `HuaweiIAPService` facilitates server-side verification of Huawei In-App Purchases. It requires client ID, client secret, and the IAP public key for initialization. The service handles token acquisition, purchase validation, RSA signature verification, and purchase confirmation. The `process_payment` method is a comprehensive workflow that validates purchase details against expected values, including price and product ID, to ensure data integrity and prevent fraud. It returns a success status along with the order ID upon successful verification and confirmation. ```python import requests import base64 import json from Crypto.PublicKey import RSA from Crypto.Signature import pkcs1_15 from Crypto.Hash import SHA256 class HuaweiIAPService: def __init__(self, client_id, client_secret, iap_public_key): self.client_id = client_id self.client_secret = client_secret self.iap_public_key = iap_public_key self.root_url = "https://orders-drcn.iap.dbankcloud.cn" self.access_token = None def get_access_token(self): """获取应用级 Access Token""" url = "https://oauth-login.cloud.huawei.com/oauth2/v3/token" headers = {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"} data = { "grant_type": "client_credentials", "client_id": self.client_id, "client_secret": self.client_secret } response = requests.post(url, headers=headers, data=data) result = response.json() if "access_token" in result: self.access_token = result["access_token"] return self.access_token else: raise Exception(f"获取 Token 失败: {result}") def _get_auth_header(self): """构造 Authorization Header""" if not self.access_token: self.get_access_token() auth_string = f"APPAT:{self.access_token}" return base64.b64encode(auth_string.encode()).decode() def verify_purchase(self, purchase_token, product_id): """验证购买 Token""" url = f"{self.root_url}/applications/purchases/tokens/verify" headers = { "Content-Type": "application/json; charset=UTF-8", "Authorization": f"Basic {self._get_auth_header()}" } data = {"purchaseToken": purchase_token, "productId": product_id} response = requests.post(url, headers=headers, json=data) return response.json() def verify_signature(self, purchase_token_data, signature): """RSA 签名验证""" try: key = RSA.import_key(self.iap_public_key) h = SHA256.new(purchase_token_data.encode()) pkcs1_15.new(key).verify(h, base64.b64decode(signature)) return True except (ValueError, TypeError): return False def confirm_purchase(self, purchase_token, product_id): """确认购买(消耗型商品)""" url = f"{self.root_url}/applications/v2/purchases/confirm" headers = { "Content-Type": "application/json; charset=UTF-8", "Authorization": f"Basic {self._get_auth_header()}" } data = {"purchaseToken": purchase_token, "productId": product_id} response = requests.post(url, headers=headers, json=data) return response.json() def process_payment(self, purchase_token, product_id, expected_price, expected_app_id): """ 完整支付处理流程 - purchase_token: 客户端上报的购买令牌 - product_id: 商品 ID - expected_price: 预期价格(分) - expected_app_id: 预期应用 ID """ # 1. 验证购买 Token verify_result = self.verify_purchase(purchase_token, product_id) if verify_result.get("responseCode") != "0": return {"success": False, "error": f"验证失败: {verify_result.get('responseMessage')}"} # 2. RSA 签名验证 purchase_data_str = verify_result.get("purchaseTokenData") signature = verify_result.get("dataSignature") if not self.verify_signature(purchase_data_str, signature): return {"success": False, "error": "签名验证失败"} # 3. 解析并校验订单数据(资损防控) purchase_data = json.loads(purchase_data_str) # 校验购买状态 if purchase_data.get("purchaseState") != 0: return {"success": False, "error": f"订单状态异常: {purchase_data.get('purchaseState')}"} # 校验金额(price 为实际价格×100) if int(purchase_data.get("price", 0)) != expected_price: return {"success": False, "error": "金额不匹配,可能存在资损风险"} # 校验应用 ID if purchase_data.get("applicationId") != expected_app_id: return {"success": False, "error": "应用 ID 不匹配"} # 校验商品 ID if purchase_data.get("productId") != product_id: return {"success": False, "error": "商品 ID 不匹配"} # 校验是否已消耗(防止重复发货) if purchase_data.get("consumptionState") == 1: return {"success": False, "error": "订单已消耗,请勿重复发货"} # 4. 执行发货逻辑(此处实现您的业务逻辑) # deliver_goods(user_id, product_id) # 5. 确认购买(消耗型商品必须调用) if purchase_data.get("kind") == 0: # 消耗型商品 confirm_result = self.confirm_purchase(purchase_token, product_id) if confirm_result.get("responseCode") != "0": return {"success": False, "error": f"确认购买失败: {confirm_result.get('responseMessage')}"} return { "success": True, "order_id": purchase_data.get("orderId"), ``` -------------------------------- ### POST /applications/purchases/tokens/verify Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md Verifies a purchase token with Huawei's In-App Payment server to confirm the accuracy of the purchase result. This endpoint is intended for non-subscription products (consumable and non-consumable). It is recommended to call this API before delivering goods and then call the confirm purchase API after successful delivery. ```APIDOC ## POST /applications/purchases/tokens/verify ### Description Verifies a purchase token with Huawei's In-App Payment server to confirm the accuracy of the purchase result. This endpoint is intended for non-subscription products (consumable and non-consumable). It is recommended to call this API before delivering goods and then call the confirm purchase API after successful delivery. ### Method POST ### Endpoint `{rootUrl}/applications/purchases/tokens/verify` ### Parameters #### Request Header - **Content-Type** (String) - Required - Must be `application/json; charset=UTF-8` - **Authorization** (String) - Required - Authentication information in the format: `Basic {Base64("APPAT:{AccessToken}")}` - **HW-IAP-APPINFO** (String) - Optional - Extended information, supports passing signature algorithms #### Request Body - **purchaseToken** (String) - Required - The purchase token to be verified, uniquely identifying the product and user relationship. - **productId** (String) - Required - The ID of the product to be delivered, obtained from the product ID configured in AppGallery Connect. ### Request Example ```http POST /applications/purchases/tokens/verify Content-Type: application/json; charset=UTF-8 Authorization: Basic QVQ6Q1Yz... { "purchaseToken": "00000173741056a37eef310dff9c6a86...", "productId": "prd1" } ``` ### Response #### Success Response (200) - **responseCode** (String) - Required - Return code. `0`: Success; others: Failure. - **responseMessage** (String) - Optional - Response description. - **purchaseTokenData** (String) - Optional - A JSON string containing purchase data (InAppPurchaseData), which is used as is for signing. - **dataSignature** (String) - Optional - Signature information of purchaseTokenData based on the application's RSA IAP private key. The application needs to verify the signature using the IAP public key. - **signatureAlgorithm** (String) - Required - Signature algorithm (e.g., `SHA256WithRSA`). #### Response Example ```json { "responseCode": "0", "purchaseTokenData": "{\"autoRenewing\":false,\"orderId\":\"202008172303339595b1212421.123456\",\"packageName\":\"com.huawei.packagename\",\"applicationId\":123456,\"kind\":0,\"productId\":\"3\",\"productName\":\"商品名称\",\"purchaseTime\":1597676623000,\"purchaseTimeMillis\":1597676623000,\"purchaseState\":0,\"developerPayload\":\"payload data\",\"purchaseToken\":\"00000173741056a37...\",\"consumptionState\":0,\"confirmed\":0,\"currency\":\"CNY\",\"price\":\"100\",\"country\":\"CN\",\"payOrderId\":\"WX123456789ce8e23ee927\",\"payType\":\"17\"}", "dataSignature": "FiJJZYRdVIFgEzDA...", "signatureAlgorithm": "SHA256WithRSA" } ``` ``` -------------------------------- ### POST /applications/v2/purchases/confirm Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md Notifies Huawei IAP server to update the delivery status of a product after successful delivery for consumable products. If this API is not called, users will be unable to purchase the product again. This is equivalent to the client's `IapClient.consumeOwnedPurchase` interface. ```APIDOC ## POST /applications/v2/purchases/confirm ### Description Notifies Huawei IAP server to update the delivery status of a product after successful delivery for consumable products. If this API is not called, users will be unable to purchase the product again. This is equivalent to the client's `IapClient.consumeOwnedPurchase` interface. ### Method POST ### Endpoint `{rootUrl}/applications/v2/purchases/confirm` ### Parameters #### Request Header - **Content-Type** (String) - Required - Must be `application/json; charset=UTF-8` - **Authorization** (String) - Required - Authentication information in the format: `Basic {Base64("APPAT:{AccessToken}")}` #### Request Body - **purchaseToken** (String) - Required - The purchase token of the product. - **productId** (String) - Required - The product ID. ### Request Example ```http POST /applications/v2/purchases/confirm Content-Type: application/json; charset=UTF-8 Authorization: Basic QVQ6Q1Yz... { "purchaseToken": "00000173741056a37eef310dff9c6a86...", "productId": "prd1" } ``` ### Response #### Success Response (200) - **responseCode** (String) - Required - Return code. `0`: Success; others: Failure. - **responseMessage** (String) - Optional - Response description. #### Response Example ```json { "responseCode": "0", "responseMessage": "consume success" } ``` ``` -------------------------------- ### Confirm Purchase (HTTP) Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md Confirms a purchase with Huawei's IAP server, primarily for consumable products. This action is necessary after successful delivery to allow the user to repurchase the item. It requires Content-Type and Authorization headers, and a JSON body containing the purchaseToken and productId. ```http POST /applications/v2/purchases/confirm Content-Type: application/json; charset=UTF-8 Authorization: Basic QVQ6Q1Yz... { "purchaseToken": "00000173741056a37eef310dff9c6a86...", "productId": "prd1" } ``` -------------------------------- ### 华为 IAP 支付流程图 (Mermaid) Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md 展示了华为 IAP 主动查询和被动回调两种支付流程的时序图。主动查询流程中,服务端主动调用华为接口验证购买结果;被动回调流程中,用户支付后,SDK 回调客户端,客户端上报服务端处理。 ```mermaid sequenceDiagram participant C as 客户端(游戏 App) participant S as 游戏服务端 participant H as 华为 IAP 服务器 C->>H: 1. 调用 IAP SDK 查询商品信息(obtainProductInfo) H-->>C: 返回商品列表(含价格、名称等) C->>H: 2. 调用 IAP SDK 创建订单(createPurchaseIntent) H-->>C: 拉起 IAP 收银台,用户完成支付 H-->>C: 3. SDK 回调返回支付结果(InAppPurchaseData + dataSignature) C->>S: 4. 上报购买信息(InAppPurchaseData + dataSignature + purchaseToken) S->>H: 5. 调用 Order 服务验证购买 Token(verifyToken) H-->>S: 返回购买数据及签名(purchaseTokenData + dataSignature) S->>S: 6. 验签(使用 RSA IAP 公钥验证签名) S->>S: 7. 校验订单信息(金额、商品 ID、状态等) S->>C: 8. 发货(下发游戏道具/货币等) S->>H: 9. 调用 Order 服务确认购买(confirm) H-->>S: 返回确认结果 Note over S,H: 消耗型商品必须调用确认购买,否则无法再次购买 ``` ```mermaid sequenceDiagram participant U as 用户 participant C as 客户端(游戏 App) participant S as 游戏服务端 participant H as 华为 IAP 服务器 U->>C: 触发购买(点击购买按钮) C->>H: 调用 createPurchaseIntent 拉起收银台 U->>H: 完成支付操作 H-->>C: SDK 回调 onActivityResult
(InAppPurchaseData + dataSignature) C->>S: 上报 purchaseToken + InAppPurchaseData S->>H: verifyToken 验证购买 Token H-->>S: 返回验签结果 S->>S: 校验通过,执行发货 S->>C: 返回发货结果 S->>H: 调用 confirm 确认消耗 ``` -------------------------------- ### Verify Purchase Token (HTTP) Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md Verifies a purchase token with Huawei's IAP server for non-subscription items. It's crucial to call this before delivering goods to ensure payment accuracy. Requires Content-Type and Authorization headers, and a JSON body with purchaseToken and productId. ```http POST /applications/purchases/tokens/verify Content-Type: application/json; charset=UTF-8 Authorization: Basic QVQ6Q1Yz... { "purchaseToken": "00000173741056a37eef310dff9c6a86...", "productId": "prd1" } ``` -------------------------------- ### 获取华为 IAP Access Token 请求示例 (HTTP) Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md 演示了如何通过 POST 请求获取华为 IAP 服务端 API 所需的应用级 Access Token。需要提供 Client ID 和 Client Secret。 ```http POST https://oauth-login.cloud.huawei.com/oauth2/v3/token Content-Type: application/x-www-form-urlencoded; charset=UTF-8 grant_type=client_credentials&client_id=1234567&client_secret=appsecret ``` -------------------------------- ### 华为 IAP 订单状态流转图 (Mermaid) Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md 展示了华为 IAP 订单从创建到消耗确认的各个状态流转。包括初始化、已购买、未消耗、已消耗、已取消和已退款等状态。 ```mermaid stateDiagram-v2 [*] --> 初始化: 创建订单(purchaseState = -1) 初始化 --> 已购买: 用户完成支付(purchaseState = 0) 初始化 --> 已取消: 用户取消支付(purchaseState = 1) 已购买 --> 未消耗: consumptionState = 0 未消耗 --> 已消耗: 调用确认购买接口(consumptionState = 1) 已购买 --> 已退款: 退款成功(purchaseState = 2) 初始化 --> 待处理: 待处理状态(purchaseState = 3) ``` -------------------------------- ### 获取华为 IAP Access Token 响应示例 (JSON) Source: https://github.com/huanggze/channeldocs/blob/main/huawei/支付流程/内购项/README.md 展示了成功获取华为 IAP 应用级 Access Token 后的 JSON 响应格式。包含 access_token、token_type 和 expires_in。 ```json { "access_token": "CFyJ...", "token_type": "Bearer", "expires_in": 3600 } ``` -------------------------------- ### InAppPurchaseData JSON Structure Source: https://context7.com/huanggze/channeldocs/llms.txt Represents the parsed structure of the purchase token data returned by the Huawei IAP service. This structure contains essential fields like orderId, purchaseState, and price, which must be validated on the server to prevent fraud. ```json { "autoRenewing": false, "orderId": "202008172303339595b1212421.123456", "packageName": "com.example.game", "applicationId": 123456, "kind": 0, "productId": "gem_100", "productName": "100颗宝石", "purchaseTime": 1597676623000, "purchaseTimeMillis": 1597676623000, "purchaseState": 0, "developerPayload": "order_12345", "purchaseToken": "00000173741056a37eef310dff9c6a86abc123def456", "consumptionState": 0, "confirmed": 0, "currency": "CNY", "price": "600", "country": "CN", "payOrderId": "WX123456789ce8e23ee927", "payType": "17", "accountFlag": 1 } ``` -------------------------------- ### Huawei IAP Service Class Source: https://context7.com/huanggze/channeldocs/llms.txt This section details the core functionalities of the Huawei IAP service, including obtaining access tokens, verifying purchases, validating signatures, and confirming orders. ```APIDOC ## Huawei IAP Service API This API provides server-side functionalities for validating Huawei In-App Purchases. ### Class Initialization - **`HuaweiIAPService(client_id, client_secret, iap_public_key)`** - Initializes the service with your application's credentials and Huawei's public key. ### Methods #### `get_access_token()` - **Description**: Retrieves an application-level Access Token required for authenticating subsequent API requests. - **Method**: POST - **Endpoint**: `https://oauth-login.cloud.huawei.com/oauth2/v3/token` - **Request Body**: - `grant_type` (string) - Required - Must be `client_credentials`. - `client_id` (string) - Required - Your application's client ID. - `client_secret` (string) - Required - Your application's client secret. - **Success Response (200)**: - `access_token` (string) - The obtained access token. - `expires_in` (integer) - The token's expiration time in seconds. - `token_type` (string) - The token type (e.g., `Bearer`). #### `verify_purchase(purchase_token, product_id)` - **Description**: Verifies the validity of a purchase token obtained from the client. - **Method**: POST - **Endpoint**: `/applications/purchases/tokens/verify` - **Headers**: - `Authorization` (string) - Required - Basic authentication with the application-level access token. - **Request Body**: - `purchaseToken` (string) - Required - The token received from the client. - `productId` (string) - Required - The ID of the purchased product. - **Success Response (200)**: - `responseCode` (string) - Response code (e.g., "0" for success). - `responseMessage` (string) - Response message. - `purchaseTokenData` (string) - Encoded purchase data. - `dataSignature` (string) - The signature of the purchase data. #### `verify_signature(purchase_token_data, signature)` - **Description**: Verifies the integrity of the purchase data using RSA signature validation. - **Method**: N/A (Internal method) - **Parameters**: - `purchase_token_data` (string) - Required - The encoded purchase data string. - `signature` (string) - Required - The base64 encoded signature to verify. - **Returns**: `True` if the signature is valid, `False` otherwise. #### `confirm_purchase(purchase_token, product_id)` - **Description**: Confirms a purchase, typically for consumable products, after successful delivery. - **Method**: POST - **Endpoint**: `/applications/v2/purchases/confirm` - **Headers**: - `Authorization` (string) - Required - Basic authentication with the application-level access token. - **Request Body**: - `purchaseToken` (string) - Required - The token of the purchase to confirm. - `productId` (string) - Required - The ID of the purchased product. - **Success Response (200)**: - `responseCode` (string) - Response code (e.g., "0" for success). - `responseMessage` (string) - Response message. #### `process_payment(purchase_token, product_id, expected_price, expected_app_id)` - **Description**: Executes the complete payment processing flow, including verification, signature validation, data integrity checks, and order confirmation. - **Method**: N/A (Orchestration method) - **Parameters**: - `purchase_token` (string) - Required - The purchase token from the client. - `product_id` (string) - Required - The ID of the purchased product. - `expected_price` (integer) - Required - The expected price of the product in cents. - `expected_app_id` (string) - Required - The expected application ID. - **Returns**: An object indicating success or failure, including an order ID on success or an error message on failure. - `success` (boolean) - True if the process was successful, False otherwise. - `order_id` (string) - The order ID if successful. - `error` (string) - An error message if the process failed. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.