Files
pangolin/client/test/unit/payment_api_test.dart

74 lines
2.9 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:http/http.dart' as http;
import 'package:http/testing.dart';
import 'package:pangolin_vpn/services/api_client.dart';
import 'package:pangolin_vpn/services/auth_api.dart';
import 'package:pangolin_vpn/services/payment_api.dart';
ApiClient _client(MockClient mock) => ApiClient(
baseUrl: 'http://x',
getToken: () => 'tok1',
refresh: () async => false,
client: mock,
);
void main() {
test('catalog 解析三档', () async {
final api = PaymentApi(_client(MockClient((req) async {
expect(req.url.path, '/v1/pay/catalog');
return http.Response(
'{"items":[{"sku":"pro_month","plan":"pro","days":31,"price_minor":2999,"currency":"CNY"},'
'{"sku":"pro_quarter","plan":"pro","days":92,"price_minor":6888,"currency":"CNY"},'
'{"sku":"pro_year","plan":"pro","days":366,"price_minor":19999,"currency":"CNY"}]}',
200);
})));
final items = await api.catalog();
expect(items.length, 3);
expect(items.first.sku, 'pro_month');
expect(items.first.priceLabel(), '¥29.99');
});
test('createOrder 只传 sku+method+metadata,解析 session', () async {
final api = PaymentApi(_client(MockClient((req) async {
expect(req.url.path, '/v1/pay/orders');
expect(req.body.contains('"amount'), isFalse, reason: '客户端绝不传金额');
return http.Response(
'{"order_no":"pay1","session":{"render_type":"crypto_address",'
'"payload":{"address":"Txx","amount":"4.201234","amount_minor":4201234,'
'"currency":"USDT","network":"TRC20"},"expires_at":"2026-07-10T12:00:00Z"}}',
200);
})));
final order = await api.createOrder(sku: 'pro_month', method: 'crypto');
expect(order.orderNo, 'pay1');
expect(order.session.renderType, 'crypto_address');
expect(order.session.payload['address'], 'Txx');
expect(order.session.expiresAt, isNotNull);
});
test('orderStatus 解析 activated/expires_at', () async {
final api = PaymentApi(_client(MockClient((req) async => http.Response(
'{"order_no":"pay1","pay_status":"succeeded","activated":true,'
'"expires_at":"2026-08-10T12:00:00Z"}',
200))));
final st = await api.orderStatus('pay1');
expect(st.activated, isTrue);
expect(st.payStatus, 'succeeded');
expect(st.expiresAt, isNotNull);
});
test('retry 409 CURRENCY_MISMATCH 抛带 code 的异常', () async {
final api = PaymentApi(_client(MockClient((req) async => http.Response(
'{"code":"CURRENCY_MISMATCH","message_zh":"该支付方式结算币种与订单不符,请重新下单",'
'"message_en":"mismatch"}',
409,
headers: {'content-type': 'application/json; charset=utf-8'}))));
try {
await api.retry('pay1', method: 'alipay');
fail('应抛异常');
} on AuthApiException catch (e) {
expect(e.statusCode, 409);
expect(e.code, 'CURRENCY_MISMATCH');
}
});
}