前言:
各位同学大家好 有段时间没有跟大家见面了 具体多久我也记不清楚了哈, 最近公司这边接入华为内购支付有点问题,所以我这边就整理一个文档 那么废话不多说我们正式开始。
需要用到的三方库
implementation 'com.huawei.hms:iap:4.0.4.301'
初始化建立链接
IapClient mClient = Iap.getIapClient(this);
IapRequestHelper.isEnvReady(mClient, new IapApiCallback<IsEnvReadyResult>() {
@Override
public void onSuccess(IsEnvReadyResult result) {
Log.e(TAG, "onSuccess: "+"检查支付成功 --- > " );
}
@Override
public void onFail(Exception e) {
Log.e(TAG, "isEnvReady fail, " + e.getMessage());
ExceptionHandle.handle(HuaWeiPayActivity.this, e);
}
});
查询商品id
/**
*
* @param productId
*
* 查询商品iD
*/
private void queryProducts(final String productId ) {
List<String> productIds = new ArrayList<String>();
productIds.add(productId);
IapRequestHelper.obtainProductInfo(mClient, productIds, IapClient.PriceType.IN_APP_CONSUMABLE, new IapApiCallback<ProductInfoResult>() {
@Override
public void onSuccess(ProductInfoResult result) {
Log.i(TAG, "obtainProductInfo, success");
if (result == null) {
return;
}
if (result.getProductInfoList() != null) {
// consumableProducts = result.getProductInfoList();
}
ProductInfo productInfo=result.getProductInfoList().get(0);
UserInfo.DataBean userInfo;
if (DataStore.getInstance().getUserInfo() == null) {
Toast.makeText(mContext, R.string.please_login_first, Toast.LENGTH_SHORT).show();
AppManager.getAppManager().finishActivity(HuaWeiPayActivity.class);
return;
} else {
userInfo = DataStore.getInstance().getUserInfo();
}
//TODO 华为支付下单逻辑
Map<String, String> params = new HashMap<>();
params.put("user_id", userInfo.getId());
params.put("token", userInfo.getToken());
params.put("gid", cosumerData.getGame_id());
params.put("cp_sid", cosumerData.getCpsid());
params.put("role_id", cosumerData.getRole_id());
params.put("role_name", cosumerData.getRole_name());
params.put("product_id", productInfo.getProductId());
params.put("product_name",productInfo.getProductName());
params.put("pay_channel_id","3");
double price = 0;
try {
price = CommonUtil.getDoubleValue(productInfo.getMicrosPrice()+"");
} catch (Exception e) {
e.printStackTrace();
}
params.put("price_amount", "" + price);
params.put("product_price", productInfo.getPrice());
params.put("currency_code", productInfo.getCurrency());
if(DataStore.getInstance()!=null&&DataStore.getInstance().getDeviceInfo()!=null) {
params.put("device_id", DataStore.getInstance().getDeviceInfo().getDevice_id());//设备ID
}
UrlHttpUtil.post(Constant.DATA_PAY_TOKEN, params, new CallBackUtil.CallBackStringWarp() {
@Override
public void onFailureData(int code, String errorMessage) {
ToastUtil.showNetwork(mContext);
}
@Override
public void onResponseData(String response) {
Log.e(TAG, "onResponseData: response ---- > "+ response );
try {
JSONObject jsonObject=new JSONObject(response);
String msg=jsonObject.optString("msg");
int code=jsonObject.optInt("code");
if(code==1){
token=jsonObject.optString("data");
gotoPay((Activity) mContext,productId, IapClient.PriceType.IN_APP_CONSUMABLE,token);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
// showProducts();
}
@Override
public void onFail(Exception e) {
Log.e(TAG, "obtainProductInfo: " + e.getMessage());
ExceptionHandle.handle(HuaWeiPayActivity.this, e);
// showProducts();
}
});
}
调起支付具体逻辑
/**
* create orders for in-app products in the PMS.
* @param activity indicates the activity object that initiates a request.
* @param productId ID list of products to be queried. Each product ID must exist and be unique in the current app.
* @param type In-app product type.
* 华为支付调起具体逻辑
*
*
*
*/
private void gotoPay(final Activity activity, String productId, int type, String token ) {
Log.i(TAG, "call createPurchaseIntent");
Log.e(TAG, "gotoPay:productId --- > "+productId +"type --- >"+ type );
IapClient mClient = Iap.getIapClient(activity);
Task<PurchaseIntentResult> task = mClient.createPurchaseIntent(createPurchaseIntentReq(type, productId,token));
task.addOnSuccessListener(new OnSuccessListener<PurchaseIntentResult>() {
@Override
public void onSuccess(PurchaseIntentResult result) {
Log.i(TAG, "createPurchaseIntent, onSuccess");
if (result == null) {
Log.e(TAG, "result is null");
return;
}
Status status = result.getStatus();
if (status == null) {
Log.e(TAG, "status is null");
return;
}
// you should pull up the page to complete the payment process.
if (status.hasResolution()) {
try {
status.startResolutionForResult(activity, REQ_CODE_BUY);
} catch (IntentSender.SendIntentException exp) {
Log.e(TAG, exp.getMessage());
}
} else {
Log.e(TAG, "intent is null");
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, e.getMessage());
Toast.makeText(activity, e.getMessage(), Toast.LENGTH_SHORT).show();
if (e instanceof IapApiException) {
IapApiException apiException = (IapApiException)e;
int returnCode = apiException.getStatusCode();
Log.e(TAG, "createPurchaseIntent, returnCode: " + returnCode);
// handle error scenarios
} else {
// Other external errors
}
}
});
}
/**
* Create a PurchaseIntentReq instance.
* @param type In-app product type.
* @param productId ID of the in-app product to be paid.
* The in-app product ID is the product ID you set during in-app product configuration in
AppGallery Connect.
* @return PurchaseIntentReq
*/
private PurchaseIntentReq createPurchaseIntentReq(int type, String productId,String token) {
PurchaseIntentReq req = new PurchaseIntentReq();
req.setProductId(productId);
req.setPriceType(type);
req.setDeveloperPayload(token);
return req;
}
支付回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQ_CODE_BUY) {
if (data == null) {
Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
return;
}
PurchaseResultInfo purchaseResultInfo = Iap.getIapClient(this).parsePurchaseResultInfoFromIntent(data);
Log.e(TAG, "onActivityResult: purchaseResultInfo.getInAppPurchaseData() ---- > "+purchaseResultInfo.getInAppPurchaseData() );
Log.e(TAG, "onActivityResult: purchaseResultInfo.getInAppDataSignature() ---- > "+purchaseResultInfo.getInAppDataSignature() );
switch(purchaseResultInfo.getReturnCode()) {
case OrderStatusCode.ORDER_STATE_SUCCESS:
// verify signature of payment results.
boolean success = CipherUtil.doCheck(purchaseResultInfo.getInAppPurchaseData(), purchaseResultInfo.getInAppDataSignature(), Key.getPublicKey());
if (success) {
hwVerify(purchaseResultInfo.getInAppPurchaseData(),purchaseResultInfo.getInAppDataSignature());
// Call the consumeOwnedPurchase interface to consume it after successfully delivering the product to your user.
consumeOwnedPurchase(this, purchaseResultInfo.getInAppPurchaseData());
} else {
Toast.makeText(this, "Pay successful,sign failed", Toast.LENGTH_SHORT).show();
finish();;
}
return;
case OrderStatusCode.ORDER_STATE_CANCEL:
// The User cancels payment.
Toast.makeText(this, "user cancel", Toast.LENGTH_SHORT).show();
finish();
return;
case OrderStatusCode.ORDER_PRODUCT_OWNED:
// The user has already owned the product.
Toast.makeText(this, "you have owned the product", Toast.LENGTH_SHORT).show();
// you can check if the user has purchased the product and decide whether to provide goods
// if the purchase is a consumable product, consuming the purchase and deliver product
finish();
return;
default:
Toast.makeText(this, "Pay failed", Toast.LENGTH_SHORT).show();
finish();
break;
}
return;
}
}
商品支付消耗
/**
* 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) {
Log.e(TAG, "onSuccess:result ---> "+result );
// Consume success
Log.i(TAG, "consumeOwnedPurchase success");
Toast.makeText(context, "Pay success, and the product has been delivered", Toast.LENGTH_SHORT).show();
finish();
}
}).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;
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;
}
支付完成数据回传校验
/**
*
* @param inAppPurchaseData
* @param inAppDataSignature
* 华为支付完成之后的order_token 的校验
*
*/
private void hwVerify(String inAppPurchaseData ,String inAppDataSignature ){
Map<String,String>map=new HashMap<>();
map.put("inapp_purchase_data",inAppPurchaseData);
map.put("inapp_data_signature",inAppDataSignature);
map.put("app_id",DataStore.getInstance().getContext().getPackageName());
UrlHttpUtil.post(Constant.DATA_SDK_HWVEROFY, map, new CallBackUtil.CallBackStringWarp() {
@Override
public void onFailureData(int code, String errorMessage) {
ToastUtil.showNetwork(mContext);
Log.e(TAG, "onFailureData:errorMessage -- > "+errorMessage );
}
@Override
public void onResponseData(String response) {
Log.e(TAG, "onResponseData: response ---- > "+ response );
try {
JSONObject jsonObject=new JSONObject(response);
String msg=jsonObject.optString("msg");
int code=jsonObject.optInt("code");
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
在支付回调里面我们拿到 inapp_purchase_data 和 inapp_data_signature 请求服务端做支付校验 。
最后总结:
华为的内购支付和google 旧版的内购支付的差不多 都是首先建立链接 然后去通过查询商品ID 去查询到商品档位配置的信息。然后我们去服务器预下单 然后调起内购支付。在 onActivityResult 方法里面接收支付回调 我们在回到里面拿到 回调的 inapp_purchase_data 和 inapp_data_signature 做数据回传校验即可 然后在客户端调用消耗的代码即可。 最后希望我的文章能帮助到各位解决问题 ,以后我还会贡献更多有用的代码分享给大家。各位同学如果觉得文章还不错 ,麻烦给关注和star,小弟在这里谢过啦!