新增Google内购相关代码

This commit is contained in:
huangjian
2022-09-26 15:42:45 +08:00
parent 975b50b205
commit 193d418e9c
19 changed files with 745 additions and 612 deletions

View File

@@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.tencent.vasdolly'
@@ -228,6 +229,9 @@ dependencies {
implementation "io.github.tencent:vap:2.0.24"
implementation 'com.github.mmin18:realtimeblurview:1.2.1'
implementation 'com.appsflyer:af-android-sdk:6.2.3'
implementation 'com.android.installreferrer:installreferrer:2.2'
}
channel {

47
app/google-services.json Normal file
View File

@@ -0,0 +1,47 @@
{
"project_info": {
"project_number": "766987211654",
"project_id": "fluid-keyword-363108",
"storage_bucket": "fluid-keyword-363108.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:766987211654:android:e22efc16d8ba608189d207",
"android_client_info": {
"package_name": "com.vele.peko"
}
},
"oauth_client": [
{
"client_id": "766987211654-2b4de5kbhe7tpgtfto4bjll3dj7ih26u.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.vele.peko",
"certificate_hash": "a8ac3327a1144cf1b566ca7702338e471f143469"
}
},
{
"client_id": "766987211654-oe8kjt7rserq31d1rdulqj2aao5b96a7.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyBLTgRb9tTIGjUvIaGl0WoLJjVFSQlEEOA"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "766987211654-oe8kjt7rserq31d1rdulqj2aao5b96a7.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}

View File

@@ -51,7 +51,7 @@ class SelectPayTypeDialog : BaseDialog<DialogSelectPayTypeBinding>() {
PayModel.get().walletInfo
.compose(bindToLifecycle())
.subscribe({
setWalletData(it)
//setWalletData(it)
}, {
SingleToastUtil.showToast(it.message)
it.printStackTrace()
@@ -77,37 +77,4 @@ class SelectPayTypeDialog : BaseDialog<DialogSelectPayTypeBinding>() {
dismissAllowingStateLoss()
}
}
/**
* defaultPay 1默认支付宝2默认微信
*/
private fun setWalletData(walletInfo: WalletInfo) {
binding.rg.visibility = View.VISIBLE
when (walletInfo.defaultPay) {
ChargeActivity.ALI_PAY_CLOSE -> {
payChannel = Constants.CHARGE_ALIPAY
removeView = binding.rbAlipay
binding.rg.removeView(binding.rbAlipay)
binding.rbWechat.isChecked = true
binding.tvMore.visibility = View.VISIBLE
}
ChargeActivity.WX_PAY_CLOSE -> {
payChannel = Constants.CHARGE_WX
removeView = binding.rbWechat
binding.rg.removeView(binding.rbWechat)
binding.rbAlipay.isChecked = true
binding.tvMore.visibility = View.VISIBLE
}
ChargeActivity.WX_PAY_OPEN -> {
payChannel = Constants.CHARGE_WX
binding.rbWechat.isChecked = true
binding.rg.removeView(binding.rbAlipay)
binding.rg.addView(binding.rbAlipay)
}
else -> {
payChannel = Constants.CHARGE_ALIPAY
binding.rbAlipay.isChecked = true
}
}
}
}

View File

@@ -1,15 +1,7 @@
package com.yizhuan.erban.pay.presenter;
import android.annotation.SuppressLint;
import android.content.Context;
import com.yizhuan.erban.pay.view.IChargeView;
import com.yizhuan.xchat_android_core.pay.PayModel;
import com.yizhuan.xchat_android_core.user.UserModel;
import com.yizhuan.xchat_android_core.user.bean.UserInfo;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* Created by MadisonRong on 05/01/2018.
@@ -26,56 +18,10 @@ public class ChargePresenter extends PayPresenter<IChargeView> {
* 加载用户信息(显示用户账号和钱包余额)
*/
public void loadUserInfo() {
UserInfo userInfo = UserModel.get().getCacheLoginUserInfo();
if (userInfo != null) {
getMvpView().setupUserInfo(userInfo);
}
refreshWalletInfo(false);
}
/**
* 获取充值产品列表
*/
@SuppressLint("CheckResult")
public void getChargeList() {
payModel.getChargeList(1,0L)
.compose(bindToLifecycle())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(chargeBeans -> {
if (chargeBeans != null) {
getMvpView().buildChargeList(chargeBeans.getList());
} else {
getMvpView().getChargeListFail("请求数据为空");
}
});
}
/**
* 显示充值选项(支付宝或者微信)
*/
public void showChargeOptionsDialog() {
getMvpView().displayChargeOptionsDialog();
}
/**
* 发起充值
* @param context context
* @param chargeProdId 充值产品 ID
* @param payChannel 充值渠道,目前只支持
*/
@SuppressLint("CheckResult")
public void requestCharge(Context context, String chargeProdId, String payChannel) {
payModel.requestCharge(context, chargeProdId, payChannel)
.compose(bindToLifecycle())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(jsonObject -> {
if (jsonObject != null) {
getMvpView().getChargeOrOrderInfo(jsonObject.toString());
} else {
getMvpView().getChargeOrOrderInfoFail("请求错误");
}
});
}
}

View File

@@ -1,26 +1,11 @@
package com.yizhuan.erban.pay.view;
import com.yizhuan.xchat_android_core.pay.bean.ChargeBean;
import com.yizhuan.xchat_android_core.user.bean.UserInfo;
import java.util.List;
/**
* Created by MadisonRong on 05/01/2018.
*/
public interface IChargeView extends IPayView {
public void setupUserInfo(UserInfo userInfo);
public void buildChargeList(List<ChargeBean> chargeBeanList);
public void getChargeListFail(String error);
public void displayChargeOptionsDialog();
public void getChargeOrOrderInfo(String data);
public void getChargeOrOrderInfoFail(String error);
}

View File

@@ -0,0 +1,242 @@
package com.yizhuan.erban.ui.pay;
import android.app.Activity;
import android.util.Log;
import androidx.annotation.NonNull;
import com.alibaba.fastjson.JSONObject;
import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClient.BillingResponseCode;
import com.android.billingclient.api.BillingClient.SkuType;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.ConsumeParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.Purchase.PurchasesResult;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class BillingManager implements PurchasesUpdatedListener {
private static final String TAG = "BillingManager";
/*购买key*/
private static final String BASE_64_ENCODED_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnagnKdJFBKmp3zb8lmnZfnRcVc7hRf39Zes2YaBQrhNIcesrbtSvV8uCHQrFLan1ekYVPT52mX+AylEvdQ3n5isotS2nfp0jf7l05bJ9bxVKGU7fe2jnT0B+rW2LJpacNzBj/pRDgp1TSN/kl/FI+SXP+jL6f8vhRMwY7GmSvOSHUl/pm8Imi0Se+Y7hBpUtTQioHF0oMiUuNH6vrB/eyx73//thS4D2YylPSN4Q8P4UTLpq4YMCGj8IbY6ZBjDRqGdUfLcb2eU6IRFoyHaBGZWfG/KdrCj1PfnEwh4hIBTBrnZXY1OhPPvztTLVx/sd8iIUX371GJ8GfWfuqvpTXQIDAQAB";
/*客户端*/
private BillingClient billingClient;
/*活动*/
private final Activity mActivity;
/*监听*/
private final BillingUpdatesListener mBillingUpdatesListener;
/*是否连接成功*/
private boolean mIsServiceConnected;
/*商品列表*/
private final List<Purchase> purchaseList = new ArrayList<>();
/*消耗令牌*/
private Set<String> mTokensToBeConsumed;
/*监听接口*/
public interface BillingUpdatesListener {
void onBillingClientSetupFinished();
void onPurchasesUpdated(List<Purchase> purchases);
void onConsumeFinished(String token, @BillingResponseCode int result);
void onFailedHandle(@BillingResponseCode int result);
}
public boolean isServiceConnected() {
return mIsServiceConnected;
}
public BillingManager(Activity activity, final BillingUpdatesListener updatesListener) {
mActivity = activity;
mBillingUpdatesListener = updatesListener;
billingClient = BillingClient.newBuilder(mActivity).enablePendingPurchases().setListener(this).build();
startServiceConnection(() -> {
mBillingUpdatesListener.onBillingClientSetupFinished();
onQueryPurchases();
});
}
/*开始连接Play*/
public void startServiceConnection(final Runnable executeOnSuccess) {
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(@NotNull BillingResult billingResult) {
Log.d(TAG, "Setup finished. Response code: " + billingResult.getDebugMessage() + " code = " + billingResult.getResponseCode());
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
mIsServiceConnected = true;
if (executeOnSuccess != null) {
executeOnSuccess.run();
}
} else {
mIsServiceConnected = true;
}
}
@Override
public void onBillingServiceDisconnected() {
mIsServiceConnected = false;
}
});
}
/*请求商品库存*/
public void onQueryPurchases() {
Runnable queryToExecute = () -> {
//系统当前时间
long time = System.currentTimeMillis();
//请求内购商品
PurchasesResult purchasesResult = billingClient.queryPurchases(SkuType.INAPP);
onQueryPurchasesFinished(purchasesResult);
};
executeServiceRequest(queryToExecute);
}
/*请求商品信息完成*/
private void onQueryPurchasesFinished(PurchasesResult result) {
if (billingClient == null || result.getResponseCode() != BillingResponseCode.OK) {
Log.w(TAG, "billingClient is null or result code (" + result.getResponseCode()
+ ") was bad - quitting");
return;
}
purchaseList.clear();
onPurchasesUpdated(result.getBillingResult(), result.getPurchasesList());
}
/*更新商品*/
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
//Log.i(TAG, "billingResult.getResponseCode()==" + billingResult.getResponseCode() + ",purchases.size()==" + purchases.size());
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
for (Purchase purchase : purchases) {
handlePurchase(purchase);
}
mBillingUpdatesListener.onPurchasesUpdated(purchaseList);
} else {
if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
} else {
}
mBillingUpdatesListener.onFailedHandle(billingResult.getResponseCode());
}
}
/*商品处理*/
private void handlePurchase(Purchase purchase) {
//验证签名数据
if (!verifyValidSignature(purchase.getOriginalJson(), purchase.getSignature())) {
return;
}
purchaseList.add(purchase);
}
/*验证签名*/
private boolean verifyValidSignature(String signedData, String signature) {
try {
return Security.verifyPurchase(BASE_64_ENCODED_PUBLIC_KEY, signedData, signature);
} catch (IOException e) {
Log.e(TAG, "Got an exception trying to validate a purchase: " + e);
return false;
}
}
/*执行服务请求*/
private void executeServiceRequest(Runnable runnable) {
if (mIsServiceConnected) {
runnable.run();
} else {
startServiceConnection(runnable);
}
}
/*查询内购商品详情*/
public void querySkuDetailsAsync(@SkuType final String itemType, final List<String> skuList,
final SkuDetailsResponseListener listener) {
Runnable queryRequest = () -> {
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList)
.setType(itemType);
billingClient.querySkuDetailsAsync(params.build(), listener);
};
executeServiceRequest(queryRequest);
}
/*启动购买,订购流程*/
public void initiatePurchaseFlow(final SkuDetails skuDetails, String recordId) {
Runnable purchaseFlowRequest = () -> {
JSONObject jsonObject = new JSONObject();
jsonObject.put("p", skuDetails.getPrice());
jsonObject.put("a", skuDetails.getPriceAmountMicros() / 10000);
jsonObject.put("c", skuDetails.getPriceCurrencyCode());
BillingFlowParams purchaseParams = BillingFlowParams.newBuilder()
.setObfuscatedAccountId(recordId)
.setObfuscatedProfileId(jsonObject.toJSONString())
.setSkuDetails(skuDetails)
.build();
BillingResult billingResult = billingClient.launchBillingFlow(mActivity, purchaseParams);
Log.i(TAG, " initiatePurchaseFlow billingResult=" + billingResult.getResponseCode() + " " + billingResult.getDebugMessage());
};
executeServiceRequest(purchaseFlowRequest);
}
public void consumeAsync(final String purchaseToken) {
if (mTokensToBeConsumed == null) {
mTokensToBeConsumed = new HashSet<>();
} else if (mTokensToBeConsumed.contains(purchaseToken)) {
Log.i(TAG, "Token was already scheduled to be consumed - skipping...");
return;
}
mTokensToBeConsumed.add(purchaseToken);
final ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchaseToken).build();
final ConsumeResponseListener consumeResponseListener = new ConsumeResponseListener() {
@Override
public void onConsumeResponse(@NonNull @NotNull BillingResult billingResult, @NonNull @NotNull String s) {
mBillingUpdatesListener.onConsumeFinished(purchaseToken, billingResult.getResponseCode());
}
};
executeServiceRequest(() -> billingClient.consumeAsync(consumeParams, consumeResponseListener));
}
public void acknowledgePurchase(AcknowledgePurchaseParams acknowledgePurchaseParams, AcknowledgePurchaseResponseListener Listener) {
billingClient.acknowledgePurchase(acknowledgePurchaseParams, Listener);
}
/* 释放连接*/
public void destroy() {
Log.d(TAG, "Destroying the manager.");
if (billingClient != null && billingClient.isReady()) {
billingClient.endConnection();
billingClient = null;
}
}
}

View File

@@ -1,504 +1,256 @@
package com.yizhuan.erban.ui.pay;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.util.Log;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.netease.nim.uikit.StatusBarUtil;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.SkuDetails;
import com.appsflyer.AFInAppEventParameterName;
import com.appsflyer.AFInAppEventType;
import com.appsflyer.AppsFlyerLib;
import com.yizhuan.erban.R;
import com.yizhuan.erban.base.BaseActivity;
import com.yizhuan.erban.base.TitleBar;
import com.yizhuan.erban.base.BaseMvpActivity;
import com.yizhuan.erban.pay.presenter.ChargePresenter;
import com.yizhuan.erban.pay.view.IChargeView;
import com.yizhuan.erban.ui.setting.ModifyPwdActivity;
import com.yizhuan.erban.ui.webview.CommonWebViewActivity;
import com.yizhuan.erban.ui.widget.password.PasswordEvent;
import com.yizhuan.xchat_android_core.Constants;
import com.yizhuan.xchat_android_core.UriProvider;
import com.yizhuan.xchat_android_core.auth.AuthModel;
import com.yizhuan.xchat_android_core.bean.response.result.ChargeListResult;
import com.yizhuan.xchat_android_core.pay.PayModel;
import com.yizhuan.xchat_android_core.pay.bean.ChargeBean;
import com.yizhuan.xchat_android_core.pay.bean.WalletInfo;
import com.yizhuan.xchat_android_core.pay.event.GetWalletInfoEvent;
import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent;
import com.yizhuan.xchat_android_core.user.UserModel;
import com.yizhuan.xchat_android_core.user.bean.UserInfo;
import com.yizhuan.xchat_android_core.utils.CheckUtils;
import com.yizhuan.xchat_android_core.utils.net.BeanObserver;
import com.yizhuan.xchat_android_core.web.event.WebViewRefreshEvent;
import com.yizhuan.xchat_android_library.utils.ListUtils;
import com.yizhuan.xchat_android_core.utils.net.IgnoreException;
import com.yizhuan.xchat_android_library.base.factory.CreatePresenter;
import com.yizhuan.xchat_android_library.utils.SingleToastUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Map;
import io.reactivex.SingleObserver;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* 充值界面
*
* @author zhouxiangfeng
* @date 2017/6/19
* Created by MadisonRong on 05/01/2018.
* 充值页面
*/
public class ChargeActivity extends BaseActivity {
public static final int ALI_PAY_CLOSE = 1;
public static final int WX_PAY_CLOSE = 2;
public static final int ALI_PAY_OPEN = 3;
public static final int WX_PAY_OPEN = 4;
@CreatePresenter(ChargePresenter.class)
public class ChargeActivity extends BaseMvpActivity<IChargeView, ChargePresenter>
implements IChargeView, BillingManager.BillingUpdatesListener {
private static final String TAG = "ChargeActivity";
private final int BINDCODE_GOLD = 200;
List<ChargeBean> mBigList;
List<ChargeBean> mList;
private TextView mTv_gold;
private LinearLayout ll_type_first;
private ImageView iv_sel_first;
private ImageView iv_type_first;
private TextView tv_type_first;
private LinearLayout ll_type_second;
private ImageView iv_sel_second;
private ImageView iv_type_second;
private TextView tv_type_second;
private TextView tvCharge;
private RecyclerView mRecyclerView;
@BindView(R.id.tv_gold)
TextView mTv_gold;
@BindView(R.id.iv_back)
ImageView ivBack;
@BindView(R.id.recyclerView)
RecyclerView mRecyclerView;
private ChargeAdapter mChargeAdapter;
private TextView tvAgreement;
private LinearLayout ll_more;
private ChargeBean mSelectChargeBean;
private int mListSize;
private volatile String payChannel = Constants.CHARGE_WX;
private boolean mIsFromH5;
private CompositeDisposable compositeDisposable = new CompositeDisposable();
private final int BINDCODE_GOLD = 200;
private BillingManager billingManager;
public static void start(Context context) {
UserInfo userInfo = UserModel.get().getCacheLoginUserInfo();
if (context == null || userInfo == null) return;
Intent intent = new Intent(context, ChargeActivity.class);
context.startActivity(intent);
}
public static void start(Context context, boolean isFromH5) {
UserInfo userInfo = UserModel.get().getCacheLoginUserInfo();
if (context == null || userInfo == null) return;
Intent intent = new Intent(context, ChargeActivity.class);
intent.putExtra("isFromH5", isFromH5);
context.startActivity(intent);
}
@SuppressLint("StringFormatMatches")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_charge);
initWhiteTitleBar(getString(R.string.label_charge_gold));
mTitleBar.setLeftClickListener(v -> finishPage());
mTitleBar.addAction(new TitleBar.TextAction("我的收益", getResources().getColor(R.color.color_333333)) {
@Override
public void performAction(View view) {
CommonWebViewActivity.start(ChargeActivity.this,
UriProvider.getMyIncomeUrl());
}
});
bindViews();
setListener();
initiate();
}
@Override
public void initWhiteTitleBar(String title) {
mTitleBar = findViewById(R.id.title_bar);
if (mTitleBar != null) {
mTitleBar.setTitle(title);
mTitleBar.setImmersive(false);
mTitleBar.setTitleColor(getResources().getColor(R.color.color_333333));
mTitleBar.setLeftImageResource(R.drawable.arrow_left);
mTitleBar.setCommonBackgroundColor(getResources().getColor(R.color.transparent));
mTitleBar.setLeftClickListener(v -> onLeftClickListener());
}
}
private void setListener() {
ll_more.setOnClickListener(v -> hideMoreButton());
tvCharge.setOnClickListener(v -> {
if (mSelectChargeBean == null) return;
getDialogManager().showProgressDialog(this, false);
});
tvAgreement.setOnClickListener(v -> {
CommonWebViewActivity.start(this, UriProvider.getRechargeAgreementUrl());
});
}
private void hideMoreButton() {
ll_more.setVisibility(View.GONE);
ll_type_second.setVisibility(View.VISIBLE);
}
private void showMoreButton() {
ll_more.setVisibility(View.VISIBLE);
ll_type_second.setVisibility(View.GONE);
}
private void bindViews() {
mTv_gold = findViewById(R.id.tv_gold);
ll_type_first = findViewById(R.id.ll_type_first);
iv_sel_first = findViewById(R.id.iv_sel_first);
iv_type_first = findViewById(R.id.iv_type_first);
ll_type_second = findViewById(R.id.ll_type_second);
ll_more = findViewById(R.id.ll_more);
iv_sel_second = findViewById(R.id.iv_sel_second);
tvCharge = findViewById(R.id.tv_charge);
tvAgreement = findViewById(R.id.tv_agreement);
iv_type_second = findViewById(R.id.iv_type_second);
tv_type_first = findViewById(R.id.tv_type_first);
tv_type_second = findViewById(R.id.tv_type_second);
}
public void selectPayChannelDisplay(String payChannel, int defaultPay) {
this.payChannel = payChannel;
boolean selectWeChatPay = (Objects.equals(this.payChannel, Constants.CHARGE_WX));
boolean selectAliPay = (Objects.equals(this.payChannel, Constants.CHARGE_ALIPAY));
if (!ListUtils.isListEmpty(mBigList)) {
if (selectAliPay) {
if (mList.size() == mListSize) {
for (ChargeBean bigList : mBigList) {
mList.add(bigList);
}
mChargeAdapter.setNewData(mList);
mChargeAdapter.notifyDataSetChanged();
}
} else {
if (mList.size() > mListSize) {
setItemSelect(0);
}
for (ChargeBean bigList : mBigList) {
mList.remove(bigList);
}
mChargeAdapter.setNewData(mList);
mChargeAdapter.notifyDataSetChanged();
}
}
switch (defaultPay) {
case ALI_PAY_CLOSE:
case ALI_PAY_OPEN:
iv_sel_first.setSelected(selectAliPay);
iv_sel_second.setSelected(selectWeChatPay);
break;
case WX_PAY_CLOSE:
case WX_PAY_OPEN:
iv_sel_first.setSelected(selectWeChatPay);
iv_sel_second.setSelected(selectAliPay);
break;
default:
defaultSetPay(selectWeChatPay, selectAliPay);
break;
}
}
/**
* 默认选择的支付方式
*
* @param selectWeChatPay
* @param selectAliPay
*/
private void defaultSetPay(boolean selectWeChatPay, boolean selectAliPay) {
iv_sel_first.setSelected(selectWeChatPay);
iv_sel_second.setSelected(selectAliPay);
}
private void initiate() {
mIsFromH5 = getIntent().getBooleanExtra("isFromH5", false);
mRecyclerView = findViewById(R.id.recyclerView);
mRecyclerView.setNestedScrollingEnabled(false);
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
mChargeAdapter = new ChargeAdapter(false);
mRecyclerView.setAdapter(mChargeAdapter);
mChargeAdapter.setOnItemClickListener((baseQuickAdapter, view, position) -> {
setItemSelect(position);
// int money = mSelectChargeBean.getMoney();
// if (money >= 30000) {
// // 大于 3w 的时候,隐藏微信支付的选项
// ll_type_first.setVisibility(View.GONE);
// // 默认选中支付宝支付的选项
// selectPayChannelDisplay(Constants.CHARGE_ALIPAY);
// } else {
// ll_type_first.setVisibility(View.VISIBLE);
// }
});
onRefreshing();
onLoadingData();
}
private void setItemSelect(int position) {
List<ChargeBean> list = mChargeAdapter.getData();
if (ListUtils.isListEmpty(list)) return;
// 空对象不让蒙板遮挡最后一个item
ChargeBean temp = list.get(position);
if (TextUtils.isEmpty(temp.getProdName()))
return;
mSelectChargeBean = list.get(position);
int size = list.size();
for (int i = 0; i < size; i++) {
list.get(i).isSelected = position == i;
}
mChargeAdapter.notifyDataSetChanged();
}
public void onLoadingData() {
UserInfo userInfos = UserModel.get().getCacheLoginUserInfo();
if (userInfos != null) {
PayModel.get().getWalletInfo(userInfos.getUid()).subscribe(new SingleObserver<WalletInfo>() {
@Override
public void onSubscribe(Disposable d) {
mCompositeDisposable.add(d);
}
@Override
public void onSuccess(WalletInfo walletInfo) {
setWalletData(walletInfo);
}
@Override
public void onError(Throwable e) {
}
});
}
}
public void onRefreshing() {
PayModel.get().getChargeList(1, AuthModel.get().getCurrentUid()).subscribe(new BeanObserver<ChargeListResult>() {
@Override
public void onSuccess(ChargeListResult chargeBeans) {
if (chargeBeans == null) return;
mBigList = chargeBeans.getBigList();
mList = chargeBeans.getList();
mListSize = chargeBeans.getList().size();
onGetChargeList(chargeBeans.getList());
//默认选中
}
@Override
public void onErrorMsg(String error) {
onGetChargeListFail(error);
}
});
}
@Override
protected void onResume() {
super.onResume();
ButterKnife.bind(this);
EventBus.getDefault().register(this);
if (PayModel.get().isFirstChargeSuccess()) {
PayModel.get().setFirstChargeSuccess(false);
onRefreshing();
initViews();
initBilling();
}
/*初始化*/
public void initBilling() {
billingManager = new BillingManager(this, this);
}
/*客户端设置成功回调*/
@SuppressLint("CheckResult")
@Override
public void onBillingClientSetupFinished() {
Log.i(TAG, "onBillingClientSetupFinished");
PayModel.get().getChargeList(4, AuthModel.get().getCurrentUid())
.compose(bindToLifecycle())
.subscribe(chargeListResult -> initProduceList(chargeListResult.getList()));
}
public void initProduceList(List<ChargeBean> chargeBeanList) {
final List<String> productKeys = new ArrayList<>();
for (ChargeBean chargeBean : chargeBeanList) {
productKeys.add(chargeBean.getChargeProdId());
}
billingManager.querySkuDetailsAsync(BillingClient.SkuType.INAPP, productKeys, (billingResult, skuDetailsList) -> {
if (billingResult.getResponseCode() != BillingClient.BillingResponseCode.OK) {
Log.w(TAG, "Unsuccessful query for type: " + BillingClient.SkuType.INAPP
+ ". Error code: " + billingResult.getResponseCode());
} else if (skuDetailsList != null && skuDetailsList.size() > 0) {
List<ChargeBean> showChargeList = new ArrayList<>();
for (ChargeBean chargeBean : chargeBeanList) {
for (SkuDetails skuDetails : skuDetailsList) {
if (skuDetails.getSku().equals(chargeBean.getChargeProdId())) {
chargeBean.setSkuDetails(skuDetails);
showChargeList.add(chargeBean);
break;
}
}
}
mChargeAdapter.setNewData(showChargeList);
}
});
}
/*商品更新回调*/
@SuppressLint("CheckResult")
@Override
public void onPurchasesUpdated(List<Purchase> purchases) {
for (Purchase purchase : purchases) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED &&
purchase.getAccountIdentifiers() != null) {
PayModel.get().verifyOrder(
purchase.getAccountIdentifiers().getObfuscatedAccountId(),
purchase.getSkus().get(0),
purchase.getPackageName(),
purchase.getPurchaseToken())
.compose(bindToLifecycle())
.subscribe(
token -> {
//L.i("token=" + token);
billingManager.consumeAsync(token);
SkuDetails skuDetails = null;
for (ChargeBean datum : mChargeAdapter.getData()) {
if (datum.getChargeProdId().equals(purchase.getSkus().get(0))) {
skuDetails = datum.getSkuDetails();
break;
}
}
if (skuDetails != null) {
Map<String, Object> eventValue = new HashMap<>();
eventValue.put(AFInAppEventParameterName.CONTENT_TYPE, "Gold");
eventValue.put(AFInAppEventParameterName.QUANTITY, 1);
eventValue.put(AFInAppEventParameterName.CONTENT_ID, purchase.getOrderId());
eventValue.put(AFInAppEventParameterName.REVENUE, skuDetails.getPriceAmountMicros() / 1000000f);
eventValue.put("Price", skuDetails.getPrice());
eventValue.put(AFInAppEventParameterName.CURRENCY, skuDetails.getPriceCurrencyCode());
AppsFlyerLib.getInstance().logEvent(getApplicationContext(), AFInAppEventType.PURCHASE, eventValue);
}
},
throwable -> {
if (!(throwable instanceof IgnoreException)) {
SingleToastUtil.showToast(throwable.getMessage());
}
});
}
}
Log.i(TAG, "onPurchasesUpdated");
}
@Override
protected void onPause() {
super.onPause();
EventBus.getDefault().unregister(this);
public void onConsumeFinished(String token, int result) {
}
public void onGetChargeList(List<ChargeBean> chargeBeanList) {
if (chargeBeanList != null && chargeBeanList.size() > 0) {
//先判断存不存在1元档位
boolean isExistOneYuan = false;
for (int i = 0; i < chargeBeanList.size(); i++) {
ChargeBean chargeBean = chargeBeanList.get(i);
if (chargeBean.getMoney() == 1) {
isExistOneYuan = true;
break;
}
}
int selectedMoney = isExistOneYuan ? 1 : 6;
for (int i = 0; i < chargeBeanList.size(); i++) {
ChargeBean chargeBean = chargeBeanList.get(i);
chargeBean.isSelected = chargeBean.getMoney() == selectedMoney;
if (selectedMoney == chargeBean.getMoney()) {
mSelectChargeBean = chargeBean;
}
}
// ChargeBean chargeBean = new ChargeBean(0);
// chargeBean.setChannel(0);
// chargeBean.setChargeProdId(0);
// chargeBean.setGiftGoldNum(0);
// chargeBean.setProdName("");
// chargeBeanList.add(chargeBean);
mChargeAdapter.setNewData(chargeBeanList);
}
/*失败处理*/
public void onFailedHandle(@BillingClient.BillingResponseCode int result) {
}
public void onGetChargeListFail(String error) {
toast(error);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
getDialogManager().dismissDialog();
if (resultCode != RESULT_OK) {
return;
}
if (requestCode == BINDCODE_GOLD) {
ModifyPwdActivity.start(this, ModifyPwdActivity.FOGERT_PAY_PWD);
}
}
private void disposeCompositeDisposable() {
if (compositeDisposable != null && !compositeDisposable.isDisposed()) {
compositeDisposable.dispose();
/*购买商品*/
@SuppressLint("CheckResult")
public void buyProduct(SkuDetails skuDetails) {
if (skuDetails != null) {
Log.d(TAG, "BuyProduct:" + skuDetails.getSku());
PayModel.get().placeOrder(skuDetails.getSku())
.compose(bindToLifecycle())
.subscribe(recordId -> billingManager.initiatePurchaseFlow(skuDetails, recordId.getRecordId()),
throwable -> SingleToastUtil.showToast(throwable.getMessage()));
} else {
Log.w(TAG, "skuDetails ==null");
}
}
@Override
protected void onDestroy() {
super.onDestroy();
disposeCompositeDisposable();
EventBus.getDefault().unregister(this);
if (billingManager != null) {
billingManager.destroy();
}
}
@Override
protected void onResume() {
super.onResume();
if (billingManager != null && billingManager.isServiceConnected()) {
billingManager.onQueryPurchases();
}
getMvpPresenter().loadUserInfo();
}
private void initViews() {
ivBack.setOnClickListener(v -> finish());
mRecyclerView.setLayoutManager(new LinearLayoutManager(context));
mChargeAdapter = new ChargeAdapter();
mRecyclerView.setAdapter(mChargeAdapter);
mChargeAdapter.setOnItemClickListener((baseQuickAdapter, view, position) -> {
buyProduct(mChargeAdapter.getItem(position).getSkuDetails());
});
}
@Override
public void onReloadDate() {
getMvpPresenter().loadUserInfo();
}
@Override
public void setupUserWalletBalance(WalletInfo walletInfo) {
mTv_gold.setText(Double.toString(walletInfo.getGoldNum()));
}
@Override
public void getUserWalletInfoFail(String error) {
toast(error);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//支付页面返回处理
if (requestCode == BINDCODE_GOLD && resultCode == Activity.RESULT_OK) {
ModifyPwdActivity.start(this, ModifyPwdActivity.FOGERT_PAY_PWD);
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onWalletInfoUpdate(UpdateWalletInfoEvent event) {
WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo();
if (walletInfo != null) {
setWalletData(walletInfo);
mTv_gold.setText(String.valueOf(walletInfo.getGoldNum()));
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onGetWalletInfo(GetWalletInfoEvent event) {
WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo();
if (walletInfo != null) {
setWalletData(walletInfo);
}
}
/**
* defaultPay 1默认支付宝2默认微信
*/
private void setWalletData(WalletInfo walletInfo) {
if (walletInfo == null) return;
mTv_gold.setText(getString(R.string.charge_gold, walletInfo.getDiamondNum()));
int defaultPay = walletInfo.getDefaultPay();
switch (defaultPay) {
case ALI_PAY_CLOSE:
payChannel = Constants.CHARGE_ALIPAY;
showMoreButton();
setAliPayFirst(defaultPay);
break;
case WX_PAY_CLOSE:
payChannel = Constants.CHARGE_WX;
showMoreButton();
setWxPayFirst(defaultPay);
break;
case ALI_PAY_OPEN:
payChannel = Constants.CHARGE_ALIPAY;
hideMoreButton();
setAliPayFirst(defaultPay);
break;
case WX_PAY_OPEN:
payChannel = Constants.CHARGE_WX;
hideMoreButton();
setWxPayFirst(defaultPay);
break;
default:
defaultPay(defaultPay);
break;
}
if (CheckUtils.isCheckUser()) {
selectPayChannelDisplay(Constants.CHARGE_ALIPAY, defaultPay);
} else {
selectPayChannelDisplay(payChannel, defaultPay);
}
}
/**
* 默认支付方式
*
* @param defaultPay
*/
private void defaultPay(int defaultPay) {
payChannel = Constants.CHARGE_WX;
hideMoreButton();
setWxPayFirst(defaultPay);
}
private void setAliPayFirst(int defaultType) {
iv_type_first.setImageDrawable(getResources().getDrawable(R.drawable.ic_ali_charge));
iv_type_second.setImageDrawable(getResources().getDrawable(R.drawable.ic_wechat_charge));
tv_type_first.setText("支付宝");
tv_type_second.setText("微信");
ll_type_first.setOnClickListener(v -> selectPayChannelDisplay(Constants.CHARGE_ALIPAY, defaultType));
ll_type_second.setOnClickListener(v -> selectPayChannelDisplay(Constants.CHARGE_WX, defaultType));
if (CheckUtils.isCheckUser()) {
ll_type_first.setVisibility(View.VISIBLE);
ll_type_second.setVisibility(View.GONE);
ll_more.setVisibility(View.GONE);
}
}
private void setWxPayFirst(int defaultType) {
iv_type_first.setImageDrawable(getResources().getDrawable(R.drawable.ic_wechat_charge));
iv_type_second.setImageDrawable(getResources().getDrawable(R.drawable.ic_ali_charge));
tv_type_first.setText("微信");
tv_type_second.setText("支付宝");
ll_type_first.setOnClickListener(v -> selectPayChannelDisplay(Constants.CHARGE_WX, defaultType));
ll_type_second.setOnClickListener(v -> selectPayChannelDisplay(Constants.CHARGE_ALIPAY, defaultType));
if (CheckUtils.isCheckUser()) {
ll_type_first.setVisibility(View.GONE);
ll_type_second.setVisibility(View.VISIBLE);
ll_more.setVisibility(View.GONE);
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onGetPassword(PasswordEvent event) {
getDialogManager().showProgressDialog(this);
}
@Override
protected boolean needSteepStateBar() {
return true;
}
@Override
protected void setStatusBar() {
super.setStatusBar();
StatusBarUtil.transparencyBar(this);
}
@Override
public void onBackPressed() {
super.onBackPressed();
finishPage();
}
private void finishPage() {
finish();
if (!mIsFromH5) return;
EventBus.getDefault().post(new WebViewRefreshEvent());
}
}

View File

@@ -1,13 +1,9 @@
package com.yizhuan.erban.ui.pay;
import android.text.TextUtils;
import android.widget.LinearLayout;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.netease.nim.uikit.common.util.sys.ScreenUtil;
import com.yizhuan.erban.R;
import com.yizhuan.xchat_android_core.pay.bean.ChargeBean;
@@ -18,32 +14,17 @@ import org.jetbrains.annotations.NotNull;
* Created by Administrator on 2017/11/20.
*/
public class ChargeAdapter extends BaseQuickAdapter<ChargeBean, BaseViewHolder> {
private final boolean isDialogCharge;
ChargeAdapter(boolean isDialogCharge) {
public ChargeAdapter() {
super(R.layout.list_item_charge);
this.isDialogCharge = isDialogCharge;
}
@Override
protected void convert(@NotNull BaseViewHolder baseViewHolder, ChargeBean chargeBean) {
if (chargeBean == null) return;
if (isDialogCharge) {
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) baseViewHolder.itemView.getLayoutParams();
layoutParams.height = ScreenUtil.dip2px(54);
baseViewHolder.itemView.setLayoutParams(layoutParams);
}
baseViewHolder.setVisible(R.id.ll_gold_charge, !TextUtils.isEmpty(chargeBean.getProdName()))
.setText(R.id.tv_money_gold, chargeBean.prodName.replace("钻石", ""))
.setText(R.id.cb_money, mContext.getString(R.string.charge_number, chargeBean.money));
LinearLayout rl_gold_charge = baseViewHolder.getView(R.id.ll_gold_charge);
rl_gold_charge.setSelected(chargeBean.isSelected);
baseViewHolder.setText(R.id.tv_title, chargeBean.getProdName())
.setText(R.id.tv_desc, chargeBean.getProdDesc())
.setText(R.id.item_charge_money, chargeBean.getSkuDetails().getPrice())
.setGone(R.id.tv_desc, !TextUtils.isEmpty(chargeBean.getProdDesc()));
}
}

View File

@@ -0,0 +1,69 @@
package com.yizhuan.erban.ui.pay;
import android.text.TextUtils;
import android.util.Base64;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
public class Security {
private static final String TAG = "GoogleIap/Security";
private static final String KEY_FACTORY_ALGORITHM = "RSA";
private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
public static boolean verifyPurchase(String base64PublicKey, String signedData,
String signature) throws IOException {
if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey)
|| TextUtils.isEmpty(signature)) {
return false;
}
PublicKey key = generatePublicKey(base64PublicKey);
return verify(key, signedData, signature);
}
public static PublicKey generatePublicKey(String encodedPublicKey) throws IOException {
try {
byte[] decodedKey = Base64.decode(encodedPublicKey, Base64.DEFAULT);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
} catch (NoSuchAlgorithmException e) {
// "RSA" is guaranteed to be available.
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
String msg = "Invalid key specification: " + e;
throw new IOException(msg);
}
}
public static boolean verify(PublicKey publicKey, String signedData, String signature) {
byte[] signatureBytes;
try {
signatureBytes = Base64.decode(signature, Base64.DEFAULT);
} catch (IllegalArgumentException e) {
return false;
}
try {
Signature signatureAlgorithm = Signature.getInstance(SIGNATURE_ALGORITHM);
signatureAlgorithm.initVerify(publicKey);
signatureAlgorithm.update(signedData.getBytes());
if (!signatureAlgorithm.verify(signatureBytes)) {
return false;
}
return true;
} catch (NoSuchAlgorithmException e) {
// "RSA" is guaranteed to be available.
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
} catch (SignatureException e) {
}
return false;
}
}

View File

@@ -109,7 +109,7 @@ public class JSInterface {
@JavascriptInterface
public void openChargePage() {
if (context != null) {
ChargeActivity.start(context, true);
ChargeActivity.start(context);
}
}

View File

@@ -1,53 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll_gold_charge"
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_margin="@dimen/dp_4"
android:background="@drawable/selector_gold_price"
android:gravity="center"
android:orientation="vertical">
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="15dp"
android:layout_marginBottom="6dp"
android:background="@drawable/bg_secondary_radius_15"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
<ImageView
android:layout_width="@dimen/dp_30"
android:layout_height="@dimen/dp_30"
android:layout_marginStart="@dimen/dp_16"
android:src="@drawable/icon_gold" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_charge_diamond" />
android:layout_marginStart="10dp">
<TextView
android:id="@+id/tv_money_gold"
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:fontFamily="sans-serif-medium"
android:gravity="center"
android:includeFontPadding="false"
android:textColor="@color/color_333333"
android:textSize="14dp"
tools:text="8" />
android:textSize="20sp"
tools:text="400" />
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/dp_5"
android:gravity="center_vertical"
android:text="@string/diamond"
android:textColor="@color/text_normal_c6c6e9"
android:textSize="@dimen/dp_11"
android:visibility="gone" />
android:layout_height="wrap_content"
android:layout_below="@+id/tv_title"
android:gravity="center"
android:maxWidth="120dp"
android:maxLines="1"
android:singleLine="true"
android:textColor="@color/color_999999"
android:textSize="12sp"
android:visibility="gone"
tools:text="哈哈哈"
tools:visibility="visible" />
</RelativeLayout>
</LinearLayout>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@+id/cb_money"
android:id="@+id/item_charge_money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/color_999999"
android:textSize="12dp"
tools:text="¥8元" />
android:layout_marginEnd="@dimen/dp_15"
android:drawablePadding="2dp"
android:gravity="end"
android:includeFontPadding="false"
android:textColor="#42425B"
android:textSize="20sp"
tools:text="6" />
<TextView
android:id="@+id/tv_buy"
android:layout_width="60dp"
android:layout_height="28dp"
android:layout_marginEnd="24dp"
android:background="@drawable/common_btn_bg"
android:gravity="center"
android:includeFontPadding="false"
android:text="购买"
android:textColor="#000B22"
android:textSize="14sp" />
</LinearLayout>

View File

@@ -25,6 +25,7 @@ buildscript {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.tencent.vasdolly:plugin:3.0.3'
classpath "com.mob.sdk:MobSDK:2018.0319.1724"
classpath 'com.google.gms:google-services:4.3.8'
}
}

View File

@@ -91,6 +91,15 @@ dependencies {
api 'com.tencent.bugly:crashreport:4.1.9'
//firebase推送、统计
implementation 'com.google.firebase:firebase-messaging:22.0.0'
implementation 'com.google.android.gms:play-services-base:17.6.0'
implementation 'com.google.firebase:firebase-core:19.0.0'
//googleplay内购
api 'com.google.android.gms:play-services-wallet:18.1.3'
api 'com.android.billingclient:billing:4.0.0'
api project(':nim_uikit')
api project(':library')
api project(':trtc_release')

View File

@@ -265,4 +265,6 @@ public class XChatConstants {
(byte) 0x33, (byte) 0x3f, (byte) 0x33, (byte) 0x90, (byte) 0x07, (byte) 0x53, (byte) 0xeb, (byte) 0xd2, (byte) 0xd2,
(byte) 0x4e, (byte) 0xc5, (byte) 0xed, (byte) 0xfd, (byte) 0x43
};
public static final int CODE_IGNORE_TOAST = 5263;
}

View File

@@ -8,6 +8,7 @@ import com.yizhuan.xchat_android_core.bean.response.ServiceResult;
import com.yizhuan.xchat_android_core.bean.response.result.ChargeListResult;
import com.yizhuan.xchat_android_core.pay.bean.FirstChargeGoods;
import com.yizhuan.xchat_android_core.pay.bean.NewUserChargeInfo;
import com.yizhuan.xchat_android_core.pay.bean.PayRecordId;
import com.yizhuan.xchat_android_core.pay.bean.WalletInfo;
import com.yizhuan.xchat_android_core.pay.bean.WxPayType;
@@ -101,4 +102,12 @@ public interface IPayModel extends IModel {
Single<List<FirstChargeGoods>> getFirstChargeList();
Single<NewUserChargeInfo> getNewUserChargeInfo();
Single<String> verifyOrder(String chargeRecordId,
String googlePlayProdId,
String packageName,
String purchaseToken);
Single<PayRecordId> placeOrder(String googlePlayProdId);
}

View File

@@ -6,6 +6,7 @@ import android.content.Context;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.yizhuan.xchat_android_constants.XChatConstants;
import com.yizhuan.xchat_android_core.auth.AuthModel;
import com.yizhuan.xchat_android_core.base.BaseModel;
import com.yizhuan.xchat_android_core.bean.response.ServiceResult;
@@ -15,6 +16,7 @@ import com.yizhuan.xchat_android_core.manager.IMNetEaseManager;
import com.yizhuan.xchat_android_core.manager.RoomEvent;
import com.yizhuan.xchat_android_core.pay.bean.FirstChargeGoods;
import com.yizhuan.xchat_android_core.pay.bean.NewUserChargeInfo;
import com.yizhuan.xchat_android_core.pay.bean.PayRecordId;
import com.yizhuan.xchat_android_core.pay.bean.WalletInfo;
import com.yizhuan.xchat_android_core.pay.bean.WxPayType;
import com.yizhuan.xchat_android_core.pay.event.ChargeCustomNotificationEvent;
@@ -22,6 +24,7 @@ import com.yizhuan.xchat_android_core.pay.event.FirstRechargeEvent;
import com.yizhuan.xchat_android_core.pay.event.GetWalletInfoEvent;
import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent;
import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent;
import com.yizhuan.xchat_android_core.utils.net.IgnoreException;
import com.yizhuan.xchat_android_core.utils.net.RxHelper;
import com.yizhuan.xchat_android_library.net.rxnet.RxNet;
import com.yizhuan.xchat_android_library.utils.NetworkUtils;
@@ -447,6 +450,32 @@ public class PayModel extends BaseModel implements IPayModel {
.compose(RxHelper.handleSchAndExce());
}
@Override
public Single<String> verifyOrder(String chargeRecordId,
String googlePlayProdId,
String packageName,
String purchaseToken) {
return api.verifyOrder(chargeRecordId, googlePlayProdId, packageName, purchaseToken)
.compose(RxHelper.handleException())
.flatMap(result -> {
if (result.isSuccess()) {
return Single.just(result.getData() == null ? "" : result.getData());
}
if (result.getCode() == XChatConstants.CODE_IGNORE_TOAST) {
return Single.error(new IgnoreException("不需要toast提示的错误"));
}
return Single.error(new Throwable(result.getMessage()));
})
.compose(RxHelper.handleSchedulers());
}
@Override
public Single<PayRecordId> placeOrder(String googlePlayProdId) {
return api.placeOrder(googlePlayProdId)
.compose(RxHelper.handleBeanData())
.compose(RxHelper.handleSchedulers());
}
public interface Api {
@@ -616,6 +645,27 @@ public class PayModel extends BaseModel implements IPayModel {
*/
@GET("/first/charge/limit/list")
Single<ServiceResult<NewUserChargeInfo>> getNewUserChargeInfo();
/**
* 验证googlePlay订单
*
* @return
*/
@FormUrlEncoded
@POST("/googlePlayBilling/verifyOrder")
Single<ServiceResult<String>> verifyOrder(@Field("chargeRecordId") String chargeRecordId,
@Field("googlePlayProdId") String googlePlayProdId,
@Field("packageName") String packageName,
@Field("purchaseToken") String purchaseToken);
/**
* googlePlay预下单
*
* @return
*/
@FormUrlEncoded
@POST("/googlePlayBilling/placeOrder")
Single<ServiceResult<PayRecordId>> placeOrder(@Field("chargeProdId") String chargeProdId);
}
}

View File

@@ -1,5 +1,7 @@
package com.yizhuan.xchat_android_core.pay.bean;
import com.android.billingclient.api.SkuDetails;
import java.io.Serializable;
/**
@@ -23,6 +25,7 @@ public class ChargeBean implements Serializable{
public int giftGoldNum;
public int channel;
public String prodDesc;
private SkuDetails skuDetails;
public boolean isSelected;
@@ -30,17 +33,6 @@ public class ChargeBean implements Serializable{
public ChargeBean(int money) {
this.money = money;
}
// public int seqNo;
//
//
// public int getSeqNo() {
// return seqNo;
// }
//
// public void setSeqNo(int seqNo) {
// this.seqNo = seqNo;
// }
public String getChargeProdId() {
return chargeProdId;
@@ -82,15 +74,40 @@ public class ChargeBean implements Serializable{
this.channel = channel;
}
public String getProdDesc() {
return prodDesc;
}
public void setProdDesc(String prodDesc) {
this.prodDesc = prodDesc;
}
public SkuDetails getSkuDetails() {
return skuDetails;
}
public void setSkuDetails(SkuDetails skuDetails) {
this.skuDetails = skuDetails;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
@Override
public String toString() {
return "ChargeBean{" +
"chargeProdId=" + chargeProdId +
"chargeProdId='" + chargeProdId + '\'' +
", prodName='" + prodName + '\'' +
", money=" + money +
", giftGoldNum=" + giftGoldNum +
", channel=" + channel +
", prodDesc='" + prodDesc + '\'' +
", skuDetails=" + skuDetails +
", isSelected=" + isSelected +
'}';
}

View File

@@ -0,0 +1,14 @@
package com.yizhuan.xchat_android_core.pay.bean;
public class PayRecordId {
private String recordId;
public String getRecordId() {
return recordId;
}
public void setRecordId(String recordId) {
this.recordId = recordId;
}
}

View File

@@ -0,0 +1,11 @@
package com.yizhuan.xchat_android_core.utils.net;
/**
* 可以忽略的异常,比如不弹toast
*/
public class IgnoreException extends Exception {
public IgnoreException(String message) {
super(message);
}
}