newbind
This commit is contained in:
199
docs/GBPAY_AIDL.md
Normal file
199
docs/GBPAY_AIDL.md
Normal 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` 写进宿主 SP(key=`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 去重逻辑短路。
|
||||
Reference in New Issue
Block a user