So I asked this question on PostgreSQL mailing list, as suggested by Craig Ringer, and I've got the answer.
In short the solution is to write a procedure which materializes JSON array to PostgreSQL array:
create function data_product_ids(JSON) returns integer[] immutable as $$
select array_agg((a->>'product_id')::integer) from
json_array_elements($1->'products') as a $$ language sql ;
and use that procedure in CHECK
statment:
alter table orders add check (1 <= ALL(data_product_ids(data)));
For more details on how this works se the answer on PostgreSQL mailing list. Credits to Joel Hoffman.