Merge branch 'biometric'

This commit is contained in:
CounterFire2023 2024-02-20 18:46:28 +08:00
commit 60bd02b5a4
10 changed files with 302 additions and 240 deletions

File diff suppressed because one or more lines are too long

View File

@ -36,6 +36,11 @@ function walletLogin(funId, channel, env, account) {
promiseCb(funId, jc.wallet.preLogin(channel, env, account));
}
function logout(funId, channel) {
channel = parseInt(channel || '0');
promiseCb(funId, jc.wallet.logout(channel));
}
function updateGameInfo(funId, info) {
jsb.updateGameInfo(funId, info);
promiseCb(funId, Promise.resolve(1));
@ -45,12 +50,14 @@ function updateGameInfo(funId, info) {
* @param {string} chain: chain id
* @param {string} pass: password for wallet
* @param {string} env: dev release
* @param {string} useApi: 1: yes, 0: no
* @return {string} address
* @throws {Error} if password is wrong
*/
function initInternalWallet(funId, chain, pass, env) {
function initInternalWallet(funId, chain, pass, env, useApi) {
chain = parseInt(chain);
promiseCb(funId, jc.wallet.initInternalWallet(chain, pass, env), () => {
useApi = (useApi && useApi == '1') ? true: false
promiseCb(funId, jc.wallet.initInternalWallet(chain, pass, env, useApi), () => {
return jc.wallet.nativeAccount;
});
}
@ -67,11 +74,10 @@ function verifyPassword(funId, pass) {
* init third party wallet
* @param {number | string} chain chain id
*/
function initThirdPartyWallet(funId, chain, env) {
function initThirdPartyWallet(funId, chain, env, wallettype, provider) {
chain = parseInt(chain);
promiseCb(funId, jc.wallet.initThirdPartyWallet(chain, env), () => {
return jc.wallet.currentAccount();
});
wallettype = parseInt(wallettype || '1');
promiseCb(funId, jc.wallet.initThirdPartyWallet(chain, env, wallettype, provider));
}
@ -285,7 +291,7 @@ function exportWalletSecKey(funId, pass) {
* mint NFT
* @param {string} address: contract address of NFT
* @param {string} tokenIds: token id of NFT, JSON string of string array
* @parsm {string} startTime: time of signature generation
* @param {string} startTime: time of signature generation
* @param {string} saltNonce: nonce of signature
* @param {string} signature: signature
* @param {string} estimate: 1: only estimate gas price
@ -758,6 +764,58 @@ function nftStakeInfo(funId, nft, tokenId) {
promiseCb(funId, jc.wallet.jcStandard.nftStakeInfo({ nft, tokenId }));
}
// end of staking
// begin of gold bricks
/**
* mint Gold Bricks
* @param {string} address: contract address of NFT
* @param {string} tokenIds: token id of NFT, JSON string of string array
* @param {string} startTime: time of signature generation
* @param {string} saltNonce: nonce of signature
* @param {string} signature: signature
* @param {string} estimate: 1: only estimate gas price
*/
function mintBricks(funId, address, tokenIds, startTime, saltNonce, signature, estimate) {
tokenIds = JSON.parse(tokenIds);
estimate = (estimate || '0') | 0;
promiseCb(
funId,
jc.wallet.jcStandard.mintBricks({
address,
tokenIds,
startTime,
saltNonce,
signature,
estimate,
}),
(v) => JSON.stringify(v)
);
}
/**
* decompose Gold Bricks
* @param {string} address: contract address of NFT
* @param {string} tokenIds: token id of NFT, JSON string of string array
* @param {string} startTime: time of signature generation
* @param {string} saltNonce: nonce of signature
* @param {string} signature: signature
* @param {string} estimate: 1: only estimate gas price
*/
function decomposeBricks(funId, address, tokenIds, startTime, saltNonce, signature, estimate) {
tokenIds = JSON.parse(tokenIds);
estimate = (estimate || '0') | 0;
promiseCb(
funId,
jc.wallet.jcStandard.decomposeBricks({
address,
tokenIds,
startTime,
saltNonce,
signature,
estimate,
}),
(v) => JSON.stringify(v)
);
}
// end of gold bricks
/**
* delete account

View File

@ -65,36 +65,32 @@
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data
android:host="www.cebg.games"
android:pathPrefix="/client" />
<data android:host="www.cebg.games"/>
<data android:pathPrefix="/client"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data
android:host="www.cebg.games"
android:pathPrefix="/client" />
<data android:host="www.cebg.games"/>
<data android:pathPrefix="/client"/>
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data
android:host="www.counterfire.games"
android:pathPrefix="/client" />
<data android:host="www.counterfire.games"/>
<data android:pathPrefix="/client"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data
android:host="www.counterfire.games"
android:pathPrefix="/client" />
<data android:host="www.counterfire.games"/>
<data android:pathPrefix="/client"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@ -157,18 +153,16 @@
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data
android:host="oauth-svr.cebggame.com"
android:pathPrefix="/google" />
<data android:host="oauth-svr.cebggame.com"/>
<data android:pathPrefix="/google"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data
android:host="oauth-svr.cebggame.com"
android:pathPrefix="/google" />
<data android:host="oauth-svr.cebggame.com"/>
<data android:pathPrefix="/google"/>
</intent-filter>
</activity>
<activity
@ -176,11 +170,10 @@
android:launchMode="singleTask"
android:taskAffinity="com.cege.games.release"
android:exported="true" />
<activity
android:name=".apple.AppleLoginActivity"
android:theme="@style/WebViewTheme" />
<activity
android:name=".apple.AppleLoginCbActivity"
<activity
android:name=".oauth.OAuthLoginCbActivity"
tools:node="replace"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@ -188,9 +181,7 @@
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="cebg"
android:path="/apple_login_result" />
<data android:scheme="cfoauthcb" android:path="/login_result" />
</intent-filter>
</activity>
<activity
@ -218,15 +209,6 @@
<category android:name="android.intent.category.default" />
</intent-filter>
</service>
<service
android:name="com.jc.jcfw.accountmanager.AuthenticatorService"
>
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
</application>
<supports-screens
@ -256,7 +238,6 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission
@ -276,8 +257,6 @@
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />

View File

@ -2,13 +2,5 @@ package com.cege.games.release;
public class Constants {
public static final String PREF_NAME = "jcwallet";
public static final String APPLE_CLIENT_ID = "wallet.cebggame.com";
public static final String APPLE_REDIRECT_URI = "https://wallet.cebggame.com/apple/oauth_redirect";
public static final String APPLE_SCOPE = "name%20email";
public static final String APPLE_AUTH_URL = "https://appleid.apple.com/auth/authorize";
public static final String FUNID_PREFIX = "webpage_";
}

View File

@ -26,7 +26,7 @@ import com.bytedance.sdk.open.tiktok.base.VideoObject;
import com.bytedance.sdk.open.tiktok.share.Share;
import com.cege.games.release.activity.WebPageActivity;
import com.cege.games.release.appauth.AppAuthSvr;
import com.cege.games.release.apple.AppleLoginActivity;
import com.cege.games.release.oauth.OAuthUtil;
import com.cege.games.release.ui.UIManager;
import com.cege.games.release.wallet.WalletUtil;
import com.facebook.AccessToken;
@ -106,6 +106,7 @@ public class MainActivity extends UnityPlayerActivity
private FirebaseAnalytics mFirebaseAnalytics;
private AppEventsLogger fbLogger;
private WalletUtil mWalletUtil;
private OAuthUtil mOAuthUtil;
public boolean isGooglePlayServicesAvailable() {
return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS;
@ -125,11 +126,7 @@ public class MainActivity extends UnityPlayerActivity
CocosJSHelper.initJSEnv(getApplicationContext());
// begin of google sign
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(new Scope(Scopes.EMAIL))
.requestIdToken(getString(R.string.default_web_client_id1))
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
// mGoogleSignInClient = initGsiClient();
// end of google sign
// begin of google oauth sign
@ -240,6 +237,14 @@ public class MainActivity extends UnityPlayerActivity
}
private GoogleSignInClient initGsiClient() {
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(new Scope(Scopes.EMAIL))
.requestIdToken(getString(R.string.default_web_client_id1))
.build();
return GoogleSignIn.getClient(this, gso);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
@ -251,6 +256,9 @@ public class MainActivity extends UnityPlayerActivity
public void signWithGoogle(String funId) {
this.mFunID = funId;
if (isGooglePlayServicesAvailable()) {
if (mGoogleSignInClient == null) {
mGoogleSignInClient = initGsiClient();
}
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
if (account != null) {
Log.w(TAG, "already login: " + account.getIdToken());
@ -279,17 +287,20 @@ public class MainActivity extends UnityPlayerActivity
}
public void signOutGoogle(String funId) {
mGoogleSignInClient.signOut()
.addOnCompleteListener(this, task -> {
// ...
});
if (isGooglePlayServicesAvailable()) {
if (mGoogleSignInClient != null) {
mGoogleSignInClient.signOut()
.addOnCompleteListener(this, task -> {
// ...
});
}
}
}
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
Log.w(TAG, "signIn success: ");
Log.w(TAG, "gsa idToken: " + account.getIdToken());
Log.w(TAG, "gso signIn success: " + account.getIdToken());
JcSDK.nativeCb(this.mFunID, null, account.getIdToken());
// Signed in successfully, show authenticated UI.
} catch (ApiException e) {
@ -378,6 +389,17 @@ public class MainActivity extends UnityPlayerActivity
this.mFunID = funId;
}
public void oauthLogin(String funId, String jsonData) {
if (this.mOAuthUtil == null) {
this.mOAuthUtil = new OAuthUtil(this);
}
try {
this.mOAuthUtil.startLogin(funId, jsonData);
} catch (JSONException e) {
JcSDK.nativeCb(funId, e.getMessage(), null);
}
}
public void logEvent(String content) {
try {
Bundle bundle = JsonUtils.convertJsonToBundle(content);
@ -391,16 +413,6 @@ public class MainActivity extends UnityPlayerActivity
}
}
public void signWithApple(String funId) {
this.mFunID = funId;
Log.i(TAG, "login with apple: " + funId);
runOnUiThread(() -> {
Intent intent = new Intent(this, AppleLoginActivity.class);
intent.putExtra("funId", funId);
startActivity(intent);
});
}
public void showPage(String fid, final String url) {
runOnUiThread(() -> {
Intent intent = new Intent(this, WebPageActivity.class);

View File

@ -1,80 +0,0 @@
package com.cege.games.release.apple;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Rect;
import android.net.Uri;
import android.util.Log;
import android.view.ViewGroup;
import android.view.Window;
import android.webkit.CookieManager;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.cege.games.release.Constants;
import com.cege.games.release.R;
public class AppleLoginActivity extends Activity {
private static final String TAG = AppleLoginActivity.class.getSimpleName();
@SuppressLint("SetJavaScriptEnabled")
@Override
public void onCreate(android.os.Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
setContentView(R.layout.activity_web_page);
WebView.setWebContentsDebuggingEnabled(true);
WebView mWebView = findViewById(R.id.web_view);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setDatabaseEnabled(true);
webSettings.setAllowContentAccess(true);
webSettings.setAppCacheEnabled(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
CookieManager.getInstance().setAcceptThirdPartyCookies(mWebView,true);
// get url from intent
String funId = intent.getStringExtra("funId");
String url = Constants.APPLE_AUTH_URL
+ "?response_type=code%20id_token&v=1.1.6&response_mode=form_post&client_id="
+ Constants.APPLE_CLIENT_ID + "&scope=" + Constants.APPLE_SCOPE + "&state=" + funId + "&redirect_uri="
+ Constants.APPLE_REDIRECT_URI;
// show web view
mWebView.loadUrl(url);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
String url = request.getUrl().toString();
Log.i(TAG, url);
if (url.startsWith("cebg")) {
// Close the dialog after getting the authorization code
Intent myapp_intent = new Intent(Intent.ACTION_VIEW);
myapp_intent.setData(Uri.parse(url));
startActivity(myapp_intent);
finish();
return true;
}
return false;
}
// @Override
// public void onPageFinished(WebView view, String url) {
// super.onPageFinished(view, url);
// Rect displayRectangle = new Rect();
// Window window = getWindow();
// window.getDecorView().getWindowVisibleDisplayFrame(displayRectangle);
// ViewGroup.LayoutParams layoutparms = view.getLayoutParams();
// layoutparms.height = displayRectangle.height();
// layoutparms.width = displayRectangle.width();
// view.setLayoutParams(layoutparms);
// }
});
}
}

View File

@ -1,34 +0,0 @@
package com.cege.games.release.apple;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.Nullable;
import com.jc.jcfw.JcSDK;
public class AppleLoginCbActivity extends Activity {
private static final String TAG = AppleLoginCbActivity.class.getSimpleName();
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "receive apple login callback");
Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Uri uri = intent.getData();
String error = uri.getQueryParameter("error");
String state = uri.getQueryParameter("state");
if (null != error && !error.isEmpty()) {
JcSDK.nativeCb(state, error, null);
} else {
String token = uri.getQueryParameter("token");
JcSDK.nativeCb(state, null, token);
}
finish();
}
}
}

View File

@ -0,0 +1,52 @@
package com.cege.games.release.oauth;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.Nullable;
import com.cege.games.release.MainActivity;
import com.jc.jcfw.JcSDK;
public class OAuthLoginCbActivity extends Activity {
private static final String TAG = OAuthLoginCbActivity.class.getSimpleName();
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "receive oauth login callback");
Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Uri uri = intent.getData();
String error = uri.getQueryParameter("error");
String state = uri.getQueryParameter("state");
if (null != error && !error.isEmpty()) {
JcSDK.nativeCb(state, error, null);
} else {
String token = uri.getQueryParameter("token");
// if token is null, get token and state from uri fragment
if (null == token || "undefined".equals(token) || token.isEmpty()){
String fragment = uri.getFragment();
String[] vals = fragment.split("&");
for (String val : vals) {
if (val.startsWith("token=")) {
token = val.substring(6);
} else if (val.startsWith("id_token=")) {
token = val.substring(9);
} else if (val.startsWith("state=")) {
state = val.substring(6);
}
}
}
JcSDK.nativeCb(state, null, token);
}
Intent intentMain = new Intent(this, MainActivity.class);
startActivity(intentMain);
finish();
}
}
}

View File

@ -0,0 +1,61 @@
package com.cege.games.release.oauth;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import net.openid.appauth.AuthorizationRequest;
import net.openid.appauth.AuthorizationService;
import net.openid.appauth.AuthorizationServiceConfiguration;
import org.json.JSONException;
import org.json.JSONObject;
public class OAuthUtil {
private final Activity mActivity;
public OAuthUtil(Activity activity) {
this.mActivity = activity;
}
/**
*
* @param funId
* @param jsonData: {
* "endpoint": "",
* "client_id": "",
* "redirect_uri": "",
* "response_type": "code",
* "response_mode": "form_post", nullable
* "scopes": "",
* }
* @throws JSONException
*/
public void startLogin(String funId, String jsonData) throws JSONException {
JSONObject data = new JSONObject(jsonData);
AuthorizationServiceConfiguration config = new AuthorizationServiceConfiguration(
Uri.parse(data.getString("endpoint")),
Uri.parse("")
);
AuthorizationRequest.Builder authRequestBuilder = new AuthorizationRequest.Builder(
config,
data.getString("client_id"),
data.getString("response_type"),
Uri.parse(data.getString("redirect_uri"))
);
String[] scopes = data.getString("scopes").split(" +");
if (data.has("response_mode")) {
authRequestBuilder.setResponseMode(data.getString("response_mode"));
}
AuthorizationRequest authRequest = authRequestBuilder
.setScopes(scopes)
.setCodeVerifier(null, null, null)
.setState(funId)
.setNonce(funId)
.build();
AuthorizationService service = new AuthorizationService(this.mActivity);
Intent authIntent = service.getAuthorizationRequestIntent(authRequest);
this.mActivity.startActivity(authIntent);
}
}

View File

@ -17,6 +17,7 @@ import com.google.common.base.Strings;
import com.jc.jcfw.google.PayClient;
import com.jc.jcfw.util.ThreadUtils;
import com.jc.jcfw.util.UIUtils;
import com.unity3d.player.UnityPlayer;
import org.cocos2dx.lib.CocosJSHelper;
import org.greenrobot.eventbus.EventBus;
@ -129,7 +130,11 @@ public class JcSDK {
}
public static void signWithApple(String funid) {
MainActivity.app.signWithApple(funid);
// MainActivity.app.signWithApple(funid);
}
public static void signWithOAuth(String funid, String jsonData) {
MainActivity.app.oauthLogin(funid, jsonData);
}
public static void signOutGoogle(String funid) {
@ -229,4 +234,21 @@ public class JcSDK {
public static void nativeCb(NativeResult result) {
nativeCb(result.getFunid(), result.getError(), result.getDataStr());
}
public static void toUnity(String funId, String error, String dataStr) {
JSONObject result = new JSONObject();
try {
result.put("funid", funId);
if (Strings.isNullOrEmpty(error)) {
result.put("errcode", 0);
result.put("data", dataStr);
} else {
result.put("errcode", 1);
result.put("errmessage", error);
}
} catch (JSONException e) {
Log.e(TAG, "JSONException: " + e.getMessage());
}
UnityPlayer.UnitySendMessage("WalletPanel1", "onNativeCallback", result.toString());
}
}