# 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 去重逻辑短路。