0

I am trying to implement an incoming webhook on my WordPress website to send a message to MS Teams when I receive a form submission. The message includes an ActionCard with a multiple choice input updating the status.

I have everything working in terms of sending the message to Teams and including the multiple choice input, but when I make a choice on the Teams message and click on the button to update the status, it's supposed to send the response back to my site, but I get an error message saying "Failed to send - There was a problem submitting your changes. Try again in a minute."

I have registered a custom rest route to capture the response which works fine when I use JavaScript fetch(), so I know the target url works; however, I cannot get it to work with this Teams response. Is there a different method I'm supposed to be using or what am I missing?

My class:

class ERI_MICROSOFT_TEAMS {

    /**
     * The webhook for the MS Teams channel
     *
     * @var string
     */
    public static $webhook;


    /**
     * The option name where we store the chat messages
     *
     * @var string
     */
    public static $option_name;


    /**
     * Load when the site loads
     *
     * @return void
     */
    public function init() {

        // The webhook
        self::$webhook = 'https://[hidden]';

        // The option name
        self::$option_name = 'microsoft_teams_webhook';

        // Register custom API route for Teams
        add_action( 'rest_api_init', [ $this, 'register_route' ] );

    } // End init()


    /**
     * Process API $_POST request from Teams
     *
     * @param WP_REST_Request $request
     * @return void
     */
    public function process_request( WP_REST_Request $request ) {
        // Get the request body
        $message_data = $request->get_json_params();

        // Attempt to do something with it, let's just try to update a site option for now
        if ( update_option( self::$option_name, $message_data ) ) {

            // If it worked, then send success response and status
            $response = new WP_REST_Response( [ 'message' => 'Successful' ] );
            $response->set_status( 200 );
            return $response;

        // Otherwise respond with an error
        } else {
             return new WP_Error( 'invalid_request', 'Something went wrong', [ 'status' => 403 ] );
        }
    } // End process_request()


    /**
     * Register a custom API route
     * https://example.com/wp-json/eri/v1/msteams
     *
     * @return void
     */
    public function register_route() {
        register_rest_route( 'eri/v1', '/msteams', [
             'methods'  => 'POST',
             'callback' => [ $this, 'process_request' ]
        ] );
    } // End register_route()


    /**
     * Send a message to MS Teams channel
     *
     * @return void
     */
    public static function send_msg( $form_id, $entry_id, $message, $name, $email, $phone = '(none)', $user_id = '(no user found)' ) {
        // Option prefix
        $pf = 'msteams_msg_';

        // Get the site name
        if ( get_option( $pf.'site_name' ) && get_option( $pf.'site_name' ) != '' ) {
            $site_name = get_option( $pf.'site_name' );
        } else {
            $site_name = get_bloginfo( 'name' );
        }

        // Get the site image
        if ( get_option( $pf.'image' ) && get_option( $pf.'image' ) != '' ) {
            $image = get_option( $pf.'image' );
        } else {
            $image = 'https://example/wp-content/uploads/logo.png'; // Our Logo
        }

        // Get the accent color
        if ( get_option( $pf.'color' ) && get_option( $pf.'color' ) != '' ) {
            $color = get_option( $pf.'color' );
        } else {
            $color = '#FF0000'; // ERI Star
        }

        // Put the message card together
        $data = [
            '@type'      => 'MessageCard',
            '@context'   => 'https://schema.org/extensions',
            'summary'    => 'Website Help Desk Support Request',
            'themeColor' => $color,
            'title'      => 'New Support Request',
            'sections'   => [
                [
                    'activityTitle'    => $site_name,
                    'activitySubtitle' => date( 'Y-m-d' ),
                    'activityImage'    => $image,
                    'text'             => $message,
                    'facts'            => [
                        [
                            'name'  => 'Name: ',
                            'value' => $name
                        ],
                        [
                            'name'  => 'Email: ',
                            'value' => $email
                        ],
                    ],
                ]
            ],
            'potentialAction' => [
                [
                    '@type'   => 'OpenUri',
                    'name'    => 'Visit Site',
                    'targets' => [
                        [
                            'os'  => 'default',
                            'uri' => home_url()
                        ]
                    ]
                ],
                [
                    '@type'  => 'ActionCard',
                    'name'   => 'Update Status',
                    'inputs' => [
                        [
                            '@type'   => 'MultichoiceInput',
                            'id'      => 'status',
                            'title'   => 'Status',
                            'choices' => [
                                [
                                    'display' => 'Unresolved',
                                    'value'   => 'unresolved'
                                ],
                                [
                                    'display' => 'In Progress',
                                    'value'   => 'in_progress'
                                ],
                                [
                                    'display' => 'Resolved',
                                    'value'   => 'resolved'
                                ]
                            ]
                        ]
                    ],
                    'actions' => [ // WHERE I NEED HELP
                        [
                            '@type'  => 'HttpPOST',
                            'name'   => 'Update',
                            'target' => 'https://example.com/wp-json/eri/v1/msteams',
                            'body'   => '{{status.value}}'
                        ]
                    ]
                ],
            ]
        ];

        // Encode
        $json_data = json_encode( $data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );

        // Send it to discord
        $ch = curl_init( self::$webhook );
        curl_setopt( $ch, CURLOPT_HTTPHEADER, [ 'Content-type: application/json' ] );
        curl_setopt( $ch, CURLOPT_POST, 1 );
        curl_setopt( $ch, CURLOPT_POSTFIELDS, $json_data );
        curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 );
        curl_setopt( $ch, CURLOPT_HEADER, 0 );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );

        $response = curl_exec( $ch );
        echo $response;
        curl_close( $ch );
    } // End send_msg()
}

The documentation includes a JSON example, and I also tried using Postman to send just like their example shows, but I get the same error which makes me believe it's a problem with my rest route.

1
  • I posted an answer, but if the same problem persists, then, "I also tried using Postman to send just like their example shows, but I get the same error" - what are the request and response body and headers?
    – Sally CJ
    Commented Mar 11, 2023 at 9:59

1 Answer 1

1

I'm not completely sure if this is the problem, but note that update_option() returns a false if the the old and new option values are the same, so you should not simply do a if ( update_option( self::$option_name, $message_data ) ) check.

So for example, you would instead do something like this:

if ( get_option( self::$option_name ) === $message_data ||
    update_option( self::$option_name, $message_data )
) {
    // your code here - send a success response and status, etc.
}

Or maybe this:

if ( get_option( self::$option_name ) === $message_data ) {
    $message = 'The old and new ' . self::$option_name . ' values are identical.';
    return [ 'message' => $message ];
} elseif ( update_option( self::$option_name, $message_data ) ) {
    return [ 'message' => 'Successful' ];
} // else, return a WP_Error instance

Additionally, just a note that you should always include set the permission_callback argument, even for REST API routes that are intended to be public (and if it's public, then you can use 'permission_callback' => '__return_true',).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.