5

我正在使用 ASP.NET MVC 4、.NET Braintree Payments API 和 Braintree.js。

这是我为 Braintree 构建的一个简单包装器:

public class PaymentBL
{
    private static BraintreeGateway _braintreeGateway = new BraintreeGateway
        {
            Environment = Braintree.Environment.SANDBOX,
            MerchantId = "xxxxxxx",
            PublicKey = "xxxxxxxxxxxx",
            PrivateKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        };

    public Result<Transaction> ChargeCardOnce(decimal amount, string cardholderName, string cardNumber, string expiration,
        string cvv)
    {
        TransactionCreditCardRequest creditCardRequest = new TransactionCreditCardRequest();
        creditCardRequest.CardholderName = cardholderName;
        creditCardRequest.Number = cardNumber;
        creditCardRequest.ExpirationDate = expiration;
        creditCardRequest.CVV = cvv;

        TransactionOptionsRequest optionsRequest = new TransactionOptionsRequest();
        optionsRequest.SubmitForSettlement = true;

        TransactionRequest transactionRequest = new TransactionRequest();
        transactionRequest.Amount = amount;
        transactionRequest.CreditCard = creditCardRequest;
        transactionRequest.Options = optionsRequest;

        return _braintreeGateway.Transaction.Sale(transactionRequest);
    }

    /// <summary>
    /// Stores a credit card in the Braintree vault.  In some cases, will put a $1 temporary charge
    /// on the credit card that will come off a few days later.
    /// 
    /// From BrainTree: Regardless of card type, any instance where a $1 authorization returns a successful result, 
    /// we immediately follow-up with an automatic void request to ensure that the transaction will fall off 
    /// of the cardholder's statement as soon as possible.
    /// </summary>
    public Result<CreditCard> StoreCustomer(int customerId, string cardholderName, string cardNumber, string expiration, string cvv)
    {
        //CreditCardAddressRequest addressRequest = new CreditCardAddressRequest();
        //addressRequest.PostalCode = postalCode;

        CreditCardOptionsRequest optionsRequest = new CreditCardOptionsRequest();
        optionsRequest.VerifyCard = true;
        optionsRequest.VerificationMerchantAccountId = _braintreeGateway.MerchantId;

        CreditCardRequest creditCard = new CreditCardRequest();
        creditCard.CustomerId = customerId.ToString();
        creditCard.Token = customerId.ToString();   // Use same token to ensure overwrite
        creditCard.CardholderName = cardholderName;
        creditCard.Number = cardNumber;
        creditCard.ExpirationDate = expiration;
        creditCard.CVV = cvv;
        creditCard.Options = optionsRequest;

        return _braintreeGateway.CreditCard.Create(creditCard);
    }

    /// <summary>
    /// Search BrainTree vault to retrieve credit card
    /// </summary>
    /// <param name="customerId"></param>
    public CreditCard GetCreditCardOnFile(int customerId)
    {
        Customer customer = null;

        try
        {
            customer = _braintreeGateway.Customer.Find(customerId.ToString());
        }
        catch (Braintree.Exceptions.NotFoundException)
        {
            return null;
        }

        if (customer.CreditCards == null || customer.CreditCards.Length == 0)
        {
            return null;
        }

        if (customer.CreditCards.Length >= 2)
        {
            throw new Exception(string.Format("Customer {0} has {1} credit cards",
                customerId, customer.CreditCards.Length));
        }

        return customer.CreditCards[0];
    }
}

当我调用此方法时,它可以工作:

            Result<Transaction> result = paymentBL.ChargeCardOnce(
                2.34m
                , formCollection["name"]
                , formCollection["number"]
                , formCollection["exp"]
                , formCollection["cvv"]
            );

随后,我可以在 Braintree 仪表板中查看已完成的测试事务。因此,我知道来自 Braintree.js 的加密表单值正确地到达了我的控制器操作,并且我的密钥和商家帐户 ID 都已正确设置。

当我将上述对 ChargeCardOnce 的调用替换为对 StoreCustomer 的以下调用时,我在该行收到 Braintree.Exceptions.AuthorizationExceptionreturn _braintreeGateway.CreditCard.Create(creditCard);

            Result<CreditCard> result = paymentBL.StoreCustomer(
                systemHost.Customer.CustomerId
                , formCollection["name"]
                , formCollection["number"]
                , formCollection["exp"]
                , formCollection["cvv"]
            );

来自 Braintree 支持:“您可以在沙盒中创建客户和信用卡,因为它的构建完全反映了生产环境的样子。”

有没有人也经历过这个?我指的是 Braintree 对这个问题的支持,但如果 SO 上的任何人都看到了这一点并且知道解决方案或解决方法,我会松一口气。

4

1 回答 1

18

我在布伦特里工作。看起来我们已经回复了您的问题的答案,但我也会在这里为将来遇到相同问题的任何人回答。

在这种情况下,问题是:

optionsRequest.VerificationMerchantAccountId = _braintreeGateway.MerchantId;

您的商家 ID 标识您的支付网关帐户,而您的商家帐户 ID 标识您要用于验证的银行帐户。我们支持中心的一篇文章解释了不同之处

MerchantAccountId

使用 Braintree,您可以拥有多个商家帐户,所有这些帐户都通过同一个网关帐户进行处理。这意味着您可以在一个帐户下设置和处理多个位置、多个业务、多种货币等。这使您可以通过统一的报告和访问轻松跟踪您的所有处理,甚至可以为您节省资金。

您可以按照以下步骤在您的网关账户中找到所有商家账户的 ID:

  • 登录到您的帐户

  • 将鼠标悬停在您的帐户名称上,然后单击“处理中”

  • 滚动到页面底部到标有“商家帐户”的部分。

AnAuthorizationExceptionHTTP 状态码 403 Forbidden。这意味着服务器正在拒绝您的请求,因为您无权访问资源(即使您可能已通过身份验证)。

由于您指定的 ID 没有可供您的用户使用的商家帐户(因为它根本不是商家帐户 ID),因此您将获得AuthorizationException.

如果您的商家通常只有一个商家账户,或者您想使用默认账户,则无需指定VerificationMerchantAccountId.

于 2013-03-28T01:15:12.953 回答