65.9K
CodeProject 正在变化。 阅读更多。
Home

Braintree 支付 - ASP.Net Core2.1

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2018年8月16日

CPOL

1分钟阅读

viewsIcon

36990

downloadIcon

429

在本文中,我们将使用 ASP.NET Core 2.1 实现 Braintree 支付网关。

引言

基于 之前的文章,本文将扩展实现支付网关。我们将通过从 github 下载完整的源代码来修改/扩展现有的示例应用程序。

让我们从打开现有应用程序开始,首先,我们将添加 Braintree 包。转到 NuGet 安装 Braintree .NET 客户端库,它同时支持 .NET Framework 和 .NET Core。

配置:这是我们为 Braintree 配置环境、商家和 API 密钥的地方。

public class BraintreeConfiguration : IBraintreeConfiguration
{
    public string Environment { get; set; }
    public string MerchantId { get; set; }
    public string PublicKey { get; set; }
    public string PrivateKey { get; set; }
    private IBraintreeGateway BraintreeGateway { get; set; }

    public IBraintreeGateway CreateGateway()
    {
        Environment = System.Environment.GetEnvironmentVariable("BraintreeEnvironment");
        MerchantId = System.Environment.GetEnvironmentVariable("BraintreeMerchantId");
        PublicKey = System.Environment.GetEnvironmentVariable("BraintreePublicKey");
        PrivateKey = System.Environment.GetEnvironmentVariable("BraintreePrivateKey");

        if (MerchantId == null || PublicKey == null || PrivateKey == null)
        {
            Environment = "sandbox";
            MerchantId = "9j4ynyf697k9685t";
            PublicKey = "25sy94dv3rqgg355";
            PrivateKey = "b0d5e1b1fa9dc24c263a3e83a148a7b3";
        }

        return new BraintreeGateway(Environment, MerchantId, PublicKey, PrivateKey);
    }

    public IBraintreeGateway GetGateway()
    {
        if (BraintreeGateway == null)
        {
            BraintreeGateway = CreateGateway();
        }

        return BraintreeGateway;
    }
}

支付控制器

生成客户端令牌:最初,名为 GenerateTokenHttpGet 方法被调用以生成客户端令牌,用于授权以初始化客户端 UI。

[HttpGet, Route("GenerateToken")]
public object GenerateToken()
{
    var gateway = config.GetGateway();
    var clientToken = gateway.ClientToken.Generate();
    return clientToken;
}

创建交易:最后,使用 AmountPaymentMethodNonce 完成交易,这是由客户端脚本生成的客户的支付授权。

[HttpPost, Route("Checkout")]
public object Checkout(vmCheckout model)
{
    string paymentStatus = string.Empty;
    var gateway = config.GetGateway();

    var request = new TransactionRequest
    {
        Amount = model.Price,
        PaymentMethodNonce = model.PaymentMethodNonce,
        Options = new TransactionOptionsRequest
        {
            SubmitForSettlement = true
        }
    };

    Result<Transaction> result = gateway.Transaction.Sale(request);
    if (result.IsSuccess())
    {
        paymentStatus = "Succeded";

        //Do Database Operations Here
    }
    else
    {
        string errorMessages = "";
        foreach (ValidationError error in result.Errors.DeepAll())
        {
            errorMessages += "Error: " + (int)error.Code + " - " + error.Message + "\n";
        }

        paymentStatus = errorMessages;
    }

    return paymentStatus;
}

最后,完整的支付控制器。

[ApiController, Route("api/[controller]"), Produces("application/json")]
public class PaymentsController : ControllerBase
{
    public IBraintreeConfiguration config = new BraintreeConfiguration();

    public static readonly TransactionStatus[] transactionSuccessStatuses =
        {
            TransactionStatus.AUTHORIZED,
            TransactionStatus.AUTHORIZING,
            TransactionStatus.SETTLED,
            TransactionStatus.SETTLING,
            TransactionStatus.SETTLEMENT_CONFIRMED,
            TransactionStatus.SETTLEMENT_PENDING,
            TransactionStatus.SUBMITTED_FOR_SETTLEMENT
        };

    [HttpGet, Route("GenerateToken")]
    public object GenerateToken()
    {
        var gateway = config.GetGateway();
        var clientToken = gateway.ClientToken.Generate();
        return clientToken;
    }

    [HttpPost, Route("Checkout")]
    public object Checkout(vmCheckout model)
    {
        string paymentStatus = string.Empty;
        var gateway = config.GetGateway();

        var request = new TransactionRequest
        {
            Amount = model.Price,
            PaymentMethodNonce = model.PaymentMethodNonce,
            Options = new TransactionOptionsRequest
            {
                SubmitForSettlement = true
            }
        };

        Result<Transaction> result = gateway.Transaction.Sale(request);
        if (result.IsSuccess())
        {
            paymentStatus = "Succeded";

            //Do Database Operations Here
        }
        else
        {
            string errorMessages = "";
            foreach (ValidationError error in result.Errors.DeepAll())
            {
                errorMessages += "Error: " + (int)error.Code + " - " + error.Message + "\n";
            }

            paymentStatus = errorMessages;
        }

        return paymentStatus;
    }
}

HTML 视图

index.html 中,我们需要添加下拉库引用。

<script src="//js.braintreegateway.com/web/dropin/1.9.4/js/dropin.min.js" 
 type="text/javascript"></script>

下面的代码片段(<div id="dropin"></div>)用于在 payment.html 中呈现 Drop-in UI,用户可以在其中输入卡信息。在提供有效的卡信息后,通过单击“结账”按钮执行结账操作。

<div class="container-fluid">
    <div class="row">
        <h3> {{title}} - {{cartmodel.Price}}$</h3>
        <div id="dropin"></div>
        <button type="submit" id="checkout" class="btn btn-sm  btn-success button">
            Checkout <i class="fa fa-shopping-cart"></i>
        </button>
        <h5>{{paymentresult}}</h5>
    </div>
</div>

AngularJS 控制器

获取客户端令牌:要创建 Drop-in UI,我们需要提供由服务器生成的客户端令牌进行授权。

//Generate View
braintree.dropin.create({
    authorization: client_token,
    container: '#dropin',
    card: {
        overrides: {
            styles: {
                input: {
                    color: 'blue',
                    'font-size': '18px'
                },
                '.number': {
                    'font-family': 'monospace'
                },
                '.invalid': {
                    color: 'red'
                }
            },
            fields: {
                number: {
                    //placeholder: 'Card Number',
                    formatInput: true // Turn off automatic formatting
                }
            }
        }
    }

}, function (createErr, instance) {

});

请求支付方式:这是客户端请求支付方式信息(PaymentMethodNonce)的地方,稍后 PaymentMethodNonce 将在服务器中使用以对卡进行收费。

//Checkout Submit
document.getElementById("checkout").addEventListener('click', function () {
    //event.preventDefault();
    instance.requestPaymentMethod(function (err, payload) {
        if (err) {
            console.log('Error', err);
            return;
        }
        //Token Braintree
        $scope.cartmodel.PaymentMethodNonce = payload.nonce;
        $scope.checkOut();
    });
});

最后,完整的客户端脚本。

templatingApp.controller('PaymentController', ['$scope', '$http', function ($scope, $http) {
    $scope.title = "Braintree Payment";
    $scope.paymentresult = null;
    $scope.cartmodel = {
        FirstName: "Shashangka",
        LastName: "LastName",
        Email: "shashangka@gmail.com",
        Street: "Bejpara, Jessore",
        Price: 50
    };

    //Generate Token PaymentGateway
    PaymentGateway();
    function PaymentGateway() {
        $http({
            method: 'GET',
            url: '/api/Payments/GenerateToken'
        }).then(function successCallback(response) {
            //console.log(response.data);
            var client_token = response.data;

            //Generate View
            braintree.dropin.create({
                authorization: client_token,
                container: '#dropin',
                card: {
                    overrides: {
                        styles: {
                            input: {
                                color: 'blue',
                                'font-size': '18px'
                            },
                            '.number': {
                                'font-family': 'monospace'
                            },
                            '.invalid': {
                                color: 'red'
                            }
                        },
                        fields: {
                            number: {
                                //placeholder: 'Card Number',
                                formatInput: true // Turn off automatic formatting
                            }
                        }
                    }
                }

            }, function (createErr, instance) {
                //Checkout Submit
                document.getElementById("checkout").addEventListener('click', function () {
                    //event.preventDefault();
                    instance.requestPaymentMethod(function (err, payload) {
                        if (err) {
                            console.log('Error', err);
                            return;
                        }
                        //Token Braintree
                        $scope.cartmodel.PaymentMethodNonce = payload.nonce;
                        $scope.checkOut();
                    });
                });
            });

        }, function errorCallback(response) {
            console.log(response);
        });
    };

    //CheckOut
    $scope.checkOut = function () {
        console.log($scope.cartmodel);
        $http({
            method: 'POST',
            url: '/api/Payments/Checkout',
            data: $scope.cartmodel
        }).then(function successCallback(response) {
            console.log(response.data);
            $scope.paymentresult = response.data;
        }, function errorCallback(response) {
            console.log(response);
        });
    };
}]);

测试:现成的支付 Drop-in UI,测试 号:378282246310005 或 4111111111111111

交易成功后,将出现以下屏幕

Braintree:正如我们所看到的,Braintree 中的交易列表。

希望这会有所帮助,感谢您的阅读!🙂

参考文献

© . All rights reserved.