DocuSign,cURL,json - 来自bash - 错误:ENVELOPE_IS_INCOMPLETE

时间:2016-08-24 17:47:09

标签: json bash curl docusignapi

我的cURL有点生疏,但我正在尝试做一个简单的测试并重新创建'基本场景' - 从V2 REST api文档中创建一个文档信封,只需一页.docx文件。

这是我的curl命令:

curl -X POST https://demo.docusign.net/restapi/v2/accounts/xxx/envelopes \
-H "X-DocuSign-Authentication: \
<DocuSignCredentials><Username>me/Username><Password>pp</Password><IntegratorKey>...</IntegratorKey></DocuSignCredentials>" \
-H "Accept: application/json" \
-H "Content-Type: multipart/form-data; boundary=AAA" \
-d '--AAA \
Content-Type: application/json \
Content-Disposition: form-data \
\
{ \
"status":"sent", \
"emailBlurb":"Test Email Body", \
"emailSubject": "Test Email Subject EnvelopeDefFull", \
"documents": [{ \
        "name": "test1.docx", \
        "documentId":"1", \
        "order":"1" \
}], \
"recipients": { \
"signers" : [{ \
        "email": "me@myemail.com", \
        "name": "my name", \
        "recipientId":"1" \
}] \
} \
--AAA \
Content-Type: application/docx \
Content-Disposition: file; filename="test1.docx"; documentid=1 \
 \
@test1.docx \
 \
--AAA--'

我得到的错误是:

{
  "errorCode": "ENVELOPE_IS_INCOMPLETE",
  "message": "The Envelope is not Complete. A Complete Envelope Requires Documents, Recipients, Tabs, and a Subject Line. Envelope definition missing."
}

怀疑实际上不是问题。

我认为我有一个cURL问题

可能的问题: (1)内部反斜杠-d单引号 (2)docx类型和包含来自@

提前感谢!!

3 个答案:

答案 0 :(得分:1)

这与你的间距有关(你在json部分错过})。

如果您采取相同的请求并将其扔进邮递员,请删除所有尾随空格。它运作得很好。

答案 1 :(得分:0)

我无法让你的cURL请求正常工作,但这里有一个链接,演示了发送有效负载的另一种方式:https://docs.docusign.com/esign/guide/usage/request_a_signature.html

要指出的一件事(虽然不影响当前的错误)是确保并在文档中包含fileExtension,否则假定它是pdf:

"documents": [{ 
    "name": "test1.docx", 
    "documentId":"1", 
    "order":"1",
    "fileExtension" : "docx"
}], 

答案 2 :(得分:0)

好吧,事实证明我犯了很多错误,安德鲁和尼克都是对的。为了完整起见,这是我最后的工作解决方案。

首先是bash脚本:

--AAA
Content-Type: application/json
Content-Distribution: form-data

{
"status":"sent",
"emailBlurb":"...",
"emailSubject":"Renew...",
"compositeTemplates":[{
        "serverTemplates": [{
                "sequence":1,
                "templateId":"xxxx",
                "templateRoles":[
                ]
        }],
        "inlineTemplates":[{
                "sequence":2,
                "recipients": {
                        "signers" :
                                [{
                                "email": "s...@yahoo.com",
                                "name": "...",
                                "recipientId": "1",
                                "accessCode": "xxxx",
                                "roleName": "..."
                                },]
                        },
        }],
"document": {
        "name": "Renew.pdf",
        "documentId":"1",
},
}],"notification": {
        "UseAccountDefaults":"false",
        "reminders": {
                "reminderEnabled": "true",
                "reminderDelay": "3",
                "reminderFrequency": "10"
        },
        "expirations": {
                "expireEnabled": "true",
                "expireAfter": "7",
                "expireWarn": "1"
        },
},
}

--AAA
Content-Type: application/pdf
Content-Disposition: file; filename="Renew.pdf"; documentid=1

%PDF-1.4^M%âãÏÓ^M1 0 obj
<<
...pdf bytes here...
/Info 29 0 R
>>
startxref
84324
%%EOF

--AAA--

现在,send.txt的内容。

请注意以下内容:我必须将doc转换为PDF,然后将PDF字节内联插入文档,然后关闭它。当我看到尼克的解决方案时,我完成了这件事。包括它通过@没有用,我不得不使用'cat'将它附加到实际的send.txt文件

#include <pthread.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>

#define USAGE_ERR "Usage: ./hw3 <WNUM> <RNUM> <MAX> <TIME>\n"

/* Argc parameter indexing consts */
#define INPUT_WNUM_IDX 1
#define INPUT_RNUM_IDX 2
#define OUTPUT_MAX_IDX 3
#define OUTPUT_TIME_IDX 4

typedef struct node {
    int value;

    struct node * previous;
    struct node * next;
}
node;

typedef struct {
    int length;
    node * head;
    node * tail;
    pthread_mutex_t mutex;
}
list;

list * global_list;
int stop_threads = 0;
int MAX_LIST_SIZE;
pthread_cond_t      gc_cond  = PTHREAD_COND_INITIALIZER;
pthread_mutex_t     gc_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t      read_cond  = PTHREAD_COND_INITIALIZER;
pthread_mutex_t     read_mutex = PTHREAD_MUTEX_INITIALIZER;

list * initlist_create();
void initlist_destroy(list * target_list);
list * initlist_push_head(list * target_list, int value);
int initlist_pop_tail(list * target_list);
void initlist_remove_last_k(list * target_list, int k);
int initlist_size(list * target_list);
pthread_mutex_t initlist_get_mutex(list * target_list);
void writer_thread();
void reader_thread();
void garbage_collect_thread();


list * initlist_create() {
    size_t list_size = sizeof(list);
    list * new_list = (list * ) malloc(list_size);
    new_list->head = NULL;
    new_list->tail = NULL;
    new_list->length = 0;
    if (0 != pthread_mutex_init( & (new_list->mutex), NULL)) {
        exit(errno);
    }
    return new_list;
}

void initlist_destroy(list * target_list) {
    node * current_node;
    node * temp_node;

    if (0 != pthread_mutex_lock( & (target_list->mutex))) {
        exit(errno);
    }

    if (0 != target_list->length) {
        current_node = target_list->head;
        while (current_node != NULL) {
            temp_node = current_node->next;
            free(current_node);
            current_node = temp_node;
        }
    }

    if (0 != pthread_mutex_unlock( & (target_list->mutex))) {
        exit(errno);
    }

    if (0 != pthread_mutex_destroy( & (target_list->mutex))) {
        exit(errno);
    }

    free(target_list);
}

list * initlist_push_head(list * target_list, int value) {
    node * new_node;
    size_t node_size = sizeof(node);


    if (0 != pthread_mutex_lock( & (target_list->mutex))) {
        exit(errno);
    }

    new_node = (node * ) malloc(node_size);
    if (NULL == new_node)
    {
        printf("Malloc failed\n" );
        exit(errno);
    }
    new_node->value = value;

    if (0 == target_list->length) {
        target_list->tail = new_node;
    }
    else {
        target_list->head->previous = new_node;
    }
    new_node->next = target_list->head;
    target_list->head = new_node;

    pthread_cond_signal(&read_cond);
    target_list->length++;
    if (0 != pthread_mutex_unlock( & (target_list->mutex))) {
        exit(errno);
    }
    return target_list;
}

int initlist_pop_tail(list * target_list) {
    int deleted_node_value;

    if (0 != pthread_mutex_lock( & (target_list->mutex))) {
        exit(errno);
    }
    while(0 == target_list->length) {
        pthread_cond_wait(&read_cond, &target_list->mutex);
    }
    node * last_node = target_list->tail;
    deleted_node_value = last_node->value;
    target_list->tail = last_node->previous;
    if (last_node->previous != NULL) {
        last_node->previous->next = NULL;
        }
    else
    {
        target_list->head = NULL;

    }
    target_list->length--;
    if (0 != pthread_mutex_unlock( & ( target_list->mutex) )) {
        exit(errno);
    }
    last_node->next = NULL;
    last_node->previous = NULL;
    free(last_node);



    //  node *result = NULL;
    // lock(&list_ptr->mutex);
    // if (list_ptr->head != NULL) {
    //     result = list_ptr->tail;
    //     list_ptr->tail = result->prev;
    //     if (result->prev != NULL) {
    //         result->prev->next = NULL;
    //     }
    //     else {
    //         list_ptr->head = NULL;
    //     }
    //     list_ptr->length--;
    // }
    // unlock(&list_ptr->mutex);
    // if (result != NULL) {
    //     result->next = NULL;
    //     result->prev = NULL;
    // }
    // return result;

    return deleted_node_value;
}

void initlist_remove_last_k(list * target_list, int k) {
    int remove_size = k;
    if (0 != pthread_mutex_lock( & (target_list->mutex))) {
        exit(errno);
    }
    if (k > target_list->length)
    {
        remove_size = target_list->length;
    }
    if (0 != pthread_mutex_unlock( & (target_list->mutex))) {
        exit(errno);
    }
    for (int i = 0; i < remove_size; ++i) {
        initlist_pop_tail(target_list);
    }
}

int initlist_size(list * target_list) {
    int list_size;

    if (0 != pthread_mutex_lock( & (target_list->mutex))) {
        exit(errno);
    }

    list_size = target_list->length;

    if (0 != pthread_mutex_unlock( & (target_list->mutex))) {
        exit(errno);
    }

    return list_size;
}

pthread_mutex_t initlist_get_mutex(list * target_list) {
    pthread_mutex_t list_mutex;

    list_mutex = target_list->mutex;

    return list_mutex;

}

void writer_thread()
{
    while (1)
    {
        if (stop_threads) {
            return;
        }
        if (MAX_LIST_SIZE < initlist_size(global_list))
        {

            pthread_cond_signal(&gc_cond);
        }
        initlist_push_head(global_list, rand());

    }
}


void reader_thread()
{
    while (1)
    {
        if (stop_threads) {
            return;
        }
        if (MAX_LIST_SIZE < initlist_size(global_list))
        {
            pthread_cond_signal(&gc_cond);
        }
        initlist_pop_tail(global_list);

    }
}

void garbage_collect_thread()
{
    while(1) {
        if (stop_threads) {
            return;
        }

        if (0 != pthread_mutex_lock( & (gc_mutex))) {
            exit(errno);
        }
        pthread_cond_wait(&gc_cond, &(gc_mutex));
        int remove_count = (initlist_size(global_list) / 2);
        if (0 == remove_count){
            continue;
        }
        initlist_remove_last_k(global_list, remove_count);
        printf("GC – %d items removed from the list\r\n", remove_count);
        if (0 != pthread_mutex_unlock( & (gc_mutex))) {
            exit(errno);
        }
    }
}

int main(int argc, char * * argv) {
    /* Validate arguments */
    if (5 != argc) {
        printf(USAGE_ERR);
        exit(errno);
    }

    int writers_count        = atoi(argv[INPUT_WNUM_IDX]);
    int readers_count        = atoi(argv[INPUT_RNUM_IDX]);
    int max_run_time         = atoi(argv[OUTPUT_TIME_IDX]);
    MAX_LIST_SIZE            = atoi(argv[OUTPUT_MAX_IDX]);
    global_list = initlist_create();


    pthread_t garbage_collector_thread;

    pthread_t writer_threads[writers_count];
    pthread_t reader_threads[readers_count];

    if (0 != pthread_create(&garbage_collector_thread, NULL, garbage_collect_thread, NULL))

    {   exit(errno);
    }

    for (int i = 0; i < writers_count; ++i)
    {
        if (0 != pthread_create(&writer_threads[i], NULL, writer_thread, NULL))
        {
            exit(errno);
        }
    }


    for (int x = 0; x < readers_count; ++x)
    {
        if (0 != pthread_create(&reader_threads[x], NULL, reader_thread, NULL))
        {
            exit(errno);
        }
    }


    sleep(max_run_time);
    stop_threads = 1;
    int list_size = initlist_size(global_list);
    printf("List size: %d\r\n", list_size);

    for (int i = 0; i < readers_count; ++i)
    {
        pthread_cancel(&reader_threads[i]);
    }
     for (int i = 0; i < writers_count; ++i)
    {
        pthread_cancel(&writer_threads[i]);
    }

    for (int i = 0; i < list_size; ++i)
    {
        printf("num is %d\r\n", initlist_pop_tail(global_list));
    }

    initlist_destroy(global_list);


}

我必须制作特定于此应用程序的模板,更简单,不太可能扩展或收缩,以便签名标签可以放置在文档上而不是锚定的绝对坐标。交互使用的普通模板不起作用。

最后,HTML标题必须在新行字符方面完全正确,一个额外或缺失,并且失败。

再次感谢您的帮助

亚光