如何使用 MERN 中的 webhook API 端点从 NMI 支付网关获取定期自动付款

问题描述 投票:0回答:1

我正在使用 NMI 进行支付集成。我已经创建了 NMI API,用于使用此文档添加自定义订阅。

我正在使用 webhooks API 端点来获取这些信息以及付款和订阅的状态。我在其中获取订阅的添加和删除信息,但没有获取定期自动付款信息。我已订阅每日基础,因此经常性费用将通过信用卡自动付款,我将使用 NMI webhook API 获取信息。我没有获得这些经常性自动付款详细信息。我将这些信息存储在我的 MongoDb 中。我不知道如何获取定期自动付款详细信息,例如付款成功或拒绝或其他状态。 注意:我已经添加了每日经常性费用,以便我可以获得这些付款响应,但我仍然没有收到任何自动付款。

我的 Webhook API :

router.post("/nmi", async (req, res) => {
  try {
    const signingKey = "MY SIGNING KEY";
    const webhookBody = JSON.stringify(req.body); // Assuming body is JSON
    const sigHeader = req.headers["webhook-signature"];

    if (!sigHeader || sigHeader.length < 1) {
      throw new Error("Invalid webhook - signature header missing");
    }

    const sigMatches = sigHeader.match(/t=(.*),s=(.*)/);
    if (!sigMatches || sigMatches.length !== 3) {
      throw new Error("Unrecognized webhook signature format");
    }

    const nonce = sigMatches[1];
    const signature = sigMatches[2];

    if (!webhookIsVerified(webhookBody, signingKey, nonce, signature)) {
      throw new Error(
        "Invalid webhook - invalid signature, cannot verify sender"
      );
    }

    // Webhook is now verified to have been sent by you, continue processing
    console.log("Webhook is verified");
    const webhook = req.body; // Assuming JSON payload

    if (webhook.event_type === "recurring.subscription.add") {
parsedWebhook.event_body.subscription_id})

      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging added",
        amount: webhook.event_body.plan.amount,
      });
      console.log("req.body is here : ", req.body);
      await payment.save();
    } else if (webhook.event_type === "recurring.subscription.update") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging subscription update",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "recurring.subscription.delete") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging subscription delete",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "recurring.plan.add") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging plan add",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "recurring.plan.update") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging plan update",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "recurring.plan.delete") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging plan delete",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.auth.failure") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction auth failure",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.auth.success") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction auth success",
        amount: webhook.event_body.plan.amount,
      });

      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.auth.unknown") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction auth unknown",
        amount: webhook.event_body.plan.amount,
      });

      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.capture.success") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction capture success",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.capture.failure") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction capture failure",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.capture.unknown") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction capture unknown",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.credit.success") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction credit success",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.credit.failure") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction credit failure",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.credit.unknown") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction credit unknown",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "settlement.batch.complete") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging settlement batch complete",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "settlement.batch.failure") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging settlement batch failure",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.sale.failure") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction sale failure",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.sale.success") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction sale success",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.sale.unknown") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction sale unknown",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.void.success") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction void success",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.void.failure") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction void failure",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.void.unknown") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction void unknown",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.refund.success") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction refund success",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.refund.failure") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction refund failure",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.refund.unknown") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction refund unknown",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.validate.success") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction validate success",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.validate.failure") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction validate failure",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "transaction.validate.unknown") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging transaction validate unknown",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    } else if (webhook.event_type === "chargeback.batch.complete") {
      const payment = await AutoRecPayments.create({
        nmisubscriptionId: webhook.event_body.subscription_id,
        email: webhook.event_body.billing_address.email,
        description: "Recurring charging chargeback batch complete",
        amount: webhook.event_body.plan.amount,
      });
      //Save payment details of the user in payment collection
      await payment.save();
    }

    res.status(200).send("Webhook processed successfully");
  } catch (error) {
    console.error("Error handling webhook:", error);
    res.status(500).send("Error processing webhook");
  }
});

这里是自定义订阅 API :

router.post("/custom-add-subscription", async (req, res) => {
  try {
    
    const {
      security_key,
      recurring,
      plan_payments,
      plan_amount,
      dayFrequency,
      ccnumber,
      ccexp,
      first_name,
      last_name,
      address,
      email,
    } = req.body;

    let postData = {
      security_key: "MY SIGNING KEY",
      recurring: "add_subscription",
      plan_payments,
      plan_amount,
      day_frequency: dayFrequency ? dayFrequency : 30,
      ccnumber,
      ccexp,
      first_name: first_name,
      last_name: last_name,
      address1: address,
      email,
    };
    
    postData = querystring.stringify(postData);

    var config = {
      method: "post",
      url: "https://secure.nmi.com/api/transact.php",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
      },
      data: postData,
    };
    axios(config)
      .then(async (response) => {
        const parsedResponse = querystring.parse(response.data);
        console.log("ek ek krne", parsedResponse);
        if (parsedResponse.response_code == 100) {
          // Handle successful subscription creation
          sendResponse(res, "Custom subscription added successfully.");
        } else {
          // Handle subscription creation failure
          sendResponse(res, parsedResponse.responsetext, 403);
        }
      })
      .catch(function (error) {
        sendResponse(res, error, 500);
      });
  } catch (error) {
    sendResponse(res, "Something went wrong!", 500);
  }
});

reactjs node.js webhooks payment-gateway nmi
1个回答
0
投票

我也遇到了和你一样的问题,我联系了 NMI 支持团队,这是支持团队的回复。

重复性 Webhooks 将显示为信用卡销售 Webhooks,但是 其来源重复出现,以区分其起源。 请订阅 "event_type": "transaction.sale.success" WebHook, 接收定期交易详细信息。另外,重复失败 交易将以同样的方式出现,但是 transaction.sale.failure Webhook 事件,而不是 success。
“transaction.sale.success”示例,来源为重复出现 (“来源”:“经常性”)

{
"event_id": "9b312dfd-3174-4748-9447-d63c8744305a",
"event_type": "transaction.sale.success",
"event_body": {
    "merchant": {
        "id": "1234",
        "name": "Test Account"
    },
    "features": {
        "is_test_mode": true
    },
    "transaction_id": "1234560000",
    "transaction_type": "cc",
    "condition": "pendingsettlement",
    "processor_id": "ccprocessora",
    "ponumber": "123456789",
    "order_description": "this is a description",
    "order_id": "12345678",
    "customerid": "",
    "customertaxid": "",
    "website": "https://example.com",
    "shipping": "",
    "currency": "USD",
    "tax": "0.08",
    "surcharge": "",
    "cash_discount": "",
    "tip": "",
    "requested_amount": "54.04",
    "shipping_carrier": "",
    "tracking_number": "",
    "shipping_date": "",
    "partial_payment_id": "",
    "partial_payment_balance": "",
    "platform_id": "",
    "authorization_code": "123456",
    "social_security_number": "",
    "drivers_license_number": "",
    "drivers_license_state": "",
    "drivers_license_dob": "",
    "billing_address": {
        "first_name": "Jessica",
        "last_name": "Jones",
        "address_1": "123 Fake St.",
        "address_2": "123123",
        "company": "Alias Investigations",
        "city": "New York City",
        "state": "NY",
        "postal_code": "12345",
        "country": "US",
        "email": "[email protected]",
        "phone": "555-555-5555",
        "cell_phone": "",
        "fax": "444-555-6666"
    },
    "shipping_address": {
        "first_name": "Jessica",
        "last_name": "Jones",
        "address_1": "123 Fake St.",
        "address_2": "123123",
        "company": "Alias Investigations",
        "city": "New York City",
        "state": "NY",
        "postal_code": "12345",
        "country": "US",
        "email": "[email protected]",
        "phone": "",
        "fax": ""
    },
    "card": {
        "cc_number": "411111******1111",
        "cc_exp": "1022",
        "cavv": "",
        "cavv_result": "",
        "xid": "",
        "eci": "",
        "avs_response": "N",
        "csc_response": "",
        "cardholder_auth": "",
        "cc_start_date": "",
        "cc_issue_number": "",
        "card_balance": "",
        "card_available_balance": "",
        "entry_mode": "",
        "cc_bin": "",
        "cc_type": ""
    },
    "action": {
        "amount": "54.04",
        "action_type": "sale",
        "date": "20200406175755",
        "success": "1",
        "ip_address": "1.2.3.4",
        "source": "recurring",
        "api_method": "virtual_terminal",
        "username": "exampleuser",
        "response_text": "SUCCESS",
        "response_code": "100",
        "processor_response_text": "",
        "processor_response_code": "",
        "device_license_number": "",
        "device_nickname": ""
    }
}

}

希望这对您有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.