Accept cryptocurrency payments on your website or application. Create hosted crypto checkout sessions, monitor transaction state, and receive signed merchant webhook notifications — all through a simple REST API.
📋 Table of Contents
The GrineoPay API allows you to programmatically create cryptocurrency payment sessions for your customers. Each payment generates a unique hosted checkout URL where your customer can complete their payment using the cryptocurrency and network of your choice.
To use the API, you need an active GrineoPay merchant account with at least one payout wallet configured for the asset/network combinations you want to accept. API credentials (Key and Secret) can be generated from your Merchant Dashboard → API Credentials tab.
Log in to your Merchant Dashboard and generate your Live or Sandbox API Key and Secret pair.
Send a POST request to /payments/create with the fiat amount, fiat currency, and desired crypto asset/network. You will receive a hosted checkout URL in the response.
Redirect your customer to the returned payment_url. GrineoPay will handle the hosted crypto checkout flow and send you merchant webhook notifications on status changes.
Public merchant API requests require authentication using your API Key and API Secret. These are passed as custom HTTP headers with every server-to-server request.
X-Api-KeyX-Api-SecretYour API Secret is shown only once when generated. Store it securely and never expose it in client-side JavaScript, mobile apps, or public repositories. If compromised, regenerate your keys immediately from the Merchant Dashboard.
# Example: Fetch your active wallet-backed payment options
curl -X GET "https://app.grineopay.com/api/grineopay/v1/merchant/wallets/active" \
-H "X-Api-Key: gp_live_your_api_key_here" \
-H "X-Api-Secret: gp_secret_your_api_secret_here"
GrineoPay issues separate credentials for Live and Sandbox environments. The environment is determined automatically by the API key you use — you do not pass an environment field in public server-to-server requests.
| Environment | API Key Prefix | API Secret Prefix | Behaviour |
|---|---|---|---|
| Live | gp_live_ |
gp_secret_ |
Creates real crypto payment sessions using the live provider flow. |
| Sandbox | gp_test_ |
gp_test_secret_ |
Creates simulated crypto payment sessions with fake deposit addresses for testing. |
For hosted GrineoPay merchant integrations, use the GrineoPay production API base below:
https://app.grineopay.com/api/grineopay/v1
Example health check URL:
https://app.grineopay.com/api/grineopay/v1/health
This documentation assumes you are integrating with the hosted GrineoPay platform API. If you operate a self-hosted GrineoPay-connected instance, your actual API base may differ.
GrineoPay supports the following cryptocurrencies and blockchain networks. When creating a payment, you specify both the crypto_currency and, where applicable, the crypto_network.
| Symbol | Name | Supported Networks |
|---|---|---|
| BTC | Bitcoin | BTC |
| ETH | Ethereum | ETH |
| SOL | Solana | SOL |
| USDT | Tether | TRX, ETH, POLYGON, BSC |
| USDC | USD Coin | POLYGON, ETH, BSC, ARB, OP, SOL |
| LTC | Litecoin | LTC |
| XMR | Monero | XMR |
| BNB | Binance Coin | BNB |
| XRP | Ripple | XRP |
| DOGE | Dogecoin | DOGE |
| ADA | Cardano | ADA |
| TRX | Tron | TRX |
The payment amount you send to GrineoPay is denominated in fiat. GrineoPay calculates the exact crypto amount required at the moment the payment session is created.
| Code | Currency | Code | Currency | Code | Currency |
|---|---|---|---|---|---|
| USD | U.S. Dollar | EUR | Euro | GBP | Pound Sterling |
| CAD | Canadian Dollar | AUD | Australian Dollar | JPY | Japanese Yen |
| CNY | Chinese Renminbi | CHF | Swiss Franc | HKD | Hong Kong Dollar |
| SGD | Singapore Dollar | INR | Indian Rupee | KRW | South Korean Won |
| NGN | Nigerian Naira | ZAR | South African Rand | AED | UAE Dirham |
Not all GrineoPay endpoints are intended for the same use case. The table below distinguishes public merchant API endpoints from authenticated dashboard/session endpoints.
| Endpoint | Method | Auth Type | Use Case |
|---|---|---|---|
/payments/create |
POST | API Key + Secret | Public merchant integration endpoint for creating payment sessions. |
/merchant/wallets/active |
GET | API Key + Secret | Public merchant integration endpoint for checking wallet-backed asset availability. |
/health |
GET | Public | Public health and environment check. |
/merchant/transactions |
GET | Logged-in Session | Merchant Dashboard/internal browser endpoint. |
/wallets/validate |
POST | Logged-in Session | Merchant Dashboard/internal wallet validation endpoint. |
/webhooks/provider |
POST | Provider → GrineoPay | Internal provider callback endpoint, not for merchant integrations. |
For external merchant integrations, the core public endpoints are /payments/create and /merchant/wallets/active. Endpoints like /merchant/transactions and /wallets/validate are intended for dashboard/session-authenticated use inside the GrineoPay merchant environment.
If you want to test the GrineoPay API quickly from your terminal, the following cURL examples cover the most common merchant integration flows.
# 1) Check API health
curl -X GET "https://app.grineopay.com/api/grineopay/v1/health"
# 2) Check active wallet-backed assets
curl -X GET "https://app.grineopay.com/api/grineopay/v1/merchant/wallets/active" \
-H "X-Api-Key: gp_live_your_api_key" \
-H "X-Api-Secret: gp_secret_your_api_secret"
# 3) Create a payment session
curl -X POST "https://app.grineopay.com/api/grineopay/v1/payments/create" \
-H "Content-Type: application/json" \
-H "X-Api-Key: gp_live_your_api_key" \
-H "X-Api-Secret: gp_secret_your_api_secret" \
-d '{
"amount": 49.99,
"currency": "USD",
"crypto_currency": "BTC",
"order_id": "ORD-2024-00123",
"email": "[email protected]",
"return_url": "https://shop.com/thank-you",
"source": "api",
"domain": "shop.com",
"order_context": "checkout"
}'
Create a new cryptocurrency payment session. This endpoint converts your fiat amount into the equivalent crypto amount at the current rate, validates the merchant’s payout wallet configuration, generates a deposit address, and returns a hosted checkout URL for the customer.
| Parameter | Type | Required | Description |
|---|---|---|---|
amount |
number | Required | The fiat amount to charge (example: 29.99). Must be greater than zero. |
currency |
string | Required | Fiat currency code such as USD or EUR. |
crypto_currency |
string | Required | The cryptocurrency to accept, such as BTC, ETH, or USDT. |
crypto_network |
string | Optional | The blockchain network, such as TRX for USDT on Tron. If omitted, the default/native network is used where applicable. |
order_id |
string | Required | Your unique order or reference identifier, for example ORD-2024-00123. |
email |
string | Optional | Customer email address. Used for recovery reminders and customer-facing flows if supported. |
return_url |
string | Optional | URL to redirect the customer after payment completion. |
webhook_url |
string | Optional | Merchant webhook override URL for this specific transaction. |
refund_address |
string | Optional | Customer refund wallet address if you want refund routing defined upfront. |
refund_extra_id |
string | Optional | Extra memo/tag for refund destinations on chains that require it. |
source |
string | Optional | Source identifier for analytics, such as woocommerce or api. |
domain |
string | Optional | The originating domain, for example shop.com. |
order_context |
string | Optional | Context label, such as woocommerce, donation, or dashboard. |
You must have at least one active payout wallet configured for the requested crypto_currency and crypto_network combination in your Merchant Dashboard. Payment creation will fail if no matching wallet-backed payout route exists.
curl -X POST "https://app.grineopay.com/api/grineopay/v1/payments/create" \
-H "Content-Type: application/json" \
-H "X-Api-Key: gp_live_your_api_key" \
-H "X-Api-Secret: gp_secret_your_api_secret" \
-d '{
"amount": 49.99,
"currency": "USD",
"crypto_currency": "BTC",
"order_id": "ORD-2024-00123",
"email": "[email protected]",
"return_url": "https://shop.com/thank-you",
"source": "woocommerce",
"domain": "shop.com",
"order_context": "woocommerce"
}'
<?php
$payload = [
'amount' => 49.99,
'currency' => 'USD',
'crypto_currency' => 'BTC',
'order_id' => 'ORD-2024-00123',
'email' => '[email protected]',
'return_url' => 'https://shop.com/thank-you',
'source' => 'woocommerce',
'domain' => 'shop.com',
'order_context' => 'woocommerce',
];
$ch = curl_init('https://app.grineopay.com/api/grineopay/v1/payments/create');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'X-Api-Key: gp_live_your_api_key',
'X-Api-Secret: gp_secret_your_api_secret',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);
if ($http_code === 200 && !empty($data['success'])) {
header('Location: ' . $data['payment_url']);
exit;
} else {
error_log('Payment creation failed: ' . ($data['message'] ?? 'Unknown error'));
}
const response = await fetch('https://app.grineopay.com/api/grineopay/v1/payments/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': 'gp_live_your_api_key',
'X-Api-Secret': 'gp_secret_your_api_secret'
},
body: JSON.stringify({
amount: 49.99,
currency: 'USD',
crypto_currency: 'BTC',
order_id: 'ORD-2024-00123',
email: '[email protected]',
return_url: 'https://shop.com/thank-you',
source: 'woocommerce',
domain: 'shop.com',
order_context: 'woocommerce'
})
});
const data = await response.json();
if (data.success) {
window.location.href = data.payment_url;
} else {
console.error('Payment failed:', data.message);
}
import requests
url = "https://app.grineopay.com/api/grineopay/v1/payments/create"
headers = {
"Content-Type": "application/json",
"X-Api-Key": "gp_live_your_api_key",
"X-Api-Secret": "gp_secret_your_api_secret",
}
payload = {
"amount": 49.99,
"currency": "USD",
"crypto_currency": "BTC",
"order_id": "ORD-2024-00123",
"email": "[email protected]",
"return_url": "https://shop.com/thank-you",
"source": "woocommerce",
"domain": "shop.com",
"order_context": "woocommerce",
}
response = requests.post(url, headers=headers, json=payload)
data = response.json()
if data.get("success"):
print(f"Redirect to: {data['payment_url']}")
else:
print(f"Error: {data.get('message', 'Unknown error')}")
const axios = require('axios');
async function createPayment() {
try {
const { data } = await axios.post(
'https://app.grineopay.com/api/grineopay/v1/payments/create',
{
amount: 49.99,
currency: 'USD',
crypto_currency: 'BTC',
order_id: 'ORD-2024-00123',
email: '[email protected]',
return_url: 'https://shop.com/thank-you',
source: 'woocommerce',
domain: 'shop.com',
order_context: 'woocommerce'
},
{
headers: {
'Content-Type': 'application/json',
'X-Api-Key': 'gp_live_your_api_key',
'X-Api-Secret': 'gp_secret_your_api_secret'
}
}
);
if (data.success) {
console.log('Checkout URL:', data.payment_url);
return data;
} else {
console.error('Error:', data.message);
}
} catch (error) {
console.error('Request failed:', error.message);
}
}
createPayment();
{
"success": true,
"transaction_id": 1042,
"provider_id": "a1b2c3d4e5f6g7h8",
"payment_url": "https://grineopay.com/?grineopay_crypto_checkout=1&tx_id=1042&token=abc123...",
"deposit_address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"payin_extra_id": "",
"crypto_amount": 0.00081234,
"crypto_currency": "BTC",
"crypto_network": "BTC",
"environment": "live"
}
Retrieve the list of active wallet-backed payout configurations currently available for the API credentials you are using. This is the correct public way to determine which crypto/network combinations are actually available for checkout.
curl -X GET "https://app.grineopay.com/api/grineopay/v1/merchant/wallets/active" \
-H "X-Api-Key: gp_live_your_api_key" \
-H "X-Api-Secret: gp_secret_your_api_secret"
{
"success": true,
"wallets": [
{
"currency": "BTC",
"network": "BTC",
"is_active": true
},
{
"currency": "USDT",
"network": "TRX",
"is_active": true
},
{
"currency": "ETH",
"network": "ETH",
"is_active": true
}
]
}
The following endpoints exist in the GrineoPay merchant environment but are primarily intended for authenticated Merchant Dashboard use rather than external server-to-server integrations.
Returns the authenticated merchant’s transaction list. Supports pagination and filtering by status/environment. This endpoint is intended for use inside the Merchant Dashboard session context.
# Example only — requires a valid authenticated session cookie
curl -X GET "https://app.grineopay.com/api/grineopay/v1/merchant/transactions?limit=20&offset=0&status=completed&environment=live" \
-H "Cookie: wordpress_logged_in_your_session_cookie_here"
Validates a wallet address for a given currency/network combination. This endpoint is primarily used inside the merchant environment and dashboard flows.
| Parameter | Type | Required | Description |
|---|---|---|---|
currency | string | Required | Cryptocurrency symbol (for example BTC). |
network | string | Optional | Blockchain network (for example TRX). |
address | string | Required | The wallet address to validate. |
# Example only — requires a valid authenticated session cookie
curl -X POST "https://app.grineopay.com/api/grineopay/v1/wallets/validate" \
-H "Content-Type: application/json" \
-H "Cookie: wordpress_logged_in_your_session_cookie_here" \
-d '{
"currency": "BTC",
"network": "BTC",
"address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
}'
{
"success": true,
"result": true,
"message": "Address is valid",
"isActivated": null
}
External merchant applications should rely primarily on the public API endpoints and on signed merchant webhook notifications for state changes, rather than trying to use session-based dashboard endpoints.
Verify that the GrineoPay API is operational and inspect general environment configuration. This endpoint is public and does not require authentication.
curl -X GET "https://app.grineopay.com/api/grineopay/v1/health"
{
"success": true,
"plugin": "GrineoPay Crypto Admin",
"version": "current-deployment-version",
"configured": true,
"environment": "live",
"api_alias": "https://app.grineopay.com/api/grineopay/v1/health",
"rest_url": "https://app.grineopay.com/wp-json/grineopay/v1/health"
}
GrineoPay sends real-time HTTP POST notifications to your configured merchant webhook URL whenever a transaction’s state changes. These webhook deliveries are sent from GrineoPay to your system after the platform updates its internal transaction status.
GrineoPay also receives internal provider callbacks on a separate provider webhook endpoint inside the platform. That provider webhook is not part of the merchant integration surface. The webhook documented below is the merchant-facing webhook GrineoPay sends to your system.
Set your merchant webhook URL in the Merchant Dashboard → Webhooks tab. You can also override the merchant webhook destination per transaction by passing the webhook_url parameter when creating a payment.
Every merchant webhook notification includes a cryptographic signature in the X-GrineoPay-Signature header. The signature is an HMAC-SHA256 hash of the raw JSON request body, signed using your merchant webhook signing secret.
Always verify the merchant webhook signature before processing the payload. Failing to do so may allow spoofed webhook deliveries to trigger false order fulfilment.
{
"event": "crypto_payment.updated",
"transaction_id": 1042,
"order_id": "ORD-2024-00123",
"status": "completed",
"fiat_amount": 49.99,
"fiat_currency": "USD",
"crypto_amount": 0.00081234,
"crypto_currency": "BTC",
"crypto_network": "BTC",
"deposit_address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"tx_hash_in": "a1b2c3d4e5f6...",
"tx_hash_out": "f6e5d4c3b2a1...",
"provider_id": "a1b2c3d4e5f6g7h8",
"timestamp": "2024-07-15 14:45:22"
}
You can simulate delivery of a webhook payload to your own webhook endpoint using cURL. This is useful when testing your webhook handler logic locally or in staging.
# Replace the JSON body and signature with values generated using your webhook secret
curl -X POST "https://yourdomain.com/webhooks/grineopay" \
-H "Content-Type: application/json" \
-H "X-GrineoPay-Signature: your_generated_hmac_signature_here" \
-d '{
"event": "crypto_payment.updated",
"transaction_id": 1042,
"order_id": "ORD-2024-00123",
"status": "completed",
"fiat_amount": 49.99,
"fiat_currency": "USD",
"crypto_amount": 0.00081234,
"crypto_currency": "BTC",
"crypto_network": "BTC",
"deposit_address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"tx_hash_in": "a1b2c3d4e5f6...",
"tx_hash_out": "f6e5d4c3b2a1...",
"provider_id": "a1b2c3d4e5f6g7h8",
"timestamp": "2024-07-15 14:45:22"
}'
| Field | Type | Description |
|---|---|---|
event | string | Event type. Currently crypto_payment.updated. |
transaction_id | integer | GrineoPay transaction ID returned during payment creation. |
order_id | string | Your original order/reference identifier. |
status | string | New transaction status. See status values below. |
fiat_amount | float | Original fiat amount charged. |
fiat_currency | string | Original fiat currency code. |
crypto_amount | float | Crypto amount expected/processed for the transaction. |
crypto_currency | string | Cryptocurrency symbol. |
crypto_network | string | Blockchain network used for this transaction. |
deposit_address | string | The deposit address used for the customer payment. |
tx_hash_in | string | Incoming blockchain transaction hash when available. |
tx_hash_out | string | Outgoing blockchain transaction hash when available. |
provider_id | string | Provider/external payment identifier associated with the GrineoPay transaction. |
timestamp | string | Webhook dispatch timestamp from the GrineoPay platform. |
| Status | Description | Recommended Merchant Action |
|---|---|---|
| pending | Payment session created. Waiting for the customer to send the required crypto amount. | Mark order as awaiting payment. |
| processing | Customer payment detected. GrineoPay/provider is confirming and processing the blockchain/payment flow. | Mark order as payment processing. |
| completed | Payment confirmed and payout flow completed. | Fulfil the order ✅ |
| failed | Payment could not be completed. | Mark order as failed or cancelled. |
| refunded | The transaction has been marked refunded by the system/provider. | Cancel the order and notify the customer if applicable. |
<?php
$webhook_secret = 'whsec_your_signing_secret';
$raw_body = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_GRINEOPAY_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', $raw_body, $webhook_secret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
$payload = json_decode($raw_body, true);
if ($payload['status'] === 'completed') {
$order_id = $payload['order_id'];
// Fulfil the order...
}
http_response_code(200);
echo 'OK';
const crypto = require('crypto');
const express = require('express');
const app = express();
app.use(express.json({
verify: (req, res, buf) => { req.rawBody = buf; }
}));
const WEBHOOK_SECRET = 'whsec_your_signing_secret';
app.post('/webhooks/grineopay', (req, res) => {
const signature = req.header('X-GrineoPay-Signature') || '';
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(req.rawBody)
.digest('hex');
if (signature !== expected) {
return res.status(401).send('Invalid signature');
}
const payload = req.body;
if (payload.status === 'completed') {
const orderId = payload.order_id;
// Fulfil the order...
}
res.status(200).send('OK');
});
app.listen(3000);
from flask import Flask, request, jsonify
import hmac
import hashlib
app = Flask(__name__)
WEBHOOK_SECRET = "whsec_your_signing_secret"
@app.route("/webhooks/grineopay", methods=["POST"])
def handle_webhook():
raw_body = request.get_data()
signature = request.headers.get("X-GrineoPay-Signature", "")
expected = hmac.new(
WEBHOOK_SECRET.encode(),
raw_body,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature):
return jsonify({"error": "Invalid signature"}), 401
payload = request.get_json()
if payload.get("status") == "completed":
order_id = payload.get("order_id")
# Fulfil the order...
return jsonify({"status": "ok"}), 200
if __name__ == "__main__":
app.run(port=5000)
Your merchant webhook endpoint should respond with 200 OK quickly after verifying and accepting the payload. If you need to run slower follow-up tasks, queue them asynchronously after responding.
Merchant webhooks may be delivered more than once. Design your webhook handler to be idempotent so processing the same transaction_id + status combination repeatedly produces the same final result.
The GrineoPay checkout flow is straightforward and merchant-friendly.
Your application collects the customer order and the merchant-selected crypto payment option.
Your server calls /payments/create using your GrineoPay API credentials.
You send the customer to the returned payment_url.
The customer pays from their wallet using the deposit address and exact amount shown on the hosted checkout page.
GrineoPay receives provider updates, confirms the transaction internally, and updates the transaction state.
GrineoPay dispatches a signed merchant webhook to your system whenever the transaction state changes.
Once you receive and verify a completed merchant webhook, you can safely fulfil the order.
The hosted checkout page may poll GrineoPay transaction state to improve customer-facing UX, but merchants should always rely on signed merchant webhook notifications as their fulfilment trigger — not browser polling.
GrineoPay uses standard HTTP status codes. Error responses typically include a success field set to false and a message field describing the issue.
| HTTP Status | Meaning | When It Occurs |
|---|---|---|
| 200 | OK | Request successful. |
| 400 | Bad Request | Missing required fields, invalid parameters, amount below minimum, or no matching payout wallet. |
| 401 | Unauthorized | Missing, invalid, or mismatched API credentials. |
| 403 | Forbidden | Authenticated but not permitted to access the resource or feature. |
| 404 | Not Found | The requested resource was not found. |
| 500 | Server Error | An unexpected server-side error occurred. |
| Error Message | Likely Cause | Recommended Resolution |
|---|---|---|
Missing crypto API credentials. |
Required auth headers not sent. | Send both X-Api-Key and X-Api-Secret. |
Invalid crypto API key. |
API key not found or wrong environment. | Verify you are using the correct live or sandbox credential pair. |
Invalid crypto API secret. |
API secret does not match the key. | Regenerate credentials if needed and update your integration. |
Missing required payment creation fields. |
Required request parameters missing. | Provide at least amount, currency, crypto_currency, and order_id. |
No matching crypto payout wallet is configured for this merchant. |
No wallet-backed payout route exists for the selected crypto/network. | Add an active matching wallet in the Merchant Dashboard. |
Unable to calculate crypto amount for checkout. |
Rate lookup or conversion issue. | Retry after a short delay. |
Merchant payout wallet validation failed. |
The stored wallet address failed validation for the selected chain. | Update the merchant payout wallet to a valid address. |
Amount is below provider minimum for this crypto/network. |
The calculated crypto amount is below the provider minimum. | Increase the fiat amount or choose a different asset/network. |
For temporary failures such as timeouts or server-side issues, use exponential backoff.
# Recommended retry strategy
attempt 1: wait 0 seconds
attempt 2: wait 2 seconds
attempt 3: wait 4 seconds
attempt 4: wait 8 seconds
attempt 5: wait 16 seconds
# Stop after a sensible retry limit and log the failure
<?php
class GrineoPay_Client {
private $api_key;
private $api_secret;
private $base_url;
public function __construct($api_key, $api_secret, $base_url) {
$this->api_key = $api_key;
$this->api_secret = $api_secret;
$this->base_url = rtrim($base_url, '/');
}
public function createPayment(array $params) {
$ch = curl_init($this->base_url . '/payments/create');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'X-Api-Key: ' . $this->api_key,
'X-Api-Secret: ' . $this->api_secret,
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return [
'status' => $http_code,
'data' => json_decode($response, true),
];
}
public function verifyMerchantWebhookSignature($raw_body, $signature, $webhook_secret) {
$expected = hash_hmac('sha256', $raw_body, $webhook_secret);
return hash_equals($expected, $signature);
}
}
$client = new GrineoPay_Client(
'gp_live_your_api_key',
'gp_secret_your_api_secret',
'https://app.grineopay.com/api/grineopay/v1'
);
$result = $client->createPayment([
'amount' => 99.50,
'currency' => 'USD',
'crypto_currency' => 'USDT',
'crypto_network' => 'TRX',
'order_id' => 'SHOP-' . uniqid(),
'email' => '[email protected]',
'return_url' => 'https://shop.com/success',
'source' => 'woocommerce',
'domain' => 'shop.com',
'order_context' => 'woocommerce',
]);
if ($result['status'] === 200 && !empty($result['data']['success'])) {
// Store the transaction_id in your system
header('Location: ' . $result['data']['payment_url']);
exit;
}
// Merchant webhook handler example:
$raw_body = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_GRINEOPAY_SIGNATURE'] ?? '';
$webhook_secret = 'whsec_your_signing_secret';
if (!$client->verifyMerchantWebhookSignature($raw_body, $signature, $webhook_secret)) {
http_response_code(401);
exit('Invalid signature');
}
$payload = json_decode($raw_body, true);
switch ($payload['status']) {
case 'completed':
// fulfilOrder($payload['order_id'], $payload['transaction_id']);
break;
case 'failed':
// failOrder($payload['order_id']);
break;
case 'refunded':
// markRefunded($payload['order_id']);
break;
}
http_response_code(200);
echo 'OK';
In a real production integration, your frontend should call your own backend, and your backend should call GrineoPay server-to-server.
<button id="gp-checkout-btn" onclick="initiateCryptoPayment()">
Pay with Crypto
</button>
<script>
async function initiateCryptoPayment() {
const btn = document.getElementById('gp-checkout-btn');
btn.disabled = true;
btn.textContent = 'Processing...';
try {
// Call YOUR backend, not GrineoPay directly from the browser
const response = await fetch('/api/create-crypto-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
orderId: 'ORD-' + Date.now(),
amount: 49.99,
currency: 'USD',
crypto: 'BTC',
customerEmail: '[email protected]'
})
});
const data = await response.json();
if (data.success) {
window.location.href = data.payment_url;
} else {
alert('Payment initialization failed: ' + data.message);
}
} catch (error) {
alert('Network error. Please try again.');
} finally {
btn.disabled = false;
btn.textContent = 'Pay with Crypto';
}
}
</script>
Never expose your API Key or Secret in browser JavaScript, frontend source, or mobile app code. Always call GrineoPay from your backend/server only.
GrineoPay API v1 — Merchant Documentation
Need help? Contact support through your Merchant Dashboard or email [email protected]