|
| 1 | +# Integrating a custom payment gateway |
| 2 | +Before you get started, make sure you [configured your merchant dashboard](/v3/custom-payment-gateway/merchant-configuration). |
| 3 | + |
| 4 | +## 1. Creating the checkout page |
| 5 | +The first step to integrate a custom payment gateway, is to create the checkout page. This is the page the user will be redirected to when using the custom gateway. We will redirect them to `YOUR_CHECKOUT_URL.com?publicToken=<THE_TOKEN>`. |
| 6 | + |
| 7 | +In the checkout page, you will want to retrieve information about the order. To do so, you will need to call our payment-session API endpoint. This will allow you to display order information on the checkout page. |
| 8 | +Learn how to [retrieve information about the payment session](/v3/custom-payment-gateway/definition#retrieve-a-payment-session). |
| 9 | + |
| 10 | +This is how our demo checkout page looks. It uses the [Payment Request API](https://developer.mozilla.org/en-US/docs/Web/API/Payment_Request_API). |
| 11 | + |
| 12 | +[see Github repo for more details](https://github.com/snipcart/paymentrequest-custom-gateway) |
| 13 | + |
| 14 | +## 2. Payment methods endpoint |
| 15 | +The second step to integrate a custom payment gateway, is to create the payment methods endpoint. The `publicToken` will be provided in the request body. |
| 16 | + |
| 17 | +__Make sure you [validate](/v3/custom-payment-gateway/definition#validate-public-token) the request was made by our API.__ |
| 18 | + |
| 19 | +[Payment methods webhook reference](/v3/custom-payment-gateway/definition#payment-methods). |
| 20 | +```javascript |
| 21 | +async (req, res) => { |
| 22 | + if (req.body && req.body.publicToken) { |
| 23 | + try { |
| 24 | + // Validate the request was made by Snipcart |
| 25 | + await axios.get(`https://payment.snipcart.com/api/public/custom-payment-gateway/validate?publicToken=${req.body.publicToken}`) |
| 26 | + |
| 27 | + // Return the payment methods |
| 28 | + return res.json([{ |
| 29 | + id: 'paymentrequest-custom-gateway', |
| 30 | + name: 'Google pay', |
| 31 | + checkoutUrl: 'https://paymentrequest-custom-gateway.snipcart.vercel.app', |
| 32 | + iconUrl: `https://paymentrequest-custom-gateway.snipcart.vercel.app/google_pay.png` |
| 33 | + }]) |
| 34 | + }catch(e){ |
| 35 | + // Couldn't validate the request |
| 36 | + console.error(e) |
| 37 | + return res.status(401).send() |
| 38 | + } |
| 39 | + } |
| 40 | + |
| 41 | + // No publicToken provided. This means the request was NOT made by Snipcart |
| 42 | + return res.status(401).send() |
| 43 | +} |
| 44 | +``` |
| 45 | + |
| 46 | +## 3. Confirm payment |
| 47 | +This endpoint is used to validate the Payment with Snipcart when the payment is approved by your payment gateway. It should be called with the payment information. This has to be done server-side since we don't want to leak our __secret__ API Key. |
| 48 | + |
| 49 | +[Create payment reference](/v3/custom-payment-gateway/definition#create-payment). |
| 50 | +```javascript |
| 51 | +async (req, res) => { |
| 52 | + |
| 53 | + // TODO: Validate the request was approved by your payment gateway (in this case Google Pay) |
| 54 | + |
| 55 | + // Parse the gateway payment info to match Snipcart's schema |
| 56 | + // This will change depending on the payment gateway you choose |
| 57 | + const paymentSessionId = req.query.sessionId |
| 58 | + const data = { |
| 59 | + paymentSessionId, |
| 60 | + state: 'processed', |
| 61 | + transactionId: req.body.requestId, |
| 62 | + instructions: 'Your payment will appear on your statement in the coming days', |
| 63 | + links: { |
| 64 | + refunds: `https://paymentrequest-custom-gateway.snipcart.vercel.app/api/refund?transactionId=${req.body.requestId}` |
| 65 | + }, |
| 66 | + } |
| 67 | + |
| 68 | + // Add authentification |
| 69 | + // This is the secret API key created in Snipcart's merchant dashboar |
| 70 | + const options = { |
| 71 | + headers: { |
| 72 | + Authorization: 'Bearer <YOUR_SECRET_API_KEY>' |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + try{ |
| 77 | + // Confirm payment with Snipcart |
| 78 | + const resp = await axios.post(`${process.env.PAYMENT_URL}/api/private/custom-payment-gateway/payment`,data, options) |
| 79 | + |
| 80 | + // ReturnUrl will redirect the user to the Order confirmation page of Snipcart |
| 81 | + return res.json({ |
| 82 | + returnUrl: resp.data.returnUrl |
| 83 | + }) |
| 84 | + }catch(e){ |
| 85 | + console.error(e) |
| 86 | + } |
| 87 | + |
| 88 | + return res.status(500).send() |
| 89 | +} |
| 90 | +``` |
| 91 | + |
| 92 | +## 4. Refund (Optional) |
| 93 | +This will be called when refunding an order via the merchant dashboard. |
| 94 | + |
| 95 | +__Make sure you [validate](/v3/custom-payment-gateway/definition#validate-public-token) the request was made by our API.__ |
| 96 | + |
| 97 | +[Refund webhook reference](/v3/custom-payment-gateway/definition#refund) |
| 98 | +```javascript |
| 99 | +async (req, res) => { |
| 100 | + const { transactionId } = req.query |
| 101 | + try { |
| 102 | + // Validate the request was made by Snipcart |
| 103 | + await axios.get(`https://payment.snipcart.com/api/public/custom-payment-gateway/validate?publicToken=${req.body.publicToken}`) |
| 104 | + |
| 105 | + // TODO: Refund the order via the gateway |
| 106 | + |
| 107 | + return res.json({ |
| 108 | + refundId: transactionId |
| 109 | + }) |
| 110 | + } catch (e) { |
| 111 | + // Couldn't validate the request |
| 112 | + console.error(e) |
| 113 | + return res.status(401) |
| 114 | + } |
| 115 | +} |
| 116 | +``` |
| 117 | + |
0 commit comments