Skip to content

Request signature mismatch when create applicantId in flutter #18

@vinaye42

Description

@vinaye42
import 'dart:convert';
import 'dart:io';
import 'package:crypto/crypto.dart';
import 'package:http/http.dart';
import 'package:uuid/uuid.dart';
import 'package:flutter/material.dart';

const SUB_SUM_URL = 'https://api.sumsub.com';
const APP_TOKEN = 'APP_TOKEN';
const SECRETE_KEY = 'SECRETE_KEY';

class GetApplicantUI extends StatefulWidget {
  static String tag = '/GetApplicantUI';

  @override
  GetApplicantUIState createState() => GetApplicantUIState();
}

class GetApplicantUIState extends State<GetApplicantUI> {
  @override
  void initState() {
    super.initState();
  }

  @override
  void setState(fn) {
    if (mounted) super.setState(fn);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("SumSub")),
      body: TextButton(
        onPressed: () {
          var externalUserId = Uuid().v4();
          Map req = {
            "externalUserId": externalUserId,
          };
          createApplicant((req)).then((value) {
            print(value);
          }).catchError((e) {
            print(e.toString());
          });
        },
        child: Text("Get Applicant ID"),
      ),
    );
  }
}

Future<ApplicantModel> createApplicant(Map req) async {
  return ApplicantModel.fromJson(await handleResponse(await buildHttpResponse('/resources/applicants?levelName=basic-kyc-level', request: req, method: HttpMethod.POST)));
}

Map<String, String> buildHeaderTokens(HttpMethod httpMethod, String endPoint, [Map? request]) {
  var stamp = new DateTime.now().millisecondsSinceEpoch ~/ 1000;

  Map<String, String> header = {
    "X-App-Token": APP_TOKEN,
    "X-App-Access-Sig": createSignature(httpMethod, endPoint, request),
    "X-App-Access-Ts": stamp.toString(),
    HttpHeaders.acceptHeader: 'application/json',
    HttpHeaders.connectionHeader: 'application/json; charset=utf-8',
  };
  return header;
}

String createSignature(HttpMethod httpMethod, String path, Map? request) {
  int timestamp = new DateTime.now().millisecondsSinceEpoch ~/ 1000;
  
  var valueToSign = timestamp.toString() + httpMethod.name + path + request.toString();
  var key = utf8.encode(SECRETE_KEY);
  var bytes = utf8.encode(valueToSign);
  var hmacSha256 = Hmac(sha512, key);
  var digest = hmacSha256.convert(bytes);
  return digest.toString();
}

Uri buildBaseUrl(String endPoint) {
  Uri url = Uri.parse(endPoint);
  if (!endPoint.startsWith('http')) url = Uri.parse('$SUB_SUM_URL$endPoint');
  return url;
}

Future<Response> buildHttpResponse(String endPoint, {HttpMethod method = HttpMethod.POST, Map? request}) async {
  var headers = buildHeaderTokens(method, endPoint, request);
  Uri url = buildBaseUrl(endPoint);
  Response response;
  response = await post(url, body: jsonEncode(request), headers: headers, encoding: Encoding.getByName('utf-8'));
  return response;
}

Future handleResponse(Response response, [bool? avoidTokenError]) async {
  if (response.statusCode == 401) {
    throw 'Try again';
  }

  if (response.statusCode == 200) {
    return jsonDecode(response.body);
  } else {
    try {
      var body = jsonDecode(response.body);
      throw body['message'];
    } on Exception catch (e) {
      print(e.toString());
      throw "Something went wrong";
    }
  }
}

enum HttpMethod { GET, POST, DELETE, PUT }
``

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions