{"_id":"5adcc1185cd1890003da8174","category":{"_id":"5adcc1185cd1890003da8167","version":"5adcc1185cd1890003da8165","project":"5530bfac57cea10d00a3aa3b","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-08-18T18:14:59.726Z","from_sync":false,"order":2,"slug":"orders","title":"Private"},"user":"5530bf7457cea10d00a3aa3a","parentDoc":null,"project":"5530bfac57cea10d00a3aa3b","version":{"_id":"5adcc1185cd1890003da8165","project":"5530bfac57cea10d00a3aa3b","__v":3,"createdAt":"2018-04-22T17:06:32.152Z","releaseDate":"2018-04-22T17:06:32.152Z","categories":["5adcc1185cd1890003da8166","5adcc1185cd1890003da8167","5adcf4b3ce4b3f00035317e9","5adfb8e9452bd900036d115b"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"2.0.0","version":"2"},"githubsync":"","__v":0,"updates":["5aa277f59a7333003cc30725"],"next":{"pages":[],"description":""},"createdAt":"2015-08-19T09:17:13.529Z","link_external":false,"link_url":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":6,"body":"Payment callback (Payment notification) will be sent to merchant's ***callback_url*** when [order status](doc:order-statuses) is changed to *pending* *confirming*, *paid*, *invalid*, *canceled*, *refunded* or *expired*.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"Callback data is sent in **POST** method.\"\n}\n[/block]\nCoinGate callback sends data below:\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Name\",\n    \"h-1\": \"Value\",\n    \"0-0\": \"`id`\",\n    \"0-1\": \"CoinGate order (invoice) ID.\",\n    \"1-0\": \"`order_id`\",\n    \"1-1\": \"Custom order ID of the merchant. Should be used to identify order or invoice number.\",\n    \"2-0\": \"`status`\",\n    \"2-1\": \"CoinGate [payment status](doc:order-statuses).\",\n    \"3-0\": \"`price_amount`\",\n    \"3-1\": \"The price set by the merchant; for example, *499.95*.\",\n    \"4-0\": \"`price_currency`\",\n    \"4-1\": \"The currency code which defines the currency in which the merchant's goods/services are priced; for example, *USD*, *CHF*, *BTC* (see [supported currencies](https://coingate.com/currencies)).\",\n    \"5-0\": \"`receive_currency`\",\n    \"5-1\": \"The currency code which defines the currency in which the merchant's settlements will be paid. Currency conversions are done by CoinGate automatically. Possible values: *EUR*, *USD*, *BTC*. Please note that merchant verification is required to receive fiat settlements.\",\n    \"6-0\": \"`receive_amount`\",\n    \"9-0\": \"`created_at`\",\n    \"9-1\": \"Invoice creation time.\",\n    \"6-1\": \"The amount which will be credited to the merchant when the invoice is paid. It is calculated by taking the `price` amount (converted to currency units set in `receive_currency`) and subtracting CoinGate processing fee from it.\",\n    \"10-0\": \"`token`\",\n    \"7-0\": \"`pay_amount`\",\n    \"8-0\": \"`pay_currency`\",\n    \"10-1\": \"Your custom token (or generated by CoinGate) to validate payment callback\",\n    \"7-1\": \"The amount of cryptocurrency (defined by `pay_currency`) paid by the buyer.\",\n    \"8-1\": \"The cryptocurrency in which the payment was made; for example, *BTC*, *LTC*, *ETH*.\"\n  },\n  \"cols\": 2,\n  \"rows\": 11\n}\n[/block]\n**Content-Type: application/x-www-form-urlencoded** \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// print_r($_POST)\\n\\nArray\\n(\\n    [id] => 343\\n    [order_id] => 14037\\n    [status] => paid\\n    [price_amount] => 1050.99\\n    [price_currency] => USD\\n    [receive_amount] => 926.73\\n    [receive_currency] => EUR\\n    [pay_amount] => 4.81849315\\n    [pay_currency] => BTC\\n    [created_at] => 2014-11-03T13:07:28+00:00\\n\\t\\t[token] => ff7a7343-93bf-42b7-b82c-b38687081a4e\\n)\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nSee the code below how to accept callback.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Callback Retry Time\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"CoinGate sends payment notification while your application returns response **200 (OK) HTTP** status code.\"\n}\n[/block]\n* Sends every 1 minute if retry count is <= 5\n* Sends every 5 minutes if retry count is > 5 and <= 10\n* Sends every 10 minutes if retry count is > 10 and <= 15\n* Sends every 20 minutes if retry count is > 15 and <= 20\n* Sends every 30 minutes if retry count is > 20 and <= 25\n* Sends every 1 hour if retry count is > 25 and <= 30\n* Sends every 5 hours if retry count is > 30 and <= 35\n* Sends every 1 day if try count is > 35 and <= 40\n* Callback will be canceled if retry count is >= 41\n\nAfter sending payment notification, CoinGate waits for a response for 20 seconds.\n\nPayment notification will be canceled and terminated if one of the following conditions occur:\n\n* Payment notification is sent 40 times.\n* After sending payment notification, response status received is 301, 302 (Redirect). This commonly happens if you use \"http\" in your URL and it gets redirected to \"https\".\n* After sending payment notification, response status received is 401 (Unauthorized). This commonly happens when your website is password-protected (Basic access authentication). Ensure your website is publicly accessible.\n* Payment notification is sent to TOR network.\n* Payment notification is sent to a private network, such as localhost.\n[block:api-header]\n{\n  \"title\": \"IP Addresses\"\n}\n[/block]\nPayment Callback is sent from servers described in API endpoint. This API endpoint is public, authentication is not required.\nLive: https://api.coingate.com/v2/ips-v4\nSandbox: https://api-sandbox.coingate.com/v2/ips-v4\n\nEach IP is separated by a new line. Make sure that your server, as well as third-party security services (cloudflare, incapsula, etc.), are not blocking these IP addresses.\n\nWe recommend update your IP whitelist from this API endpoint regularly.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Private Nework & Localhost\"\n}\n[/block]\nCoinGate payment callback will not send notifications to private networks (for example: localhost).\nIn localhost, you can send test payment notification with [cURL library](https://curl.haxx.se/):\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X POST -d \\\"id=343&order_id=ORDER-1415020039&status=paid&price=1050.99&currency=USD&receive_currency=EUR&receive_amount=926.73&btc_amount=4.81849315&created_at=2014-11-03T13:07:28%2B00:00\\\" http://localhost/coingate-payment-callback\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Payment Callback Logs\"\n}\n[/block]\nYou can review payment callbacks and your server response to callback in your account panel. Login to your account and locate API » Payment Callbacks.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Accepting Payment Callback\"\n}\n[/block]\nExample: save the code below as `accept-coingate-callback.php` and execute cURL command in your command line tool:\n\n```\ncurl -X POST -d \"id=343&order_id=14037&status=paid&price=1050.99&currency=USD&receive_currency=EUR&receive_amount=926.73&btc_amount=4.81849315&created_at=2014-11-03T13:07:28%2B00:00\" http://localhost/accept-coingate-callback.php?token=5d02161be9bfb6192a33\n```\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?php\\n\\n// Your custom order_id is defined when you creating new order: https://developer.coingate.com/docs/create-order\\n// Also don't forget to prevent SQL injection\\n$result = mysql_query(\\\"SELECT * FROM orders WHERE id = \\\" . $_POST['order_id']);\\n$order = mysql_fetch_assoc($result);\\n\\n// token is your random secure string (for example: 5d02161be9bfb6192a33) for each order\\nif ($_POST['token'] == $order['token']) {\\n  // Handle CoinGate order status: https://developer.coingate.com/docs/order-statuses\\n  $status = NULL;\\n  if ($_POST['status'] == 'paid') {\\n    if ($_POST['price'] >= $order['amount']) {\\n      $status = 'paid';\\n    }\\n  }\\n  else {\\n    $status = $_POST['status'];\\n  }\\n\\n  if (!is_null($status)) {\\n      mysql_query(\\\"UPDATE orders SET status = '\\\".$status.\\\"' WHERE id = \\\".$_POST['order_id']);\\n  }\\n}\",\n      \"language\": \"php\"\n    },\n    {\n      \"code\": \"class CoingateCallbackController < ApplicationController\\n  skip_before_action :verify_authenticity_token, only: :create\\n\\n  def create\\n    order = Order.find_by(id: params[:order_id])\\n\\n    if order.present?\\n      if params[:token].present? && order.token == params[:token]\\n        status = nil\\n\\n        if params[:status] == 'paid'\\n          if params[:price].to_d >= order.amount # in addition you can check currency (params[:currency] == order.currency)\\n            status = 'paid'\\n          end\\n        else\\n          status = params[:status]\\n        end\\n\\n        if status.present?\\n          order.update_attribute(:status, status)\\n        end\\n      end\\n    end\\n  end\\nend\",\n      \"language\": \"ruby\",\n      \"name\": \"Ruby on Rails\"\n    }\n  ]\n}\n[/block]","excerpt":"","slug":"payment-callback","type":"basic","title":"Payment Callback"}
Payment callback (Payment notification) will be sent to merchant's ***callback_url*** when [order status](doc:order-statuses) is changed to *pending* *confirming*, *paid*, *invalid*, *canceled*, *refunded* or *expired*. [block:callout] { "type": "warning", "body": "Callback data is sent in **POST** method." } [/block] CoinGate callback sends data below: [block:parameters] { "data": { "h-0": "Name", "h-1": "Value", "0-0": "`id`", "0-1": "CoinGate order (invoice) ID.", "1-0": "`order_id`", "1-1": "Custom order ID of the merchant. Should be used to identify order or invoice number.", "2-0": "`status`", "2-1": "CoinGate [payment status](doc:order-statuses).", "3-0": "`price_amount`", "3-1": "The price set by the merchant; for example, *499.95*.", "4-0": "`price_currency`", "4-1": "The currency code which defines the currency in which the merchant's goods/services are priced; for example, *USD*, *CHF*, *BTC* (see [supported currencies](https://coingate.com/currencies)).", "5-0": "`receive_currency`", "5-1": "The currency code which defines the currency in which the merchant's settlements will be paid. Currency conversions are done by CoinGate automatically. Possible values: *EUR*, *USD*, *BTC*. Please note that merchant verification is required to receive fiat settlements.", "6-0": "`receive_amount`", "9-0": "`created_at`", "9-1": "Invoice creation time.", "6-1": "The amount which will be credited to the merchant when the invoice is paid. It is calculated by taking the `price` amount (converted to currency units set in `receive_currency`) and subtracting CoinGate processing fee from it.", "10-0": "`token`", "7-0": "`pay_amount`", "8-0": "`pay_currency`", "10-1": "Your custom token (or generated by CoinGate) to validate payment callback", "7-1": "The amount of cryptocurrency (defined by `pay_currency`) paid by the buyer.", "8-1": "The cryptocurrency in which the payment was made; for example, *BTC*, *LTC*, *ETH*." }, "cols": 2, "rows": 11 } [/block] **Content-Type: application/x-www-form-urlencoded** [block:code] { "codes": [ { "code": "// print_r($_POST)\n\nArray\n(\n [id] => 343\n [order_id] => 14037\n [status] => paid\n [price_amount] => 1050.99\n [price_currency] => USD\n [receive_amount] => 926.73\n [receive_currency] => EUR\n [pay_amount] => 4.81849315\n [pay_currency] => BTC\n [created_at] => 2014-11-03T13:07:28+00:00\n\t\t[token] => ff7a7343-93bf-42b7-b82c-b38687081a4e\n)", "language": "php" } ] } [/block] See the code below how to accept callback. [block:api-header] { "type": "basic", "title": "Callback Retry Time" } [/block] [block:callout] { "type": "info", "body": "CoinGate sends payment notification while your application returns response **200 (OK) HTTP** status code." } [/block] * Sends every 1 minute if retry count is <= 5 * Sends every 5 minutes if retry count is > 5 and <= 10 * Sends every 10 minutes if retry count is > 10 and <= 15 * Sends every 20 minutes if retry count is > 15 and <= 20 * Sends every 30 minutes if retry count is > 20 and <= 25 * Sends every 1 hour if retry count is > 25 and <= 30 * Sends every 5 hours if retry count is > 30 and <= 35 * Sends every 1 day if try count is > 35 and <= 40 * Callback will be canceled if retry count is >= 41 After sending payment notification, CoinGate waits for a response for 20 seconds. Payment notification will be canceled and terminated if one of the following conditions occur: * Payment notification is sent 40 times. * After sending payment notification, response status received is 301, 302 (Redirect). This commonly happens if you use "http" in your URL and it gets redirected to "https". * After sending payment notification, response status received is 401 (Unauthorized). This commonly happens when your website is password-protected (Basic access authentication). Ensure your website is publicly accessible. * Payment notification is sent to TOR network. * Payment notification is sent to a private network, such as localhost. [block:api-header] { "title": "IP Addresses" } [/block] Payment Callback is sent from servers described in API endpoint. This API endpoint is public, authentication is not required. Live: https://api.coingate.com/v2/ips-v4 Sandbox: https://api-sandbox.coingate.com/v2/ips-v4 Each IP is separated by a new line. Make sure that your server, as well as third-party security services (cloudflare, incapsula, etc.), are not blocking these IP addresses. We recommend update your IP whitelist from this API endpoint regularly. [block:api-header] { "type": "basic", "title": "Private Nework & Localhost" } [/block] CoinGate payment callback will not send notifications to private networks (for example: localhost). In localhost, you can send test payment notification with [cURL library](https://curl.haxx.se/): [block:code] { "codes": [ { "code": "curl -X POST -d \"id=343&order_id=ORDER-1415020039&status=paid&price=1050.99&currency=USD&receive_currency=EUR&receive_amount=926.73&btc_amount=4.81849315&created_at=2014-11-03T13:07:28%2B00:00\" http://localhost/coingate-payment-callback", "language": "curl" } ] } [/block] [block:api-header] { "type": "basic", "title": "Payment Callback Logs" } [/block] You can review payment callbacks and your server response to callback in your account panel. Login to your account and locate API » Payment Callbacks. [block:api-header] { "type": "basic", "title": "Accepting Payment Callback" } [/block] Example: save the code below as `accept-coingate-callback.php` and execute cURL command in your command line tool: ``` curl -X POST -d "id=343&order_id=14037&status=paid&price=1050.99&currency=USD&receive_currency=EUR&receive_amount=926.73&btc_amount=4.81849315&created_at=2014-11-03T13:07:28%2B00:00" http://localhost/accept-coingate-callback.php?token=5d02161be9bfb6192a33 ``` [block:code] { "codes": [ { "code": "<?php\n\n// Your custom order_id is defined when you creating new order: https://developer.coingate.com/docs/create-order\n// Also don't forget to prevent SQL injection\n$result = mysql_query(\"SELECT * FROM orders WHERE id = \" . $_POST['order_id']);\n$order = mysql_fetch_assoc($result);\n\n// token is your random secure string (for example: 5d02161be9bfb6192a33) for each order\nif ($_POST['token'] == $order['token']) {\n // Handle CoinGate order status: https://developer.coingate.com/docs/order-statuses\n $status = NULL;\n if ($_POST['status'] == 'paid') {\n if ($_POST['price'] >= $order['amount']) {\n $status = 'paid';\n }\n }\n else {\n $status = $_POST['status'];\n }\n\n if (!is_null($status)) {\n mysql_query(\"UPDATE orders SET status = '\".$status.\"' WHERE id = \".$_POST['order_id']);\n }\n}", "language": "php" }, { "code": "class CoingateCallbackController < ApplicationController\n skip_before_action :verify_authenticity_token, only: :create\n\n def create\n order = Order.find_by(id: params[:order_id])\n\n if order.present?\n if params[:token].present? && order.token == params[:token]\n status = nil\n\n if params[:status] == 'paid'\n if params[:price].to_d >= order.amount # in addition you can check currency (params[:currency] == order.currency)\n status = 'paid'\n end\n else\n status = params[:status]\n end\n\n if status.present?\n order.update_attribute(:status, status)\n end\n end\n end\n end\nend", "language": "ruby", "name": "Ruby on Rails" } ] } [/block]