Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request signature mismatch when create applicantId in flutter #18

Open
vinaye42 opened this issue Jan 11, 2023 · 2 comments
Open

Request signature mismatch when create applicantId in flutter #18

vinaye42 opened this issue Jan 11, 2023 · 2 comments

Comments

@vinaye42
Copy link

vinaye42 commented Jan 11, 2023

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 }
``
@akanxa
Copy link

akanxa commented Jan 17, 2023

Hello, you can replace createSignature method.

import 'package:buffer/buffer.dart';

String createSignature(HttpMethod httpMethod, String path, Map? request) {
  int timestamp = new DateTime.now().millisecondsSinceEpoch ~/ 1000;
  var valueToSign = timestamp.toString() + httpMethod.name + path;

  var key = utf8.encode(SECRETE_KEY);
  var bytes = utf8.encode(valueToSign);

  var hmacSha256 = Hmac(sha256, key);
  var mByteBuffer = BytesBuffer();
  mByteBuffer.add(utf8.encode(jsonEncode(request)));
  var digest = hmacSha256.convert(bytes + mByteBuffer.toBytes());

  return digest.toString();
}

@Olivi-tech
Copy link

Hi @vinaye42
I am too late for this conversation; I am not sure if you are active here or not. were you able to implement it in flutter. I am working on sumsub for ID verification in Flutter, but i am having some issues getting a user ID.

Please let me know if you were able to do it.
Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants