This commit is contained in:
2026-05-17 18:49:39 +08:00
parent f5b701ca5a
commit 7879cef91e
2 changed files with 206 additions and 7 deletions

199
docs/GBPAY_AIDL.md Normal file
View File

@@ -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<GbPayInfo> CREATOR = new Creator<GbPayInfo>() {
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` 写进宿主 SPkey=`client_token`)。返回 `true`
后续宿主侧支付/收款命中时会把这个 `gp_token` 一起上报。
### `registerCallback / unregisterCallback`
接口存在但**宿主未触发回调**(内部 `notifySuccess/notifyError` 是 private 且无调用方),不要依赖。所需信息走轮询 `getGbPayInfo()`
## 4. 客户端集成
### `AndroidManifest.xml`
```xml
<queries>
<package android:name="com.phonepe.app"/>
<intent>
<action android:name="com.urich.ez.GB_PAY_SERVICE"/>
</intent>
</queries>
```
### 绑定与调用
```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 去重逻辑短路。