File size: 2,373 Bytes
45a105b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
de6cac5
 
 
 
 
 
 
 
 
45a105b
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import { apiRequest } from './client'
import type { PaymentView, ProvidersResponse } from '../types'

export interface CreatePaymentInput {
  userId: string
  amountMinor: number
  merchantId: string
  payeeIban: string
  country?: string
  currency?: string
  description?: string
  idempotencyKey: string // preserved across retries of the SAME user action
}

export async function createPayment(input: CreatePaymentInput): Promise<PaymentView> {
  return apiRequest<PaymentView>('/payments', {
    headers: { 'Idempotency-Key': input.idempotencyKey },
    body: {
      user_id: input.userId,
      amount_minor: input.amountMinor,
      merchant_id: input.merchantId,
      payee_iban: input.payeeIban,
      country: input.country,
      currency: input.currency,
      description: input.description ?? '',
      consent: { granted: true, purpose: 'payment initiation' },
    },
  })
}

export async function getPayment(paymentId: string): Promise<PaymentView> {
  // Authoritative status comes from the backend (which relies on signed webhooks).
  return apiRequest<PaymentView>(`/payments/${encodeURIComponent(paymentId)}`)
}

export async function cancelPayment(paymentId: string): Promise<PaymentView> {
  return apiRequest<PaymentView>(`/payments/${encodeURIComponent(paymentId)}/cancel`, { method: 'POST', body: {} })
}

/** Refund via the real Payment Core refund API (amount in minor units / halalas).
 *  Omit amountMinor for a full refund of the remaining balance. */
export async function refundPayment(paymentId: string, amountMinor?: number, reason?: string): Promise<PaymentView> {
  const body: Record<string, unknown> = {}
  if (amountMinor !== undefined) body.amount_minor = amountMinor
  if (reason) body.reason = reason
  return apiRequest<PaymentView>(`/payments/${encodeURIComponent(paymentId)}/refund`, { method: 'POST', body })
}

export async function getProviders(): Promise<ProvidersResponse> {
  return apiRequest<ProvidersResponse>('/payments/providers')
}

/** DEV/mock only: ask the backend to simulate the provider advancing this payment
 *  (server-side signed webhook). Rejected by the backend for real providers. */
export async function mockAdvance(paymentId: string, rawStatus: string): Promise<unknown> {
  return apiRequest(`/payments/${encodeURIComponent(paymentId)}/mock-advance`, {
    body: { raw_status: rawStatus },
  })
}