Skip to main content
Glama
yop-platform

yeepay-mcp

by yop-platform

query_yeepay_payment_status

Check the status of Yeepay payments by querying with the merchant order ID to verify transaction details and ensure accurate payment processing.

Instructions

查询支付状态工具

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
orderIdYes商户订单号

Implementation Reference

  • src/index.ts:67-94 (registration)
    MCP server registration of the 'query_yeepay_payment_status' tool, defining input schema and thin wrapper handler that calls the core queryYeepayPaymentStatus function.
    server.tool(
      "query_yeepay_payment_status",
      "查询支付状态工具",
      QueryPaymentStatusInputSchema.shape, // Pass the shape
      async (input: QueryPaymentStatusInput) => {
        // Zod schema handles validation
    
        try {
          // Dynamically import the module to avoid circular dependencies
          const { queryYeepayPaymentStatus } = await import(
            "./tools/queryPayment.js"
          );
    
          const queryResult = await queryYeepayPaymentStatus(input);
          return {
            content: [
              { type: "text" as const, text: JSON.stringify(queryResult, null, 2) },
            ],
          };
        } catch (error) {
          console.error(
            "Error caught in query_yeepay_payment_status tool handler:",
            error,
          );
          throw error; // Let SDK handle the error
        }
      },
    );
  • The core handler logic for querying Yeepay payment status, called by the MCP tool registration. Uses YopClient to make GET request to Yeepay API.
    export async function queryYeepayPaymentStatus(input: QueryRequest): Promise<YeepayQueryResult> {
      try {
        const { parentMerchantNo, merchantNo, appKey, appPrivateKey } = appConfig;
    
        const yopConfig: YopConfig = {
            appKey,
            appPrivateKey,
        };
    
        const yopClient = new YopClient(yopConfig);
    
    
        const queryParams = {
          parentMerchantNo,
          merchantNo,
          orderId: input.orderId
        };
        console.info("[QueryPayment] Request Params:", JSON.stringify(queryParams, null, 2));
    
        const apiUrl = '/rest/v1.0/trade/order/query';
    
        // Add double assertion for consistency, similar to the post method usage
        const responseData = await yopClient.get(apiUrl, queryParams as unknown as Record<string, unknown>) as YeepayQueryResponse; // 使用 SDK 的 get 方法
        console.info("[QueryPayment] Raw Response Data:", JSON.stringify(responseData, null, 2)); // 打印原始响应
    
        if (responseData && responseData.state === 'SUCCESS') {
            if (responseData.result && responseData.result.code === 'OPR00000') {
                // 成功状态且业务码为 OPR00000
                console.info("[QueryPayment] Success:", JSON.stringify(responseData.result));
                return responseData.result;
            } else {
                // 成功状态但业务码非 OPR00000,表示业务失败
                const errorCode = responseData.result?.code || 'UNKNOWN_CODE';
                const errorMessage = responseData.result?.message || 'Unknown Yeepay business error message';
                const errorLog = `[QueryPayment] Yeepay API Business Error (state: SUCCESS): Code=${errorCode}, Message=${errorMessage}`;
                console.error(errorLog);
                throw new Error(`Yeepay Business Error: ${errorCode} - ${errorMessage}`);
            }
        } else if (responseData && responseData.state === 'FAILURE') {
            // Failure state
            const errorCode = responseData.error?.code || 'UNKNOWN_FAILURE_CODE';
            const errorMessage = responseData.error?.message || 'Unknown Yeepay failure message';
            const errorLog = `[QueryPayment] Yeepay API Failure (state: FAILURE): Code=${errorCode}, Message=${errorMessage}`;
            console.error(errorLog);
            throw new Error(`Yeepay API Failure: ${errorCode} - ${errorMessage}`);
        } else {
            // Unknown state or other unexpected response structure
            const errorLog = `[QueryPayment] Unknown or Unexpected Yeepay API Response State: ${responseData?.state || 'State Undefined'}. Response: ${JSON.stringify(responseData)}`;
            console.error(errorLog);
            throw new Error(`Unknown Yeepay API response state: ${responseData?.state}`);
        }
      } catch (error: unknown) {
        // Catch standardized errors from YopClient or other errors within this function
        console.error("[QueryPayment] Overall Error:", error);
        // Re-throw the error directly
        if (error instanceof Error) {
            throw error;
        } else {
            throw new Error(`Unknown error in queryYeepayPaymentStatus: ${String(error)}`);
        }
      }
    }
  • Zod schema defining the input parameters for the query_yeepay_payment_status tool (orderId: string).
    // Define Zod schema for query payment status input
    const QueryPaymentStatusInputSchema = z.object({
      orderId: z.string().describe("商户订单号"),
    });
    type QueryPaymentStatusInput = z.infer<typeof QueryPaymentStatusInputSchema>;
  • TypeScript interfaces defining input (QueryRequest), output (YeepayQueryResult), and internal response structures for type safety.
    // Expected structure for a successful query result
    export interface YeepayQueryResult { // Add export
      code: string;
      message: string;
      orderId: string;
      uniqueOrderNo: string;
      status: string; // e.g., 'PROCESSING', 'SUCCESS', 'FAILED'
    }
    
    // Expected structure for a query error
    interface YeepayQueryError {
        code: string;
        message: string;
    }
    
    // Complete SDK response structure
    interface YeepayQueryResponse {
        state: 'SUCCESS' | 'FAILURE' | string;
        result?: YeepayQueryResult;
        error?: YeepayQueryError;
    }
    
    
    export interface QueryRequest { // Add export
      orderId: string;
    }
    
    export async function queryYeepayPaymentStatus(input: QueryRequest): Promise<YeepayQueryResult> {
      try {
        const { parentMerchantNo, merchantNo, appKey, appPrivateKey } = appConfig;
    
        const yopConfig: YopConfig = {
            appKey,
            appPrivateKey,
        };
    
        const yopClient = new YopClient(yopConfig);
    
    
        const queryParams = {
          parentMerchantNo,
          merchantNo,
          orderId: input.orderId
        };
        console.info("[QueryPayment] Request Params:", JSON.stringify(queryParams, null, 2));
    
        const apiUrl = '/rest/v1.0/trade/order/query';
    
        // Add double assertion for consistency, similar to the post method usage
        const responseData = await yopClient.get(apiUrl, queryParams as unknown as Record<string, unknown>) as YeepayQueryResponse; // 使用 SDK 的 get 方法
        console.info("[QueryPayment] Raw Response Data:", JSON.stringify(responseData, null, 2)); // 打印原始响应
    
        if (responseData && responseData.state === 'SUCCESS') {
            if (responseData.result && responseData.result.code === 'OPR00000') {
                // 成功状态且业务码为 OPR00000
                console.info("[QueryPayment] Success:", JSON.stringify(responseData.result));
                return responseData.result;
            } else {
                // 成功状态但业务码非 OPR00000,表示业务失败
                const errorCode = responseData.result?.code || 'UNKNOWN_CODE';
                const errorMessage = responseData.result?.message || 'Unknown Yeepay business error message';
                const errorLog = `[QueryPayment] Yeepay API Business Error (state: SUCCESS): Code=${errorCode}, Message=${errorMessage}`;
                console.error(errorLog);
                throw new Error(`Yeepay Business Error: ${errorCode} - ${errorMessage}`);
            }
        } else if (responseData && responseData.state === 'FAILURE') {
            // Failure state
            const errorCode = responseData.error?.code || 'UNKNOWN_FAILURE_CODE';
            const errorMessage = responseData.error?.message || 'Unknown Yeepay failure message';
            const errorLog = `[QueryPayment] Yeepay API Failure (state: FAILURE): Code=${errorCode}, Message=${errorMessage}`;
            console.error(errorLog);
            throw new Error(`Yeepay API Failure: ${errorCode} - ${errorMessage}`);
        } else {
            // Unknown state or other unexpected response structure
            const errorLog = `[QueryPayment] Unknown or Unexpected Yeepay API Response State: ${responseData?.state || 'State Undefined'}. Response: ${JSON.stringify(responseData)}`;
            console.error(errorLog);
            throw new Error(`Unknown Yeepay API response state: ${responseData?.state}`);
        }
      } catch (error: unknown) {
        // Catch standardized errors from YopClient or other errors within this function
        console.error("[QueryPayment] Overall Error:", error);
        // Re-throw the error directly
        if (error instanceof Error) {
            throw error;
        } else {
            throw new Error(`Unknown error in queryYeepayPaymentStatus: ${String(error)}`);
        }
      }
    }
  • Alternative standalone handler export for a tool runtime, implementing full logic including validation, SDK init with hardcoded creds, API call, and error handling for query_yeepay_payment_status.
    export async function handler({ input, logger }: Args<Input>): Promise<Output> {
      // 0. Input Validation
      try {
        if (!input || typeof input !== 'object') {
          throw new Error('Missing or invalid event object.');
        }
    
        // Required parameters
        const requiredFields = ['orderId'];
    
        const missingFields = requiredFields.filter(key => !input[key]);
        if (missingFields.length > 0) {
          throw new Error(`Missing required fields in event object: ${missingFields.join(', ')}`);
        }
      } catch (error) {
        logger.error('Input validation failed:', error.message);
        return {
          error: 'INVALID_PARAMETERS',
          message: error.message,
        };
      }
    
      try {
        // 2. Prepare Request Data
        const queryParams = {
          parentMerchantNo: '10086032562',
          merchantNo: '10086039518',
          orderId: input.orderId
        };
    
        logger.debug('Prepared query parameters:', JSON.stringify(queryParams));
    
        // Use dynamic import() for ES modules
        const sdk = await import('@yeepay/yop-typescript-sdk');
        const YopClient = sdk.YopClient;
    
        if (!YopClient) {
          throw new Error('Could not find YopClient in the dynamically imported module');
        }
    
        logger.info('YopClient loaded from dynamic import');
    
        // Initialize YopClient with config
        const yopClientInstance = new YopClient({
          appKey: 'app_10086032562',
          appPrivateKey: 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDdnBKx03zrrPzJ/Z8rJMEaYvmes19qIPGcgncUQNOYauaXy99iT2P3O1H3qZceKZ8ngeha5ckuV4ke3tLlMRHn3GvTzd1l6EEntwL6SRUopmhj/635bkGUlQvEZrWAtwfO0wcoI0XnRB3JLc+r8nTf64vIi2UovqcZ6LKJj96btie7rYZZqqtr2+e7S0HDqH6nHcqvBYVGYGrYnDNKyjSvKdjGIq+JMQu1tJOtqT4JoeFAOBSTw3Jqkpvnudc1GgWVOepuGVyaXHXVNQTjnap7LMbJ+IJXBLSgGi1uC4u8Ypc2u0kDLXKkff0X/DG9cJXMaLcf/3yBH2/UoebTTJudAgMBAAECggEACptTfrzlW/9b2wwfT+iSsIFfurORo8n/XnMVIXxH1GH7dvT8VF+B5J2reuvcToaF9lVeqmkYo7XvW3GlTPB4D62qYIkYKW5AHhdBlnqkf11VnkGo0UkwbNzkYwpachZwknrhuw9TI3JMbapaZ/uzEdubhWX8mcJkS5ZqYzCmYjPzKfYMuowZ4ygOETOER9pl8J7dt4CYYI+GLwVT39D6ptf74fzlKohT506ulLUu3AWsavvW3QTPSxzS2ARO7QaLco8Dly8AJiGmSUdwSzzwVgYD1kVHtUUukbtnjFBTN8PqGt+TM+gcv8s5LlaZSYp4Zlwt9LTdW2sFCSoRj8HLaQKBgQD3u6c2PyRckNpwGuOjTJHy+uF7OGoiFyuGAxmyC8UzNG+nLBghZjCJmzkfzKrjNINrNT4zxepXhKurW0vxd9ZSkjpyEteRDSfdyvsDEbfR3p6w9ObA8iZkCvesYchrwrdWO7V4sjynvEhWkLSctLWaASbj7zuyYu0OYiSo28MN+QKBgQDlAUB3mLEpBvWIlMnXhfz/RrmEqlg6yygu37Xjjs7wjyPSz3RqUIB2YYT9d5wGob2nBLD4IvoSWvysNegt0TiklAHYW7LNW1DB1Oo0M5xOgToOOA545aR8DG9XJGOlKRiGJQS0q9T4X4z1TOx93W8bzNeUZgL5Kk5WQE8cuUxzxQKBgQC4nhgWzSeD9E9VjDRo1f9OXLj84yX1Ed9Vl6nmje8AIeuzYaD6AvXZFtyTXitb9x6ZHqykWLIzVqO4p+kIoo4OKvtzV6deabd0CnjV6LZcqNMKfPgaglsp4yKATL7Xz9xhX032DJ43QpGGMYDn56QOiR06cGbEogSX23wGev/5wQKBgQCMQc8FMNzYnu2FAHP675J7mwqG6XnuUH1E8DlLrSyrg0/SjsLjVnjHiITWZQqHuUoZ4DKvV2TIFzgIFWAlp63Ehu32YHtLcTEt9kSXQkDqiBVRnh2nCCdM3qTWv2/UOS5PAp82NMPUd1ky6DE0CYpCgZxLxIrvpmyiQPLzSb48bQKBgAF0EpSRsPQhPjUYsPc3FA71R0GSRyxr9ktM5hqsG/qrh0ep4jIFKibGA+VJo/ed2QC4MNAjPR285v6ytBcFyoEAacf7noSavVvYU5/KaQ5wJYSue0+M5IBJrrwLv0k1ppe86Xp8890NT2XHbaALY3hcSBTGs2aHPUNEma7H+2T9',
          yopApiBaseUrl: 'https://openapi-a.yeepay.com',
          yopPublicKey: 'MIIE2TCCA8GgAwIBAgIFQ5cTlZgwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEXMBUGA1UEAwwOQ0ZDQSBBQ1MgT0NBMzEwHhcNMjEwNDI1MDIwOTAwWhcNMjMwNDI1MDIwOTAwWjCBhzELMAkGA1UEBhMCQ04xFzAVBgNVBAoMDkNGQ0EgQUNTIE9DQTMxMRAwDgYDVQQLDAdURVNUIFJBMRkwFwYDVQQLDBBPcmdhbmlzYXRpb25hbC0xMTIwMAYDVQQDDCkwNTFA5piT5a6d5byA5pS+5bmz5Y+wQDMxMTAwMDAwMDU4MDQyMjlANTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOqdF1o7HGPoLMqikYcPTHi7BJoRXQUYU9npjnJPxdTpsN/GVoScYfZA37OR8xSTK1aM4FPkiRQzjcbPFAdMDCCykZqny3HwpRvTMgjbiZJH5tBxUL9YURnTr2T149wXJLsGuxaxFwUWFISu7yeNGn7prKbYZrHum7OpmcTZ/5gC2dl9O7s5zq63Nq5ONWNh37XbsWcOk+BJrVrjdseAmfIMEsjwFuWc2SS0OrWQ6IwSuBmUwBoZ5924OWwbAZcNvhS5AkAbg7CVbBT4hof2+iv/sxk71slHLvi1I9jHo2EBCwzt4tr0F1Q5O5VYtv03FGHn7yHLLJ87Hwn42qK8bLsCAwEAAaOCAXgwggF0MGwGCCsGAQUFBwEBBGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL29jc3AuY2ZjYS5jb20uY24vb2NzcDAyBggrBgEFBQcwAoYmaHR0cDovL2NybC5jZmNhLmNvbS5jbi9vY2EzMS9vY2EzMS5jZXIwHwYDVR0jBBgwFoAU4rQJy81hoXNKeX/xioML3bR+jB0wDAYDVR0TAQH/BAIwADBIBgNVHSAEQTA/MD0GCGCBHIbvKgEEMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTQuaHRtMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jcmwuY2ZjYS5jb20uY24vb2NhMzEvUlNBL2NybDMwMjAuY3JsMA4GA1UdDwEB/wQEAwIGwDAdBgNVHQ4EFgQU4swobhCzosrPL4Gv8clxRwbHy0EwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQBpZpClbx+FJo5WpuJW+TJKYRayKeAx3/+VvlMyWvdcbABPlvwBY1m3xl1k+tsqqtBGvjathGmw1w7YESdRFTT/ty04MDLmz62USS4DJlZ2EWMxPm0bKpuAPsWb3+EtvizyZ0l1gX/D0YHDcH+VljYlGAv+yQEUzD+0c9NZSWr4V19yRVDQEicll5hJko7RFQUrwW+wNSrexzlyQFbUlbljwAnHO0TF3zgTXKRu2YNiKZGlxr28FjOeMQdvpiNqHCW9ACjQqL0vz1l9IImn0lm+0vh0YhAN0oFzJZvs5lFG9Bg+kNkyhgf9eVcUUxXKnA6UwXq2amoTa4Iq3NW6YuPI'
        });
        logger.info('YopClient initialized successfully');
    
        // 4. Define API URI
        const apiUri = '/rest/v1.0/trade/order/query';
    
        // 5. API Call
        const response = await yopClientInstance.get(apiUri, queryParams);
        logger.debug('API Response:', JSON.stringify(response));
    
        // 6. Result Handling
        const isProduction = process.env.NODE_ENV === 'production'; // Check env for logging control
        if (response && response.result) {
          const resultData = response.result;
          logger.info('YeePay API query successful.');
          const queryResponse = {
            code: resultData.code,
            message: resultData.message,
            orderId: resultData.orderId,
            uniqueOrderNo: resultData.uniqueOrderNo,
            status: resultData.status,
            orderAmount: resultData.orderAmount,
            payAmount: resultData.payAmount
          };
          logger.debug('Processed successful response:', JSON.stringify(queryResponse));
          return queryResponse;
        } else {
          logger.error('YeePay API call failed or returned an error state.');
          const errorDetails = response ? (response.error || response.result || response) : 'No response object';
          logger.error('Error details:', JSON.stringify(errorDetails));
          /** @type {YeePayError} */
          const errorResponse = {
            error: response?.error?.code || response?.result?.code || 'YOP_API_ERROR',
            message: response?.error?.message || response?.result?.message || 'Unknown YeePay API error',
            subCode: response?.error?.subCode,
            subMessage: response?.error?.subMessage,
            rawResponse: !isProduction ? response : undefined,
          };
          return errorResponse;
        }
      } catch (error) {
        logger.error('An unexpected error occurred during YeePay payment status query:', error);
        if (error.stack) {
          logger.error('Stack trace:', error.stack);
        }
        return {
          error: 'INTERNAL_SERVER_ERROR',
          message: error.message || 'An unexpected error occurred.',
        };
      }
    };
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden for behavioral disclosure. '查询' (query) implies a read-only operation, but the description doesn't specify authentication requirements, rate limits, error conditions, or what happens when querying non-existent orders. For a payment status tool with zero annotation coverage, this leaves significant behavioral gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise - just 6 Chinese characters that directly state the tool's purpose. There's zero wasted language, though this conciseness comes at the cost of completeness. The structure is front-loaded with the core function stated immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a payment status query tool with no annotations and no output schema, the description is insufficient. It doesn't explain what information is returned, possible status values, error handling, or integration context. The agent would need to guess about the response format and behavioral characteristics, making this incomplete for practical use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with the parameter 'orderId' documented as '商户订单号' (merchant order number). The description adds no additional parameter information beyond what's in the schema. With high schema coverage, the baseline score of 3 is appropriate as the schema does the heavy lifting for parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description '查询支付状态工具' (Query payment status tool) states the basic purpose of querying payment status, which is clear but vague. It specifies the verb '查询' (query) and resource '支付状态' (payment status), but doesn't distinguish from its sibling 'create_webpage_yeepay_payment' or provide specific details about what payment system or scope is involved.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. There's no mention of prerequisites, timing considerations, or comparison with the sibling tool 'create_webpage_yeepay_payment'. The agent must infer usage context solely from the tool name and basic purpose.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yop-platform/yeepay-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server