braintree
Version:
A library for server-side integrating with Braintree.
677 lines (626 loc) • 22.9 kB
JavaScript
"use strict";
let Buffer = require("buffer").Buffer;
let Digest = require("./digest").Digest;
let Gateway = require("./gateway").Gateway;
let WebhookNotification = require("./webhook_notification").WebhookNotification;
let dateFormat = require("dateformat");
let wrapPrototype = require("@braintree/wrap-promise").wrapPrototype;
class WebhookTestingGateway extends Gateway {
constructor(gateway) {
super();
this.gateway = gateway;
this.config = this.gateway.config;
}
sampleNotification(kind, id, sourceMerchantId) {
const xml = this.sampleXml(kind, id, sourceMerchantId);
const payload = Buffer.from(xml).toString("base64") + "\n";
const signature = this.sampleSignature(payload);
return {
bt_signature: signature, // eslint-disable-line camelcase
bt_payload: payload, // eslint-disable-line camelcase
};
}
sampleSignature(payload) {
return `${this.gateway.config.publicKey}|${Digest.Sha1hexdigest(
this.gateway.config.privateKey,
payload
)}`;
}
sampleXml(kind, id, sourceMerchantId) {
let sourceMerchantIdXml = "";
if (sourceMerchantId) {
sourceMerchantIdXml = `<source-merchant-id>${sourceMerchantId}</source-merchant-id>`;
}
return `<notification>
<timestamp type="datetime">${dateFormat(
new Date(),
dateFormat.masks.isoUtcDateTime,
true
)}</timestamp>
<kind>${kind}</kind>
${sourceMerchantIdXml}
<subject>${this.subjectXmlFor(kind, id)}</subject>
</notification>`;
}
// eslint-disable-next-line complexity
subjectXmlFor(kind, id) {
switch (kind) {
case WebhookNotification.Kind.AccountUpdaterDailyReport:
return this.subjectXmlForAccountUpdaterDailyReport();
case WebhookNotification.Kind.Check:
return this.subjectXmlForCheck();
case WebhookNotification.Kind.ConnectedMerchantPayPalStatusChanged:
return this.subjectXmlForConnectedMerchantPayPalStatusChanged(id);
case WebhookNotification.Kind.ConnectedMerchantStatusTransitioned:
return this.subjectXmlForConnectedMerchantStatusTransitioned(id);
case WebhookNotification.Kind.Disbursement:
return this.subjectXmlForDisbursement(id);
case WebhookNotification.Kind.DisputeAccepted:
return this.subjectXmlForDisputeAccepted(id);
case WebhookNotification.Kind.DisputeAutoAccepted:
return this.subjectXmlForDisputeAutoAccepted(id);
case WebhookNotification.Kind.DisputeDisputed:
return this.subjectXmlForDisputeDisputed(id);
case WebhookNotification.Kind.DisputeExpired:
return this.subjectXmlForDisputeExpired(id);
case WebhookNotification.Kind.DisputeLost:
return this.subjectXmlForDisputeLost(id);
case WebhookNotification.Kind.DisputeOpened:
return this.subjectXmlForDisputeOpened(id);
case WebhookNotification.Kind.DisputeUnderReview:
return this.subjectXmlForDisputeUnderReview(id);
case WebhookNotification.Kind.DisputeWon:
return this.subjectXmlForDisputeWon(id);
case WebhookNotification.Kind.GrantedPaymentMethodRevoked:
return this.subjectXmlForGrantedPaymentMethodRevoked(id);
case WebhookNotification.Kind.GrantorUpdatedGrantedPaymentMethod:
return this.subjectXmlForGrantedPaymentInstrumentUpdate();
case WebhookNotification.Kind.LocalPaymentCompleted:
return this.subjectXmlForLocalPaymentCompleted(id);
case WebhookNotification.Kind.LocalPaymentExpired:
return this.subjectXmlForLocalPaymentExpired(id);
case WebhookNotification.Kind.LocalPaymentFunded:
return this.subjectXmlForLocalPaymentFunded(id);
case WebhookNotification.Kind.LocalPaymentReversed:
return this.subjectXmlForLocalPaymentReversed(id);
case WebhookNotification.Kind.OAuthAccessRevoked:
return this.subjectXmlForOAuthAccessRevocation(id);
case WebhookNotification.Kind.PartnerMerchantConnected:
return this.subjectXmlForPartnerMerchantConnected();
case WebhookNotification.Kind.PartnerMerchantDeclined:
return this.subjectXmlForPartnerMerchantDeclined();
case WebhookNotification.Kind.PartnerMerchantDisconnected:
return this.subjectXmlForPartnerMerchantDisconnected();
case WebhookNotification.Kind.PaymentMethodCustomerDataUpdated:
return this.subjectXmlForPaymentMethodCustomerDataUpdated(id);
case WebhookNotification.Kind.PaymentMethodRevokedByCustomer:
return this.subjectXmlForPaymentMethodRevokedByCustomer(id);
case WebhookNotification.Kind.RecipientUpdatedGrantedPaymentMethod:
return this.subjectXmlForGrantedPaymentInstrumentUpdate();
case WebhookNotification.Kind.RefundFailed:
return this.subjectXmlForRefundFailed(id);
case WebhookNotification.Kind.SubscriptionBillingSkipped:
return this.subjectXmlForSubscriptionBillingSkipped(id);
case WebhookNotification.Kind.SubscriptionChargedSuccessfully:
return this.subjectXmlForSubscriptionChargedSuccessfully(id);
case WebhookNotification.Kind.SubscriptionChargedUnsuccessfully:
return this.subjectXmlForSubscriptionChargedUnsuccessfully(id);
case WebhookNotification.Kind.TransactionDisbursed:
return this.subjectXmlForTransactionDisbursed(id);
case WebhookNotification.Kind.TransactionRetried:
return this.subjectXmlForTransactionRetried(id);
case WebhookNotification.Kind.TransactionReviewed:
return this.subjectXmlForTransactionReviewed(id);
case WebhookNotification.Kind.TransactionSettled:
return this.subjectXmlForTransactionSettled(id);
case WebhookNotification.Kind.TransactionSettlementDeclined:
return this.subjectXmlForTransactionSettlementDeclined(id);
default:
return this.subjectXmlForSubscription(id);
}
}
subjectXmlForAccountUpdaterDailyReport() {
return `<account-updater-daily-report>
<report-date type="date">2016-01-14</report-date>
<report-url>link-to-csv-report</report-url>
</account-updater-daily-report>`;
}
subjectXmlForCheck() {
return '<check type="boolean">true</check>';
}
subjectXmlForTransactionDisbursed(id) {
return `<transaction>
<id>${id}</id>
<amount>100</amount>
<disbursement-details>
<disbursement-date type="datetime">2013-07-09T18:23:29Z</disbursement-date>
</disbursement-details>
</transaction>`;
}
subjectXmlForTransactionRetried(id) {
return `<transaction>
<id>${id}</id>
<status>submitted_for_settlement</status>
<type>sale</type>
<currency-iso-code>USD</currency-iso-code>
<amount>100</amount>
<retried-transaction-id>original_txn_id</retried-transaction-id>
</transaction>`;
}
subjectXmlForTransactionReviewed(id) {
return `<transaction-review>
<transaction-id>${id}</transaction-id>
<decision>a smart decision</decision>
<reviewer-email>hey@girl.com</reviewer-email>
<reviewer-note>I reviewed this</reviewer-note>
<reviewed-time type="datetime">2021-04-20T06:09:00Z</reviewed-time>
</transaction-review>`;
}
subjectXmlForTransactionSettled(id) {
return `<transaction>
<id>${id}</id>
<status>settled</status>
<type>sale</type>
<currency-iso-code>USD</currency-iso-code>
<amount>100</amount>
<merchant-account-id>ogaotkivejpfayqfeaimuktty</merchant-account-id>
<payment-instrument-type>us_bank_account</payment-instrument-type>
<us-bank-account>
<routing-number>123456789</routing-number>
<last-4>1234</last-4>
<account-type>checking</account-type>
<account-holder-name>Dan Schulman</account-holder-name>
</us-bank-account>
</transaction>`;
}
subjectXmlForTransactionSettlementDeclined(id) {
return `<transaction>
<id>${id}</id>
<status>settlement_declined</status>
<type>sale</type>
<currency-iso-code>USD</currency-iso-code>
<amount>100</amount>
<merchant-account-id>ogaotkivejpfayqfeaimuktty</merchant-account-id>
<payment-instrument-type>us_bank_account</payment-instrument-type>
<us-bank-account>
<routing-number>123456789</routing-number>
<last-4>1234</last-4>
<account-type>checking</account-type>
<account-holder-name>Dan Schulman</account-holder-name>
</us-bank-account>
</transaction>`;
}
subjectXmlForDisputeUnderReview(id) {
return `<dispute>
<amount>250.00</amount>
<amount-disputed>250.0</amount-disputed>
<amount-won>245.00</amount-won>
<currency-iso-code>USD</currency-iso-code>
<received-date type="date">2014-03-01</received-date>
<reply-by-date type="date">2014-03-21</reply-by-date>
<kind>chargeback</kind>
<status>under_review</status>
<reason>fraud</reason>
<id>${id}</id>
<transaction>
<id>${id}</id>
<amount>250.00</amount>
</transaction>
<date-opened type="date">2014-03-28</date-opened>
</dispute>`;
}
subjectXmlForDisputeOpened(id) {
return `<dispute>
<amount>250.00</amount>
<amount-disputed>250.0</amount-disputed>
<amount-won>245.00</amount-won>
<currency-iso-code>USD</currency-iso-code>
<received-date type="date">2014-03-01</received-date>
<reply-by-date type="date">2014-03-21</reply-by-date>
<kind>chargeback</kind>
<status>open</status>
<reason>fraud</reason>
<id>${id}</id>
<transaction>
<id>${id}</id>
<amount>250.00</amount>
</transaction>
<date-opened type="date">2014-03-28</date-opened>
</dispute>`;
}
subjectXmlForDisputeLost(id) {
return `<dispute>
<amount>250.00</amount>
<amount-disputed>250.0</amount-disputed>
<amount-won>245.00</amount-won>
<currency-iso-code>USD</currency-iso-code>
<received-date type="date">2014-03-01</received-date>
<reply-by-date type="date">2014-03-21</reply-by-date>
<kind>chargeback</kind>
<status>lost</status>
<reason>fraud</reason>
<id>${id}</id>
<transaction>
<id>${id}</id>
<amount>250.00</amount>
</transaction>
<date-opened type="date">2014-03-28</date-opened>
</dispute>`;
}
subjectXmlForDisputeWon(id) {
return `<dispute>
<amount>250.00</amount>
<amount-disputed>250.0</amount-disputed>
<amount-won>245.00</amount-won>
<currency-iso-code>USD</currency-iso-code>
<received-date type="date">2014-03-01</received-date>
<reply-by-date type="date">2014-03-21</reply-by-date>
<kind>chargeback</kind>
<status>won</status>
<reason>fraud</reason>
<id>${id}</id>
<transaction>
<id>${id}</id>
<amount>250.00</amount>
</transaction>
<date-opened type="date">2014-03-28</date-opened>
<date-won type="date">2014-09-01</date-won>
</dispute>`;
}
subjectXmlForDisputeAccepted(id) {
return `<dispute>
<amount>250.00</amount>
<amount-disputed>250.0</amount-disputed>
<amount-won>245.00</amount-won>
<currency-iso-code>USD</currency-iso-code>
<received-date type="date">2014-03-01</received-date>
<reply-by-date type="date">2014-03-21</reply-by-date>
<kind>chargeback</kind>
<status>accepted</status>
<reason>fraud</reason>
<id>${id}</id>
<transaction>
<id>${id}</id>
<amount>250.00</amount>
</transaction>
<date-opened type="date">2014-03-28</date-opened>
</dispute>`;
}
subjectXmlForDisputeAutoAccepted(id) {
return `<dispute>
<amount>250.00</amount>
<amount-disputed>250.0</amount-disputed>
<amount-won>245.00</amount-won>
<currency-iso-code>USD</currency-iso-code>
<received-date type="date">2014-03-01</received-date>
<reply-by-date type="date">2014-03-21</reply-by-date>
<kind>chargeback</kind>
<status>auto_accepted</status>
<reason>fraud</reason>
<id>${id}</id>
<transaction>
<id>${id}</id>
<amount>250.00</amount>
</transaction>
<date-opened type="date">2014-03-28</date-opened>
</dispute>`;
}
subjectXmlForDisputeDisputed(id) {
return `<dispute>
<amount>250.00</amount>
<amount-disputed>250.0</amount-disputed>
<amount-won>245.00</amount-won>
<currency-iso-code>USD</currency-iso-code>
<received-date type="date">2014-03-01</received-date>
<reply-by-date type="date">2014-03-21</reply-by-date>
<kind>chargeback</kind>
<status>disputed</status>
<reason>fraud</reason>
<id>${id}</id>
<transaction>
<id>${id}</id>
<amount>250.00</amount>
</transaction>
<date-opened type="date">2014-03-28</date-opened>
</dispute>`;
}
subjectXmlForDisputeExpired(id) {
return `<dispute>
<amount>250.00</amount>
<amount-disputed>250.0</amount-disputed>
<amount-won>245.00</amount-won>
<currency-iso-code>USD</currency-iso-code>
<received-date type="date">2014-03-01</received-date>
<reply-by-date type="date">2014-03-21</reply-by-date>
<kind>chargeback</kind>
<status>expired</status>
<reason>fraud</reason>
<id>${id}</id>
<transaction>
<id>${id}</id>
<amount>250.00</amount>
</transaction>
<date-opened type="date">2014-03-28</date-opened>
</dispute>`;
}
subjectXmlForDisbursement(id) {
return `<disbursement>
<id>${id}</id>
<transaction-ids type="array">
<item>afv56j</item>
<item>kj8hjk</item>
</transaction-ids>
<success type="boolean">true</success>
<retry type="boolean">false</retry>
<merchant-account>
<id>merchant_account_token</id>
<currency-iso-code>USD</currency-iso-code>
<sub-merchant-account type="boolean">false</sub-merchant-account>
<status>active</status>
</merchant-account>
<amount>100.00</amount>
<disbursement-date type="date">2014-02-10</disbursement-date>
<exception-message nil="true"/>
<follow-up-action nil="true"/>
</disbursement>`;
}
subjectXmlForGrantedPaymentInstrumentUpdate() {
return `<granted-payment-instrument-update>
<grant-owner-merchant-id>vczo7jqrpwrsi2px</grant-owner-merchant-id>
<grant-recipient-merchant-id>cf0i8wgarszuy6hc</grant-recipient-merchant-id>
<payment-method-nonce>
<nonce>ee257d98-de40-47e8-96b3-a6954ea7a9a4</nonce>
<consumed type="boolean">false</consumed>
<locked type="boolean">false</locked>
</payment-method-nonce>
<token>abc123z</token>
<updated-fields type="array">
<item>expiration-month</item>
<item>expiration-year</item>
</updated-fields>
</granted-payment-instrument-update>`;
}
subjectXmlForRefundFailed(id) {
return `<transaction>
<id>${id}</id>
<amount>100</amount>
<credit-card>
<number>1234560000001234</number>
<cvv>123</cvv>
<card-type>MasterCard</card-type>
</credit-card>
<status>processor_declined</status>
<refunded-transaction-fk>1</refunded-transaction-fk>
</transaction>`;
}
errorSampleXml() {
return `<error>
<code>82621</code>
<message>Credit score is too low</message>
<attribute type=\"symbol\">base</attribute>
</error>`;
}
subjectXmlForSubscription(id) {
return `<subscription>
<id>${id}</id>
<transactions type="array"></transactions>
<add_ons type="array"></add_ons>
<discounts type="array"></discounts>
</subscription>`;
}
subjectXmlForSubscriptionBillingSkipped(id) {
return `<subscription>
<id>${id}</id>
<transactions type="array"></transactions>
<add_ons type="array"></add_ons>
<discounts type="array"></discounts>
</subscription>`;
}
subjectXmlForSubscriptionChargedSuccessfully(id) {
return `<subscription>
<id>${id}</id>
<transactions type="array">
<transaction>
<id>${id}</id>
<status>submitted_for_settlement</status>
<amount>49.99</amount>
</transaction>
</transactions>
<add_ons type="array"></add_ons>
<discounts type="array"></discounts>
</subscription>`;
}
subjectXmlForSubscriptionChargedUnsuccessfully(id) {
return `<subscription>
<id>${id}</id>
<transactions type="array">
<transaction>
<id>${id}</id>
<status>failed</status>
<amount>49.99</amount>
</transaction>
</transactions>
<add_ons type="array"></add_ons>
<discounts type="array"></discounts>
</subscription>`;
}
subjectXmlForGrantedPaymentMethodRevoked(id) {
return this._venmoAccountXml(id);
}
subjectXmlForPartnerMerchantConnected() {
return `<partner-merchant>
<merchant-public-id>public_id</merchant-public-id>
<public-key>public_key</public-key>
<private-key>private_key</private-key>
<partner-merchant-id>abc123</partner-merchant-id>
<client-side-encryption-key>cse_key</client-side-encryption-key>
</partner-merchant>`;
}
subjectXmlForPartnerMerchantDisconnected() {
return `<partner-merchant>
<partner-merchant-id>abc123</partner-merchant-id>
</partner-merchant>`;
}
subjectXmlForConnectedMerchantStatusTransitioned(id) {
return `<connected-merchant-status-transitioned>
<merchant-public-id>${id}</merchant-public-id>
<status>new_status</status>
<oauth-application-client-id>oauth_application_client_id</oauth-application-client-id>
</connected-merchant-status-transitioned>`;
}
subjectXmlForConnectedMerchantPayPalStatusChanged(id) {
return `<connected-merchant-paypal-status-changed>
<merchant-public-id>${id}</merchant-public-id>
<action>link</action>
<oauth-application-client-id>oauth_application_client_id</oauth-application-client-id>
</connected-merchant-paypal-status-changed>`;
}
subjectXmlForPartnerMerchantDeclined() {
return `<partner-merchant>
<partner-merchant-id>abc123</partner-merchant-id>
</partner-merchant>`;
}
subjectXmlForOAuthAccessRevocation(id) {
return `<oauth-application-revocation>
<merchant-id>${id}</merchant-id>
<oauth-application-client-id>oauth_application_client_id</oauth-application-client-id>
</oauth-application-revocation>`;
}
subjectXmlForPaymentMethodRevokedByCustomer(id) {
return `<paypal-account>
<billing-agreement-id>a-billing-agreement-id</billing-agreement-id>
<created-at type="datetime">2019-01-01T12:00:00Z</created-at>
<customer-id>a-customer-id</customer-id>
<default type="boolean">true</default>
<email>name@email.com</email>
<global-id>cGF5bWVudG1ldGhvZF9jaDZieXNz</global-id>
<image-url>https://assets.braintreegateway.com/payment_method_logo/paypal.png?environment=test</image-url>
<subscriptions type="array"/>
<token>${id}</token>
<updated-at type="datetime">2019-01-02T12:00:00Z</updated-at>
<is-channel-initiated nil="true"/>
<payer-id>a-payer-id</payer-id>
<payer-info nil="true"/>
<limited-use-order-id nil="true"/>
<revoked-at type="datetime">2019-01-02T12:00:00Z</revoked-at>
</paypal-account>`;
}
subjectXmlForLocalPaymentCompleted(id) {
if (id === "blik_one_click_id") {
return this.blikOneClickSubjectXmlForLocalPaymentCompleted();
}
return this.defaultSubjectXmlForLocalPaymentCompleted();
}
defaultSubjectXmlForLocalPaymentCompleted() {
return `<local-payment>
<bic>a-bic</bic>
<iban-last-chars>1234</iban-last-chars>
<payer-id>a-payer-id</payer-id>
<payer-name>a-payer-name</payer-name>
<payment-id>a-payment-id</payment-id>
<payment-method-nonce>ee257d98-de40-47e8-96b3-a6954ea7a9a4</payment-method-nonce>
<transaction>
<id>1</id>
<status>authorizing</status>
<amount>10.00</amount>
<order-id>order1234</order-id>
</transaction>
</local-payment>`;
}
blikOneClickSubjectXmlForLocalPaymentCompleted() {
return `<local-payment>
<bic>a-bic</bic>
<blik-aliases type='array'>
<blik-alias>
<key>alias-key-1</key>
<label>alias-label-1</label>
</blik-alias>
</blik-aliases>
<iban-last-chars>1234</iban-last-chars>
<payer-id>a-payer-id</payer-id>
<payer-name>a-payer-name</payer-name>
<payment-id>a-payment-id</payment-id>
<payment-method-nonce>ee257d98-de40-47e8-96b3-a6954ea7a9a4</payment-method-nonce>
<transaction>
<id>1</id>
<status>authorizing</status>
<amount>10.00</amount>
<order-id>order1234</order-id>
</transaction>
</local-payment>`;
}
subjectXmlForLocalPaymentExpired() {
return `<local-payment-expired>
<payment-id>a-payment-id</payment-id>
<payment-context-id>a-payment-context-id</payment-context-id>
</local-payment-expired>`;
}
subjectXmlForLocalPaymentFunded() {
return `<local-payment-funded>
<payment-id>a-payment-id</payment-id>
<payment-context-id>a-payment-context-id</payment-context-id>
<transaction>
<id>1</id>
<status>settled</status>
<amount>10.00</amount>
<order-id>order1234</order-id>
</transaction>
</local-payment-funded>`;
}
subjectXmlForLocalPaymentReversed() {
return `<local-payment-reversed>
<payment-id>a-payment-id</payment-id>
</local-payment-reversed>`;
}
subjectXmlForPaymentMethodCustomerDataUpdated(id) {
return `<payment-method-customer-data-updated-metadata>
<token>TOKEN-12345</token>
<payment-method>
${this._venmoAccountXml(id)}
</payment-method>
<datetime-updated type='dateTime'>2022-01-01T21:28:37Z</datetime-updated>
<enriched-customer-data>
<fields-updated type='array'>
<item>username</item>
</fields-updated>
<profile-data>
<username>venmo_username</username>
<first-name>John</first-name>
<last-name>Doe</last-name>
<phone-number>1231231234</phone-number>
<email>john.doe@paypal.com</email>
<billing-address>
<street-address>Billing Street Address</street-address>
<extended-address>Billing Extended Address</extended-address>
<locality>Locality</locality>
<region>Region</region>
<postal-code>Postal Code</postal-code>
</billing-address>
<shipping-address>
<street-address>Shipping Street Address</street-address>
<extended-address>Shipping Extended Address</extended-address>
<locality>Locality</locality>
<region>Region</region>
<postal-code>Postal Code</postal-code>
</shipping-address>
</profile-data>
</enriched-customer-data>
</payment-method-customer-data-updated-metadata>`;
}
_venmoAccountXml(id) {
return `<venmo-account>
<default type="boolean">true</default>
<image-url>https://assets.braintreegateway.com/payment_method_logo/venmo.png?environment=test</image-url>
<token>${id}</token>
<source-description>Venmo Account: venmojoe</source-description>
<username>venmojoe</username>
<venmo-user-id>456</venmo-user-id>
<subscriptions type="array"/>
<customer-id>venmo_customer_id</customer-id>
<global-id>cGF5bWVudG1ldGhvZF92ZW5tb2FjY291bnQ</global-id>
</venmo-account>`;
}
}
module.exports = {
WebhookTestingGateway: wrapPrototype(WebhookTestingGateway),
};