如何将 asp.net mvc 5 与最新的 Paypal checkout .net sdk v2 集成?

Posted

技术标签:

【中文标题】如何将 asp.net mvc 5 与最新的 Paypal checkout .net sdk v2 集成?【英文标题】:how to integrate asp.net mvc 5 with latest Paypal checkout .net sdk v2? 【发布时间】:2021-02-19 03:42:14 【问题描述】:

我尝试在我的 Asp.Net MVC 5 项目中使用 Paypal Checkout SDK V2 和 .Net Framework 4.7.2,但这似乎是我的缺失或错误。

我只是想集成 Paypal Checkout sdk 并想创建一个订单,以便我的付款将由一些 paypal 用户进行,我只想显示一个“立即付款”按钮。

SDK 链接在这里:

https://github.com/paypal/Checkout-NET-SDK

并点击这些链接

https://developer.paypal.com/docs/checkout/reference/server-integration/get-transaction/#on-the-client https://developer.paypal.com/demo/checkout/#/pattern/server

这是我尝试的代码

C# Code


public class CheckoutController : Controller

   
    public ActionResult Index()
    
        ViewBag.ClientId = PayPalClient.ClientId;
        ViewBag.CurrencyCode = "GBP"; // Get from a data store
        ViewBag.CurrencySign = "£";   // Get from a data store

        return View();
    
    //[Route("api/paypal/checkout/order/create")]
    public async static Task<HttpResponse> createOrder()
    
        HttpResponse response;
        // Construct a request object and set desired parameters
        // Here, OrdersCreateRequest() creates a POST request to /v2/checkout/orders
        var order = new OrderRequest()
        
            CheckoutPaymentIntent = "CAPTURE",
            PurchaseUnits = new List<PurchaseUnitRequest>()
                
                    new PurchaseUnitRequest()
                    
                        AmountWithBreakdown = new AmountWithBreakdown()
                        
                            CurrencyCode = "USD",
                            Value = "100.00"
                        
                    
                ,
            ApplicationContext = new ApplicationContext()
            
                ReturnUrl = "https://www.example.com",
                CancelUrl = "https://www.example.com"
            
        ;


        // Call API with your client and get a response for your call
        var request = new OrdersCreateRequest();
        request.Prefer("return=representation");
        request.RequestBody(order);
        response = await PayPalClient.Client().Execute(request);
        var statusCode = response.StatusCode;
        Order result = response.Result<Order>();
        Console.WriteLine("Status: 0", result.Status);
        Console.WriteLine("Order Id: 0", result.Id);
        Console.WriteLine("Intent: 0", result.CheckoutPaymentIntent);
        Console.WriteLine("Links:");
        foreach (LinkDescription link in result.Links)
        
            Console.WriteLine("\t0: 1\tCall Type: 2", link.Rel, link.Href, link.Method);
        
        return response;
    

    public async static Task<HttpResponse> captureOrder()
    
        // Construct a request object and set desired parameters
        // Replace ORDER-ID with the approved order id from create order
        var request = new OrdersCaptureRequest("APPROVED-ORDER-ID");
        request.RequestBody(new OrderActionRequest());
        HttpResponse response = await PayPalClient.Client().Execute(request);
        var statusCode = response.StatusCode;
        Order result = response.Result<Order>();
        Console.WriteLine("Status: 0", result.Status);
        Console.WriteLine("Capture Id: 0", result.Id);
        return response;
    

    /// <summary>
    /// This action is called when the user clicks on the PayPal button.
    /// </summary>
    /// <returns></returns>
    //[Route("api/paypal/checkout/order/create")]
    public async Task<SmartButtonHttpResponse> Create()
    
        var request = new PayPalCheckoutSdk.Orders.OrdersCreateRequest();

        request.Prefer("return=representation");
        request.RequestBody(OrderBuilder.Build());

        // Call PayPal to set up a transaction
        var response = await PayPalClient.Client().Execute(request);

        // Create a response, with an order id.
        var result = response.Result<PayPalCheckoutSdk.Orders.Order>();
        var payPalHttpResponse = new SmartButtonHttpResponse(response)
        
            orderID = result.Id
        ;
        return payPalHttpResponse;
    


    /// <summary>
    /// This action is called once the PayPal transaction is approved
    /// </summary>
    /// <param name="orderId"></param>
    /// <returns></returns>
    //[Route("api/paypal/checkout/order/approved/orderId")]
    public ActionResult Approved(string orderId)
    
        return Json("Sucess", JsonRequestBehavior.AllowGet);
    

    /// <summary>
    /// This action is called once the PayPal transaction is complete
    /// </summary>
    /// <param name="orderId"></param>
    /// <returns></returns>
    //[Route("api/paypal/checkout/order/complete/orderId")]
    public ActionResult Complete(string orderId)
    
        // 1. Update the database.
        // 2. Complete the order process. Create and send invoices etc.
        // 3. Complete the shipping process.
        return Json("Completed", JsonRequestBehavior.AllowGet);
    

    /// <summary>
    /// This action is called once the PayPal transaction is complete
    /// </summary>
    /// <param name="orderId"></param>
    /// <returns></returns>
    //[Route("api/paypal/checkout/order/cancel/orderId")]
    public ActionResult Cancel(string orderId)
    
        // 1. Remove the orderId from the database.
        return Json("Cancel", JsonRequestBehavior.AllowGet);
    

    /// <summary>
    /// This action is called once the PayPal transaction is complete
    /// </summary>
    /// <param name="orderId"></param>
    /// <returns></returns>
    //[Route("api/paypal/checkout/order/error/orderId/error")]
    public ActionResult Error(string orderId,
                               string error)
    
        // Log the error.
        // Notify the user.
        string temp = System.Web.HttpUtility.UrlDecode(error);
        return Json(temp, JsonRequestBehavior.AllowGet);
    


public static class OrderBuilder

    /// <summary>
    /// Use classes from the PayPalCheckoutSdk to build an OrderRequest
    /// </summary>
    /// <returns></returns>
    public static OrderRequest Build()
    
        // Construct a request object and set desired parameters
        // Here, OrdersCreateRequest() creates a POST request to /v2/checkout/orders
        OrderRequest order = new OrderRequest()
        
            CheckoutPaymentIntent = "CAPTURE",
            PurchaseUnits = new List<PurchaseUnitRequest>()
                
                    new PurchaseUnitRequest()
                    
                        AmountWithBreakdown = new AmountWithBreakdown()
                        
                            CurrencyCode = "USD",
                            Value = "100.00"
                        
                    
                ,
            ApplicationContext = new ApplicationContext()
            
                ReturnUrl = "https://www.example.com",
                CancelUrl = "https://www.example.com"
            
        ;


        // Call API with your client and get a response for your call
        var request = new OrdersCreateRequest();
        request.Prefer("return=representation");
        request.RequestBody(order);
        return order;
    


public class PayPalClient


    public static string ClientId = " your client id";
    public static string Secrets = "your client secret";
    public static string SandboxClientId  get; set;  =
                         "<alert>SandboxClientId</alert>";
    public static string SandboxClientSecret  get; set;  =
                         "<alert>SandboxClientSecret</alert>";

    public static string LiveClientId  get; set;  =
                  "<alert>PayPal LIVE Client Id</alert>";
    public static string LiveClientSecret  get; set;  =
                  "<alert>PayPal LIVE Client Secret</alert>";


    public static PayPalEnvironment Environment()
    
        //return new SandboxEnvironment("<alert>SandboxClientId</alert>",
        //                              "<alert>SandboxClientSecret</alert>");
        return new SandboxEnvironment(ClientId, Secrets);
    
    public static PayPalCheckoutSdk.Core.PayPalHttpClient Client()
    
        return new PayPalHttpClient(Environment());
    

    public static PayPalCheckoutSdk.Core.PayPalHttpClient Client(string refreshToken)
    
        return new PayPalHttpClient(Environment(), refreshToken);
    

    public static String ObjectToJSONString(Object serializableObject)
    
        MemoryStream memoryStream = new MemoryStream();
        var writer = JsonReaderWriterFactory.CreateJsonWriter(memoryStream,
                                                              Encoding.UTF8,
                                                              true,
                                                              true,
                                                              "  ");

        var ser = new DataContractJsonSerializer(serializableObject.GetType(),
                                             new DataContractJsonSerializerSettings
                                             
                                                 UseSimpleDictionaryFormat = true
                                             );

        ser.WriteObject(writer,
                        serializableObject);

        memoryStream.Position = 0;
        StreamReader sr = new StreamReader(memoryStream);

        return sr.ReadToEnd();
    


public class SmartButtonHttpResponse

    readonly PayPalCheckoutSdk.Orders.Order _result;
    public SmartButtonHttpResponse(PayPalHttp.HttpResponse httpResponse)
    
        Headers = httpResponse.Headers;
        StatusCode = httpResponse.StatusCode;
        _result = httpResponse.Result<PayPalCheckoutSdk.Orders.Order>();
    

    public HttpHeaders Headers  get; 
    public HttpStatusCode StatusCode  get; 

    public PayPalCheckoutSdk.Orders.Order Result()
    
        return _result;
    

    public string orderID  get; set; 






View html is

<!-- Set up a container element for the PayPal smart button -->
<div id="paypal-button-container"></div>
@section scripts

<script src="https://www.paypal.com/sdk/js?client-id=@ViewBag.ClientId"></script>
<script type="text/javascript">
       

        var orderId;
    function httpGet(url) 
        var xmlHttp = new XMLHttpRequest();
        xmlHttp.open("GET", url, false);
        xmlHttp.send(null);
        return xmlHttp.responseText;
    
       
    paypal.Buttons(
        // Set up the transaction
        enableStandardCardFields: true,
        createOrder: function (data, actions) 
            orderId = data.orderID;
            console.log("Start");
            console.log(data);
            console.log(actions);
            console.log("End");
            return fetch(
                '/PaypalPayments/create/', 
                method: 'post'
            ).then(function (res) 
                return res.json();
            ).then(function (data) 
                return data.orderID;
            );
        ,

        // Finalise the transaction
        onApprove: function (data, actions) 
            return fetch('/PaypalPayments/approved/' + data.orderID, 
                method: 'post'
            ).then(function (res) 
                return actions.order.capture();
            ).then(function (details) 

                // (Preferred) Notify the server that the transaction id complete
                // and have an option to display an order completed screen.
                window.location.replace('/PaypalPayments/complete/' +
                                         data.orderID + '/@ViewBag.CurrencyCode');

                // OR
                // Notify the server that the transaction id complete
                //httpGet('/api/paypal/checkout/order/complete/' + data.orderID);

                // Show a success message to the buyer
                alert('Transaction completed by ' + details.payer.name.given_name + '!');
            );
        ,

        // Buyer cancelled the payment
        onCancel: function (data, actions) 
            httpGet('/PaypalPayments/cancel/' + data.orderID);
        ,

        // An error occurred during the transaction
        onError: function (err) 
            debugger;
            fetch(
                '/PaypalPayments/error/', 
                    method: 'post',
                    headers:  'Content-type': 'application/json' ,
                    body: JSON.stringify( orderId: orderId, error: encodeURIComponent(err))
            ).then(function (res) 
                return res.json();
            ).then(function (data) 
                return data.orderID;
            );           
        

    ).render('#paypal-button-container');

</script>

我必须收到的错误如下: 我的创建帖子请求成功,返回 200 状态。

在这个请求之后,控件立即进入错误函数并抛出这个错误。

错误:JSON 中位置 0 处的意外标记 P"

下面提到了完整的错误细节

SyntaxError: Unexpected token P in JSON at position 0

Error: Unexpected token P in JSON at position 0
    at Qt.error (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:60544)
    at Object.<anonymous> (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68311)
    at JSON.parse (<anonymous>)
    at o (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68170)
    at dr (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68323)
    at u.on (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:72994)
    at br (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:73131)
    at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79250
    at Function.n.try (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:14118)
    at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79047

Error: Unexpected token P in JSON at position 0
    at Qt.error (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:60544)
    at Array.<anonymous> (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68311)
    at JSON.parse (<anonymous>)
    at o (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68170)
    at dr (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68323)
    at u.on (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:72994)
    at br (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:73131)
    at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79250
    at Function.n.try (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:14118)
    at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79047

有人可以正确指导我吗?我尝试了不同的文章,但仍然收到这些错误。

【问题讨论】:

如果您正在寻找 ASP.NET(Web 表单或核心 MVC)中 PayPal 结账的最新解决方案(使用带有 PayPal JavaScript SDK、服务器端集成的 Orders v2 REST API),请查看演示 > >>techtolia.com/PayPal 【参考方案1】:

当您从服务器获取/PaypalPayments/create/ 时,您会返回什么?

显然您没有返回有效的 JSON,但您的代码正在尝试将其解析为 JSON。

更改您的服务器代码以仅返回有效的 JSON。代码实际上看起来没问题,所以客户端代码中硬编码的 /PayPalPayments/create/ 路由可能有问题。

更改客户端代码以遵循https://developer.paypal.com/demo/checkout/#/pattern/server 上的最佳示例也是明智之举,该示例演示了如何正确处理捕获错误

(刚刚注意到您的示例中的代码使用actions.order.capture() 与此服务器端集成相结合,这相当糟糕——似乎服务器端 captureOrder 任务甚至从未被调用,这正是使用服务器的重点-side APIs,如果你不从服务器捕获,你将得不到任何好处)

【讨论】:

谢谢普雷斯顿 PHX。我还在想它会怎么样?你能看看吗?我已删除 actions.order.capture() 并从 createOrder 返回 res/*.json()*/。但仍有问题。查看新错误。 1)。 create_order_error err:“错误:postMessage createOrder() i 2) 没有 ack。click_initiate_payment_reject err:“错误:htt 中 postMessage createOrder() 没有 ack…47fPl3cl 3).unhandled_error err:“错误:postMessage 没有 ack kn() in www.…47fPl3cligEbl Prestob PHX,你在吗?我们可以做一个远程桌面吗?我想展示。在服务器端的代码中,我在 payPalHttpResponse 对象中添加了 orderId 和 OrderResult。但是当响应来自针对 createOrder 的 fetch 函数时,两者都丢失了 修复了 PrestobPHX 的问题。你的解决方案奏效了。我的服务器端调用不正确。谢谢

以上是关于如何将 asp.net mvc 5 与最新的 Paypal checkout .net sdk v2 集成?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Web API 添加到现有的 ASP.NET MVC (5) Web 应用程序项目中?

使用 ASP.NET 5 MVC 6 Web API 进行 Cookie 身份验证

ASP.Net MVC 5 身份验证与另一个 MVC 5 身份网站

如何只显示数据库中最近的 5 条记录 - ASP.NET MVC

将 asp.net 5 MVC 6 与 Identity 和 EF 6 一起使用的示例

如何在 Asp.Net Core Mvc 5.0 中将 sql 数据库与 ado.net 连接?