我正在使用 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);
}
});
我也遇到了和你一样的问题,我联系了 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": ""
}
}
}
希望这对您有帮助。