Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions bruno/collections/Rafiki/POS Service APIs/Initiate Payment.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
meta {
name: Initiate Payment
type: http
seq: 3
}

post {
url: http://localhost:3008/payment
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
url: http://localhost:3008/payment
url: http://localhost:4008/payment

Let's do this, such that the incoming payment will be on the happy-life side of things, and cloud nine will pay into it.

body: json
auth: inherit
}

body:json {
{
"card": {
"walletAddress": "http://cloud-nine-wallet-backend/accounts/gfranklin",
"trasactionCounter": 1,
"expiry": "2025-09-13T13:00:00Z"
},
"signature": "signature",
"value": 1,
"merchantWalletAddress": "http://localhost:3000/accounts/gfranklin"
}
}
8 changes: 8 additions & 0 deletions localenv/cloud-nine-wallet/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ services:
LOG_LEVEL: debug
CARD_SERVICE_PORT: 3007
DATABASE_URL: postgresql://cloud_nine_wallet_card_service:cloud_nine_wallet_card_service@shared-database/cloud_nine_wallet_card_service
GRAPHQL_URL: http://cloud-nine-wallet-backend:3001/graphql
TENANT_ID: 438fa74a-fa7d-4317-9ced-dde32ece1787
TENANT_SECRET: tenant_secret
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TENANT_SECRET should match the API_SECRET from backend container

TENANT_SIGNATURE_VERSION: tenant_signature_version
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TENANT_SIGNATURE_VERSION: tenant_signature_version
TENANT_SIGNATURE_VERSION: 1

depends_on:
- shared-database
healthcheck:
Expand Down Expand Up @@ -55,6 +59,10 @@ services:
LOG_LEVEL: debug
PORT: 3008
DATABASE_URL: postgresql://cloud_nine_wallet_point_of_sale:cloud_nine_wallet_point_of_sale@shared-database/cloud_nine_wallet_point_of_sale
TENANT_ID: 438fa74a-fa7d-4317-9ced-dde32ece1787
TENANT_SECRET: secret
GRAPHQL_URL: http://cloud-nine-wallet-backend:3001/graphql
WEBHOOK_SIGNATURE_SECRET: webhook_secret
depends_on:
- shared-database
healthcheck:
Expand Down
8 changes: 8 additions & 0 deletions localenv/happy-life-bank/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ services:
LOG_LEVEL: debug
CARD_SERVICE_PORT: 4007
DATABASE_URL: postgresql://happy_life_bank_card_service:happy_life_bank_card_service@shared-database/happy_life_bank_card_service
GRAPHQL_URL: http://happy-life-bank-backend:3001/graphql
TENANT_ID: cf5fd7d3-1eb1-4041-8e43-ba45747e9e5d
TENANT_SECRET: tenant_secret
TENANT_SIGNATURE_VERSION: tenant_signature_version
depends_on:
- shared-database
- cloud-nine-wallet-card-service
Expand Down Expand Up @@ -56,6 +60,10 @@ services:
LOG_LEVEL: debug
PORT: 4008
DATABASE_URL: postgresql://happy_life_bank_point_of_sale:happy_life_bank_point_of_sale@shared-database/happy_life_bank_point_of_sale
TENANT_ID: cf5fd7d3-1eb1-4041-8e43-ba45747e9e5d
TENANT_SECRET: secret
GRAPHQL_URL: http://happy-life-bank-backend:3001/graphql
WEBHOOK_SIGNATURE_SECRET: webhook_secret
depends_on:
- shared-database
- cloud-nine-wallet-point-of-sale
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ export class App {
// For tests, we still need to get the tenant in the middleware, but
// we don't need to verify the signature nor prevent replay attacks
koa.use(
this.config.env !== 'test'
this.config.env !== 'test' && this.config.env !== 'development'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this so that I can bypass the tenant signature check for now while testing

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if the TENANT_SECRET matches the API_SECRET from above, then this validation should work without having to bypass it

? tenantSignatureMiddleware
: testTenantSignatureMiddleware
)
Expand Down
5 changes: 4 additions & 1 deletion packages/point-of-sale/src/payments/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ async function payment(
ctx: PaymentContext
): Promise<void> {
const body = ctx.request.body
const tenantId = ctx.request.header['tenant-id'] as string | undefined
try {
const walletAddress = await deps.paymentService.getWalletAddress(
body.card.walletAddress
Expand All @@ -73,7 +74,8 @@ async function payment(
}
const incomingPayment = await deps.paymentService.createIncomingPayment(
walletAddress.id,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be the UUID of the wallet address, not the actual address. Will add a request to fetch that.

incomingAmount
incomingAmount,
tenantId
)
const deferred = new Deferred<WebhookBody>()
webhookWaitMap.setWithExpiry(
Expand Down Expand Up @@ -101,6 +103,7 @@ async function payment(
ctx.body = result
ctx.status = 200
} catch (err) {
deps.logger.debug(err)
if (err instanceof IncomingPaymentEventTimeoutError)
webhookWaitMap.delete(err.incomingPaymentId)
const { body, status } = handlePaymentError(err)
Expand Down
31 changes: 21 additions & 10 deletions packages/point-of-sale/src/payments/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { IAppConfig } from '../config/app'
import { ApolloClient, NormalizedCacheObject } from '@apollo/client'
import {
AmountInput,
CreateIncomingPaymentInput,
IncomingPayment,
MutationCreateIncomingPaymentArgs,
type Mutation
} from '../graphql/generated/graphql'
import { FnWithDeps } from '../shared/types'
Expand Down Expand Up @@ -37,7 +37,8 @@ export type WalletAddress = OpenPaymentsWalletAddress & {
export type PaymentService = {
createIncomingPayment: (
walletAddressId: string,
incomingAmount: AmountInput
incomingAmount: AmountInput,
tenantId?: string
) => Promise<IncomingPayment>
getWalletAddress: (walletAddressUrl: string) => Promise<WalletAddress>
}
Expand Down Expand Up @@ -66,19 +67,28 @@ export function createPaymentService(
const createIncomingPayment: FnWithDeps<
ServiceDependencies,
PaymentService['createIncomingPayment']
> = async (deps, walletAddressId, incomingAmount) => {
> = async (deps, walletAddressId, incomingAmount, tenantId) => {
const client = deps.apolloClient
const { data } = await client.mutate<
Mutation['createIncomingPayment'],
CreateIncomingPaymentInput
MutationCreateIncomingPaymentArgs
>({
mutation: CREATE_INCOMING_PAYMENT,
variables: {
walletAddressId,
incomingAmount,
idempotencyKey: v4(),
isCardPayment: true
}
input: {
walletAddressId,
incomingAmount,
idempotencyKey: v4(),
isCardPayment: true
}
},
...(tenantId && {
context: {
headers: {
'tenant-id': tenantId
}
}
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are already passing in the tenantId when we are setting up the apolloClient (index.ts), so I think we can leave this out

})

const incomingPayment = data?.payment
Expand All @@ -101,7 +111,8 @@ async function getWalletAddress(
): Promise<WalletAddress> {
const config: AxiosRequestConfig = {
headers: {
'Content-Type': 'application/json'
Accept: 'application/json',
host: 'cloud-nine-wallet-backend'
}
}
const { data: walletAddress } = await deps.axios.get<
Expand Down