| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859 |
- /**
- * 支付控制器:创建支付 / 查询状态 / 模拟成功(仅 mock)
- */
- const express = require('express');
- const config = require('../config');
- const { ok, fail } = require('../utils/response');
- const gateway = require('../services/pay_gateway.service');
- const orderService = require('../services/order.service');
- const router = express.Router();
- /**
- * 创建支付
- * POST /v1/payment/:channel/
- * body: { product_id, source?: 'app'|'web', currency?: 'usd'|'cny' }
- */
- router.post('/:channel/', async (req, res) => {
- try {
- const { channel } = req.params;
- const { product_id, source = 'app', currency } = req.body || {};
- const data = await gateway.createPayment({ channel, productId: product_id, source, currency });
- return ok(res, data);
- } catch (e) {
- const status = e.code === 'PRODUCT_NOT_FOUND' ? 404 : e.code === 'BAD_CHANNEL' ? 400 : 500;
- return fail(res, status, e.code || 'PAYMENT_CREATE_FAILED', e.message);
- }
- });
- /**
- * 查询支付状态(前端轮询/最终确认)
- * GET /v1/payment/:payment_id
- */
- router.get('/:payment_id', (req, res) => {
- return ok(res, orderService.getStatus(req.params.payment_id));
- });
- /**
- * 模拟支付结果(仅 MOCK_MODE):走与真实回调相同的 markPaid 幂等流程
- * POST /v1/payment/simulate/:result result: success|fail
- * body: { payment_id }
- */
- router.post('/simulate/:result', (req, res) => {
- if (!config.mock) {
- return fail(res, 403, 'MOCK_DISABLED', 'simulate only available in MOCK_MODE');
- }
- const { payment_id } = req.body || {};
- const result = req.params.result;
- if (!payment_id) return fail(res, 400, 'BAD_REQUEST', 'payment_id required');
- let changed = false;
- if (result === 'success') {
- changed = orderService.markPaid(payment_id, { channel: 'mock', channelTradeNo: `mock_${payment_id}` });
- } else {
- changed = Boolean(orderService.getOrder(payment_id));
- }
- return ok(res, { payment_id, simulated: changed, result });
- });
- module.exports = router;
|