Reputation: 708
I have built a function to give my users the ability to pay with PayPal:
class PaypalServicesService {
String domain = "https://api.sandbox.paypal.com"; // for sandbox mode
//String domain = "https://api.paypal.com"; // for production mode
// change clientId and secret with your own, provided by paypal
String clientId = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
String secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
// for getting the access token from Paypal
Future<String> getAccessToken() async {
try {
var client = BasicAuthClient(clientId, secret);
var response = await client.post('$domain/v1/oauth2/token?grant_type=client_credentials');
if (response.statusCode == 200) {
final body = convert.jsonDecode(response.body);
return body["access_token"];
}
return null;
} catch (e) {
rethrow;
}
}
// for creating the payment request with Paypal
Future<Map<String, String>> createPaypalPayment(
transactions, accessToken) async {
try {
var response = await http.post("$domain/v1/payments/payment",
body: convert.jsonEncode(transactions),
headers: {
"content-type": "application/json",
'Authorization': 'Bearer ' + accessToken
});
final body = convert.jsonDecode(response.body);
if (response.statusCode == 201) {
if (body["links"] != null && body["links"].length > 0) {
List links = body["links"];
String executeUrl = "";
String approvalUrl = "";
final item = links.firstWhere((o) => o["rel"] == "approval_url",
orElse: () => null);
if (item != null) {
approvalUrl = item["href"];
}
final item1 = links.firstWhere((o) => o["rel"] == "execute",
orElse: () => null);
if (item1 != null) {
executeUrl = item1["href"];
}
return {"executeUrl": executeUrl, "approvalUrl": approvalUrl};
}
return null;
} else {
throw Exception(body["message"]);
}
} catch (e) {
rethrow;
}
}
// for executing the payment transaction
Future<String> executePayment(url, payerId, accessToken) async {
try {
var response = await http.post(url,
body: convert.jsonEncode({"payer_id": payerId}),
headers: {
"content-type": "application/json",
'Authorization': 'Bearer ' + accessToken
});
final body = convert.jsonDecode(response.body);
if (response.statusCode == 200) {
return body["id"];
}
return null;
} catch (e) {
rethrow;
}
}
}
On an emulator of Android 10 it works fine for both sandbox and live.
However, on a physical Android 10 device (RedNote pro 9) the payment process is stuck on the PayPal screen, before loading the complete WebView:
Here is the log on RedNote device side:
02-08 10:54:27.819 I/Perf (17856): Connecting to perf service.
02-08 10:54:27.839 I/FeatureParser(17856): can't find joyeuse.xml in assets/device_features/,it may be in /vendor/etc/device_features
02-08 10:54:27.827 W/m.tortel.syslog(17856): type=1400 audit(0.0:197147): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=12172 scontext=u:r:untrusted_app:s0:c253,c256,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
02-08 10:54:27.840 E/libc (17856): Access denied finding property "ro.vendor.df.effect.conflict"
02-08 10:54:27.866 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.870 I/chatty (17856): uid=10253(com.tortel.syslog) identical 6 lines
02-08 10:54:27.877 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.877 D/SysLog (17856): Fragment null, replacing
02-08 10:54:27.879 D/SysLog (17856): Loading settings
02-08 10:54:27.882 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.894 I/chatty (17856): uid=10253(com.tortel.syslog) identical 7 lines
02-08 10:54:27.895 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.895 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.897 I/chatty (17856): uid=10253(com.tortel.syslog) identical 3 lines
02-08 10:54:27.898 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.899 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.900 I/chatty (17856): uid=10253(com.tortel.syslog) identical 1 line
02-08 10:54:27.907 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.919 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.919 I/chatty (17856): uid=10253(com.tortel.syslog) identical 1 line
02-08 10:54:27.919 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.925 D/SysLog (17856): Checking for root
02-08 10:54:27.925 D/SysLog (17856): Setting the checkboxes
02-08 10:54:27.925 D/SysLog (17856): Checking if last_kmsg and radio are available
02-08 10:54:27.952 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.953 I/chatty (17856): uid=10253(com.tortel.syslog) identical 1 line
02-08 10:54:27.954 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.961 I/AdrenoGLES(17856): QUALCOMM build : 57da73e, I82b4603a7a
02-08 10:54:27.961 I/AdrenoGLES(17856): Build Date : 12/03/20
02-08 10:54:27.961 I/AdrenoGLES(17856): OpenGL ES Shader Compiler Version: EV031.27.05.03
02-08 10:54:27.961 I/AdrenoGLES(17856): Local Branch :
02-08 10:54:27.961 I/AdrenoGLES(17856): Remote Branch : refs/tags/AU_LINUX_ANDROID_LA.UM.8.9.R1.10.00.00.558.071
02-08 10:54:27.961 I/AdrenoGLES(17856): Remote Branch : NONE
02-08 10:54:27.961 I/AdrenoGLES(17856): Reconstruct Branch : NOTHING
02-08 10:54:27.961 I/AdrenoGLES(17856): Build Config : S P 8.0.12 AArch64
02-08 10:54:27.962 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.963 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:27.963 I/AdrenoGLES(17856): PFP: 0x016ee187, ME: 0x00000000
02-08 10:54:27.986 W/Gralloc3(17856): mapper 3.x is not supported
02-08 10:54:27.999 D/SysLog (17856): Root not available
02-08 10:54:28.026 D/SysLog (17856): Enabling log button: true
02-08 10:54:28.031 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:28.031 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:28.032 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:28.039 I/chatty (17856): uid=10253(com.tortel.syslog) identical 2 lines
02-08 10:54:28.040 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:29.798 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:29.798 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:29.800 V/SysLog (17856): Path: /data/user/0/com.tortel.syslog/cache/logs/2021-02-08_10.54/
02-08 10:54:29.801 D/ForceDarkHelper(17856): updateByCheckExcludeList: pkg: com.tortel.syslog activity: com.tortel.syslog.FragmentMainActivity@b885376
02-08 10:54:29.806 V/SysLog (17856): Done grabbing logs
Upvotes: 1
Views: 1264
Reputation: 30377
PayPal doesn't support 'WebViews'. Only Chrome Custom Tabs (Android) or Safari View Controllers (iOS), which have an address bar. Ref: https://developer.paypal.com/docs/api/info-security-guidelines/#secure-applications
Also you are using the original REST v1/payments API, which will still work but is deprecated. The current PayPal Checkout API is v2/checkout/orders, documented here.
Upvotes: 3