{"__v":0,"_id":"56c31f3ec0d06a0d006680c4","initVersion":{"_id":"54dec8b6c2b4b70d009c3f0f","version":"1"},"project":"54c83b5aab706219009e067b","user":{"_id":"566be70acb3d040d00abae1d","username":"","name":"Giridaran M"},"hidden":false,"createdAt":"2016-02-16T13:08:14.220Z","fullscreen":false,"htmlmode":false,"html":"","body":"Orders API is the more powerful integration method available today with a bunch of extra advantages over the standard integration method.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Advantages of Orders API\"\n}\n[/block]\nOrders API adds few extra features on top of the normal payments API. For eg:\n\n\n- Orders API restricts successful payments to 1 per order. This prevents multiple payments.\n- Orders API allows you to enable auto-capture, if you want. This is explained in detail in a section below.\n- Order API allows to combine payments that are corresponding to one single order, making it easier to query Razorpay’s systems for an order.\n\n\nOrders API is more powerful because of these features and hence it is the recommended integration method for tech savvy merchants. We will be adding more features to this API soon.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Pre-requisite\",\n  \"body\": \"Before you go ahead with this doc, please go through the following sections in our main doc:\\n- [Getting Started](https://docs.razorpay.com/docs/getting-started)\\n- [Payment Flow](https://docs.razorpay.com/docs/payment-flow)\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Orders API Flow\"\n}\n[/block]\nThe flow of Orders API is as follows:\n\n\n- Merchant Server sends a create order request to Razorpay's server\nIn response, Razorpay returns an `order_id`. Store this `order_id` in your database corresponding to the order on your end.\n- This `order_id` needs to be passed to [Razorpay Checkout](https://docs.razorpay.com/docs/checkout-form) on web or mobile\n- The payment now proceeds as normal, in the customer's device\n- Once the payment is complete on the customer's device, Checkout will return the `razorpay_payment_id`, `razorpay_order_id` and `razorpay_signature`.\n- These parameters need to be passed to merchant's backend\n- The merchant's backend will now capture this payment (further explained below)\n- The payment is now complete\n\n\nThe flow is almost identical to the standard payment flow, from step 3 onwards. The first 2 steps are the only changes in the flow.\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Capturing a payment\"\n}\n[/block]\nWith Orders API there are two way you can capture a payment:\n- Standard Capture API documented [here](https://docs.razorpay.com/docs/v1paymentsidcapture) and available for all integrations\n- Auto Capture process, only available for Orders API integration\n\nAuto Capture is explained in a section below.\nIf you are using the standard Capture API, you can safely ignore the `signature` param returned.\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Fields to be stored in your Database\"\n}\n[/block]\nIn your system you will be creating a `transaction_id`/`order_id`/`checkout_id` etc. which corresponds to the order from the customer. This is created in your server and is NOT the order_id returned by Razorpay. Let’s call this the `merchant_order_id`. Corresponding to your `merchant_order_id` you should be storing at least the following from Razorpay:\n\n- `razorpay_order_id` (obtained in step 1)\n- `razorpay_payment_id` (obtained after payment was successful, in step 4)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Order Lifecycle\"\n}\n[/block]\nAn order goes through the following statuses in its lifecycle.\n[block:parameters]\n{\n  \"data\": {\n    \"0-0\": \"`created`\",\n    \"1-0\": \"`attempted`\",\n    \"2-0\": \"`paid`\",\n    \"0-1\": \"This indicates that the order has been created.\",\n    \"1-1\": \"Payment for this order has been attempted but it hasn’t been successful.\\nThe number of attempts is indicated by the attempts field\",\n    \"2-1\": \"This is the final status of an order, when a payment has been made against it successfully.\",\n    \"h-0\": \"Status\",\n    \"h-1\": \"Description\"\n  },\n  \"cols\": 2,\n  \"rows\": 3\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Auto Capturing Payment\"\n}\n[/block]\nWhile the normal flow works perfectly well, the last network request i.e., the capture step between your server and Razorpay's server can be safely removed. The capture step is required for security purposes and it helps in ensuring with 100% certainty that the `payment_id` and `amount` collected are correct. This security step does not necessarily have to involve a network request.\n\nYou can enable auto-capture of payments by passing `payment_capture = 1` in the create order request in _Step 1_.\n\nThe other differences are from _Step 6_ onwards. Apart from `payment_id`, Checkout will also be returning `razorpay_signature`, which is a hexadecimal string with special properties. Instead of making the Capture API call, you can simply verify the signature in your backend server. If the signature is valid, the payment is successful and auto-captured. The verification process is explained below.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"While `razorpay_signature` is passed in all cases and can also be verified in all cases, it signifies that a payment has _also_ been captured only if you had sent `payment_capture = 1`.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"You do not need to call the standard capture api if you are using the auto-capture mode.\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Verifying Signature\"\n}\n[/block]\nThe `razorpay_signature` is returned to you by the Checkout form on successful transaction. This signature needs to be verified in your backend server. In order to verify the signature, you need to create a signature in your backend server, using `razorpay_payment_id`, `razorpay_order_id` and `key_secret`.\n\n\n`razorpay_payment_id` and `razorpay_order_id` are returned to you by Checkout\n`key_secret` will be available in your backend server\n\n\nYou now have to generate a signature on your end which is calculated as HMAC hex digest using SHA256 algorithm and using these fields. The `razorpay_payment_id` and `razorpay_order_id` fields are concatenated using the `|` (pipe) symbol.\n\n\nPseudo Code:\n\n\n```\n  generated_signature = hmac_sha256(razorpay_order_id + \"|\" + razorpay_payment_id, secret);\n \n  if (generated_signature == razorpay_signature) {\n    payment is successful\n  }\n```\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Post Signature Verification Steps\"\n}\n[/block]\nIf you have passed `payment_capture = 1` in the initial request and validated the signature, the payment will be in `captured` state in Razorpay’s system. After verifying the signature, fetch the order in your system which has this `razorpay_order_id` stored corresponding to it in your database. You can now mark this fetched order as successful and process the order.\n[block:callout]\n{\n  \"type\": \"danger\",\n  \"body\": \"Please note that you should be storing `razorpay_order_id` in your system right after it was returned in the response to create order request. After validating the signature, you should then fetch the order in your system corresponding the `razorpay_order_id` and mark only this order successful.\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Changes in Integration\"\n}\n[/block]\nApart from the changes in your backend server, you need to make changes in your Checkout integration too and these are documented below.\n\n## Passing Order ID to Checkout\n\nThe `razorpay_order_id` received on your backend server after calling the _create order_ request needs to be passed to Checkout form, on both web and mobile. This can be done by simply adding an extra key-value pair as part of the options that you are already sending:\n\n\n```\n{\n  \"amount\": \"100\",\n   // and other options\n\n\n  \"order_id\": \"<razorpay_order_id>\"\n}\n```\n\n\n## Getting Payment ID and Signature in Response\nThe handling of this will vary between Checkout on Web, Android and iOS.\n\n\nPlease note that the following applies only if you are using auto capturing of payments. If not, then all that you need is the `razorpay_payment_id` and this is passed normally.\n\n\n### Checkout on Web\nIf `order_id` was passed in the options at the start of the payment, the returned `json` object will now look like following:\n\n\n```\n{\n  \"razorpay_payment_id\": \"pay_xxxxxxxxxxxxxx\",\n  \"razorpay_signature\": \"<Hexadecimal String>\", \n  “razorpay_order_id”: “order_xxxxxxxxxxxxxx”\n}\n```\n\n\nThese two parameters need to be sent to your backend for either capturing or for signature verification if you are using auto capturing.\n\n### Checkout on Android\nYou need to be using Android SDK `v1.0.+` at least for the following to work.\n\n\nAndroid SDK by default only returns the `payment_id`. To get the `razorpay_signature`, your activity will need to implement the `PaymentResultWithDataListener` interface to receive the `razorpay_signature` in the `onPaymentSuccess` callback.\n\n\n```\npublic class MerchantActivity extends Activity implements PaymentResultWithDataListener {\n  // ...\n\n\n  @Override\n  public void onPaymentSuccess(String razorpayPaymentID, PaymentData data) {\n       String paymentId = data.getPaymentId();\n       String signature = data.getSignature();\n       String orderId = data.getOrderId();\n  }\n\n\n  @Override\n  public void onPaymentError(int code, String response, PaymentData data) {\n \n  }\n```\n\n\n### Checkout on iOS\nImplement `RazorpayPaymentCompletionProtocolWithData`:\n\n\n```\nViewController.m\n#import <Razorpay/Razorpay.h>\n\n\n@interface ViewController () <RazorpayPaymentCompletionProtocol, UIWebViewDelegate> {\n  Razorpay *razorpay;\n..  \n..\n}\n@property(weak, nonatomic) IBOutlet UIWebView *myWebview;\n..\n..\n  \n// Any place before initiating the payment (eg. viewDidLoad)\n- (void)viewDidLoad {\n  [super viewDidLoad];\n  ..\n  ..\n  razorpay = [Razorpay initWithKey:@\"rzp_test_1DP5mmOlF5G5ag\"\n                       andDelegate:self\n                withPaymentWebView:self.myWebview];\n}\n```\n\n\nSuccess/Error handlers will receive a dictionary containing `order_id` and `signature`:\n\n\n```\n- (void)onPaymentSuccess:(nonnull NSString*)payment_id andData:(nullable NSDictionary *)response{\n      [[[UIAlertView alloc] initWithTitle:@\"Payment Successful\" message:payment_id delegate:self cancelButtonTitle:@\"OK\" otherButtonTitles:nil] show];\n}\n\n\n- (void)onPaymentError:(int)code description:(nonnull NSString *)str andData:(nullable NSDictionary *)response {\n      [[[UIAlertView alloc] initWithTitle:@\"Error\" message:str delegate:self cancelButtonTitle:@\"OK\" otherButtonTitles:nil] show];\n}\n```\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Entity\"\n}\n[/block]\nThe order entity consists of the following fields\n[block:parameters]\n{\n  \"data\": {\n    \"0-0\": \"`id`\",\n    \"0-1\": \"string\",\n    \"1-0\": \"`amount`\",\n    \"1-1\": \"integer\",\n    \"2-0\": \"`currency`\",\n    \"3-0\": \"`attempts`\",\n    \"4-0\": \"`status`\",\n    \"5-0\": \"`receipt`\",\n    \"2-1\": \"string\",\n    \"3-1\": \"integer\",\n    \"4-1\": \"string\",\n    \"5-1\": \"string\",\n    \"h-0\": \"Attribute\",\n    \"h-1\": \"Type\",\n    \"0-2\": \"The order of this particular order\",\n    \"1-2\": \"The amount (in paisa) that this order was created for\",\n    \"2-2\": \"The currency associated with this order's amount\",\n    \"3-2\": \"The number of payment attempts that have been made against this order\",\n    \"4-2\": \"This order's status in the Order lifecycle\",\n    \"5-2\": \"Your receipt id corresponding to this order. Maximum length 40 chars.\",\n    \"h-2\": \"Description\",\n    \"7-0\": \"`created_at`\",\n    \"7-1\": \"timestamp\",\n    \"7-2\": \"The timestamp corresponding to this order's creation time.\",\n    \"8-0\": \"`notes`\",\n    \"8-1\": \"object\",\n    \"8-2\": \"Object consisting of notes passed while creating an order Entity\",\n    \"6-0\": \"`payment_capture`\",\n    \"6-1\": \"boolean\",\n    \"6-2\": \"Flag for auto capturing the payment\"\n  },\n  \"cols\": 3,\n  \"rows\": 9\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"Once a successful payment is captured by you, the order status will advance to `paid`. \\n\\nThe order status will continue to remain `attempted` in the mean while. However no more payments can be made against this order.\",\n  \"title\": \"Order Status\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"post\",\n  \"title\": \"/orders\"\n}\n[/block]\nThis endpoint creates an order. Following are the parameters that can be passed:\n[block:parameters]\n{\n  \"data\": {\n    \"0-0\": \"amount\\n_required_\",\n    \"0-1\": \"Amount for the order in paisa. Payment can only be made for this amount against the order.\",\n    \"1-0\": \"currency\\n_required_\",\n    \"1-1\": \"`INR` is the only supported currency currently.\",\n    \"2-0\": \"receipt\\n_required_\",\n    \"2-1\": \"You receipt id for this order should be passed in here. Maximum length 40 characters.\",\n    \"h-0\": \"Parameters\",\n    \"h-1\": \"Description\",\n    \"4-0\": \"notes\\n_optional_\",\n    \"4-1\": \"Object consisting of key value pairs as notes. Read more - [Notes Doc](https://docs.razorpay.com/docs/notes)\",\n    \"3-0\": \"payment_capture\\n_optional_\",\n    \"3-1\": \"Payment capture flag for auto capturing payment\"\n  },\n  \"cols\": 2,\n  \"rows\": 5\n}\n[/block]\nBelow is a sample curl request for creating an `order`.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -u rzp_test_26ccbdbfe0e84b:69b2e24411e384f91213f22a \\\\\\n   -X POST \\\\\\n   --data \\\"amount=500\\\" \\\\\\n   --data \\\"currency=INR\\\" \\\\\\n   --data \\\"receipt=Receipt #20\\\" \\\\\\n   https://api.razorpay.com/v1/orders\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"Dictionary<string, object> options = new Dictionary<string, object>();\\noptions.Add(\\\"amount\\\", \\\"1000\\\");\\noptions.Add(\\\"currency\\\", \\\"INR\\\");\\noptions.Add(\\\"receipt\\\", \\\"<merchant-order-id>\\\");\\n\\nRazorpayClient client = new RazorpayClient(\\\"<key>\\\", \\\"<secret>\\\");\\nOrder order = client.Order.Create(options);\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\nThe response is an orders entity.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"id\\\": \\\"order_4xbQrmEoA5WJ0G\\\",\\n  \\\"entity\\\": \\\"order\\\",\\n  \\\"amount\\\": 500,\\n  \\\"currency\\\": \\\"INR\\\",\\n  \\\"receipt\\\": \\\"Receipt #20\\\",\\n  \\\"status\\\": \\\"created\\\",\\n  \\\"attempts\\\": 0,\\n  \\\"created_at\\\": 1455696638,\\n  \\\"notes\\\": {}\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"get\",\n  \"title\": \"/orders\"\n}\n[/block]\nThis end point fetches the order details\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Params\",\n    \"h-1\": \"Description\",\n    \"0-0\": \"from\\n_optional_\",\n    \"0-1\": \"Timestamp from when orders are to be fetched\",\n    \"2-0\": \"count\\n_optional_\",\n    \"2-1\": \"Count of orders to be fetched\\nDefault Count is 10\",\n    \"3-0\": \"skip\\n_optional_\",\n    \"3-1\": \"Numbers of orders to be skipped\\nDefault Skip is 0\",\n    \"1-0\": \"to\\n_optional_\",\n    \"1-1\": \"Timestamp up till when orders are to be fetched\",\n    \"4-0\": \"authorized\\n_optional_\",\n    \"4-1\": \"Orders for which payments are currently in authorized state\",\n    \"5-0\": \"receipt\\n_optional_\",\n    \"5-1\": \"Orders with the provided value for receipt\"\n  },\n  \"cols\": 2,\n  \"rows\": 6\n}\n[/block]\nResponse \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"entity\\\": \\\"collection\\\",\\n  \\\"count\\\": 2,\\n  \\\"items\\\": [\\n    {\\n      \\\"id\\\": \\\"order_4xbVikJiVknbcr\\\",\\n      \\\"entity\\\": \\\"order\\\",\\n      \\\"amount\\\": 500,\\n      \\\"currency\\\": \\\"INR\\\",\\n      \\\"receipt\\\": \\\"order36\\\",\\n      \\\"status\\\": \\\"created\\\",\\n      \\\"attempts\\\": 0,\\n      \\\"created_at\\\": 1455696913,\\n      \\\"notes\\\": {}\\n    },\\n    {\\n      \\\"id\\\": \\\"order_4xbSwsPABDJ8oK\\\",\\n      \\\"entity\\\": \\\"order\\\",\\n      \\\"amount\\\": 500,\\n      \\\"currency\\\": \\\"INR\\\",\\n      \\\"receipt\\\": \\\"order33\\\",\\n      \\\"status\\\": \\\"created\\\",\\n      \\\"attempts\\\": 0,\\n      \\\"created_at\\\": 1455696756,\\n      \\\"notes\\\": {}\\n    }\\n  ]\\n}\",\n      \"language\": \"json\",\n      \"name\": null\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"get\",\n  \"title\": \"/orders/:id\"\n}\n[/block]\nThis endpoint fetches the order details of a particular order.\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Params\",\n    \"h-1\": \"Description\",\n    \"0-0\": \"id\\n_required_\",\n    \"0-1\": \"Id of order to be fetched.\"\n  },\n  \"cols\": 2,\n  \"rows\": 1\n}\n[/block]\nThe response will be an order entity\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"id\\\": \\\"order_4xbVikJiVknbcr\\\",\\n  \\\"entity\\\": \\\"order\\\",\\n  \\\"amount\\\": 600,\\n  \\\"currency\\\": \\\"INR\\\",\\n  \\\"receipt\\\": \\\"order33\\\",\\n  \\\"status\\\": \\\"created\\\",\\n  \\\"attempts\\\": 0,\\n  \\\"notes\\\": {},\\n  \\\"created_at\\\": 1455696913\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"get\",\n  \"title\": \"/orders/:id/payments\"\n}\n[/block]\nThe payments corresponding to an order can be obtained from the GET /orders/:id/payments API. \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"count\\\": 1,\\n  \\\"entity\\\": \\\"collection\\\",\\n  \\\"items\\\": [\\n    {\\n      \\\"id\\\": \\\"pay_29QQoUBi66xm2f\\\",\\n      \\\"entity\\\": \\\"payment\\\",\\n      \\\"amount\\\": 600,\\n      \\\"currency\\\": \\\"INR\\\",\\n      \\\"status\\\": \\\"captured\\\",\\n      \\\"amount_refunded\\\": 0,\\n      \\\"refund_status\\\": null,\\n      \\\"email\\\": \\\"test@razorpay.com\\\",\\n      \\\"contact\\\": \\\"9364591752\\\",\\n      \\\"error_code\\\": null,\\n      \\\"error_description\\\": null,\\n      \\\"notes\\\": {},\\n      \\\"created_at\\\": 1400826750\\n    },\\n  ]\\n}\",\n      \"language\": \"json\",\n      \"name\": null\n    }\n  ]\n}\n[/block]","slug":"orders","title":"Orders"}

Orders


Orders API is the more powerful integration method available today with a bunch of extra advantages over the standard integration method. [block:api-header] { "type": "basic", "title": "Advantages of Orders API" } [/block] Orders API adds few extra features on top of the normal payments API. For eg: - Orders API restricts successful payments to 1 per order. This prevents multiple payments. - Orders API allows you to enable auto-capture, if you want. This is explained in detail in a section below. - Order API allows to combine payments that are corresponding to one single order, making it easier to query Razorpay’s systems for an order. Orders API is more powerful because of these features and hence it is the recommended integration method for tech savvy merchants. We will be adding more features to this API soon. [block:callout] { "type": "info", "title": "Pre-requisite", "body": "Before you go ahead with this doc, please go through the following sections in our main doc:\n- [Getting Started](https://docs.razorpay.com/docs/getting-started)\n- [Payment Flow](https://docs.razorpay.com/docs/payment-flow)" } [/block] [block:api-header] { "type": "basic", "title": "Orders API Flow" } [/block] The flow of Orders API is as follows: - Merchant Server sends a create order request to Razorpay's server In response, Razorpay returns an `order_id`. Store this `order_id` in your database corresponding to the order on your end. - This `order_id` needs to be passed to [Razorpay Checkout](https://docs.razorpay.com/docs/checkout-form) on web or mobile - The payment now proceeds as normal, in the customer's device - Once the payment is complete on the customer's device, Checkout will return the `razorpay_payment_id`, `razorpay_order_id` and `razorpay_signature`. - These parameters need to be passed to merchant's backend - The merchant's backend will now capture this payment (further explained below) - The payment is now complete The flow is almost identical to the standard payment flow, from step 3 onwards. The first 2 steps are the only changes in the flow. [block:api-header] { "type": "basic", "title": "Capturing a payment" } [/block] With Orders API there are two way you can capture a payment: - Standard Capture API documented [here](https://docs.razorpay.com/docs/v1paymentsidcapture) and available for all integrations - Auto Capture process, only available for Orders API integration Auto Capture is explained in a section below. If you are using the standard Capture API, you can safely ignore the `signature` param returned. [block:api-header] { "type": "basic", "title": "Fields to be stored in your Database" } [/block] In your system you will be creating a `transaction_id`/`order_id`/`checkout_id` etc. which corresponds to the order from the customer. This is created in your server and is NOT the order_id returned by Razorpay. Let’s call this the `merchant_order_id`. Corresponding to your `merchant_order_id` you should be storing at least the following from Razorpay: - `razorpay_order_id` (obtained in step 1) - `razorpay_payment_id` (obtained after payment was successful, in step 4) [block:api-header] { "type": "basic", "title": "Order Lifecycle" } [/block] An order goes through the following statuses in its lifecycle. [block:parameters] { "data": { "0-0": "`created`", "1-0": "`attempted`", "2-0": "`paid`", "0-1": "This indicates that the order has been created.", "1-1": "Payment for this order has been attempted but it hasn’t been successful.\nThe number of attempts is indicated by the attempts field", "2-1": "This is the final status of an order, when a payment has been made against it successfully.", "h-0": "Status", "h-1": "Description" }, "cols": 2, "rows": 3 } [/block] [block:api-header] { "type": "basic", "title": "Auto Capturing Payment" } [/block] While the normal flow works perfectly well, the last network request i.e., the capture step between your server and Razorpay's server can be safely removed. The capture step is required for security purposes and it helps in ensuring with 100% certainty that the `payment_id` and `amount` collected are correct. This security step does not necessarily have to involve a network request. You can enable auto-capture of payments by passing `payment_capture = 1` in the create order request in _Step 1_. The other differences are from _Step 6_ onwards. Apart from `payment_id`, Checkout will also be returning `razorpay_signature`, which is a hexadecimal string with special properties. Instead of making the Capture API call, you can simply verify the signature in your backend server. If the signature is valid, the payment is successful and auto-captured. The verification process is explained below. [block:callout] { "type": "warning", "body": "While `razorpay_signature` is passed in all cases and can also be verified in all cases, it signifies that a payment has _also_ been captured only if you had sent `payment_capture = 1`." } [/block] [block:callout] { "type": "warning", "body": "You do not need to call the standard capture api if you are using the auto-capture mode." } [/block] [block:api-header] { "type": "basic", "title": "Verifying Signature" } [/block] The `razorpay_signature` is returned to you by the Checkout form on successful transaction. This signature needs to be verified in your backend server. In order to verify the signature, you need to create a signature in your backend server, using `razorpay_payment_id`, `razorpay_order_id` and `key_secret`. `razorpay_payment_id` and `razorpay_order_id` are returned to you by Checkout `key_secret` will be available in your backend server You now have to generate a signature on your end which is calculated as HMAC hex digest using SHA256 algorithm and using these fields. The `razorpay_payment_id` and `razorpay_order_id` fields are concatenated using the `|` (pipe) symbol. Pseudo Code: ``` generated_signature = hmac_sha256(razorpay_order_id + "|" + razorpay_payment_id, secret); if (generated_signature == razorpay_signature) { payment is successful } ``` [block:api-header] { "type": "basic", "title": "Post Signature Verification Steps" } [/block] If you have passed `payment_capture = 1` in the initial request and validated the signature, the payment will be in `captured` state in Razorpay’s system. After verifying the signature, fetch the order in your system which has this `razorpay_order_id` stored corresponding to it in your database. You can now mark this fetched order as successful and process the order. [block:callout] { "type": "danger", "body": "Please note that you should be storing `razorpay_order_id` in your system right after it was returned in the response to create order request. After validating the signature, you should then fetch the order in your system corresponding the `razorpay_order_id` and mark only this order successful." } [/block] [block:api-header] { "type": "basic", "title": "Changes in Integration" } [/block] Apart from the changes in your backend server, you need to make changes in your Checkout integration too and these are documented below. ## Passing Order ID to Checkout The `razorpay_order_id` received on your backend server after calling the _create order_ request needs to be passed to Checkout form, on both web and mobile. This can be done by simply adding an extra key-value pair as part of the options that you are already sending: ``` { "amount": "100", // and other options "order_id": "<razorpay_order_id>" } ``` ## Getting Payment ID and Signature in Response The handling of this will vary between Checkout on Web, Android and iOS. Please note that the following applies only if you are using auto capturing of payments. If not, then all that you need is the `razorpay_payment_id` and this is passed normally. ### Checkout on Web If `order_id` was passed in the options at the start of the payment, the returned `json` object will now look like following: ``` { "razorpay_payment_id": "pay_xxxxxxxxxxxxxx", "razorpay_signature": "<Hexadecimal String>", “razorpay_order_id”: “order_xxxxxxxxxxxxxx” } ``` These two parameters need to be sent to your backend for either capturing or for signature verification if you are using auto capturing. ### Checkout on Android You need to be using Android SDK `v1.0.+` at least for the following to work. Android SDK by default only returns the `payment_id`. To get the `razorpay_signature`, your activity will need to implement the `PaymentResultWithDataListener` interface to receive the `razorpay_signature` in the `onPaymentSuccess` callback. ``` public class MerchantActivity extends Activity implements PaymentResultWithDataListener { // ... @Override public void onPaymentSuccess(String razorpayPaymentID, PaymentData data) { String paymentId = data.getPaymentId(); String signature = data.getSignature(); String orderId = data.getOrderId(); } @Override public void onPaymentError(int code, String response, PaymentData data) { } ``` ### Checkout on iOS Implement `RazorpayPaymentCompletionProtocolWithData`: ``` ViewController.m #import <Razorpay/Razorpay.h> @interface ViewController () <RazorpayPaymentCompletionProtocol, UIWebViewDelegate> { Razorpay *razorpay; .. .. } @property(weak, nonatomic) IBOutlet UIWebView *myWebview; .. .. // Any place before initiating the payment (eg. viewDidLoad) - (void)viewDidLoad { [super viewDidLoad]; .. .. razorpay = [Razorpay initWithKey:@"rzp_test_1DP5mmOlF5G5ag" andDelegate:self withPaymentWebView:self.myWebview]; } ``` Success/Error handlers will receive a dictionary containing `order_id` and `signature`: ``` - (void)onPaymentSuccess:(nonnull NSString*)payment_id andData:(nullable NSDictionary *)response{ [[[UIAlertView alloc] initWithTitle:@"Payment Successful" message:payment_id delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; } - (void)onPaymentError:(int)code description:(nonnull NSString *)str andData:(nullable NSDictionary *)response { [[[UIAlertView alloc] initWithTitle:@"Error" message:str delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; } ``` [block:api-header] { "type": "basic", "title": "Entity" } [/block] The order entity consists of the following fields [block:parameters] { "data": { "0-0": "`id`", "0-1": "string", "1-0": "`amount`", "1-1": "integer", "2-0": "`currency`", "3-0": "`attempts`", "4-0": "`status`", "5-0": "`receipt`", "2-1": "string", "3-1": "integer", "4-1": "string", "5-1": "string", "h-0": "Attribute", "h-1": "Type", "0-2": "The order of this particular order", "1-2": "The amount (in paisa) that this order was created for", "2-2": "The currency associated with this order's amount", "3-2": "The number of payment attempts that have been made against this order", "4-2": "This order's status in the Order lifecycle", "5-2": "Your receipt id corresponding to this order. Maximum length 40 chars.", "h-2": "Description", "7-0": "`created_at`", "7-1": "timestamp", "7-2": "The timestamp corresponding to this order's creation time.", "8-0": "`notes`", "8-1": "object", "8-2": "Object consisting of notes passed while creating an order Entity", "6-0": "`payment_capture`", "6-1": "boolean", "6-2": "Flag for auto capturing the payment" }, "cols": 3, "rows": 9 } [/block] [block:callout] { "type": "warning", "body": "Once a successful payment is captured by you, the order status will advance to `paid`. \n\nThe order status will continue to remain `attempted` in the mean while. However no more payments can be made against this order.", "title": "Order Status" } [/block] [block:api-header] { "type": "post", "title": "/orders" } [/block] This endpoint creates an order. Following are the parameters that can be passed: [block:parameters] { "data": { "0-0": "amount\n_required_", "0-1": "Amount for the order in paisa. Payment can only be made for this amount against the order.", "1-0": "currency\n_required_", "1-1": "`INR` is the only supported currency currently.", "2-0": "receipt\n_required_", "2-1": "You receipt id for this order should be passed in here. Maximum length 40 characters.", "h-0": "Parameters", "h-1": "Description", "4-0": "notes\n_optional_", "4-1": "Object consisting of key value pairs as notes. Read more - [Notes Doc](https://docs.razorpay.com/docs/notes)", "3-0": "payment_capture\n_optional_", "3-1": "Payment capture flag for auto capturing payment" }, "cols": 2, "rows": 5 } [/block] Below is a sample curl request for creating an `order`. [block:code] { "codes": [ { "code": "curl -u rzp_test_26ccbdbfe0e84b:69b2e24411e384f91213f22a \\\n -X POST \\\n --data \"amount=500\" \\\n --data \"currency=INR\" \\\n --data \"receipt=Receipt #20\" \\\n https://api.razorpay.com/v1/orders", "language": "curl" }, { "code": "Dictionary<string, object> options = new Dictionary<string, object>();\noptions.Add(\"amount\", \"1000\");\noptions.Add(\"currency\", \"INR\");\noptions.Add(\"receipt\", \"<merchant-order-id>\");\n\nRazorpayClient client = new RazorpayClient(\"<key>\", \"<secret>\");\nOrder order = client.Order.Create(options);", "language": "csharp" } ] } [/block] The response is an orders entity. [block:code] { "codes": [ { "code": "{\n \"id\": \"order_4xbQrmEoA5WJ0G\",\n \"entity\": \"order\",\n \"amount\": 500,\n \"currency\": \"INR\",\n \"receipt\": \"Receipt #20\",\n \"status\": \"created\",\n \"attempts\": 0,\n \"created_at\": 1455696638,\n \"notes\": {}\n}", "language": "json" } ] } [/block] [block:api-header] { "type": "get", "title": "/orders" } [/block] This end point fetches the order details [block:parameters] { "data": { "h-0": "Params", "h-1": "Description", "0-0": "from\n_optional_", "0-1": "Timestamp from when orders are to be fetched", "2-0": "count\n_optional_", "2-1": "Count of orders to be fetched\nDefault Count is 10", "3-0": "skip\n_optional_", "3-1": "Numbers of orders to be skipped\nDefault Skip is 0", "1-0": "to\n_optional_", "1-1": "Timestamp up till when orders are to be fetched", "4-0": "authorized\n_optional_", "4-1": "Orders for which payments are currently in authorized state", "5-0": "receipt\n_optional_", "5-1": "Orders with the provided value for receipt" }, "cols": 2, "rows": 6 } [/block] Response [block:code] { "codes": [ { "code": "{\n \"entity\": \"collection\",\n \"count\": 2,\n \"items\": [\n {\n \"id\": \"order_4xbVikJiVknbcr\",\n \"entity\": \"order\",\n \"amount\": 500,\n \"currency\": \"INR\",\n \"receipt\": \"order36\",\n \"status\": \"created\",\n \"attempts\": 0,\n \"created_at\": 1455696913,\n \"notes\": {}\n },\n {\n \"id\": \"order_4xbSwsPABDJ8oK\",\n \"entity\": \"order\",\n \"amount\": 500,\n \"currency\": \"INR\",\n \"receipt\": \"order33\",\n \"status\": \"created\",\n \"attempts\": 0,\n \"created_at\": 1455696756,\n \"notes\": {}\n }\n ]\n}", "language": "json", "name": null } ] } [/block] [block:api-header] { "type": "get", "title": "/orders/:id" } [/block] This endpoint fetches the order details of a particular order. [block:parameters] { "data": { "h-0": "Params", "h-1": "Description", "0-0": "id\n_required_", "0-1": "Id of order to be fetched." }, "cols": 2, "rows": 1 } [/block] The response will be an order entity [block:code] { "codes": [ { "code": "{\n \"id\": \"order_4xbVikJiVknbcr\",\n \"entity\": \"order\",\n \"amount\": 600,\n \"currency\": \"INR\",\n \"receipt\": \"order33\",\n \"status\": \"created\",\n \"attempts\": 0,\n \"notes\": {},\n \"created_at\": 1455696913\n}", "language": "json" } ] } [/block] [block:api-header] { "type": "get", "title": "/orders/:id/payments" } [/block] The payments corresponding to an order can be obtained from the GET /orders/:id/payments API. [block:code] { "codes": [ { "code": "{\n \"count\": 1,\n \"entity\": \"collection\",\n \"items\": [\n {\n \"id\": \"pay_29QQoUBi66xm2f\",\n \"entity\": \"payment\",\n \"amount\": 600,\n \"currency\": \"INR\",\n \"status\": \"captured\",\n \"amount_refunded\": 0,\n \"refund_status\": null,\n \"email\": \"test@razorpay.com\",\n \"contact\": \"9364591752\",\n \"error_code\": null,\n \"error_description\": null,\n \"notes\": {},\n \"created_at\": 1400826750\n },\n ]\n}", "language": "json", "name": null } ] } [/block]