Использование HtmlElementView с PayPal - PullRequest
1 голос
/ 19 апреля 2020

У меня есть веб-проект Flutter. У меня есть следующий HTML скрипт, который мне нужно вставить в HtmlElementView:

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

из здесь . Я пробовал это:

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',
        ),
      ),
    );
  }

Примечание: этот код используется из https://developer.paypal.com/demo/checkout/# / pattern / client

Этот код не показывает никаких кнопок и дает следующие ошибки:

Плохое состояние: будущее уже завершено

Запросы ресурсов, URL-адреса которых содержат как удаленные пробельные символы (\n, \r, \t), так и менее чем символы (<) заблокированы. Удалите символы новой строки и закодируйте меньше символов из таких мест, как значения атрибутов элемента, чтобы загрузить эти ресурсы. См. https://www.chromestatus.com/feature/5735596811091968 для получения более подробной информации.

Что мне нужно знать, так это то, как я могу отобразить этот фрагмент кода в качестве виджета, чтобы мой веб-проект Flutter мог принимать платежи Paypal. Спасибо за любую помощь!

1 Ответ

1 голос
/ 19 апреля 2020

В настоящее время единственный способ интеграции кнопок PayPal в flutter web - это обернуть их в контейнер IFrame:

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'),
    );
  }
}

Но имейте в виду, что этот метод далеко не идеален, поскольку IFrame воссоздается каждый раз, когда виджет обновляется. Я добавил код, чтобы продемонстрировать этот эффект понижения:

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
// ...

Pu sh Кнопка «Сделать звук» для отображения панели закусок - когда сообщение исчезает, кнопки тоже исчезают. Или наведите курсор мыши на «стрелку назад» в панели приложений и отойдите, чтобы показать тот же эффект.

...