;; lib/commerce/payment.sx — provider-neutral payment-request envelope. ;; ;; The order flow (order.sx) suspends on `(request 'payment oid)` — it carries ;; ONLY the order-id and calls no provider. This layer materialises, at the IO ;; edge, the envelope a provider adapter needs to initiate payment: ;; ;; {:order oid :amount :currency C :return-url U} ;; ;; amount comes from the ledger (the :created quote total); currency + return-url ;; are host/provider config (legitimately host-supplied). The engine stays ;; vendor-agnostic: SumUp/Stripe/etc. adapters consume this envelope, and ;; order-settle!(ref, amount) is the vendor-neutral resume seam. No provider ;; SDK, HTTP, or webhook parsing lives here — that is the orders service's job. (define payment-request (fn (b oid currency return-url) {:order oid :amount (order-total b oid) :return-url return-url :currency currency})) (define payment-request-order (fn (pr) (get pr :order))) (define payment-request-amount (fn (pr) (get pr :amount))) (define payment-request-currency (fn (pr) (get pr :currency))) (define payment-request-return-url (fn (pr) (get pr :return-url))) ;; A Scheme string carried as a flow payload round-trips back to SX wrapped as ;; {:scm-string "..."}; unwrap it to the bare order-id. (define scm->string (fn (v) (if (and (dict? v) (has-key? v :scm-string)) (get v :scm-string) v))) ;; Host poller seam: every order currently suspended awaiting payment, each with ;; its envelope. A provider adapter iterates these, initiates payment, and later ;; calls order-settle! when the webhook arrives. Needs the flow env. (define pending-payments (fn (env b currency return-url) (let ((reqs (flow-run-in env "(flow-host-requests)"))) (map (fn (r) {:id (first r) :request (payment-request b (scm->string (nth r 2)) currency return-url)}) (filter (fn (r) (= (nth r 1) "payment")) reqs)))))