Using HtmlElementView With PayPal

≡放荡痞女 提交于 2020-06-27 16:58:49

问题


I have a Flutter Web project. I have the following HTML script that I need to put into HtmlElementView:

<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID"></script>
<script>paypal.Buttons().render('body');</script>

from here. I have tried this:

Widget build(BuildContext context) {
    // ignore: undefined_prefixed_name
    ui.platformViewRegistry.registerViewFactory(
      'paypal-button',
        (int viewId) => IFrameElement()
        ..width = '500'
        ..height = '500'
        ..src = '''
        <div id="paypal-button-container"></div>
        <script src="https://paypal.com/sdk/js?client-id=MY_CLIENT_ID"></script>
        <script>
        paypal.Buttons({

            // Set up the transaction
            createOrder: function(data, actions) {
                return actions.order.create({
                    purchase_units: [{
                        amount: {
                            value: '0.01'
                        }
                    }]
                });
            },

            // Finalize the transaction
            onApprove: function(data, actions) {
                return actions.order.capture().then(function(details) {
                    // Show a success message to the buyer
                    alert('Transaction completed by ' + details.payer.name.given_name + '!');
                });
            }


        }).render('#paypal-button-container');
    </script>
        '''
    );
    return SizedBox(
      height: 300,
      width: 500,
      child: Center(
        child: HtmlElementView(
          viewType: 'paypal-button',
        ),
      ),
    );
  }

Note: This code is used from https://developer.paypal.com/demo/checkout/#/pattern/client

This code doesn't show any buttons and gives the following errors:

Bad state: Future already completed

Resource requests whose URLs contained both removed whitespace (\n, \r, \t) characters and less-than characters (<) are blocked. Please remove newlines and encode less-than characters from places like element attribute values in order to load these resources. See https://www.chromestatus.com/feature/5735596811091968 for more details.

What I need to know is how can I display this code snippet as a Widget in order for my Flutter Web project to be able to accept Paypal payments. Thanks for any help!


回答1:


Currently, the only way to integrate PayPal buttons into flutter web is to wrap them in an IFrame container:

class PayPalWidget extends StatefulWidget {
  @override
  _PayPalState createState() => _PayPalState();
}

class _PayPalState extends State<PayPalWidget> {
  html.IFrameElement _element;

  @override
  void initState() {
    _element = html.IFrameElement()
      ..width = "200px"
      ..height = "200px"
      ..style.border = 'none'
      ..srcdoc = """
        <!DOCTYPE html>
        <html>
          <body>
            <script src="https://www.paypal.com/sdk/js?client-id=sb"></script>
            <script>
              paypal.Buttons(
                {
                  createOrder: function(data, actions) {
                    return actions.order.create({
                      purchase_units: parent.purchase_units
                    });
                  },
                  onApprove: function(data, actions) {
                    return actions.order.capture().then(function(details) {
                      parent.flutter_feedback('Transaction completed by ' + details.payer.name.given_name);
                    });
                  }
                }

              ).render('body');
            </script>
          </body>
        </html>
        """;

    js.context["purchase_units"] = js.JsObject.jsify([
      {
        'amount': {'value': '0.02'}
      }
    ]);
    js.context["flutter_feedback"] = (msg) {
      Scaffold.of(context).showSnackBar(SnackBar(content: Text(msg)));
    };

    // ignore:undefined_prefixed_name
    ui.platformViewRegistry.registerViewFactory(
      'PayPalButtons',
      (int viewId) => _element,
    );

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 220,
      height: 220,
      child: HtmlElementView(viewType: 'PayPalButtons'),
    );
  }
}

But keep in mind that this method is far from ideal, since the IFrame is re-created every time the widget is updated. I added code to demonstrate this downside effect:

import 'dart:ui' as ui;
import 'dart:js' as js;
import 'package:universal_html/html.dart' as html;
import 'package:flutter/material.dart';

class NextLabPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          leading: BackButton(),
          title: Text('PayPal integration'),
          centerTitle: true,
        ),
        body: Center(
          child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Noise(),
                PayPalWidget(),
              ]),
        ),
      ),
    );
  }
}

class Noise extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: RaisedButton(
        child: Text('Make Noise'),
        onPressed: () {
          Scaffold.of(context).showSnackBar(
            SnackBar(
              content:
                  Text("PayPal buttons will be re-created when I disappear"),
            ),
          );
        },
      ),
    );
  }
}

// PayPalWidget code
// ...

Push 'Make sound' button to show snackbar - when message disappears, the buttons disappear too. Or hover your mouse over the "back arrow" in the AppBar and move away to show the same effect.



来源:https://stackoverflow.com/questions/61298630/using-htmlelementview-with-paypal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!