E-commerce checkout
Create a payment, redirect the customer to pay, receive a webhook when payment confirms, and redirect the customer to your order confirmation page.
Flow
Your server → POST /payments/requests → DropPay
Customer → Redirected to pay page
Customer → Pays with XRP wallet
DropPay → Redirects customer back to your redirect_url
DropPay → Sends payment.confirmed webhook to your server
Your server → Fulfills order
Step 1 - Create the payment at checkout
When the customer clicks "Pay with XRP", create a payment request server-side and redirect to pay_url.
import requests
from flask import Flask, redirect, session
app = Flask(__name__)
BASE = "https://droppayxrp.com"
API_KEY = "dp_live_your_api_key_here"
@app.route("/checkout", methods=["POST"])
def checkout():
order_id = session.get("pending_order_id")
amount = get_order_total(order_id) # your function
response = requests.post(
f"{BASE}/payments/requests",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"amount": amount,
"currency": "XRP",
"description": f"Order #{order_id}",
"order_id": order_id,
"redirect_url": "https://yourstore.com/payment-complete"
}
)
payment = response.json()
return redirect(BASE + payment["pay_url"])
import express from "express";
const BASE = "https://droppayxrp.com";
const API_KEY = "dp_live_your_api_key_here";
router.post("/checkout", async (req, res) => {
const { orderId } = req.session;
const amount = await getOrderTotal(orderId);
const response = await fetch(`${BASE}/payments/requests`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
amount,
currency: "XRP",
description: `Order #${orderId}`,
order_id: orderId,
redirect_url: "https://yourstore.com/payment-complete"
})
});
const payment = await response.json();
res.redirect(BASE + payment.pay_url);
});
Step 2 - Handle the customer return
After payment, DropPay redirects the customer to your redirect_url with:
https://yourstore.com/payment-complete?request_id=dp_xxxxxxxxxx&tx_hash=ABC123...&order_id=order_1234
Show the customer a "Thank you" page. Do not fulfill the order here.
Warning
Anyone can visit your redirect_url with arbitrary parameters. Never use the redirect to fulfill an order.
Step 3 - Fulfill from the webhook
When DropPay confirms the transaction on-chain, it sends payment.confirmed to your webhook endpoint.
import hmac, hashlib, time
from flask import request, abort
WEBHOOK_SECRET = "your_webhook_secret"
@app.route("/webhook/droppay", methods=["POST"])
def droppay_webhook():
timestamp = request.headers.get("X-DropPay-Timestamp", "")
signature = request.headers.get("X-DropPay-Signature", "")
body = request.get_data()
if abs(int(time.time()) - int(timestamp)) > 300:
abort(400)
expected = "sha256=" + hmac.new(
WEBHOOK_SECRET.encode(),
timestamp.encode() + b"." + body,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature):
abort(400)
event = request.json
if event["event"] == "payment.confirmed":
order_id = event["data"]["order_id"]
if not already_fulfilled(order_id):
fulfill_order(order_id)
return "", 200
import crypto from "crypto";
const WEBHOOK_SECRET = "your_webhook_secret";
router.post("/webhook/droppay",
express.raw({ type: "application/json" }),
async (req, res) => {
const timestamp = req.headers["x-droppay-timestamp"];
const signature = req.headers["x-droppay-signature"];
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
return res.status(400).end();
}
const expected = "sha256=" + crypto
.createHmac("sha256", WEBHOOK_SECRET)
.update(timestamp + "." + req.body)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
return res.status(400).end();
}
const event = JSON.parse(req.body);
if (event.event === "payment.confirmed") {
const { order_id } = event.data;
if (!await alreadyFulfilled(order_id)) {
await fulfillOrder(order_id);
}
}
res.status(200).end();
}
);
USD pricing
If your store prices products in USD, pass currency: "USD" and let DropPay handle the XRP conversion. The rate is locked when the customer opens the pay page.
The payment.confirmed webhook includes amount and currency showing what was requested, and xrp_usd_rate showing the rate at creation time.
Next steps
- Webhooks reference - full payload, signature verification, security checklist
- Pay-per-access - gate downloads or content behind a one-time payment
- API payments - accept programmatic payments per API call without a browser