Skip to content

Request signature mismatch when create applicantId in flutter #18

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 }
``

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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