fix(payment): return paymentUrl from adapters, strip base64 from tool output
Alipay/WeChat adapters now return the source payment URL alongside the QR base64. The generate_payment tool only returns paymentUrl (short text) to Claude API — base64 qrCodeUrl is stripped to prevent AI from dumping raw data:image into text responses. Frontend QRCodeSVG renders from paymentUrl instead of base64. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6609e50100
commit
389f975e33
|
|
@ -553,6 +553,9 @@ export class ImmigrationToolsService {
|
|||
return { success: false, error: '生成支付失败,请稍后重试', orderId: order.id };
|
||||
}
|
||||
|
||||
// paymentUrl 是支付链接(短文本),前端用 QRCodeSVG 从它生成二维码
|
||||
// qrCodeUrl 是 base64 data URL(~数KB),绝不能传给 AI(会被塞进文本回复)
|
||||
// 只返回 paymentUrl,永远不返回 qrCodeUrl(base64)
|
||||
return {
|
||||
success: true,
|
||||
orderId: order.id,
|
||||
|
|
@ -560,10 +563,9 @@ export class ImmigrationToolsService {
|
|||
amount: payment.amount,
|
||||
currency: order.currency,
|
||||
paymentMethod: payment.method,
|
||||
qrCodeUrl: payment.qrCodeUrl,
|
||||
paymentUrl: payment.paymentUrl,
|
||||
expiresAt: payment.expiresAt,
|
||||
message: `请扫描二维码支付 ¥${payment.amount} 完成${category}类别的移民资格评估服务`,
|
||||
_ui_hint: '前端已自动渲染支付二维码,回复中不要包含任何链接、URL或二维码数据',
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { OrderEntity } from '../../../domain/entities/order.entity';
|
|||
|
||||
export interface AlipayPaymentResult {
|
||||
qrCodeUrl: string;
|
||||
paymentUrl: string;
|
||||
tradeNo: string;
|
||||
}
|
||||
|
||||
|
|
@ -49,6 +50,7 @@ export class AlipayAdapter {
|
|||
|
||||
return {
|
||||
qrCodeUrl: qrCodeDataUrl,
|
||||
paymentUrl: mockPaymentUrl,
|
||||
tradeNo: `ALIPAY_${Date.now()}`,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { OrderEntity } from '../../../domain/entities/order.entity';
|
|||
|
||||
export interface WechatPaymentResult {
|
||||
qrCodeUrl: string;
|
||||
paymentUrl: string;
|
||||
prepayId: string;
|
||||
}
|
||||
|
||||
|
|
@ -49,6 +50,7 @@ export class WechatPayAdapter {
|
|||
|
||||
return {
|
||||
qrCodeUrl: qrCodeDataUrl,
|
||||
paymentUrl: mockPaymentUrl,
|
||||
prepayId: `WECHAT_${Date.now()}`,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,11 +87,13 @@ export class PaymentService {
|
|||
case PaymentMethod.ALIPAY:
|
||||
const alipayResult = await this.alipayAdapter.createPayment(order);
|
||||
qrCodeUrl = alipayResult.qrCodeUrl;
|
||||
paymentUrl = alipayResult.paymentUrl;
|
||||
break;
|
||||
|
||||
case PaymentMethod.WECHAT:
|
||||
const wechatResult = await this.wechatPayAdapter.createPayment(order);
|
||||
qrCodeUrl = wechatResult.qrCodeUrl;
|
||||
paymentUrl = wechatResult.paymentUrl;
|
||||
break;
|
||||
|
||||
case PaymentMethod.CREDIT_CARD:
|
||||
|
|
|
|||
|
|
@ -220,19 +220,10 @@ function ToolCallResult({
|
|||
<div className="mt-3 p-4 bg-white rounded-lg border border-secondary-200">
|
||||
<p className="text-sm text-secondary-600 mb-3">{result.message}</p>
|
||||
<div className="flex flex-col items-center">
|
||||
{result.qrCodeUrl ? (
|
||||
{result.paymentUrl ? (
|
||||
<div className="p-3 bg-white rounded-lg border border-secondary-100">
|
||||
<QRCodeSVG value={result.qrCodeUrl} size={160} level="M" />
|
||||
<QRCodeSVG value={result.paymentUrl} size={160} level="M" />
|
||||
</div>
|
||||
) : result.paymentUrl ? (
|
||||
<a
|
||||
href={result.paymentUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors"
|
||||
>
|
||||
前往支付
|
||||
</a>
|
||||
) : null}
|
||||
<p className="mt-3 text-xl font-semibold text-primary-600">
|
||||
¥{result.amount}
|
||||
|
|
|
|||
Loading…
Reference in New Issue