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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions