问题
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