Wire up the GreenChain Eco-Receipt widget
Drop the widget on checkout, send a signed POST after payment, and share the proof pages everywhere. Secrets are hashed, requests are HMAC verified, and nothing uses customer PII.
1. Install the widget
Shopify theme snippet
<div class="gc-addon">
<label class="gc-checkbox">
<input type="checkbox" id="gc-addon" name="attributes[greenchain_addon]" value="yes" />
<span>Make my order greener (+99 PKR)</span>
</label>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const input = document.querySelector('#gc-addon');
if (!input) return;
input.addEventListener('change', function () {
window.GreenChainAddonSelected = input.checked;
});
});
</script>
Read window.GreenChainAddonSelected
after checkout to know if the shopper opted in.
WooCommerce snippet (functions.php)
<?php
add_action('woocommerce_review_order_before_submit', function () {
echo '<div class="gc-addon">';
woocommerce_form_field('greenchain_addon', [
'type' => 'checkbox',
'label' => 'Make my order greener (+99 PKR)',
], WC()->session->get('greenchain_addon'));
echo '</div>';
});
add_action('woocommerce_checkout_update_order_meta', function ($order_id) {
$selected = isset($_POST['greenchain_addon']) ? true : false;
update_post_meta($order_id, '_greenchain_addon', $selected);
});
Custom stack
Render a checkbox near the order total. Persist the boolean alongside the order. After payment call our REST endpoint with addon_selected
reflecting the shopper choice.
<label class="gc-addon">
<input type="checkbox" id="gc-addon" />
Make my order greener (+99 PKR)
</label>
2. Sign your payload
Secrets are shown once in the dashboard. Hash them with SHA-256 and use the hash as the HMAC key. This keeps secrets encrypted at rest while preserving deterministic signatures.
import crypto from 'node:crypto';
const body = JSON.stringify({
projectId: 'proj_123',
order_id: 'order-9912',
amount_minor: 124900,
addon_selected: true,
weight_grams: 1200,
ship_from_city: 'Karachi',
ship_to_city: 'Lahore'
});
const secret = process.env.GC_PROJECT_SECRET!; // gc_sec_xxx
const secretHash = crypto.createHash('sha256').update(secret).digest('hex');
const signature = crypto.createHmac('sha256', Buffer.from(secretHash, 'hex'))
.update(body)
.digest('hex');
fetch('https://greenchain.site/api/record-order', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-GC-PUBLIC-KEY': process.env.GC_PUBLIC_KEY!,
'X-GC-SIGN': signature
},
body
});
Headers required:
X-GC-PUBLIC-KEY
– your project public key.X-GC-SIGN
– hex encoded HMAC SHA-256 of the raw body using the hashed secret.Content-Type: application/json
3. Test with cURL
BODY='{ "projectId": "${PROJECT_ID}", "order_id": "demo-991", "amount_minor": 589900, "addon_selected": true, "ship_from_city": "Karachi", "ship_to_city": "Lahore"}'
SECRET_HASH=$(node -e "const c=require('crypto');process.stdout.write(c.createHash('sha256').update(process.env.GC_PROJECT_SECRET).digest('hex'))" GC_PROJECT_SECRET="$GC_PROJECT_SECRET")
SIGNATURE=$(node -e "const c=require('crypto');process.stdout.write(c.createHmac('sha256', Buffer.from(process.env.SECRET_HASH, 'hex')).update(process.env.BODY).digest('hex'))" SECRET_HASH="$SECRET_HASH" BODY="$BODY")
curl -X POST https://greenchain.site/api/record-order -H "Content-Type: application/json" -H "X-GC-PUBLIC-KEY: $GC_PUBLIC_KEY" -H "X-GC-SIGN: $SIGNATURE" -d "$BODY"
Response: { "receipt_url": "https://greenchain.site/r/abcd1234", "co2_kg": 2.84 }
4. Rotate secrets
Generate a new secret from the dashboard. Update your environment variable, deploy, then pause the previous key. Each rotation is logged in the audit trail with timestamp and actor.
Tip: expose GC_PUBLIC_KEY
, GC_PROJECT_SECRET
, and GC_SECRET_HASH
in your CI so blue/green deploys can warm up without downtime.
How we estimate CO₂
We use a truck-based proxy: co2_kg = (weight_kg × distance_km × 0.1) / 1000
. City-to-city averages cover Karachi ↔ Lahore (1210km), Karachi ↔ Islamabad (1410km), Lahore ↔ Islamabad (380km), and 10km for same-city. Everything else defaults to 800km.
Each order stores the factor version so future methodology updates do not change historic receipts. Want to plug in your own distances? Send ship_from_city
, ship_to_city
, and weight_grams
when recording the order.
Rate limiting
60 requests per minute per public key and IP. Exceeding the limit returns 429
with retry_after_ms
. Contact us for dedicated ingress if you burst above that.
Error codes
API responses
Need help?
Email hello@greenchain.site or ping us in the merchant Slack. We love pairing on checkout flows.