Python backend had FULL Alipay SDK integration for ~18 expense-control APIs. Java port has alipay-sdk-java v4.39.218 in pom.xml + AlipayClientFactory bean producing DefaultAlipayClient — but 5 expense module services return empty maps with log.warn("NOT_IMPL") where they should call the SDK.
5 payment modules already use real SDK calls as the pattern reference:
AlipayEmployeeService (D:\project2\payment-platform\java\src\main\java\com\payment\platform\module\payment\employee\service\AlipayEmployeeService.java)AlipayTransferService, AlipayEnterpriseService, AlipayDepartmentService, FacetofaceServiceGoal: Replace 18 NOT_IMPL stubs in expense module with real alipayClientFactory.getClient().execute(request) calls.
From AlipayEmployeeService.java (lines 42-70):
// 1. Build model
AlipayXxxModel model = new AlipayXxxModel();
model.setField(value);
// 2. Build request
AlipayXxxRequest request = new AlipayXxxRequest();
request.setBizModel(model);
// 3. Execute
AlipayXxxResponse response = alipayClientFactory.getClient().execute(request);
// 4. Check
if (!response.isSuccess())
throw new BusinessException(400, "失败: " +
(response.getSubMsg() != null ? response.getSubMsg() : response.getMsg()));
// 5. Catch
catch (AlipayApiException e) {
throw new BusinessException(400, "支付宝异常: " + e.getMessage());
}
Use wildcard imports: import com.alipay.api.domain.*; / request.*; / response.*; / AlipayApiException
File: java/src/main/java/com/payment/platform/module/payment/expense/institution/service/InstitutionService.java
Python: backend/app/plugin/module_payment/expense/institution/service.py
Already has AlipayClientFactory injected.
| API | Alipay SDK Class | Notes |
|---|---|---|
create() |
AlipayEbppInvoiceInstitutionCreateModel/Request/Response |
Replace UUID fallback with response.getInstitutionId() |
update() |
AlipayEbppInvoiceInstitutionModifyModel/Request/Response |
Map DTO fields to model |
delete() |
AlipayEbppInvoiceInstitutionDeleteModel/Request/Response |
Best-effort: swallow Alipay errors, always clean up local DB |
detail() |
AlipayEbppInvoiceInstitutionDetailinfoQueryModel/Request/Response |
Try Alipay first, fall back to DB |
listScope() |
AlipayEbppInvoiceInstitutionScopepageinfoQueryModel/Request/Response |
Note SDK typo: getOnwerOpenIdList() |
modifyScope() |
AlipayEbppInvoiceInstitutionScopeModifyModel/Request/Response |
Python delete_owner_id_list → Java setRemoveOwnerIdList |
createIssueRule() |
AlipayEbppInvoiceIssueruleCreateModel/Request/Response |
Includes issue_target_info_list |
updateIssueRule() / deleteIssueRule() |
Modify/Delete variants |
File: java/src/main/java/com/payment/platform/module/payment/expense/institution/service/InstitutionScopeSyncService.java
Already has AlipayClientFactory. Replace scope.modify stubs for department/employee removal. Errors logged, don't block caller.
File: java/src/main/java/com/payment/platform/module/payment/expense/quota/service/QuotaService.java
Python: backend/app/plugin/module_payment/expense/quota/service.py
Already has AlipayClientFactory (adjustInternal + outsourceNotify already work).
| Method | Alipay SDK Class |
|---|---|
create(QuotaCreateDTO) |
AlipayEbppInvoiceExpensecontrolQuotaCreateModel/Request/Response |
expenseCreate(Map) |
Same quota.create API, different DTO packaging |
expenseQuery(Map) |
AlipayEbppInvoiceExpensecontrolQuotaQueryModel/Request/Response |
Need AlipayClientFactory injection added — both currently lack it.
RuleService: java/.../expense/rule/service/RuleService.java
Python: backend/app/plugin/module_payment/expense/rule/service.py
| Method | Alipay SDK Class |
|---|---|
createExpense(Map) |
AlipayEbppInvoiceInstitutionExpenseruleCreateModel/Request/Response |
modifyExpense(String, Map) |
AlipayEbppInvoiceInstitutionExpenseruleModifyModel/Request/Response |
deleteExpense(String, Map) |
AlipayEbppInvoiceInstitutionExpenseruleDeleteModel/Request/Response |
IssueBatchService: java/.../expense/quota/service/IssueBatchService.java
| Method | Alipay SDK Class |
|---|---|
create(Map) |
AlipayEbppInvoiceExpensecontrolIssuebatchCreateModel/Request/Response |
cancel(String) |
AlipayEbppInvoiceExpensecontrolIssuebatchCancelModel/Request/Response |
File: java/.../expense/quota/service/QuotaService.java
Python: backend/app/plugin/module_payment/expense/quota/service.py
Already has AlipayClientFactory injected.
| Method | Alipay SDK Class | Notes |
|---|---|---|
expenseModify(String, Map) |
AlipayEbppInvoiceExpensecontrolQuotaModifyModel/Request/Response |
action=ADD/DEDUCT/MODIFY_SHARE_MODE, need quota_id from local DB via out_biz_no |
expenseDelete(String) |
AlipayCommerceEcExpenseDeleteModel/Request/Response |
Simple delete by out_biz_no |
Files: IssueBatchService, RuleService, QuotaService, InstitutionService
CRITICAL (wrong data / SDK rejection):
| File | Method | Fix |
|------|--------|-----|
| IssueBatchService.create | target_id→owner_id, target_type→owner_type, quota_amount→issue_quota (3 wrong JSON keys) |
| IssueBatchService.create | Add effective_start_date / effective_end_date to model (Python required) |
| RuleService.modifyExpense | Add institution_id on model (Python required) |
| QuotaService.expenseModify | quota_id from data.get("quota_id"), outer_source_id from data.get("outer_source_id") — NOT from local DB / parameter |
SEVERE (logic mismatch):
| File | Method | Fix |
|------|--------|-----|
| InstitutionService.createFullFlow | Rollback: delete Alipay institution if scope/issuerule fails (Python re-raises) |
| InstitutionService.createFullFlow | Map standard_id_info_list from Alipay response instead of using input data |
| RuleService.modifyExpense | action from data.get("action") not hardcoded |
| IssueBatchService.create | Add issue_desc, owner_open_id, user_name optional fields |
MEDIUM (optional fields):
| File | Method | Fix |
|------|--------|-----|
| RuleService.createExpense | Add payment_policy, consume_mode, open_rule_id, rule_name conditionals |
| RuleService.modifyExpense | Add standard_desc, open_rule_id, payment_policy, consume_mode conditionals |
| InstitutionService.createFullFlow | Add currency to institution create model |
| QuotaService.expenseDelete | Raise BusinessException when not found (match Python), keep SDK gap note |
| QuotaService.expenseModify | Add null response guard, add error log before throw, handle share_mode empty string |
BusinessException on !response.isSuccess()mvn compile — all SDK classes from alipay-sdk-java-4.39.218.ALL.jar compiledata["field_name"] → Java model.setFieldName(...) verified against Python referenceremoveOwnerIdList (not delete), getOnwerOpenIdList() (typo)AlipayClientFactory injection