华为In App Purchase沙盒测试,我已经购买过一次的商品无法购买
Huawei In App Purchase sandbox testing , I cannot purchase the item I have already purchased once
IAP沙盒测试中,消耗品和非消耗品购买一次后不可再次购买。导致无法显示支付页面。在 onActivityResult 中,IAP SDK returns code
ORDER_PRODUCT_OWNED 60051
这是普遍问题还是我做错了什么?
在沙盒环境中,您可以购买消耗品和非消耗品。购买后,您可以食用它们。之后可以再次购买,方便测试。
调用消费接口消费产品。
60051 表示用户已拥有该产品,因此未能购买该产品。并且@Disavowed 给出了解释和解决方案。
https://developer.huawei.com/consumer/en/doc/development/HMS-References/iap-ExceptionHandlingAndGeneralErrorCodes-v4
这是关于如何使用产品的代码。
/**
* Consume the unconsumed purchase with type 0 after successfully delivering the product, then the Huawei payment server will update the order status and the user can purchase the product again.
* @param inAppPurchaseData JSON string that contains purchase order details.
*/
private void consumeOwnedPurchase(final Context context, String inAppPurchaseData) {
Log.i(TAG, "call consumeOwnedPurchase");
IapClient mClient = Iap.getIapClient(context);
Task<ConsumeOwnedPurchaseResult> task = mClient.consumeOwnedPurchase(createConsumeOwnedPurchaseReq(inAppPurchaseData));
task.addOnSuccessListener(new OnSuccessListener<ConsumeOwnedPurchaseResult>() {
@Override
public void onSuccess(ConsumeOwnedPurchaseResult result) {
// Consume success
Log.i(TAG, "consumeOwnedPurchase success");
Toast.makeText(context, "Pay success, and the product has been delivered", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, e.getMessage());
Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
if (e instanceof IapApiException) {
IapApiException apiException = (IapApiException)e;
Status status = apiException.getStatus();
int returnCode = apiException.getStatusCode();
Log.e(TAG, "consumeOwnedPurchase fail,returnCode: " + returnCode);
} else {
// Other external errors
}
}
});
}
/**
* Create a ConsumeOwnedPurchaseReq instance.
* @param purchaseData JSON string that contains purchase order details.
* @return ConsumeOwnedPurchaseReq
*/
private ConsumeOwnedPurchaseReq createConsumeOwnedPurchaseReq(String purchaseData) {
ConsumeOwnedPurchaseReq req = new ConsumeOwnedPurchaseReq();
// Parse purchaseToken from InAppPurchaseData in JSON format.
try {
InAppPurchaseData inAppPurchaseData = new InAppPurchaseData(purchaseData);
req.setPurchaseToken(inAppPurchaseData.getPurchaseToken());
} catch (JSONException e) {
Log.e(TAG, "createConsumeOwnedPurchaseReq JSONExeption");
}
return req;
}
错误代码60051表示用户购买产品失败,因为用户已经拥有该产品。
解决方法:使用obtainOwnedPurchasesAPI查询用户是否购买了商品
已购买的消耗品,发货后调用consumeOwnedPurchaseAPI消费商品。消费后,下次可以购买该产品。
如果产品是非消耗品或订阅产品,则无法再次购买该产品。
查询所有已购买的应用内商品信息,包括消耗品、非消耗品和自动续订订阅。
- 如果返回耗材信息,则耗材
由于某些例外情况,可能无法交付。在这种情况下,您的应用
需要检查耗材是否送达。如果没有,应用程序
需要交付它们并调用 consumeOwnedPurchase API 来
消耗它们。
- 如果返回非消耗品信息,
非消耗品不需要消耗
- 如果信息
about subscriptions 被返回,所有现有的订阅
返回用户在应用中的关系。
- 如果 purchaseState 是 0,这意味着产品是 PURCHASED.
- 如果 purchaseState 是 1 那意味着产品是 CANCELED.
- 如果 purchaseState 是 2,这意味着产品是 PURCHASED.
代码:
public void checkUserOwnedTheProduct(final Context context) {
OwnedPurchasesReq ownedPurchasesReq = new OwnedPurchasesReq();
ownedPurchasesReq.setPriceType(productType);
Task<OwnedPurchasesResult> task = Iap.getIapClient(context).obtainOwnedPurchases(ownedPurchasesReq);
task.addOnSuccessListener(new OnSuccessListener<OwnedPurchasesResult>() {
@Override
public void onSuccess(OwnedPurchasesResult result) {
// Obtain the execution result.
if (result != null && result.getInAppPurchaseDataList() != null) {
for (int i = 0; i < result.getInAppPurchaseDataList().size(); i++) {
String inAppPurchaseData = result.getInAppPurchaseDataList().get(i);
String inAppSignature = result.getInAppSignature().get(i);
boolean success = CipherUtil.doCheck(inAppPurchaseData, inAppSignature, Key.getPublicKey());
if (success) {
try {
InAppPurchaseData inAppPurchaseDataBean = new InAppPurchaseData(inAppPurchaseData);
int purchaseState = inAppPurchaseDataBean.getPurchaseState();
} catch (JSONException e) {
}
}
}
} else {
if (productType == IapClient.PriceType.IN_APP_NONCONSUMABLE) {
((HmsInAppPurchaseList) context).loadList();
return;
}
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof IapApiException) {
IapApiException apiException = (IapApiException) e;
Status status = apiException.getStatus();
int returnCode = apiException.getStatusCode();
} else {
// Other external errors
}
}
});
}
有关更多信息,您可以访问以下链接:
应用内购买文章:
应用内购买Github Link:
客户端: https://github.com/DTSE-India-Community/HMS-In-App-Purchase-Kit
IAP沙盒测试中,消耗品和非消耗品购买一次后不可再次购买。导致无法显示支付页面。在 onActivityResult 中,IAP SDK returns code
ORDER_PRODUCT_OWNED 60051
这是普遍问题还是我做错了什么?
在沙盒环境中,您可以购买消耗品和非消耗品。购买后,您可以食用它们。之后可以再次购买,方便测试。
调用消费接口消费产品。
60051 表示用户已拥有该产品,因此未能购买该产品。并且@Disavowed 给出了解释和解决方案。 https://developer.huawei.com/consumer/en/doc/development/HMS-References/iap-ExceptionHandlingAndGeneralErrorCodes-v4
这是关于如何使用产品的代码。
/**
* Consume the unconsumed purchase with type 0 after successfully delivering the product, then the Huawei payment server will update the order status and the user can purchase the product again.
* @param inAppPurchaseData JSON string that contains purchase order details.
*/
private void consumeOwnedPurchase(final Context context, String inAppPurchaseData) {
Log.i(TAG, "call consumeOwnedPurchase");
IapClient mClient = Iap.getIapClient(context);
Task<ConsumeOwnedPurchaseResult> task = mClient.consumeOwnedPurchase(createConsumeOwnedPurchaseReq(inAppPurchaseData));
task.addOnSuccessListener(new OnSuccessListener<ConsumeOwnedPurchaseResult>() {
@Override
public void onSuccess(ConsumeOwnedPurchaseResult result) {
// Consume success
Log.i(TAG, "consumeOwnedPurchase success");
Toast.makeText(context, "Pay success, and the product has been delivered", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, e.getMessage());
Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
if (e instanceof IapApiException) {
IapApiException apiException = (IapApiException)e;
Status status = apiException.getStatus();
int returnCode = apiException.getStatusCode();
Log.e(TAG, "consumeOwnedPurchase fail,returnCode: " + returnCode);
} else {
// Other external errors
}
}
});
}
/**
* Create a ConsumeOwnedPurchaseReq instance.
* @param purchaseData JSON string that contains purchase order details.
* @return ConsumeOwnedPurchaseReq
*/
private ConsumeOwnedPurchaseReq createConsumeOwnedPurchaseReq(String purchaseData) {
ConsumeOwnedPurchaseReq req = new ConsumeOwnedPurchaseReq();
// Parse purchaseToken from InAppPurchaseData in JSON format.
try {
InAppPurchaseData inAppPurchaseData = new InAppPurchaseData(purchaseData);
req.setPurchaseToken(inAppPurchaseData.getPurchaseToken());
} catch (JSONException e) {
Log.e(TAG, "createConsumeOwnedPurchaseReq JSONExeption");
}
return req;
}
错误代码60051表示用户购买产品失败,因为用户已经拥有该产品。
解决方法:使用obtainOwnedPurchasesAPI查询用户是否购买了商品
已购买的消耗品,发货后调用consumeOwnedPurchaseAPI消费商品。消费后,下次可以购买该产品。 如果产品是非消耗品或订阅产品,则无法再次购买该产品。
查询所有已购买的应用内商品信息,包括消耗品、非消耗品和自动续订订阅。
- 如果返回耗材信息,则耗材 由于某些例外情况,可能无法交付。在这种情况下,您的应用 需要检查耗材是否送达。如果没有,应用程序 需要交付它们并调用 consumeOwnedPurchase API 来 消耗它们。
- 如果返回非消耗品信息, 非消耗品不需要消耗
- 如果信息 about subscriptions 被返回,所有现有的订阅 返回用户在应用中的关系。
- 如果 purchaseState 是 0,这意味着产品是 PURCHASED.
- 如果 purchaseState 是 1 那意味着产品是 CANCELED.
- 如果 purchaseState 是 2,这意味着产品是 PURCHASED.
代码:
public void checkUserOwnedTheProduct(final Context context) {
OwnedPurchasesReq ownedPurchasesReq = new OwnedPurchasesReq();
ownedPurchasesReq.setPriceType(productType);
Task<OwnedPurchasesResult> task = Iap.getIapClient(context).obtainOwnedPurchases(ownedPurchasesReq);
task.addOnSuccessListener(new OnSuccessListener<OwnedPurchasesResult>() {
@Override
public void onSuccess(OwnedPurchasesResult result) {
// Obtain the execution result.
if (result != null && result.getInAppPurchaseDataList() != null) {
for (int i = 0; i < result.getInAppPurchaseDataList().size(); i++) {
String inAppPurchaseData = result.getInAppPurchaseDataList().get(i);
String inAppSignature = result.getInAppSignature().get(i);
boolean success = CipherUtil.doCheck(inAppPurchaseData, inAppSignature, Key.getPublicKey());
if (success) {
try {
InAppPurchaseData inAppPurchaseDataBean = new InAppPurchaseData(inAppPurchaseData);
int purchaseState = inAppPurchaseDataBean.getPurchaseState();
} catch (JSONException e) {
}
}
}
} else {
if (productType == IapClient.PriceType.IN_APP_NONCONSUMABLE) {
((HmsInAppPurchaseList) context).loadList();
return;
}
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof IapApiException) {
IapApiException apiException = (IapApiException) e;
Status status = apiException.getStatus();
int returnCode = apiException.getStatusCode();
} else {
// Other external errors
}
}
});
}
有关更多信息,您可以访问以下链接: 应用内购买文章:
应用内购买Github Link:
客户端: https://github.com/DTSE-India-Community/HMS-In-App-Purchase-Kit