diff --git a/crud.py b/crud.py index 4297f7a..b8ee099 100644 --- a/crud.py +++ b/crud.py @@ -1,5 +1,4 @@ import json -import time from typing import List, Optional from lnbits.helpers import urlsafe_short_hash @@ -9,7 +8,6 @@ from .models import ( Merchant, Order, PartialMerchant, - PartialOrder, PartialProduct, PartialStall, PartialZone, @@ -380,3 +378,28 @@ async def get_orders_for_stall(user_id: str, stall_id: str) -> List[Order]: ), ) return [Order.from_row(row) for row in rows] + + +async def update_order_paid_status(order_id: str, paid: bool) -> Optional[Order]: + await db.execute( + f"UPDATE nostrmarket.orders SET paid = ? WHERE id = ?", + (paid, order_id), + ) + row = await db.fetchone( + "SELECT * FROM nostrmarket.orders WHERE id = ?", + (order_id,), + ) + return Order.from_row(row) if row else None + + +async def update_order_shipped_status(order_id: str, shipped: bool) -> Optional[Order]: + await db.execute( + f"UPDATE nostrmarket.orders SET shipped = ? WHERE id = ?", + (order_id, shipped), + ) + + row = await db.fetchone( + "SELECT * FROM nostrmarket.orders WHERE id = ?", + (order_id,), + ) + return Order.from_row(row) if row else None diff --git a/models.py b/models.py index 3c1111f..f228ed5 100644 --- a/models.py +++ b/models.py @@ -343,6 +343,13 @@ class Order(PartialOrder): return order +class OrderStatusUpdate(BaseModel): + id: str + message: Optional[str] + paid: Optional[bool] + shipped: Optional[bool] + + class PaymentOption(BaseModel): type: str link: str diff --git a/tasks.py b/tasks.py index 69df5a3..f5afec3 100644 --- a/tasks.py +++ b/tasks.py @@ -16,9 +16,10 @@ from .crud import ( get_merchant_by_pubkey, get_public_keys_for_merchants, get_wallet_for_product, + update_order_paid_status, ) from .helpers import order_from_json -from .models import PartialOrder +from .models import OrderStatusUpdate, PartialOrder from .nostr.event import NostrEvent from .nostr.nostr_client import connect_to_nostrclient_ws, publish_nostr_event @@ -36,7 +37,33 @@ async def on_invoice_paid(payment: Payment) -> None: if payment.extra.get("tag") != "nostrmarket": return - print("### on_invoice_paid", json.dumps(payment)) + order_id = payment.extra.get("order_id") + merchant_pubkey = payment.extra.get("merchant_pubkey") + if not order_id or not merchant_pubkey: + return None + + await handle_order_paid(order_id, merchant_pubkey) + + + +async def handle_order_paid(order_id: str, merchant_pubkey: str): + try: + order = await update_order_paid_status(order_id, True) + assert order, f"Paid order cannot be found. Order id: {order_id}" + order_status = OrderStatusUpdate( + id=order_id, message="Payment received.", paid=True, shipped=order.shipped + ) + + merchant = await get_merchant_by_pubkey(merchant_pubkey) + assert merchant, f"Merchant cannot be foud for order {order_id}" + dm_content = json.dumps( + order_status.dict(), separators=(",", ":"), ensure_ascii=False + ) + + dm_event = merchant.build_dm_event(dm_content, order.pubkey) + await publish_nostr_event(dm_event) + except Exception as ex: + logger.warning(ex) async def subscribe_to_nostr_client(recieve_event_queue: Queue, send_req_queue: Queue): @@ -60,7 +87,6 @@ async def subscribe_to_nostr_client(recieve_event_queue: Queue, send_req_queue: # be sure the connection is open await asyncio.sleep(3) req = await send_req_queue.get() - print("### req", req) ws.send(json.dumps(req)) except Exception as ex: logger.warning(ex) @@ -100,9 +126,9 @@ async def handle_nip04_message(public_key: str, event: NostrEvent): assert merchant, f"Merchant not found for public key '{public_key}'" clear_text_msg = merchant.decrypt_message(event.content, event.pubkey) - dm_resp = await handle_dirrect_message(event.pubkey, event.id, clear_text_msg) - if dm_resp: - dm_event = merchant.build_dm_event(dm_resp, event.pubkey) + dm_content = await handle_dirrect_message(event.pubkey, event.id, clear_text_msg) + if dm_content: + dm_event = merchant.build_dm_event(dm_content, event.pubkey) await publish_nostr_event(dm_event) diff --git a/views_api.py b/views_api.py index 48935aa..32696e4 100644 --- a/views_api.py +++ b/views_api.py @@ -93,7 +93,7 @@ async def api_get_merchant( logger.warning(ex) raise HTTPException( status_code=HTTPStatus.INTERNAL_SERVER_ERROR, - detail="Cannot create merchant", + detail="Cannot get merchant", ) @@ -108,7 +108,7 @@ async def api_get_zones(wallet: WalletTypeInfo = Depends(get_key_type)) -> List[ logger.warning(ex) raise HTTPException( status_code=HTTPStatus.INTERNAL_SERVER_ERROR, - detail="Cannot create merchant", + detail="Cannot get zone", ) @@ -123,7 +123,7 @@ async def api_create_zone( logger.warning(ex) raise HTTPException( status_code=HTTPStatus.INTERNAL_SERVER_ERROR, - detail="Cannot create merchant", + detail="Cannot create zone", ) @@ -149,7 +149,7 @@ async def api_update_zone( logger.warning(ex) raise HTTPException( status_code=HTTPStatus.INTERNAL_SERVER_ERROR, - detail="Cannot create merchant", + detail="Cannot update zone", ) @@ -170,7 +170,7 @@ async def api_delete_zone(zone_id, wallet: WalletTypeInfo = Depends(require_admi logger.warning(ex) raise HTTPException( status_code=HTTPStatus.INTERNAL_SERVER_ERROR, - detail="Cannot create merchant", + detail="Cannot delete zone", ) @@ -463,6 +463,9 @@ async def api_create_order( ): return None + merchant = await get_merchant_for_user(wallet.wallet.user) + assert merchant, "Cannot find merchant!" + products = await get_products_by_ids( wallet.wallet.user, [p.product_id for p in data.items] ) @@ -480,6 +483,7 @@ async def api_create_order( extra={ "tag": "nostrmarket", "order_id": data.id, + "merchant_pubkey": merchant.public_key, }, ) @@ -538,6 +542,26 @@ async def api_get_orders(wallet: WalletTypeInfo = Depends(get_key_type)): ) +# @nostrmarket_ext.patch("/api/v1/order/{order_id}") +# async def api_update_order( +# data: OrderStatusUpdate, +# wallet: WalletTypeInfo = Depends(require_admin_key), +# ) -> Zone: +# try: + +# zone = await update_order(wallet.wallet.user, data) +# assert zone, "Cannot find updated zone" +# return zone +# except HTTPException as ex: +# raise ex +# except Exception as ex: +# logger.warning(ex) +# raise HTTPException( +# status_code=HTTPStatus.INTERNAL_SERVER_ERROR, +# detail="Cannot update order", +# ) + + ######################################## OTHER ########################################