# API kompatibel Coinbase Commerce

> Beralih dari Coinbase Commerce ke blockwallets cukup dengan mengganti base URL SDK dan kunci: endpoint charge yang didukung, webhook dan tanda tangan, serta perbedaannya.
>
> HTML: https://blockwallets.io/docs/coinbase-commerce?lang=id · English: https://blockwallets.io/docs/coinbase-commerce.md?lang=en

## API kompatibel Coinbase Commerce

Endpoint charge, header `X-CC-Api-Key`, objek charge, dan webhook yang ditandatangani dengan `X-CC-Webhook-Signature` mengikuti dokumentasi Coinbase Commerce, sehingga SDK resminya berfungsi setelah mengubah satu baris. Coinbase Commerce berhenti melayani merchant di luar AS dan Singapura pada 2026-03-31. Datang dari tempat lain? Lihat [ringkasan migrasi](https://blockwallets.io/docs/migrate?lang=id).

Di baliknya adalah tagihan blockwallets biasa: alamat penerima milik Anda, halaman pembayaran adalah kasir yang kami host, dan pembayaran baru dihitung setelah terkonfirmasi di chain dan diperiksa silang dengan node kedua. Di bawah ini: tiga langkah, lalu apa yang didukung setiap API dan **apa bedanya dengan aslinya** — parameter yang tidak kami implementasikan mengembalikan error, bukan diabaikan diam-diam.

### Tiga langkah

- Dapatkan akun merchant ([ajukan di beranda](https://blockwallets.io/?lang=id#join)) dan tambahkan domain Anda di “Domain situs web” pada “Developer › Integrasi & kunci” di dasbor. URL callback (`ipn_callback_url`) dan URL pengalihan (`success_url` / `cancel_url` / `redirect_url`) harus berada di domain itu atau di domain URL callback Anda — kunci yang bocor tidak bisa mengarahkan webhook ke tempat lain.

- Buat kredensial kompatibel di dasbor merchant pada “Developer › Integrasi & kunci”, satu set untuk live dan satu untuk uji: NOWPayments mendapat **API key + IPN secret**, Coinbase Commerce mendapat **API key + webhook shared secret**. Semuanya ditampilkan sekali; kami hanya menyimpan hash / ciphertext.

- Arahkan kode Anda ke base URL di bawah dan pakai kunci baru. Jalankan dulu di testnet dengan kredensial uji, lalu beralih ke live.

| Sebelum | Sesudah | Header autentikasi | Tanda tangan webhook |
| --- | --- | --- | --- |
| `https://api.commerce.coinbase.com` | `https://blockwallets.io/coinbase/` | `X-CC-Api-Key` | `X-CC-Webhook-Signature` (HMAC-SHA256) |

### Coinbase Commerce

Semua SDK resmi menerima base URL — ubah satu baris (perhatikan `/` di akhir):

```sdk
// Node(coinbase-commerce-node)
const { Client } = require("coinbase-commerce-node");
- Client.init(process.env.COINBASE_COMMERCE_API_KEY);
+ Client.init(process.env.COINBASE_COMMERCE_API_KEY, "https://blockwallets.io/coinbase/");

# Python(coinbase-commerce)
- client = Client(api_key=API_KEY)
+ client = Client(api_key=API_KEY, base_api_uri="https://blockwallets.io/coinbase/")

// PHP(coinbase/coinbase-commerce)
- ApiClient::init($apiKey);
+ ApiClient::init($apiKey, 'https://blockwallets.io/coinbase/');
```

```curl
curl -X POST https://blockwallets.io/coinbase/charges \
  -H "X-CC-Api-Key: $COINBASE_COMMERCE_API_KEY" -H "X-CC-Version: 2018-03-22" \
  -H "content-type: application/json" \
  -d '{"name":"Order #12345","description":"Pro plan","pricing_type":"fixed_price",
       "local_price":{"amount":"100.00","currency":"USD"},
       "redirect_url":"https://shop.example/success","cancel_url":"https://shop.example/cancel",
       "metadata":{"order_id":"12345"}}'
# → 201 {"data": {"id": "…", "code": "7C7V5ECK", "hosted_url": "https://blockwallets.io/pay/inv_…", "timeline": [{"status": "NEW", …}], …}}
```

#### Endpoint yang didukung

| Endpoint | Catatan |
| --- | --- |
| `POST /charges` | Membuat charge; `hosted_url` adalah kasir yang kami host; berlaku 1 jam |
| `GET /charges/:code_or_id` | Cari berdasarkan kode 8 karakter atau id |
| `GET /charges` | Daftar: `limit` (≤100) / `starting_after` / `ending_before` / `order`, dengan objek `pagination` yang sama |
| `POST /charges/:code_or_id/cancel` | Membatalkan charge yang belum terlihat pembayarannya |

Tidak tersedia: `/charges/:code/resolve` (400 — tangani charge yang kurang bayar di dasbor), `/checkouts`, `/events`, `/invoices` (404).

#### Webhook

Webhook Coinbase berlaku di tingkat akun, begitu juga milik kami: dikirim ke **URL callback** yang diatur di dasbor Anda (charge yang dibuat dengan kredensial uji dikirim ke URL callback uji). Body-nya adalah `{id, scheduled_for, attempt_number, event: {id, type, api_version, created_at, data}}` milik Coinbase dengan charge lengkap di `data`; `X-CC-Webhook-Signature` = HMAC-SHA256(shared secret, body mentah), sehingga `Webhook.verifyEventBody` milik SDK berfungsi apa adanya. Pada percobaan ulang `event.id` tetap sama dan `attempt_number` naik — hindari duplikat berdasarkan `event.id`.

```nodejs
import crypto from "node:crypto";

// Same as the SDK's Webhook.verifySigHeader: HMAC-SHA256(shared secret, raw body)
function verifyWebhook(rawBody, sig, sharedSecret) {
  const hmac = crypto.createHmac("sha256", sharedSecret).update(rawBody, "utf8").digest("hex");
  return crypto.timingSafeEqual(Buffer.from(hmac), Buffer.from(sig || ""));
}
// verifyWebhook(rawBody, req.headers["x-cc-webhook-signature"], process.env.COINBASE_WEBHOOK_SECRET)
// or with the official SDK:Webhook.verifyEventBody(rawBody, signature, sharedSecret)
```

| Event | Kapan | Entri timeline terakhir |
| --- | --- | --- |
| `charge:confirmed` | Lunas (terkonfirmasi di chain dan diperiksa silang; kelebihan bayar dihitung) | `COMPLETED` |
| `charge:failed` | Kedaluwarsa tanpa pembayaran / dibatalkan oleh Anda / kedaluwarsa dalam keadaan kurang bayar | `EXPIRED` / `CANCELED` / `UNRESOLVED` (context `UNDERPAID`) |

Saat melakukan kueri Anda juga akan melihat `NEW` (menunggu pembayaran) dan `PENDING` (pembayaran terlihat di chain, sedang dikonfirmasi). **Penuhi pesanan pada `charge:confirmed`**: kami tidak mengirim `charge:created`, `charge:pending`, `charge:delayed`, atau `charge:resolved`.

#### Perbedaan dari Coinbase Commerce

- `pricing_type` harus `fixed_price`; `local_price.currency` harus USD (USDC / USDT pada 1:1). `no_price` dan fiat lain mengembalikan 400.

- Alamat muncul setelah pelanggan memilih koin dan jaringan di kasir: `addresses` hanya berisi jaringan itu, `pricing` hanya `local` plus `settlement` setelah dipilih; tidak ada field `exchange_rates`, `checkout`, atau branding.

- `metadata` disimpan dan dikembalikan apa adanya (hingga 4 KB).

- Refund tidak muncul di timeline; lihat di dasbor.

### Mode uji

Charge dan pembayaran yang dibuat dengan kredensial uji berjalan di testnet tiap chain dan webhook-nya ditandatangani dengan IPN secret / shared secret uji — sepenuhnya terpisah dari live: kunci uji tidak bisa melihat pembayaran live.

Sisanya (kasir, konfirmasi, jaringan dan minimum, refund) bekerja seperti di [dokumentasi utama](https://blockwallets.io/docs/cryptomus?lang=id).
