4. 选中应用,创建应用内商品
5. 设置付款资料,其中的商家ID后续在代码中会用到
6. 设置商家账号并与付款资料关联
//google play 结算
implementation "com.android.billingclient:billing:${project.ext.billingVersion}"
/**
* 初始化
*/
public void init() {
mBillingClient = BillingClient.newBuilder(mActivityRef.get())
.setListener(mPurchasesUpdatedListener)
.enablePendingPurchases()
.build();
if (!mBillingClient.isReady()) {
mBillingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult != null) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
getOrderID();//从后台获取订单id
} else {
ToastUtil.showToast(ReaderApplication.getInstance()
.getResources().getString(R.string.recharge_no_service));
}
}
}
@Override
public void onBillingServiceDisconnected() {
ToastUtil.showToast(ReaderApplication.getInstance()
.getResources().getString(R.string.recharge_no_service));
}
});
} else {
getOrderID();
}
}
/**
* 获取订单ID
*/
private void getOrderID() {
HashMap params = new HashMap<>(16);
params.put("productId", productId);
new NetModel().doPost(NetApi.ANDROID_URL_PAY_ORDER_GOOGLE, params, new INetCallBack() {
@Override
public void onSuccess(JSONObject result) {
boolean success = JsonUtil.getBoolean(result, "success");
String message = JsonUtil.getString(result, "message");
JSONObject data = JsonUtil.getJSONObject(result, "data");
if (success) {
mOrderID = JsonUtil.getString(data, "topUpId");
recharge();
} else {
mListener.onState(mActivityRef.get(),
RechargeResult.failOf(message));
}
}
@Override
public void onFail(String msg) {
ToastUtil.showToast(msg);
}
});
}
/**
* 购买 mUserID:就是上面提到的商家id
*/
private void recharge() {
if (mBillingClient.isReady()) {
List skuList = new ArrayList<>();
skuList.add(mSku);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
mBillingClient.querySkuDetailsAsync(params.build(),
(billingResult, skuDetailsList) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
&& skuDetailsList != null) {
for (SkuDetails skuDetails : skuDetailsList) {
String sku = skuDetails.getSku();
if (mSku.equals(sku)) {
BillingFlowParams purchaseParams =
BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.setObfuscatedAccountId(mUserID)
.setObfuscatedProfileId(mOrderID)
.build();
mBillingClient.launchBillingFlow(mActivityRef.get(), purchaseParams);
}
}
} else {
ToastUtil.showToast(ReaderApplication.getInstance()
.getResources().getString(R.string.recharge_no_service));
}
});
}
}
/**
* 购买回调
*/
private PurchasesUpdatedListener mPurchasesUpdatedListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(BillingResult billingResult, List list) {
String debugMessage = billingResult.getDebugMessage();
Log.e(TAG, debugMessage);
if (list != null && list.size() > 0) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
for (Purchase purchase : list) {
mConsume = "2";
uploadToServer(purchase.getPurchaseToken(), mOrderID);
}
} else {
ToastUtil.showToast(billingResult.getDebugMessage());
}
} else {
switch (billingResult.getResponseCode()) {
case BillingClient.BillingResponseCode.SERVICE_TIMEOUT: {//服务连接超时"-3"
// mListener.onState(mActivityRef.get(), RechargeResult.failOf("-3"));
mListener.onState(mActivityRef.get(), "服务连接超时");
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED: {//-2
// mListener.onState(mActivityRef.get(), RechargeResult.failOf("-2"));
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.SERVICE_DISCONNECTED: {//服务未连接-1
mListener.onState(mActivityRef.get(), "服务未连接");
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.USER_CANCELED: {//取消1
mListener.onState(mActivityRef.get(), "支付取消");
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE: {//服务不可用2
mListener.onState(mActivityRef.get(), "服务不可用");
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.BILLING_UNAVAILABLE: {//购买不可用3
mListener.onState(mActivityRef.get(), "购买不可用");
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.ITEM_UNAVAILABLE: {//商品不存在4
mListener.onState(mActivityRef.get(), "商品不存在");
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.DEVELOPER_ERROR: {//提供给 API 的无效参数5
mListener.onState(mActivityRef.get(), "提供给 API 的无效参数");
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.ERROR: {//错误6
mListener.onState(mActivityRef.get(), "错误");
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED: {//未消耗掉
mConsume = "1";
queryHistory();
break;
}
case BillingClient.BillingResponseCode.ITEM_NOT_OWNED: {//不可购买8
mListener.onState(mActivityRef.get(), "不可购买");
mActivityRef.get().finish();
break;
}
default:
break;
}
}
}
};
/**
* 上传到服务器验证接口
*/
private void uploadToServer(final String purchaseToken, String mOrderID) {
HashMap params = new HashMap<>(16);
Log.i(TAG, "uploadToServer: purchaseToken=" + purchaseToken + " topUpId=" + mOrderID);
params.put("purchaseToken", purchaseToken);
params.put("topUpId", mOrderID);
new NetModel().doPost(NetApi.ANDROID_URL_PAY_CALL_GOOGLE, params, new INetCallBack() {
@Override
public void onSuccess(JSONObject result) {
boolean success = JsonUtil.getBoolean(result, "success");
String message = JsonUtil.getString(result, "message");
if (success) {
ToastUtil.showToast("充值成功");
AppsFlyerPoint.purchaseSuccess(amount, bookId, chapterId);
consume(purchaseToken);
} else {
mListener.onState(mActivityRef.get(),
RechargeResult.failOf(message));
}
}
@Override
public void onFail(String msg) {
ToastUtil.showToast(msg);
}
});
}
/**
* 消耗
*/
private void consume(String purchaseToken) {
if (mBillingClient.isReady()) {
ConsumeParams consumeParams = ConsumeParams.newBuilder()
.setPurchaseToken(purchaseToken)
.build();
mBillingClient.consumeAsync(consumeParams, (billingResult, s) -> {
});
} else {
mBillingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult != null) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
ConsumeParams consumeParams = ConsumeParams.newBuilder()
.setPurchaseToken(purchaseToken)
.build();
mBillingClient.consumeAsync(consumeParams, (billingResult1, s) -> {
});
} else {
ToastUtil.showToast(ReaderApplication.getInstance()
.getResources().getString(R.string.recharge_no_service));
}
}
}
@Override
public void onBillingServiceDisconnected() {
}
});
}
}
还有流程和国内差别最大的一点,测试